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