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