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