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