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 
CreatePipelineState(GrVkGpu * gpu,const GrPipeline & pipeline,const GrStencilSettings & stencil,const GrPrimitiveProcessor & primProc,GrPrimitiveType primitiveType,GrVkPipelineState::Desc * desc,const GrVkRenderPass & renderPass)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 
GrVkPipelineStateBuilder(GrVkGpu * gpu,const GrPipeline & pipeline,const GrPrimitiveProcessor & primProc,GrProgramDesc * desc)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 
caps() const48 const GrCaps* GrVkPipelineStateBuilder::caps() const {
49     return fGpu->caps();
50 }
51 
finalizeFragmentOutputColor(GrShaderVar & outputColor)52 void GrVkPipelineStateBuilder::finalizeFragmentOutputColor(GrShaderVar& outputColor) {
53     outputColor.addLayoutQualifier("location = 0, index = 0");
54 }
55 
finalizeFragmentSecondaryColor(GrShaderVar & outputColor)56 void GrVkPipelineStateBuilder::finalizeFragmentSecondaryColor(GrShaderVar& outputColor) {
57     outputColor.addLayoutQualifier("location = 0, index = 1");
58 }
59 
createVkShaderModule(VkShaderStageFlagBits stage,const GrGLSLShaderBuilder & builder,VkShaderModule * shaderModule,VkPipelineShaderStageCreateInfo * stageInfo,const SkSL::Program::Settings & settings,GrVkPipelineState::Desc * desc)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 
finalize(const GrStencilSettings & stencil,GrPrimitiveType primitiveType,const GrVkRenderPass & renderPass,GrVkPipelineState::Desc * desc)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     SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT,
148                                               fVS,
149                                               &vertShaderModule,
150                                               &shaderStageInfo[0],
151                                               settings,
152                                               desc));
153 
154     SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT,
155                                               fFS,
156                                               &fragShaderModule,
157                                               &shaderStageInfo[1],
158                                               settings,
159                                               desc));
160 
161     int numShaderStages = 2; // We always have at least vertex and fragment stages.
162     if (this->primitiveProcessor().willUseGeoShader()) {
163         SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_GEOMETRY_BIT,
164                                                   fGS,
165                                                   &geomShaderModule,
166                                                   &shaderStageInfo[2],
167                                                   settings,
168                                                   desc));
169         ++numShaderStages;
170     }
171 
172     GrVkPipeline* pipeline = resourceProvider.createPipeline(fPipeline,
173                                                              stencil,
174                                                              fPrimProc,
175                                                              shaderStageInfo,
176                                                              numShaderStages,
177                                                              primitiveType,
178                                                              renderPass,
179                                                              pipelineLayout);
180     GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), vertShaderModule,
181                                                         nullptr));
182     GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), fragShaderModule,
183                                                         nullptr));
184     // This if check should not be needed since calling destroy on a VK_NULL_HANDLE is allowed.
185     // However this is causing a crash in certain drivers (e.g. NVidia).
186     if (this->primitiveProcessor().willUseGeoShader()) {
187         GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), geomShaderModule,
188                                                             nullptr));
189     }
190 
191     if (!pipeline) {
192         GR_VK_CALL(fGpu->vkInterface(), DestroyPipelineLayout(fGpu->device(), pipelineLayout,
193                                                               nullptr));
194         this->cleanupFragmentProcessors();
195         return nullptr;
196     }
197 
198     return new GrVkPipelineState(fGpu,
199                                  *desc,
200                                  pipeline,
201                                  pipelineLayout,
202                                  samplerDSHandle,
203                                  texelBufferDSHandle,
204                                  fUniformHandles,
205                                  fUniformHandler.fUniforms,
206                                  fUniformHandler.fCurrentGeometryUBOOffset,
207                                  fUniformHandler.fCurrentFragmentUBOOffset,
208                                  (uint32_t)fUniformHandler.numSamplers(),
209                                  (uint32_t)fUniformHandler.numTexelBuffers(),
210                                  std::move(fGeometryProcessor),
211                                  std::move(fXferProcessor),
212                                  fFragmentProcessors);
213 }
214 
215