Home | History | Annotate | Download | only in vk
      1 /*
      2 * Copyright 2016 Google Inc.
      3 *
      4 * Use of this source code is governed by a BSD-style license that can be
      5 * found in the LICENSE file.
      6 */
      7 
      8 #include "vk/GrVkPipelineStateBuilder.h"
      9 
     10 #include "GrContext.h"
     11 #include "GrContextPriv.h"
     12 #include "GrShaderCaps.h"
     13 #include "vk/GrVkDescriptorSetManager.h"
     14 #include "vk/GrVkGpu.h"
     15 #include "vk/GrVkRenderPass.h"
     16 
     17 
     18 GrVkPipelineState* GrVkPipelineStateBuilder::CreatePipelineState(
     19                                                                GrVkGpu* gpu,
     20                                                                const GrPipeline& pipeline,
     21                                                                const GrStencilSettings& stencil,
     22                                                                const GrPrimitiveProcessor& primProc,
     23                                                                GrPrimitiveType primitiveType,
     24                                                                GrVkPipelineState::Desc* desc,
     25                                                                const GrVkRenderPass& renderPass) {
     26     // create a builder.  This will be handed off to effects so they can use it to add
     27     // uniforms, varyings, textures, etc
     28     GrVkPipelineStateBuilder builder(gpu, pipeline, primProc, desc);
     29 
     30     if (!builder.emitAndInstallProcs()) {
     31         builder.cleanupFragmentProcessors();
     32         return nullptr;
     33     }
     34 
     35     return builder.finalize(stencil, primitiveType, renderPass, desc);
     36 }
     37 
     38 GrVkPipelineStateBuilder::GrVkPipelineStateBuilder(GrVkGpu* gpu,
     39                                                    const GrPipeline& pipeline,
     40                                                    const GrPrimitiveProcessor& primProc,
     41                                                    GrProgramDesc* desc)
     42     : INHERITED(pipeline, primProc, desc)
     43     , fGpu(gpu)
     44     , fVaryingHandler(this)
     45     , fUniformHandler(this) {
     46 }
     47 
     48 const GrCaps* GrVkPipelineStateBuilder::caps() const {
     49     return fGpu->caps();
     50 }
     51 
     52 void GrVkPipelineStateBuilder::finalizeFragmentOutputColor(GrShaderVar& outputColor) {
     53     outputColor.addLayoutQualifier("location = 0, index = 0");
     54 }
     55 
     56 void GrVkPipelineStateBuilder::finalizeFragmentSecondaryColor(GrShaderVar& outputColor) {
     57     outputColor.addLayoutQualifier("location = 0, index = 1");
     58 }
     59 
     60 bool GrVkPipelineStateBuilder::createVkShaderModule(VkShaderStageFlagBits stage,
     61                                                     const GrGLSLShaderBuilder& builder,
     62                                                     VkShaderModule* shaderModule,
     63                                                     VkPipelineShaderStageCreateInfo* stageInfo,
     64                                                     const SkSL::Program::Settings& settings,
     65                                                     GrVkPipelineState::Desc* desc) {
     66     SkString shaderString;
     67     for (int i = 0; i < builder.fCompilerStrings.count(); ++i) {
     68         if (builder.fCompilerStrings[i]) {
     69             shaderString.append(builder.fCompilerStrings[i]);
     70             shaderString.append("\n");
     71         }
     72     }
     73 
     74     SkSL::Program::Inputs inputs;
     75     bool result = GrCompileVkShaderModule(fGpu, shaderString.c_str(), stage, shaderModule,
     76                                           stageInfo, settings, &inputs);
     77     if (!result) {
     78         return false;
     79     }
     80     if (inputs.fRTHeight) {
     81         this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
     82     }
     83     if (inputs.fFlipY) {
     84         desc->setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(
     85                                                      this->pipeline().proxy()->origin()));
     86         desc->finalize();
     87     }
     88     return result;
     89 }
     90 
     91 GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& stencil,
     92                                                       GrPrimitiveType primitiveType,
     93                                                       const GrVkRenderPass& renderPass,
     94                                                       GrVkPipelineState::Desc* desc) {
     95     VkDescriptorSetLayout dsLayout[3];
     96     VkPipelineLayout pipelineLayout;
     97     VkShaderModule vertShaderModule = VK_NULL_HANDLE;
     98     VkShaderModule geomShaderModule = VK_NULL_HANDLE;
     99     VkShaderModule fragShaderModule = VK_NULL_HANDLE;
    100 
    101     GrVkResourceProvider& resourceProvider = fGpu->resourceProvider();
    102     // These layouts are not owned by the PipelineStateBuilder and thus should not be destroyed
    103     dsLayout[GrVkUniformHandler::kUniformBufferDescSet] = resourceProvider.getUniformDSLayout();
    104 
    105     GrVkDescriptorSetManager::Handle samplerDSHandle;
    106     resourceProvider.getSamplerDescriptorSetHandle(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
    107                                                    fUniformHandler, &samplerDSHandle);
    108     dsLayout[GrVkUniformHandler::kSamplerDescSet] =
    109             resourceProvider.getSamplerDSLayout(samplerDSHandle);
    110 
    111     GrVkDescriptorSetManager::Handle texelBufferDSHandle;
    112     resourceProvider.getSamplerDescriptorSetHandle(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
    113                                                    fUniformHandler, &texelBufferDSHandle);
    114     dsLayout[GrVkUniformHandler::kTexelBufferDescSet] =
    115             resourceProvider.getSamplerDSLayout(texelBufferDSHandle);
    116 
    117     // Create the VkPipelineLayout
    118     VkPipelineLayoutCreateInfo layoutCreateInfo;
    119     memset(&layoutCreateInfo, 0, sizeof(VkPipelineLayoutCreateFlags));
    120     layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
    121     layoutCreateInfo.pNext = 0;
    122     layoutCreateInfo.flags = 0;
    123     layoutCreateInfo.setLayoutCount = 3;
    124     layoutCreateInfo.pSetLayouts = dsLayout;
    125     layoutCreateInfo.pushConstantRangeCount = 0;
    126     layoutCreateInfo.pPushConstantRanges = nullptr;
    127 
    128     GR_VK_CALL_ERRCHECK(fGpu->vkInterface(), CreatePipelineLayout(fGpu->device(),
    129                                                                   &layoutCreateInfo,
    130                                                                   nullptr,
    131                                                                   &pipelineLayout));
    132 
    133     // We need to enable the following extensions so that the compiler can correctly make spir-v
    134     // from our glsl shaders.
    135     fVS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
    136     fFS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
    137     fVS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
    138     fFS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
    139 
    140     this->finalizeShaders();
    141 
    142     VkPipelineShaderStageCreateInfo shaderStageInfo[3];
    143     SkSL::Program::Settings settings;
    144     settings.fCaps = this->caps()->shaderCaps();
    145     settings.fFlipY = this->pipeline().proxy()->origin() != kTopLeft_GrSurfaceOrigin;
    146     settings.fSharpenTextures = this->gpu()->getContext()->contextPriv().sharpenMipmappedTextures();
    147     SkASSERT(!this->fragColorIsInOut());
    148     SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT,
    149                                               fVS,
    150                                               &vertShaderModule,
    151                                               &shaderStageInfo[0],
    152                                               settings,
    153                                               desc));
    154 
    155     SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT,
    156                                               fFS,
    157                                               &fragShaderModule,
    158                                               &shaderStageInfo[1],
    159                                               settings,
    160                                               desc));
    161 
    162     int numShaderStages = 2; // We always have at least vertex and fragment stages.
    163     if (this->primitiveProcessor().willUseGeoShader()) {
    164         SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_GEOMETRY_BIT,
    165                                                   fGS,
    166                                                   &geomShaderModule,
    167                                                   &shaderStageInfo[2],
    168                                                   settings,
    169                                                   desc));
    170         ++numShaderStages;
    171     }
    172 
    173     GrVkPipeline* pipeline = resourceProvider.createPipeline(fPipeline,
    174                                                              stencil,
    175                                                              fPrimProc,
    176                                                              shaderStageInfo,
    177                                                              numShaderStages,
    178                                                              primitiveType,
    179                                                              renderPass,
    180                                                              pipelineLayout);
    181     GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), vertShaderModule,
    182                                                         nullptr));
    183     GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), fragShaderModule,
    184                                                         nullptr));
    185     // This if check should not be needed since calling destroy on a VK_NULL_HANDLE is allowed.
    186     // However this is causing a crash in certain drivers (e.g. NVidia).
    187     if (this->primitiveProcessor().willUseGeoShader()) {
    188         GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), geomShaderModule,
    189                                                             nullptr));
    190     }
    191 
    192     if (!pipeline) {
    193         GR_VK_CALL(fGpu->vkInterface(), DestroyPipelineLayout(fGpu->device(), pipelineLayout,
    194                                                               nullptr));
    195         this->cleanupFragmentProcessors();
    196         return nullptr;
    197     }
    198 
    199     return new GrVkPipelineState(fGpu,
    200                                  *desc,
    201                                  pipeline,
    202                                  pipelineLayout,
    203                                  samplerDSHandle,
    204                                  texelBufferDSHandle,
    205                                  fUniformHandles,
    206                                  fUniformHandler.fUniforms,
    207                                  fUniformHandler.fCurrentGeometryUBOOffset,
    208                                  fUniformHandler.fCurrentFragmentUBOOffset,
    209                                  (uint32_t)fUniformHandler.numSamplers(),
    210                                  (uint32_t)fUniformHandler.numTexelBuffers(),
    211                                  std::move(fGeometryProcessor),
    212                                  std::move(fXferProcessor),
    213                                  fFragmentProcessors);
    214 }
    215 
    216