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