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