• 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 "include/gpu/GrContext.h"
9 #include "src/gpu/GrContextPriv.h"
10 #include "src/gpu/GrPersistentCacheUtils.h"
11 #include "src/gpu/GrShaderCaps.h"
12 #include "src/gpu/GrShaderUtils.h"
13 #include "src/gpu/GrStencilSettings.h"
14 #include "src/gpu/vk/GrVkDescriptorSetManager.h"
15 #include "src/gpu/vk/GrVkGpu.h"
16 #include "src/gpu/vk/GrVkPipelineStateBuilder.h"
17 #include "src/gpu/vk/GrVkRenderPass.h"
18 #include "src/gpu/vk/GrVkRenderTarget.h"
19 
20 typedef size_t shader_size;
21 
CreatePipelineState(GrVkGpu * gpu,GrRenderTarget * renderTarget,GrSurfaceOrigin origin,const GrPrimitiveProcessor & primProc,const GrTextureProxy * const primProcProxies[],const GrPipeline & pipeline,const GrStencilSettings & stencil,GrPrimitiveType primitiveType,Desc * desc,VkRenderPass compatibleRenderPass)22 GrVkPipelineState* GrVkPipelineStateBuilder::CreatePipelineState(
23         GrVkGpu* gpu,
24         GrRenderTarget* renderTarget, GrSurfaceOrigin origin,
25         const GrPrimitiveProcessor& primProc,
26         const GrTextureProxy* const primProcProxies[],
27         const GrPipeline& pipeline,
28         const GrStencilSettings& stencil,
29         GrPrimitiveType primitiveType,
30         Desc* desc,
31         VkRenderPass compatibleRenderPass) {
32     // create a builder.  This will be handed off to effects so they can use it to add
33     // uniforms, varyings, textures, etc
34     GrVkPipelineStateBuilder builder(gpu, renderTarget, origin, pipeline, primProc,
35                                      primProcProxies, desc);
36 
37     if (!builder.emitAndInstallProcs()) {
38         return nullptr;
39     }
40 
41     return builder.finalize(stencil, primitiveType, compatibleRenderPass, desc);
42 }
43 
GrVkPipelineStateBuilder(GrVkGpu * gpu,GrRenderTarget * renderTarget,GrSurfaceOrigin origin,const GrPipeline & pipeline,const GrPrimitiveProcessor & primProc,const GrTextureProxy * const primProcProxies[],GrProgramDesc * desc)44 GrVkPipelineStateBuilder::GrVkPipelineStateBuilder(GrVkGpu* gpu,
45                                                    GrRenderTarget* renderTarget,
46                                                    GrSurfaceOrigin origin,
47                                                    const GrPipeline& pipeline,
48                                                    const GrPrimitiveProcessor& primProc,
49                                                    const GrTextureProxy* const primProcProxies[],
50                                                    GrProgramDesc* desc)
51         : INHERITED(renderTarget, origin, primProc, primProcProxies, pipeline, desc)
52         , fGpu(gpu)
53         , fVaryingHandler(this)
54         , fUniformHandler(this) {}
55 
caps() const56 const GrCaps* GrVkPipelineStateBuilder::caps() const {
57     return fGpu->caps();
58 }
59 
finalizeFragmentOutputColor(GrShaderVar & outputColor)60 void GrVkPipelineStateBuilder::finalizeFragmentOutputColor(GrShaderVar& outputColor) {
61     outputColor.addLayoutQualifier("location = 0, index = 0");
62 }
63 
finalizeFragmentSecondaryColor(GrShaderVar & outputColor)64 void GrVkPipelineStateBuilder::finalizeFragmentSecondaryColor(GrShaderVar& outputColor) {
65     outputColor.addLayoutQualifier("location = 0, index = 1");
66 }
67 
createVkShaderModule(VkShaderStageFlagBits stage,const SkSL::String & sksl,VkShaderModule * shaderModule,VkPipelineShaderStageCreateInfo * stageInfo,const SkSL::Program::Settings & settings,Desc * desc,SkSL::String * outSPIRV,SkSL::Program::Inputs * outInputs)68 bool GrVkPipelineStateBuilder::createVkShaderModule(VkShaderStageFlagBits stage,
69                                                     const SkSL::String& sksl,
70                                                     VkShaderModule* shaderModule,
71                                                     VkPipelineShaderStageCreateInfo* stageInfo,
72                                                     const SkSL::Program::Settings& settings,
73                                                     Desc* desc,
74                                                     SkSL::String* outSPIRV,
75                                                     SkSL::Program::Inputs* outInputs) {
76     if (!GrCompileVkShaderModule(fGpu, sksl, stage, shaderModule,
77                                  stageInfo, settings, outSPIRV, outInputs)) {
78         return false;
79     }
80     if (outInputs->fRTHeight) {
81         this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
82     }
83     return true;
84 }
85 
installVkShaderModule(VkShaderStageFlagBits stage,const GrGLSLShaderBuilder & builder,VkShaderModule * shaderModule,VkPipelineShaderStageCreateInfo * stageInfo,SkSL::String spirv,SkSL::Program::Inputs inputs)86 bool GrVkPipelineStateBuilder::installVkShaderModule(VkShaderStageFlagBits stage,
87                                                      const GrGLSLShaderBuilder& builder,
88                                                      VkShaderModule* shaderModule,
89                                                      VkPipelineShaderStageCreateInfo* stageInfo,
90                                                      SkSL::String spirv,
91                                                      SkSL::Program::Inputs inputs) {
92     if (!GrInstallVkShaderModule(fGpu, spirv, stage, shaderModule, stageInfo)) {
93         return false;
94     }
95     if (inputs.fRTHeight) {
96         this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
97     }
98     return true;
99 }
100 
101 static constexpr SkFourByteTag kSPIRV_Tag = SkSetFourByteTag('S', 'P', 'R', 'V');
102 static constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L');
103 
loadShadersFromCache(const SkData & cached,VkShaderModule outShaderModules[],VkPipelineShaderStageCreateInfo * outStageInfo)104 int GrVkPipelineStateBuilder::loadShadersFromCache(const SkData& cached,
105                                                    VkShaderModule outShaderModules[],
106                                                    VkPipelineShaderStageCreateInfo* outStageInfo) {
107     SkSL::String shaders[kGrShaderTypeCount];
108     SkSL::Program::Inputs inputs[kGrShaderTypeCount];
109 
110     if (kSPIRV_Tag != GrPersistentCacheUtils::UnpackCachedShaders(&cached, shaders,
111                                                                   inputs, kGrShaderTypeCount)) {
112         return 0;
113     }
114 
115     SkAssertResult(this->installVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT,
116                                                fVS,
117                                                &outShaderModules[kVertex_GrShaderType],
118                                                &outStageInfo[0],
119                                                shaders[kVertex_GrShaderType],
120                                                inputs[kVertex_GrShaderType]));
121 
122     SkAssertResult(this->installVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT,
123                                                fFS,
124                                                &outShaderModules[kFragment_GrShaderType],
125                                                &outStageInfo[1],
126                                                shaders[kFragment_GrShaderType],
127                                                inputs[kFragment_GrShaderType]));
128 
129     if (!shaders[kGeometry_GrShaderType].empty()) {
130         SkAssertResult(this->installVkShaderModule(VK_SHADER_STAGE_GEOMETRY_BIT,
131                                                    fGS,
132                                                    &outShaderModules[kGeometry_GrShaderType],
133                                                    &outStageInfo[2],
134                                                    shaders[kGeometry_GrShaderType],
135                                                    inputs[kGeometry_GrShaderType]));
136         return 3;
137     } else {
138         return 2;
139     }
140 }
141 
storeShadersInCache(const SkSL::String shaders[],const SkSL::Program::Inputs inputs[],bool isSkSL)142 void GrVkPipelineStateBuilder::storeShadersInCache(const SkSL::String shaders[],
143                                                    const SkSL::Program::Inputs inputs[],
144                                                    bool isSkSL) {
145     Desc* desc = static_cast<Desc*>(this->desc());
146     sk_sp<SkData> key = SkData::MakeWithoutCopy(desc->asKey(), desc->shaderKeyLength());
147     sk_sp<SkData> data = GrPersistentCacheUtils::PackCachedShaders(isSkSL ? kSKSL_Tag : kSPIRV_Tag,
148                                                                    shaders,
149                                                                    inputs, kGrShaderTypeCount);
150     this->gpu()->getContext()->priv().getPersistentCache()->store(*key, *data);
151 }
152 
finalize(const GrStencilSettings & stencil,GrPrimitiveType primitiveType,VkRenderPass compatibleRenderPass,Desc * desc)153 GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& stencil,
154                                                       GrPrimitiveType primitiveType,
155                                                       VkRenderPass compatibleRenderPass,
156                                                       Desc* desc) {
157     VkDescriptorSetLayout dsLayout[2];
158     VkPipelineLayout pipelineLayout;
159     VkShaderModule shaderModules[kGrShaderTypeCount] = { VK_NULL_HANDLE,
160                                                          VK_NULL_HANDLE,
161                                                          VK_NULL_HANDLE };
162 
163     GrVkResourceProvider& resourceProvider = fGpu->resourceProvider();
164     // These layouts are not owned by the PipelineStateBuilder and thus should not be destroyed
165     dsLayout[GrVkUniformHandler::kUniformBufferDescSet] = resourceProvider.getUniformDSLayout();
166 
167     GrVkDescriptorSetManager::Handle samplerDSHandle;
168     resourceProvider.getSamplerDescriptorSetHandle(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
169                                                    fUniformHandler, &samplerDSHandle);
170     dsLayout[GrVkUniformHandler::kSamplerDescSet] =
171             resourceProvider.getSamplerDSLayout(samplerDSHandle);
172 
173     // Create the VkPipelineLayout
174     VkPipelineLayoutCreateInfo layoutCreateInfo;
175     memset(&layoutCreateInfo, 0, sizeof(VkPipelineLayoutCreateFlags));
176     layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
177     layoutCreateInfo.pNext = 0;
178     layoutCreateInfo.flags = 0;
179     layoutCreateInfo.setLayoutCount = 2;
180     layoutCreateInfo.pSetLayouts = dsLayout;
181     layoutCreateInfo.pushConstantRangeCount = 0;
182     layoutCreateInfo.pPushConstantRanges = nullptr;
183 
184     GR_VK_CALL_ERRCHECK(fGpu->vkInterface(), CreatePipelineLayout(fGpu->device(),
185                                                                   &layoutCreateInfo,
186                                                                   nullptr,
187                                                                   &pipelineLayout));
188 
189     // We need to enable the following extensions so that the compiler can correctly make spir-v
190     // from our glsl shaders.
191     fVS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
192     fFS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
193     fVS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
194     fFS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
195 
196     this->finalizeShaders();
197 
198     VkPipelineShaderStageCreateInfo shaderStageInfo[3];
199     SkSL::Program::Settings settings;
200     settings.fCaps = this->caps()->shaderCaps();
201     settings.fVkCaps = &this->gpu()->vkCaps();
202     settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin;
203     settings.fSharpenTextures =
204                         this->gpu()->getContext()->priv().options().fSharpenMipmappedTextures;
205     settings.fRTHeightOffset = fUniformHandler.getRTHeightOffset();
206     SkASSERT(!this->fragColorIsInOut());
207 
208     sk_sp<SkData> cached;
209     auto persistentCache = fGpu->getContext()->priv().getPersistentCache();
210     if (persistentCache) {
211         sk_sp<SkData> key = SkData::MakeWithoutCopy(desc->asKey(), desc->shaderKeyLength());
212         cached = persistentCache->load(*key);
213     }
214     bool binaryCache = true;
215 #if GR_TEST_UTILS
216     binaryCache = !fGpu->getContext()->priv().options().fCacheSKSL;
217 #endif
218     int numShaderStages = 0;
219     if (cached && binaryCache) {
220         numShaderStages = this->loadShadersFromCache(*cached, shaderModules, shaderStageInfo);
221     }
222 
223     if (!numShaderStages) {
224         numShaderStages = 2; // We always have at least vertex and fragment stages.
225         SkSL::String shaders[kGrShaderTypeCount];
226         SkSL::Program::Inputs inputs[kGrShaderTypeCount];
227 
228         SkSL::String* sksl[kGrShaderTypeCount] = {
229             &fVS.fCompilerString,
230             &fGS.fCompilerString,
231             &fFS.fCompilerString,
232         };
233 #if GR_TEST_UTILS
234         SkSL::String cached_sksl[kGrShaderTypeCount];
235         if (cached) {
236             if (kSKSL_Tag == GrPersistentCacheUtils::UnpackCachedShaders(
237                     cached.get(), cached_sksl, inputs, kGrShaderTypeCount)) {
238                 for (int i = 0; i < kGrShaderTypeCount; ++i) {
239                     sksl[i] = &cached_sksl[i];
240                 }
241             }
242         }
243 #endif
244 
245         bool success = this->createVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT,
246                                                   *sksl[kVertex_GrShaderType],
247                                                   &shaderModules[kVertex_GrShaderType],
248                                                   &shaderStageInfo[0],
249                                                   settings,
250                                                   desc,
251                                                   &shaders[kVertex_GrShaderType],
252                                                   &inputs[kVertex_GrShaderType]);
253 
254         success = success && this->createVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT,
255                                                         *sksl[kFragment_GrShaderType],
256                                                         &shaderModules[kFragment_GrShaderType],
257                                                         &shaderStageInfo[1],
258                                                         settings,
259                                                         desc,
260                                                         &shaders[kFragment_GrShaderType],
261                                                         &inputs[kFragment_GrShaderType]);
262 
263         if (this->primitiveProcessor().willUseGeoShader()) {
264             success = success && this->createVkShaderModule(VK_SHADER_STAGE_GEOMETRY_BIT,
265                                                             *sksl[kGeometry_GrShaderType],
266                                                             &shaderModules[kGeometry_GrShaderType],
267                                                             &shaderStageInfo[2],
268                                                             settings,
269                                                             desc,
270                                                             &shaders[kGeometry_GrShaderType],
271                                                             &inputs[kGeometry_GrShaderType]);
272             ++numShaderStages;
273         }
274 
275         if (!success) {
276             for (int i = 0; i < kGrShaderTypeCount; ++i) {
277                 if (shaderModules[i]) {
278                     GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(),
279                                                                         shaderModules[i], nullptr));
280                 }
281             }
282             GR_VK_CALL(fGpu->vkInterface(), DestroyPipelineLayout(fGpu->device(), pipelineLayout,
283                                                                   nullptr));
284             return nullptr;
285         }
286 
287         if (persistentCache && !cached) {
288             bool isSkSL = false;
289 #if GR_TEST_UTILS
290             if (fGpu->getContext()->priv().options().fCacheSKSL) {
291                 for (int i = 0; i < kGrShaderTypeCount; ++i) {
292                     shaders[i] = GrShaderUtils::PrettyPrint(*sksl[i]);
293                 }
294                 isSkSL = true;
295             }
296 #endif
297             this->storeShadersInCache(shaders, inputs, isSkSL);
298         }
299     }
300     GrVkPipeline* pipeline = resourceProvider.createPipeline(
301             this->renderTarget()->numSamples(), fPrimProc, fPipeline, stencil, this->origin(),
302             shaderStageInfo, numShaderStages, primitiveType, compatibleRenderPass, pipelineLayout);
303     for (int i = 0; i < kGrShaderTypeCount; ++i) {
304         // This if check should not be needed since calling destroy on a VK_NULL_HANDLE is allowed.
305         // However this is causing a crash in certain drivers (e.g. NVidia).
306         if (shaderModules[i]) {
307             GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), shaderModules[i],
308                                                                 nullptr));
309         }
310     }
311 
312     if (!pipeline) {
313         GR_VK_CALL(fGpu->vkInterface(), DestroyPipelineLayout(fGpu->device(), pipelineLayout,
314                                                               nullptr));
315         return nullptr;
316     }
317 
318     return new GrVkPipelineState(fGpu,
319                                  pipeline,
320                                  samplerDSHandle,
321                                  fUniformHandles,
322                                  fUniformHandler.fUniforms,
323                                  fUniformHandler.fCurrentUBOOffset,
324                                  fUniformHandler.fSamplers,
325                                  std::move(fGeometryProcessor),
326                                  std::move(fXferProcessor),
327                                  std::move(fFragmentProcessors),
328                                  fFragmentProcessorCnt);
329 }
330 
331 //////////////////////////////////////////////////////////////////////////////
332 
Build(Desc * desc,GrRenderTarget * renderTarget,const GrPrimitiveProcessor & primProc,const GrPipeline & pipeline,const GrStencilSettings & stencil,GrPrimitiveType primitiveType,GrVkGpu * gpu)333 bool GrVkPipelineStateBuilder::Desc::Build(Desc* desc,
334                                            GrRenderTarget* renderTarget,
335                                            const GrPrimitiveProcessor& primProc,
336                                            const GrPipeline& pipeline,
337                                            const GrStencilSettings& stencil,
338                                            GrPrimitiveType primitiveType,
339                                            GrVkGpu* gpu) {
340     if (!INHERITED::Build(desc, renderTarget, primProc,
341                           primitiveType == GrPrimitiveType::kPoints, pipeline, gpu)) {
342         return false;
343     }
344 
345     GrProcessorKeyBuilder b(&desc->key());
346 
347     b.add32(GrVkGpu::kShader_PersistentCacheKeyType);
348     int keyLength = desc->key().count();
349     SkASSERT(0 == (keyLength % 4));
350     desc->fShaderKeyLength = SkToU32(keyLength);
351 
352     GrVkRenderTarget* vkRT = (GrVkRenderTarget*)renderTarget;
353     vkRT->simpleRenderPass()->genKey(&b);
354 
355     stencil.genKey(&b);
356 
357     b.add32(pipeline.getBlendInfoKey());
358 
359     b.add32((uint32_t)primitiveType);
360 
361     return true;
362 }
363