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