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 
CreatePipelineState(GrVkGpu * gpu,const GrPipeline & pipeline,const GrStencilSettings & stencil,const GrPrimitiveProcessor & primProc,GrPrimitiveType primitiveType,GrVkPipelineState::Desc * desc,const GrVkRenderPass & renderPass)16 GrVkPipelineState* 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     GrGLSLExpr4 inputColor;
29     GrGLSLExpr4 inputCoverage;
30 
31     if (!builder.emitAndInstallProcs(&inputColor, &inputCoverage)) {
32         builder.cleanupFragmentProcessors();
33         return nullptr;
34     }
35 
36     return builder.finalize(stencil, primitiveType, renderPass, desc);
37 }
38 
GrVkPipelineStateBuilder(GrVkGpu * gpu,const GrPipeline & pipeline,const GrPrimitiveProcessor & primProc,GrProgramDesc * desc)39 GrVkPipelineStateBuilder::GrVkPipelineStateBuilder(GrVkGpu* gpu,
40                                                    const GrPipeline& pipeline,
41                                                    const GrPrimitiveProcessor& primProc,
42                                                    GrProgramDesc* desc)
43     : INHERITED(pipeline, primProc, desc)
44     , fGpu(gpu)
45     , fVaryingHandler(this)
46     , fUniformHandler(this) {
47 }
48 
caps() const49 const GrCaps* GrVkPipelineStateBuilder::caps() const {
50     return fGpu->caps();
51 }
52 
finalizeFragmentOutputColor(GrShaderVar & outputColor)53 void GrVkPipelineStateBuilder::finalizeFragmentOutputColor(GrShaderVar& outputColor) {
54     outputColor.addLayoutQualifier("location = 0, index = 0");
55 }
56 
finalizeFragmentSecondaryColor(GrShaderVar & outputColor)57 void GrVkPipelineStateBuilder::finalizeFragmentSecondaryColor(GrShaderVar& outputColor) {
58     outputColor.addLayoutQualifier("location = 0, index = 1");
59 }
60 
createVkShaderModule(VkShaderStageFlagBits stage,const GrGLSLShaderBuilder & builder,VkShaderModule * shaderModule,VkPipelineShaderStageCreateInfo * stageInfo,const SkSL::Program::Settings & settings,GrVkPipelineState::Desc * desc)61 bool GrVkPipelineStateBuilder::createVkShaderModule(VkShaderStageFlagBits stage,
62                                                     const GrGLSLShaderBuilder& builder,
63                                                     VkShaderModule* shaderModule,
64                                                     VkPipelineShaderStageCreateInfo* stageInfo,
65                                                     const SkSL::Program::Settings& settings,
66                                                     GrVkPipelineState::Desc* desc) {
67     SkString shaderString;
68     for (int i = 0; i < builder.fCompilerStrings.count(); ++i) {
69         if (builder.fCompilerStrings[i]) {
70             shaderString.append(builder.fCompilerStrings[i]);
71             shaderString.append("\n");
72         }
73     }
74 
75     SkSL::Program::Inputs inputs;
76     bool result = GrCompileVkShaderModule(fGpu, shaderString.c_str(), stage, shaderModule,
77                                           stageInfo, settings, &inputs);
78     if (!result) {
79         return false;
80     }
81     if (inputs.fRTHeight) {
82         this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
83     }
84     if (inputs.fFlipY) {
85         desc->setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(
86                                                      this->pipeline().getRenderTarget()->origin()));
87         desc->finalize();
88     }
89     return result;
90 }
91 
finalize(const GrStencilSettings & stencil,GrPrimitiveType primitiveType,const GrVkRenderPass & renderPass,GrVkPipelineState::Desc * desc)92 GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& stencil,
93                                                       GrPrimitiveType primitiveType,
94                                                       const GrVkRenderPass& renderPass,
95                                                       GrVkPipelineState::Desc* desc) {
96     VkDescriptorSetLayout dsLayout[2];
97     VkPipelineLayout pipelineLayout;
98     VkShaderModule vertShaderModule;
99     VkShaderModule fragShaderModule;
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(fUniformHandler, &samplerDSHandle);
107     dsLayout[GrVkUniformHandler::kSamplerDescSet] =
108             resourceProvider.getSamplerDSLayout(samplerDSHandle);
109 
110     // Create the VkPipelineLayout
111     VkPipelineLayoutCreateInfo layoutCreateInfo;
112     memset(&layoutCreateInfo, 0, sizeof(VkPipelineLayoutCreateFlags));
113     layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
114     layoutCreateInfo.pNext = 0;
115     layoutCreateInfo.flags = 0;
116     layoutCreateInfo.setLayoutCount = 2;
117     layoutCreateInfo.pSetLayouts = dsLayout;
118     layoutCreateInfo.pushConstantRangeCount = 0;
119     layoutCreateInfo.pPushConstantRanges = nullptr;
120 
121     GR_VK_CALL_ERRCHECK(fGpu->vkInterface(), CreatePipelineLayout(fGpu->device(),
122                                                                   &layoutCreateInfo,
123                                                                   nullptr,
124                                                                   &pipelineLayout));
125 
126     // We need to enable the following extensions so that the compiler can correctly make spir-v
127     // from our glsl shaders.
128     fVS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
129     fFS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
130     fVS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
131     fFS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
132 
133     this->finalizeShaders();
134 
135     VkPipelineShaderStageCreateInfo shaderStageInfo[2];
136     SkSL::Program::Settings settings;
137     settings.fFlipY = this->pipeline().getRenderTarget()->origin() != kTopLeft_GrSurfaceOrigin;
138     SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT,
139                                               fVS,
140                                               &vertShaderModule,
141                                               &shaderStageInfo[0],
142                                               settings,
143                                               desc));
144 
145     // TODO: geometry shader support.
146     SkASSERT(!this->primitiveProcessor().willUseGeoShader());
147 
148     SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT,
149                                               fFS,
150                                               &fragShaderModule,
151                                               &shaderStageInfo[1],
152                                               settings,
153                                               desc));
154 
155     GrVkPipeline* pipeline = resourceProvider.createPipeline(fPipeline,
156                                                              stencil,
157                                                              fPrimProc,
158                                                              shaderStageInfo,
159                                                              2,
160                                                              primitiveType,
161                                                              renderPass,
162                                                              pipelineLayout);
163     GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), vertShaderModule,
164                                                         nullptr));
165     GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), fragShaderModule,
166                                                         nullptr));
167 
168     if (!pipeline) {
169         GR_VK_CALL(fGpu->vkInterface(), DestroyPipelineLayout(fGpu->device(), pipelineLayout,
170                                                               nullptr));
171         this->cleanupFragmentProcessors();
172         return nullptr;
173     }
174 
175     return new GrVkPipelineState(fGpu,
176                                  *desc,
177                                  pipeline,
178                                  pipelineLayout,
179                                  samplerDSHandle,
180                                  fUniformHandles,
181                                  fUniformHandler.fUniforms,
182                                  fUniformHandler.fCurrentVertexUBOOffset,
183                                  fUniformHandler.fCurrentFragmentUBOOffset,
184                                  (uint32_t)fUniformHandler.numSamplers(),
185                                  fGeometryProcessor,
186                                  fXferProcessor,
187                                  fFragmentProcessors);
188 }
189 
190