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 #include "GrContext.h"
10 #include "GrContextPriv.h"
11 #include "GrShaderCaps.h"
12 #include "GrStencilSettings.h"
13 #include "GrVkRenderTarget.h"
14 #include "vk/GrVkDescriptorSetManager.h"
15 #include "vk/GrVkGpu.h"
16 #include "vk/GrVkRenderPass.h"
17 
18 typedef size_t shader_size;
19 
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)20 GrVkPipelineState* GrVkPipelineStateBuilder::CreatePipelineState(
21         GrVkGpu* gpu,
22         GrRenderTarget* renderTarget, GrSurfaceOrigin origin,
23         const GrPrimitiveProcessor& primProc,
24         const GrTextureProxy* const primProcProxies[],
25         const GrPipeline& pipeline,
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, origin, pipeline, primProc,
33                                      primProcProxies, desc);
34 
35     if (!builder.emitAndInstallProcs()) {
36         return nullptr;
37     }
38 
39     return builder.finalize(stencil, primitiveType, compatibleRenderPass, desc);
40 }
41 
GrVkPipelineStateBuilder(GrVkGpu * gpu,GrRenderTarget * renderTarget,GrSurfaceOrigin origin,const GrPipeline & pipeline,const GrPrimitiveProcessor & primProc,const GrTextureProxy * const primProcProxies[],GrProgramDesc * desc)42 GrVkPipelineStateBuilder::GrVkPipelineStateBuilder(GrVkGpu* gpu,
43                                                    GrRenderTarget* renderTarget,
44                                                    GrSurfaceOrigin origin,
45                                                    const GrPipeline& pipeline,
46                                                    const GrPrimitiveProcessor& primProc,
47                                                    const GrTextureProxy* const primProcProxies[],
48                                                    GrProgramDesc* desc)
49         : INHERITED(renderTarget, origin, primProc, primProcProxies, pipeline, desc)
50         , fGpu(gpu)
51         , fVaryingHandler(this)
52         , fUniformHandler(this) {}
53 
caps() const54 const GrCaps* GrVkPipelineStateBuilder::caps() const {
55     return fGpu->caps();
56 }
57 
finalizeFragmentOutputColor(GrShaderVar & outputColor)58 void GrVkPipelineStateBuilder::finalizeFragmentOutputColor(GrShaderVar& outputColor) {
59     outputColor.addLayoutQualifier("location = 0, index = 0");
60 }
61 
finalizeFragmentSecondaryColor(GrShaderVar & outputColor)62 void GrVkPipelineStateBuilder::finalizeFragmentSecondaryColor(GrShaderVar& outputColor) {
63     outputColor.addLayoutQualifier("location = 0, index = 1");
64 }
65 
createVkShaderModule(VkShaderStageFlagBits stage,const GrGLSLShaderBuilder & builder,VkShaderModule * shaderModule,VkPipelineShaderStageCreateInfo * stageInfo,const SkSL::Program::Settings & settings,Desc * desc,SkSL::String * outSPIRV,SkSL::Program::Inputs * outInputs)66 bool GrVkPipelineStateBuilder::createVkShaderModule(VkShaderStageFlagBits stage,
67                                                     const GrGLSLShaderBuilder& builder,
68                                                     VkShaderModule* shaderModule,
69                                                     VkPipelineShaderStageCreateInfo* stageInfo,
70                                                     const SkSL::Program::Settings& settings,
71                                                     Desc* desc,
72                                                     SkSL::String* outSPIRV,
73                                                     SkSL::Program::Inputs* outInputs) {
74     SkString shaderString;
75     for (int i = 0; i < builder.fCompilerStrings.count(); ++i) {
76         if (builder.fCompilerStrings[i]) {
77             shaderString.append(builder.fCompilerStrings[i]);
78             shaderString.append("\n");
79         }
80     }
81 
82     if (!GrCompileVkShaderModule(fGpu, shaderString.c_str(), stage, shaderModule,
83                                  stageInfo, settings, outSPIRV, outInputs)) {
84         return false;
85     }
86     if (outInputs->fRTHeight) {
87         this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
88     }
89     if (outInputs->fFlipY) {
90         desc->setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(
91                                                      this->origin()));
92     }
93     return true;
94 }
95 
installVkShaderModule(VkShaderStageFlagBits stage,const GrGLSLShaderBuilder & builder,VkShaderModule * shaderModule,VkPipelineShaderStageCreateInfo * stageInfo,SkSL::String spirv,SkSL::Program::Inputs inputs)96 bool GrVkPipelineStateBuilder::installVkShaderModule(VkShaderStageFlagBits stage,
97                                                      const GrGLSLShaderBuilder& builder,
98                                                      VkShaderModule* shaderModule,
99                                                      VkPipelineShaderStageCreateInfo* stageInfo,
100                                                      SkSL::String spirv,
101                                                      SkSL::Program::Inputs inputs) {
102     if (!GrInstallVkShaderModule(fGpu, spirv, stage, shaderModule, stageInfo)) {
103         return false;
104     }
105     if (inputs.fRTHeight) {
106         this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
107     }
108     return true;
109 }
110 
loadShadersFromCache(const SkData & cached,VkShaderModule * outVertShaderModule,VkShaderModule * outFragShaderModule,VkShaderModule * outGeomShaderModule,VkPipelineShaderStageCreateInfo * outStageInfo)111 int GrVkPipelineStateBuilder::loadShadersFromCache(const SkData& cached,
112                                                    VkShaderModule* outVertShaderModule,
113                                                    VkShaderModule* outFragShaderModule,
114                                                    VkShaderModule* outGeomShaderModule,
115                                                    VkPipelineShaderStageCreateInfo* outStageInfo) {
116     // format for shader cache entries is:
117     //     shader_size vertSize;
118     //     char[vertSize] vert;
119     //     SkSL::Program::Inputs vertInputs;
120     //     shader_size fragSize;
121     //     char[fragSize] frag;
122     //     SkSL::Program::Inputs fragInputs;
123     //     shader_size geomSize;
124     //     char[geomSize] geom;
125     //     SkSL::Program::Inputs geomInputs;
126     size_t offset = 0;
127 
128     // vertex shader
129     shader_size vertSize = *((shader_size*) ((char*) cached.data() + offset));
130     offset += sizeof(shader_size);
131     SkSL::String vert((char*) cached.data() + offset, vertSize);
132     offset += vertSize;
133     SkSL::Program::Inputs vertInputs;
134     memcpy(&vertInputs, (char*) cached.data() + offset, sizeof(vertInputs));
135     offset += sizeof(vertInputs);
136 
137     // fragment shader
138     shader_size fragSize = *((shader_size*) ((char*) cached.data() + offset));
139     offset += sizeof(shader_size);
140     SkSL::String frag((char*) cached.data() + offset, fragSize);
141     offset += fragSize;
142     SkSL::Program::Inputs fragInputs;
143     memcpy(&fragInputs, (char*) cached.data() + offset, sizeof(fragInputs));
144     offset += sizeof(fragInputs);
145 
146     // geometry shader
147     shader_size geomSize = *((shader_size*) ((char*) cached.data() + offset));
148     offset += sizeof(shader_size);
149     SkSL::String geom((char*) cached.data() + offset, geomSize);
150     offset += geomSize;
151     SkSL::Program::Inputs geomInputs;
152     memcpy(&geomInputs, (char*) cached.data() + offset, sizeof(geomInputs));
153     offset += sizeof(geomInputs);
154 
155     SkASSERT(offset == cached.size());
156 
157     SkAssertResult(this->installVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT,
158                                                fVS,
159                                                outVertShaderModule,
160                                                &outStageInfo[0],
161                                                vert,
162                                                vertInputs));
163 
164     SkAssertResult(this->installVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT,
165                                                fFS,
166                                                outFragShaderModule,
167                                                &outStageInfo[1],
168                                                frag,
169                                                fragInputs));
170 
171     if (geomSize) {
172         SkAssertResult(this->installVkShaderModule(VK_SHADER_STAGE_GEOMETRY_BIT,
173                                                    fGS,
174                                                    outGeomShaderModule,
175                                                    &outStageInfo[2],
176                                                    geom,
177                                                    geomInputs));
178         return 3;
179     } else {
180         return 2;
181     }
182 }
183 
storeShadersInCache(const SkSL::String & vert,const SkSL::Program::Inputs & vertInputs,const SkSL::String & frag,const SkSL::Program::Inputs & fragInputs,const SkSL::String & geom,const SkSL::Program::Inputs & geomInputs)184 void GrVkPipelineStateBuilder::storeShadersInCache(const SkSL::String& vert,
185                                                    const SkSL::Program::Inputs& vertInputs,
186                                                    const SkSL::String& frag,
187                                                    const SkSL::Program::Inputs& fragInputs,
188                                                    const SkSL::String& geom,
189                                                    const SkSL::Program::Inputs& geomInputs) {
190     Desc* desc = static_cast<Desc*>(this->desc());
191 
192     // see loadShadersFromCache for the layout of cache entries
193     sk_sp<SkData> key = SkData::MakeWithoutCopy(desc->asKey(), desc->shaderKeyLength());
194     size_t dataLength = (sizeof(shader_size) + sizeof(SkSL::Program::Inputs)) * 3 + vert.length() +
195                         frag.length() + geom.length();
196     std::unique_ptr<uint8_t[]> data(new uint8_t[dataLength]);
197     size_t offset = 0;
198 
199     // vertex shader
200     *((shader_size*) (data.get() + offset)) = (shader_size) vert.length();
201     offset += sizeof(shader_size);
202     memcpy(data.get() + offset, vert.data(), vert.length());
203     offset += vert.length();
204     memcpy(data.get() + offset, &vertInputs, sizeof(vertInputs));
205     offset += sizeof(vertInputs);
206 
207     // fragment shader
208     *((shader_size*) (data.get() + offset)) = (shader_size) frag.length();
209     offset += sizeof(shader_size);
210     memcpy(data.get() + offset, frag.data(), frag.length());
211     offset += frag.length();
212     memcpy(data.get() + offset, &fragInputs, sizeof(fragInputs));
213     offset += sizeof(fragInputs);
214 
215     // geometry shader
216     *((shader_size*) (data.get() + offset)) = (shader_size) geom.length();
217     offset += sizeof(shader_size);
218     memcpy(data.get() + offset, geom.data(), geom.length());
219     offset += geom.length();
220     memcpy(data.get() + offset, &geomInputs, sizeof(geomInputs));
221     offset += sizeof(geomInputs);
222 
223     SkASSERT(offset == dataLength);
224 
225     this->gpu()->getContext()->contextPriv().getPersistentCache()->store(
226                                                   *key,
227                                                   *SkData::MakeWithoutCopy(data.get(), dataLength));
228 }
229 
finalize(const GrStencilSettings & stencil,GrPrimitiveType primitiveType,VkRenderPass compatibleRenderPass,Desc * desc)230 GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& stencil,
231                                                       GrPrimitiveType primitiveType,
232                                                       VkRenderPass compatibleRenderPass,
233                                                       Desc* desc) {
234     VkDescriptorSetLayout dsLayout[2];
235     VkPipelineLayout pipelineLayout;
236     VkShaderModule vertShaderModule = VK_NULL_HANDLE;
237     VkShaderModule geomShaderModule = VK_NULL_HANDLE;
238     VkShaderModule fragShaderModule = VK_NULL_HANDLE;
239 
240     GrVkResourceProvider& resourceProvider = fGpu->resourceProvider();
241     // These layouts are not owned by the PipelineStateBuilder and thus should not be destroyed
242     dsLayout[GrVkUniformHandler::kUniformBufferDescSet] = resourceProvider.getUniformDSLayout();
243 
244     GrVkDescriptorSetManager::Handle samplerDSHandle;
245     resourceProvider.getSamplerDescriptorSetHandle(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
246                                                    fUniformHandler, &samplerDSHandle);
247     dsLayout[GrVkUniformHandler::kSamplerDescSet] =
248             resourceProvider.getSamplerDSLayout(samplerDSHandle);
249 
250     // Create the VkPipelineLayout
251     VkPipelineLayoutCreateInfo layoutCreateInfo;
252     memset(&layoutCreateInfo, 0, sizeof(VkPipelineLayoutCreateFlags));
253     layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
254     layoutCreateInfo.pNext = 0;
255     layoutCreateInfo.flags = 0;
256     layoutCreateInfo.setLayoutCount = 2;
257     layoutCreateInfo.pSetLayouts = dsLayout;
258     layoutCreateInfo.pushConstantRangeCount = 0;
259     layoutCreateInfo.pPushConstantRanges = nullptr;
260 
261     GR_VK_CALL_ERRCHECK(fGpu->vkInterface(), CreatePipelineLayout(fGpu->device(),
262                                                                   &layoutCreateInfo,
263                                                                   nullptr,
264                                                                   &pipelineLayout));
265 
266     // We need to enable the following extensions so that the compiler can correctly make spir-v
267     // from our glsl shaders.
268     fVS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
269     fFS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
270     fVS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
271     fFS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
272 
273     this->finalizeShaders();
274 
275     VkPipelineShaderStageCreateInfo shaderStageInfo[3];
276     SkSL::Program::Settings settings;
277     settings.fCaps = this->caps()->shaderCaps();
278     settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin;
279     settings.fSharpenTextures = this->gpu()->getContext()->contextPriv().sharpenMipmappedTextures();
280     SkASSERT(!this->fragColorIsInOut());
281 
282     sk_sp<SkData> cached;
283     auto persistentCache = fGpu->getContext()->contextPriv().getPersistentCache();
284     if (persistentCache) {
285         sk_sp<SkData> key = SkData::MakeWithoutCopy(desc->asKey(), desc->shaderKeyLength());
286         cached = persistentCache->load(*key);
287     }
288     int numShaderStages;
289     if (cached) {
290         numShaderStages = this->loadShadersFromCache(*cached, &vertShaderModule, &fragShaderModule,
291                                                      &geomShaderModule, shaderStageInfo);
292     } else {
293         numShaderStages = 2; // We always have at least vertex and fragment stages.
294         SkSL::String vert;
295         SkSL::Program::Inputs vertInputs;
296         SkSL::String frag;
297         SkSL::Program::Inputs fragInputs;
298         SkSL::String geom;
299         SkSL::Program::Inputs geomInputs;
300         SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT,
301                                                   fVS,
302                                                   &vertShaderModule,
303                                                   &shaderStageInfo[0],
304                                                   settings,
305                                                   desc,
306                                                   &vert,
307                                                   &vertInputs));
308 
309         SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT,
310                                                   fFS,
311                                                   &fragShaderModule,
312                                                   &shaderStageInfo[1],
313                                                   settings,
314                                                   desc,
315                                                   &frag,
316                                                   &fragInputs));
317 
318         if (this->primitiveProcessor().willUseGeoShader()) {
319             SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_GEOMETRY_BIT,
320                                                       fGS,
321                                                       &geomShaderModule,
322                                                       &shaderStageInfo[2],
323                                                       settings,
324                                                       desc,
325                                                       &geom,
326                                                       &geomInputs));
327             ++numShaderStages;
328         }
329         if (persistentCache) {
330             this->storeShadersInCache(vert, vertInputs, frag, fragInputs, geom, geomInputs);
331         }
332     }
333     GrVkPipeline* pipeline = resourceProvider.createPipeline(this->numColorSamples(),
334                                                              fPrimProc,
335                                                              fPipeline,
336                                                              stencil,
337                                                              shaderStageInfo,
338                                                              numShaderStages,
339                                                              primitiveType,
340                                                              compatibleRenderPass,
341                                                              pipelineLayout);
342     GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), vertShaderModule,
343                                                         nullptr));
344     GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), fragShaderModule,
345                                                         nullptr));
346     // This if check should not be needed since calling destroy on a VK_NULL_HANDLE is allowed.
347     // However this is causing a crash in certain drivers (e.g. NVidia).
348     if (this->primitiveProcessor().willUseGeoShader()) {
349         GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), geomShaderModule,
350                                                             nullptr));
351     }
352 
353     if (!pipeline) {
354         GR_VK_CALL(fGpu->vkInterface(), DestroyPipelineLayout(fGpu->device(), pipelineLayout,
355                                                               nullptr));
356         return nullptr;
357     }
358 
359     return new GrVkPipelineState(fGpu,
360                                  pipeline,
361                                  pipelineLayout,
362                                  samplerDSHandle,
363                                  fUniformHandles,
364                                  fUniformHandler.fUniforms,
365                                  fUniformHandler.fCurrentGeometryUBOOffset,
366                                  fUniformHandler.fCurrentFragmentUBOOffset,
367                                  fUniformHandler.fSamplers,
368                                  std::move(fGeometryProcessor),
369                                  std::move(fXferProcessor),
370                                  std::move(fFragmentProcessors),
371                                  fFragmentProcessorCnt);
372 }
373 
374 //////////////////////////////////////////////////////////////////////////////
375 
get_blend_info_key(const GrPipeline & pipeline)376 uint32_t get_blend_info_key(const GrPipeline& pipeline) {
377     GrXferProcessor::BlendInfo blendInfo;
378     pipeline.getXferProcessor().getBlendInfo(&blendInfo);
379 
380     static const uint32_t kBlendWriteShift = 1;
381     static const uint32_t kBlendCoeffShift = 5;
382     GR_STATIC_ASSERT(kLast_GrBlendCoeff < (1 << kBlendCoeffShift));
383     GR_STATIC_ASSERT(kFirstAdvancedGrBlendEquation - 1 < 4);
384 
385     uint32_t key = blendInfo.fWriteColor;
386     key |= (blendInfo.fSrcBlend << kBlendWriteShift);
387     key |= (blendInfo.fDstBlend << (kBlendWriteShift + kBlendCoeffShift));
388     key |= (blendInfo.fEquation << (kBlendWriteShift + 2 * kBlendCoeffShift));
389 
390     return key;
391 }
392 
Build(Desc * desc,GrRenderTarget * renderTarget,const GrPrimitiveProcessor & primProc,const GrPipeline & pipeline,const GrStencilSettings & stencil,GrPrimitiveType primitiveType,GrVkGpu * gpu)393 bool GrVkPipelineStateBuilder::Desc::Build(Desc* desc,
394                                            GrRenderTarget* renderTarget,
395                                            const GrPrimitiveProcessor& primProc,
396                                            const GrPipeline& pipeline,
397                                            const GrStencilSettings& stencil,
398                                            GrPrimitiveType primitiveType,
399                                            GrVkGpu* gpu) {
400     if (!INHERITED::Build(desc, renderTarget->config(), primProc,
401                           primitiveType == GrPrimitiveType::kPoints, pipeline, gpu)) {
402         return false;
403     }
404 
405     GrProcessorKeyBuilder b(&desc->key());
406 
407     b.add32(GrVkGpu::kShader_PersistentCacheKeyType);
408     int keyLength = desc->key().count();
409     SkASSERT(0 == (keyLength % 4));
410     desc->fShaderKeyLength = SkToU32(keyLength);
411 
412     GrVkRenderTarget* vkRT = (GrVkRenderTarget*)renderTarget;
413     vkRT->simpleRenderPass()->genKey(&b);
414 
415     stencil.genKey(&b);
416 
417     b.add32(get_blend_info_key(pipeline));
418 
419     b.add32((uint32_t)primitiveType);
420 
421     return true;
422 }
423