1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2016 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/vk/GrVkPipelineStateBuilder.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkData.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFourByteTag.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrContextOptions.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrDirectContext.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTo.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/gpu/ganesh/GrTypesPriv.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkReadBuffer.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkTraceEvent.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrAutoLocaleSetter.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDirectContextPriv.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrPersistentCacheUtils.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrProgramDesc.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrProgramInfo.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrShaderVar.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrThreadSafePipelineBuilder.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrXferProcessor.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/glsl/GrGLSLFragmentShaderBuilder.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/glsl/GrGLSLVertexGeoBuilder.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/vk/GrVkCaps.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/vk/GrVkDescriptorSetManager.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/vk/GrVkGpu.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/vk/GrVkPipeline.h"
34*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/vk/GrVkPipelineState.h"
35*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/vk/GrVkResourceProvider.h"
36*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/vk/GrVkUtil.h"
37*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLProgramSettings.h"
38*c8dee2aaSAndroid Build Coastguard Worker #include "src/utils/SkShaderUtils.h"
39*c8dee2aaSAndroid Build Coastguard Worker
40*c8dee2aaSAndroid Build Coastguard Worker #include <string.h>
41*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
42*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
43*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
44*c8dee2aaSAndroid Build Coastguard Worker
45*c8dee2aaSAndroid Build Coastguard Worker class GrCaps;
46*c8dee2aaSAndroid Build Coastguard Worker
CreatePipelineState(GrVkGpu * gpu,const GrProgramDesc & desc,const GrProgramInfo & programInfo,VkRenderPass compatibleRenderPass,bool overrideSubpassForResolveLoad)47*c8dee2aaSAndroid Build Coastguard Worker GrVkPipelineState* GrVkPipelineStateBuilder::CreatePipelineState(
48*c8dee2aaSAndroid Build Coastguard Worker GrVkGpu* gpu,
49*c8dee2aaSAndroid Build Coastguard Worker const GrProgramDesc& desc,
50*c8dee2aaSAndroid Build Coastguard Worker const GrProgramInfo& programInfo,
51*c8dee2aaSAndroid Build Coastguard Worker VkRenderPass compatibleRenderPass,
52*c8dee2aaSAndroid Build Coastguard Worker bool overrideSubpassForResolveLoad) {
53*c8dee2aaSAndroid Build Coastguard Worker
54*c8dee2aaSAndroid Build Coastguard Worker GrVkResourceProvider& resourceProvider = gpu->resourceProvider();
55*c8dee2aaSAndroid Build Coastguard Worker
56*c8dee2aaSAndroid Build Coastguard Worker resourceProvider.pipelineStateCache()->stats()->incShaderCompilations();
57*c8dee2aaSAndroid Build Coastguard Worker
58*c8dee2aaSAndroid Build Coastguard Worker // ensure that we use "." as a decimal separator when creating SkSL code
59*c8dee2aaSAndroid Build Coastguard Worker GrAutoLocaleSetter als("C");
60*c8dee2aaSAndroid Build Coastguard Worker
61*c8dee2aaSAndroid Build Coastguard Worker // create a builder. This will be handed off to effects so they can use it to add
62*c8dee2aaSAndroid Build Coastguard Worker // uniforms, varyings, textures, etc
63*c8dee2aaSAndroid Build Coastguard Worker GrVkPipelineStateBuilder builder(gpu, desc, programInfo);
64*c8dee2aaSAndroid Build Coastguard Worker
65*c8dee2aaSAndroid Build Coastguard Worker if (!builder.emitAndInstallProcs()) {
66*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
67*c8dee2aaSAndroid Build Coastguard Worker }
68*c8dee2aaSAndroid Build Coastguard Worker
69*c8dee2aaSAndroid Build Coastguard Worker return builder.finalize(desc, compatibleRenderPass, overrideSubpassForResolveLoad);
70*c8dee2aaSAndroid Build Coastguard Worker }
71*c8dee2aaSAndroid Build Coastguard Worker
GrVkPipelineStateBuilder(GrVkGpu * gpu,const GrProgramDesc & desc,const GrProgramInfo & programInfo)72*c8dee2aaSAndroid Build Coastguard Worker GrVkPipelineStateBuilder::GrVkPipelineStateBuilder(GrVkGpu* gpu,
73*c8dee2aaSAndroid Build Coastguard Worker const GrProgramDesc& desc,
74*c8dee2aaSAndroid Build Coastguard Worker const GrProgramInfo& programInfo)
75*c8dee2aaSAndroid Build Coastguard Worker : INHERITED(desc, programInfo)
76*c8dee2aaSAndroid Build Coastguard Worker , fGpu(gpu)
77*c8dee2aaSAndroid Build Coastguard Worker , fVaryingHandler(this)
78*c8dee2aaSAndroid Build Coastguard Worker , fUniformHandler(this) {}
79*c8dee2aaSAndroid Build Coastguard Worker
caps() const80*c8dee2aaSAndroid Build Coastguard Worker const GrCaps* GrVkPipelineStateBuilder::caps() const {
81*c8dee2aaSAndroid Build Coastguard Worker return fGpu->caps();
82*c8dee2aaSAndroid Build Coastguard Worker }
83*c8dee2aaSAndroid Build Coastguard Worker
finalizeFragmentSecondaryColor(GrShaderVar & outputColor)84*c8dee2aaSAndroid Build Coastguard Worker void GrVkPipelineStateBuilder::finalizeFragmentSecondaryColor(GrShaderVar& outputColor) {
85*c8dee2aaSAndroid Build Coastguard Worker outputColor.addLayoutQualifier("location = 0, index = 1");
86*c8dee2aaSAndroid Build Coastguard Worker }
87*c8dee2aaSAndroid Build Coastguard Worker
createVkShaderModule(VkShaderStageFlagBits stage,const std::string & sksl,VkShaderModule * shaderModule,VkPipelineShaderStageCreateInfo * stageInfo,const SkSL::ProgramSettings & settings,std::string * outSPIRV,SkSL::Program::Interface * outInterface)88*c8dee2aaSAndroid Build Coastguard Worker bool GrVkPipelineStateBuilder::createVkShaderModule(VkShaderStageFlagBits stage,
89*c8dee2aaSAndroid Build Coastguard Worker const std::string& sksl,
90*c8dee2aaSAndroid Build Coastguard Worker VkShaderModule* shaderModule,
91*c8dee2aaSAndroid Build Coastguard Worker VkPipelineShaderStageCreateInfo* stageInfo,
92*c8dee2aaSAndroid Build Coastguard Worker const SkSL::ProgramSettings& settings,
93*c8dee2aaSAndroid Build Coastguard Worker std::string* outSPIRV,
94*c8dee2aaSAndroid Build Coastguard Worker SkSL::Program::Interface* outInterface) {
95*c8dee2aaSAndroid Build Coastguard Worker if (!GrCompileVkShaderModule(fGpu, sksl, stage, shaderModule,
96*c8dee2aaSAndroid Build Coastguard Worker stageInfo, settings, outSPIRV, outInterface)) {
97*c8dee2aaSAndroid Build Coastguard Worker return false;
98*c8dee2aaSAndroid Build Coastguard Worker }
99*c8dee2aaSAndroid Build Coastguard Worker if (outInterface->fRTFlipUniform != SkSL::Program::Interface::kRTFlip_None) {
100*c8dee2aaSAndroid Build Coastguard Worker this->addRTFlipUniform(SKSL_RTFLIP_NAME);
101*c8dee2aaSAndroid Build Coastguard Worker }
102*c8dee2aaSAndroid Build Coastguard Worker return true;
103*c8dee2aaSAndroid Build Coastguard Worker }
104*c8dee2aaSAndroid Build Coastguard Worker
installVkShaderModule(VkShaderStageFlagBits stage,const GrGLSLShaderBuilder & builder,VkShaderModule * shaderModule,VkPipelineShaderStageCreateInfo * stageInfo,std::string spirv,SkSL::Program::Interface interface)105*c8dee2aaSAndroid Build Coastguard Worker bool GrVkPipelineStateBuilder::installVkShaderModule(VkShaderStageFlagBits stage,
106*c8dee2aaSAndroid Build Coastguard Worker const GrGLSLShaderBuilder& builder,
107*c8dee2aaSAndroid Build Coastguard Worker VkShaderModule* shaderModule,
108*c8dee2aaSAndroid Build Coastguard Worker VkPipelineShaderStageCreateInfo* stageInfo,
109*c8dee2aaSAndroid Build Coastguard Worker std::string spirv,
110*c8dee2aaSAndroid Build Coastguard Worker SkSL::Program::Interface interface) {
111*c8dee2aaSAndroid Build Coastguard Worker if (!GrInstallVkShaderModule(fGpu, spirv, stage, shaderModule, stageInfo)) {
112*c8dee2aaSAndroid Build Coastguard Worker return false;
113*c8dee2aaSAndroid Build Coastguard Worker }
114*c8dee2aaSAndroid Build Coastguard Worker if (interface.fRTFlipUniform != SkSL::Program::Interface::kRTFlip_None) {
115*c8dee2aaSAndroid Build Coastguard Worker this->addRTFlipUniform(SKSL_RTFLIP_NAME);
116*c8dee2aaSAndroid Build Coastguard Worker }
117*c8dee2aaSAndroid Build Coastguard Worker return true;
118*c8dee2aaSAndroid Build Coastguard Worker }
119*c8dee2aaSAndroid Build Coastguard Worker
120*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkFourByteTag kSPIRV_Tag = SkSetFourByteTag('S', 'P', 'R', 'V');
121*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L');
122*c8dee2aaSAndroid Build Coastguard Worker
loadShadersFromCache(SkReadBuffer * cached,VkShaderModule outShaderModules[],VkPipelineShaderStageCreateInfo * outStageInfo)123*c8dee2aaSAndroid Build Coastguard Worker int GrVkPipelineStateBuilder::loadShadersFromCache(SkReadBuffer* cached,
124*c8dee2aaSAndroid Build Coastguard Worker VkShaderModule outShaderModules[],
125*c8dee2aaSAndroid Build Coastguard Worker VkPipelineShaderStageCreateInfo* outStageInfo) {
126*c8dee2aaSAndroid Build Coastguard Worker std::string shaders[kGrShaderTypeCount];
127*c8dee2aaSAndroid Build Coastguard Worker SkSL::Program::Interface interfaces[kGrShaderTypeCount];
128*c8dee2aaSAndroid Build Coastguard Worker
129*c8dee2aaSAndroid Build Coastguard Worker if (!GrPersistentCacheUtils::UnpackCachedShaders(
130*c8dee2aaSAndroid Build Coastguard Worker cached, shaders, interfaces, kGrShaderTypeCount)) {
131*c8dee2aaSAndroid Build Coastguard Worker return 0;
132*c8dee2aaSAndroid Build Coastguard Worker }
133*c8dee2aaSAndroid Build Coastguard Worker
134*c8dee2aaSAndroid Build Coastguard Worker bool success = this->installVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT,
135*c8dee2aaSAndroid Build Coastguard Worker fVS,
136*c8dee2aaSAndroid Build Coastguard Worker &outShaderModules[kVertex_GrShaderType],
137*c8dee2aaSAndroid Build Coastguard Worker &outStageInfo[0],
138*c8dee2aaSAndroid Build Coastguard Worker shaders[kVertex_GrShaderType],
139*c8dee2aaSAndroid Build Coastguard Worker interfaces[kVertex_GrShaderType]);
140*c8dee2aaSAndroid Build Coastguard Worker
141*c8dee2aaSAndroid Build Coastguard Worker success = success && this->installVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT,
142*c8dee2aaSAndroid Build Coastguard Worker fFS,
143*c8dee2aaSAndroid Build Coastguard Worker &outShaderModules[kFragment_GrShaderType],
144*c8dee2aaSAndroid Build Coastguard Worker &outStageInfo[1],
145*c8dee2aaSAndroid Build Coastguard Worker shaders[kFragment_GrShaderType],
146*c8dee2aaSAndroid Build Coastguard Worker interfaces[kFragment_GrShaderType]);
147*c8dee2aaSAndroid Build Coastguard Worker
148*c8dee2aaSAndroid Build Coastguard Worker if (!success) {
149*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < kGrShaderTypeCount; ++i) {
150*c8dee2aaSAndroid Build Coastguard Worker if (outShaderModules[i]) {
151*c8dee2aaSAndroid Build Coastguard Worker GR_VK_CALL(fGpu->vkInterface(),
152*c8dee2aaSAndroid Build Coastguard Worker DestroyShaderModule(fGpu->device(), outShaderModules[i], nullptr));
153*c8dee2aaSAndroid Build Coastguard Worker }
154*c8dee2aaSAndroid Build Coastguard Worker }
155*c8dee2aaSAndroid Build Coastguard Worker return 0;
156*c8dee2aaSAndroid Build Coastguard Worker }
157*c8dee2aaSAndroid Build Coastguard Worker return 2;
158*c8dee2aaSAndroid Build Coastguard Worker }
159*c8dee2aaSAndroid Build Coastguard Worker
storeShadersInCache(const std::string shaders[],const SkSL::Program::Interface interfaces[],bool isSkSL)160*c8dee2aaSAndroid Build Coastguard Worker void GrVkPipelineStateBuilder::storeShadersInCache(const std::string shaders[],
161*c8dee2aaSAndroid Build Coastguard Worker const SkSL::Program::Interface interfaces[],
162*c8dee2aaSAndroid Build Coastguard Worker bool isSkSL) {
163*c8dee2aaSAndroid Build Coastguard Worker // Here we shear off the Vk-specific portion of the Desc in order to create the
164*c8dee2aaSAndroid Build Coastguard Worker // persistent key. This is bc Vk only caches the SPIRV code, not the fully compiled
165*c8dee2aaSAndroid Build Coastguard Worker // program, and that only depends on the base GrProgramDesc data.
166*c8dee2aaSAndroid Build Coastguard Worker // The +4 is to include the kShader_PersistentCacheKeyType code the Vulkan backend adds
167*c8dee2aaSAndroid Build Coastguard Worker // to the key right after the base key.
168*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> key = SkData::MakeWithoutCopy(this->desc().asKey(),
169*c8dee2aaSAndroid Build Coastguard Worker this->desc().initialKeyLength()+4);
170*c8dee2aaSAndroid Build Coastguard Worker SkString description = GrProgramDesc::Describe(fProgramInfo, *this->caps());
171*c8dee2aaSAndroid Build Coastguard Worker
172*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> data = GrPersistentCacheUtils::PackCachedShaders(isSkSL ? kSKSL_Tag : kSPIRV_Tag,
173*c8dee2aaSAndroid Build Coastguard Worker shaders,
174*c8dee2aaSAndroid Build Coastguard Worker interfaces, kGrShaderTypeCount);
175*c8dee2aaSAndroid Build Coastguard Worker
176*c8dee2aaSAndroid Build Coastguard Worker this->gpu()->getContext()->priv().getPersistentCache()->store(*key, *data, description);
177*c8dee2aaSAndroid Build Coastguard Worker }
178*c8dee2aaSAndroid Build Coastguard Worker
finalize(const GrProgramDesc & desc,VkRenderPass compatibleRenderPass,bool overrideSubpassForResolveLoad)179*c8dee2aaSAndroid Build Coastguard Worker GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrProgramDesc& desc,
180*c8dee2aaSAndroid Build Coastguard Worker VkRenderPass compatibleRenderPass,
181*c8dee2aaSAndroid Build Coastguard Worker bool overrideSubpassForResolveLoad) {
182*c8dee2aaSAndroid Build Coastguard Worker TRACE_EVENT0("skia.shaders", TRACE_FUNC);
183*c8dee2aaSAndroid Build Coastguard Worker
184*c8dee2aaSAndroid Build Coastguard Worker VkDescriptorSetLayout dsLayout[GrVkUniformHandler::kDescSetCount];
185*c8dee2aaSAndroid Build Coastguard Worker VkShaderModule shaderModules[kGrShaderTypeCount] = { VK_NULL_HANDLE,
186*c8dee2aaSAndroid Build Coastguard Worker VK_NULL_HANDLE };
187*c8dee2aaSAndroid Build Coastguard Worker
188*c8dee2aaSAndroid Build Coastguard Worker GrVkResourceProvider& resourceProvider = fGpu->resourceProvider();
189*c8dee2aaSAndroid Build Coastguard Worker // These layouts are not owned by the PipelineStateBuilder and thus should not be destroyed
190*c8dee2aaSAndroid Build Coastguard Worker dsLayout[GrVkUniformHandler::kUniformBufferDescSet] = resourceProvider.getUniformDSLayout();
191*c8dee2aaSAndroid Build Coastguard Worker
192*c8dee2aaSAndroid Build Coastguard Worker GrVkDescriptorSetManager::Handle samplerDSHandle;
193*c8dee2aaSAndroid Build Coastguard Worker resourceProvider.getSamplerDescriptorSetHandle(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
194*c8dee2aaSAndroid Build Coastguard Worker fUniformHandler, &samplerDSHandle);
195*c8dee2aaSAndroid Build Coastguard Worker dsLayout[GrVkUniformHandler::kSamplerDescSet] =
196*c8dee2aaSAndroid Build Coastguard Worker resourceProvider.getSamplerDSLayout(samplerDSHandle);
197*c8dee2aaSAndroid Build Coastguard Worker
198*c8dee2aaSAndroid Build Coastguard Worker dsLayout[GrVkUniformHandler::kInputDescSet] = resourceProvider.getInputDSLayout();
199*c8dee2aaSAndroid Build Coastguard Worker
200*c8dee2aaSAndroid Build Coastguard Worker this->finalizeShaders();
201*c8dee2aaSAndroid Build Coastguard Worker
202*c8dee2aaSAndroid Build Coastguard Worker bool usePushConstants = fUniformHandler.usePushConstants();
203*c8dee2aaSAndroid Build Coastguard Worker VkPipelineShaderStageCreateInfo shaderStageInfo[3];
204*c8dee2aaSAndroid Build Coastguard Worker SkSL::ProgramSettings settings;
205*c8dee2aaSAndroid Build Coastguard Worker settings.fRTFlipBinding = this->gpu()->vkCaps().getFragmentUniformBinding();
206*c8dee2aaSAndroid Build Coastguard Worker settings.fRTFlipSet = this->gpu()->vkCaps().getFragmentUniformSet();
207*c8dee2aaSAndroid Build Coastguard Worker settings.fSharpenTextures =
208*c8dee2aaSAndroid Build Coastguard Worker this->gpu()->getContext()->priv().options().fSharpenMipmappedTextures;
209*c8dee2aaSAndroid Build Coastguard Worker settings.fRTFlipOffset = fUniformHandler.getRTFlipOffset();
210*c8dee2aaSAndroid Build Coastguard Worker settings.fUsePushConstants = usePushConstants;
211*c8dee2aaSAndroid Build Coastguard Worker if (fFS.fForceHighPrecision) {
212*c8dee2aaSAndroid Build Coastguard Worker settings.fForceHighPrecision = true;
213*c8dee2aaSAndroid Build Coastguard Worker }
214*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!this->fragColorIsInOut());
215*c8dee2aaSAndroid Build Coastguard Worker
216*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> cached;
217*c8dee2aaSAndroid Build Coastguard Worker SkReadBuffer reader;
218*c8dee2aaSAndroid Build Coastguard Worker SkFourByteTag shaderType = 0;
219*c8dee2aaSAndroid Build Coastguard Worker auto persistentCache = fGpu->getContext()->priv().getPersistentCache();
220*c8dee2aaSAndroid Build Coastguard Worker if (persistentCache) {
221*c8dee2aaSAndroid Build Coastguard Worker // Here we shear off the Vk-specific portion of the Desc in order to create the
222*c8dee2aaSAndroid Build Coastguard Worker // persistent key. This is bc Vk only caches the SPIRV code, not the fully compiled
223*c8dee2aaSAndroid Build Coastguard Worker // program, and that only depends on the base GrProgramDesc data.
224*c8dee2aaSAndroid Build Coastguard Worker // The +4 is to include the kShader_PersistentCacheKeyType code the Vulkan backend adds
225*c8dee2aaSAndroid Build Coastguard Worker // to the key right after the base key.
226*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> key = SkData::MakeWithoutCopy(desc.asKey(), desc.initialKeyLength()+4);
227*c8dee2aaSAndroid Build Coastguard Worker cached = persistentCache->load(*key);
228*c8dee2aaSAndroid Build Coastguard Worker if (cached) {
229*c8dee2aaSAndroid Build Coastguard Worker reader.setMemory(cached->data(), cached->size());
230*c8dee2aaSAndroid Build Coastguard Worker shaderType = GrPersistentCacheUtils::GetType(&reader);
231*c8dee2aaSAndroid Build Coastguard Worker }
232*c8dee2aaSAndroid Build Coastguard Worker }
233*c8dee2aaSAndroid Build Coastguard Worker
234*c8dee2aaSAndroid Build Coastguard Worker int numShaderStages = 0;
235*c8dee2aaSAndroid Build Coastguard Worker if (kSPIRV_Tag == shaderType) {
236*c8dee2aaSAndroid Build Coastguard Worker numShaderStages = this->loadShadersFromCache(&reader, shaderModules, shaderStageInfo);
237*c8dee2aaSAndroid Build Coastguard Worker }
238*c8dee2aaSAndroid Build Coastguard Worker
239*c8dee2aaSAndroid Build Coastguard Worker // Proceed from sources if we didn't get a SPIRV cache (or the cache was invalid)
240*c8dee2aaSAndroid Build Coastguard Worker if (!numShaderStages) {
241*c8dee2aaSAndroid Build Coastguard Worker numShaderStages = 2; // We always have at least vertex and fragment stages.
242*c8dee2aaSAndroid Build Coastguard Worker std::string shaders[kGrShaderTypeCount];
243*c8dee2aaSAndroid Build Coastguard Worker SkSL::Program::Interface interfaces[kGrShaderTypeCount];
244*c8dee2aaSAndroid Build Coastguard Worker
245*c8dee2aaSAndroid Build Coastguard Worker std::string* sksl[kGrShaderTypeCount] = {
246*c8dee2aaSAndroid Build Coastguard Worker &fVS.fCompilerString,
247*c8dee2aaSAndroid Build Coastguard Worker &fFS.fCompilerString,
248*c8dee2aaSAndroid Build Coastguard Worker };
249*c8dee2aaSAndroid Build Coastguard Worker std::string cached_sksl[kGrShaderTypeCount];
250*c8dee2aaSAndroid Build Coastguard Worker if (kSKSL_Tag == shaderType) {
251*c8dee2aaSAndroid Build Coastguard Worker if (GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, interfaces,
252*c8dee2aaSAndroid Build Coastguard Worker kGrShaderTypeCount)) {
253*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < kGrShaderTypeCount; ++i) {
254*c8dee2aaSAndroid Build Coastguard Worker sksl[i] = &cached_sksl[i];
255*c8dee2aaSAndroid Build Coastguard Worker }
256*c8dee2aaSAndroid Build Coastguard Worker }
257*c8dee2aaSAndroid Build Coastguard Worker }
258*c8dee2aaSAndroid Build Coastguard Worker
259*c8dee2aaSAndroid Build Coastguard Worker bool success = this->createVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT,
260*c8dee2aaSAndroid Build Coastguard Worker *sksl[kVertex_GrShaderType],
261*c8dee2aaSAndroid Build Coastguard Worker &shaderModules[kVertex_GrShaderType],
262*c8dee2aaSAndroid Build Coastguard Worker &shaderStageInfo[0],
263*c8dee2aaSAndroid Build Coastguard Worker settings,
264*c8dee2aaSAndroid Build Coastguard Worker &shaders[kVertex_GrShaderType],
265*c8dee2aaSAndroid Build Coastguard Worker &interfaces[kVertex_GrShaderType]);
266*c8dee2aaSAndroid Build Coastguard Worker
267*c8dee2aaSAndroid Build Coastguard Worker success = success && this->createVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT,
268*c8dee2aaSAndroid Build Coastguard Worker *sksl[kFragment_GrShaderType],
269*c8dee2aaSAndroid Build Coastguard Worker &shaderModules[kFragment_GrShaderType],
270*c8dee2aaSAndroid Build Coastguard Worker &shaderStageInfo[1],
271*c8dee2aaSAndroid Build Coastguard Worker settings,
272*c8dee2aaSAndroid Build Coastguard Worker &shaders[kFragment_GrShaderType],
273*c8dee2aaSAndroid Build Coastguard Worker &interfaces[kFragment_GrShaderType]);
274*c8dee2aaSAndroid Build Coastguard Worker
275*c8dee2aaSAndroid Build Coastguard Worker if (!success) {
276*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < kGrShaderTypeCount; ++i) {
277*c8dee2aaSAndroid Build Coastguard Worker if (shaderModules[i]) {
278*c8dee2aaSAndroid Build Coastguard Worker GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(),
279*c8dee2aaSAndroid Build Coastguard Worker shaderModules[i], nullptr));
280*c8dee2aaSAndroid Build Coastguard Worker }
281*c8dee2aaSAndroid Build Coastguard Worker }
282*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
283*c8dee2aaSAndroid Build Coastguard Worker }
284*c8dee2aaSAndroid Build Coastguard Worker
285*c8dee2aaSAndroid Build Coastguard Worker if (persistentCache && !cached) {
286*c8dee2aaSAndroid Build Coastguard Worker bool isSkSL = false;
287*c8dee2aaSAndroid Build Coastguard Worker if (fGpu->getContext()->priv().options().fShaderCacheStrategy ==
288*c8dee2aaSAndroid Build Coastguard Worker GrContextOptions::ShaderCacheStrategy::kSkSL) {
289*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < kGrShaderTypeCount; ++i) {
290*c8dee2aaSAndroid Build Coastguard Worker shaders[i] = SkShaderUtils::PrettyPrint(*sksl[i]);
291*c8dee2aaSAndroid Build Coastguard Worker }
292*c8dee2aaSAndroid Build Coastguard Worker isSkSL = true;
293*c8dee2aaSAndroid Build Coastguard Worker }
294*c8dee2aaSAndroid Build Coastguard Worker this->storeShadersInCache(shaders, interfaces, isSkSL);
295*c8dee2aaSAndroid Build Coastguard Worker }
296*c8dee2aaSAndroid Build Coastguard Worker }
297*c8dee2aaSAndroid Build Coastguard Worker
298*c8dee2aaSAndroid Build Coastguard Worker // The vulkan spec says that if a subpass has an input attachment, then the input attachment
299*c8dee2aaSAndroid Build Coastguard Worker // descriptor set must be bound to all pipelines in that subpass. This includes pipelines that
300*c8dee2aaSAndroid Build Coastguard Worker // don't actually use the input attachment. Thus we look at the renderPassBarriers and not just
301*c8dee2aaSAndroid Build Coastguard Worker // the DstProxyView barrier flags to determine if we use the input attachment.
302*c8dee2aaSAndroid Build Coastguard Worker bool usesInput = SkToBool(fProgramInfo.renderPassBarriers() & GrXferBarrierFlags::kTexture);
303*c8dee2aaSAndroid Build Coastguard Worker uint32_t layoutCount =
304*c8dee2aaSAndroid Build Coastguard Worker usesInput ? GrVkUniformHandler::kDescSetCount : (GrVkUniformHandler::kDescSetCount - 1);
305*c8dee2aaSAndroid Build Coastguard Worker // Create the VkPipelineLayout
306*c8dee2aaSAndroid Build Coastguard Worker VkPipelineLayoutCreateInfo layoutCreateInfo;
307*c8dee2aaSAndroid Build Coastguard Worker memset(&layoutCreateInfo, 0, sizeof(VkPipelineLayoutCreateFlags));
308*c8dee2aaSAndroid Build Coastguard Worker layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
309*c8dee2aaSAndroid Build Coastguard Worker layoutCreateInfo.pNext = nullptr;
310*c8dee2aaSAndroid Build Coastguard Worker layoutCreateInfo.flags = 0;
311*c8dee2aaSAndroid Build Coastguard Worker layoutCreateInfo.setLayoutCount = layoutCount;
312*c8dee2aaSAndroid Build Coastguard Worker layoutCreateInfo.pSetLayouts = dsLayout;
313*c8dee2aaSAndroid Build Coastguard Worker VkPushConstantRange pushConstantRange = {};
314*c8dee2aaSAndroid Build Coastguard Worker if (usePushConstants) {
315*c8dee2aaSAndroid Build Coastguard Worker pushConstantRange.stageFlags = fGpu->vkCaps().getPushConstantStageFlags();
316*c8dee2aaSAndroid Build Coastguard Worker pushConstantRange.offset = 0;
317*c8dee2aaSAndroid Build Coastguard Worker // size must be a multiple of 4
318*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!SkToBool(fUniformHandler.currentOffset() & 0x3));
319*c8dee2aaSAndroid Build Coastguard Worker pushConstantRange.size = fUniformHandler.currentOffset();
320*c8dee2aaSAndroid Build Coastguard Worker layoutCreateInfo.pushConstantRangeCount = 1;
321*c8dee2aaSAndroid Build Coastguard Worker layoutCreateInfo.pPushConstantRanges = &pushConstantRange;
322*c8dee2aaSAndroid Build Coastguard Worker } else {
323*c8dee2aaSAndroid Build Coastguard Worker layoutCreateInfo.pushConstantRangeCount = 0;
324*c8dee2aaSAndroid Build Coastguard Worker layoutCreateInfo.pPushConstantRanges = nullptr;
325*c8dee2aaSAndroid Build Coastguard Worker }
326*c8dee2aaSAndroid Build Coastguard Worker
327*c8dee2aaSAndroid Build Coastguard Worker VkPipelineLayout pipelineLayout;
328*c8dee2aaSAndroid Build Coastguard Worker VkResult result;
329*c8dee2aaSAndroid Build Coastguard Worker GR_VK_CALL_RESULT(fGpu, result, CreatePipelineLayout(fGpu->device(), &layoutCreateInfo, nullptr,
330*c8dee2aaSAndroid Build Coastguard Worker &pipelineLayout));
331*c8dee2aaSAndroid Build Coastguard Worker if (result != VK_SUCCESS) {
332*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
333*c8dee2aaSAndroid Build Coastguard Worker }
334*c8dee2aaSAndroid Build Coastguard Worker
335*c8dee2aaSAndroid Build Coastguard Worker // For the vast majority of cases we only have one subpass so we default piplines to subpass 0.
336*c8dee2aaSAndroid Build Coastguard Worker // However, if we need to load a resolve into msaa attachment for discardable msaa then the
337*c8dee2aaSAndroid Build Coastguard Worker // main subpass will be 1.
338*c8dee2aaSAndroid Build Coastguard Worker uint32_t subpass = 0;
339*c8dee2aaSAndroid Build Coastguard Worker if (overrideSubpassForResolveLoad ||
340*c8dee2aaSAndroid Build Coastguard Worker (fProgramInfo.colorLoadOp() == GrLoadOp::kLoad &&
341*c8dee2aaSAndroid Build Coastguard Worker fGpu->vkCaps().programInfoWillUseDiscardableMSAA(fProgramInfo))) {
342*c8dee2aaSAndroid Build Coastguard Worker subpass = 1;
343*c8dee2aaSAndroid Build Coastguard Worker }
344*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const GrVkPipeline> pipeline = resourceProvider.makePipeline(
345*c8dee2aaSAndroid Build Coastguard Worker fProgramInfo, shaderStageInfo, numShaderStages, compatibleRenderPass, pipelineLayout,
346*c8dee2aaSAndroid Build Coastguard Worker subpass);
347*c8dee2aaSAndroid Build Coastguard Worker
348*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < kGrShaderTypeCount; ++i) {
349*c8dee2aaSAndroid Build Coastguard Worker // This if check should not be needed since calling destroy on a VK_NULL_HANDLE is allowed.
350*c8dee2aaSAndroid Build Coastguard Worker // However this is causing a crash in certain drivers (e.g. NVidia).
351*c8dee2aaSAndroid Build Coastguard Worker if (shaderModules[i]) {
352*c8dee2aaSAndroid Build Coastguard Worker GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), shaderModules[i],
353*c8dee2aaSAndroid Build Coastguard Worker nullptr));
354*c8dee2aaSAndroid Build Coastguard Worker }
355*c8dee2aaSAndroid Build Coastguard Worker }
356*c8dee2aaSAndroid Build Coastguard Worker
357*c8dee2aaSAndroid Build Coastguard Worker if (!pipeline) {
358*c8dee2aaSAndroid Build Coastguard Worker GR_VK_CALL(fGpu->vkInterface(), DestroyPipelineLayout(fGpu->device(), pipelineLayout,
359*c8dee2aaSAndroid Build Coastguard Worker nullptr));
360*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
361*c8dee2aaSAndroid Build Coastguard Worker }
362*c8dee2aaSAndroid Build Coastguard Worker
363*c8dee2aaSAndroid Build Coastguard Worker return new GrVkPipelineState(fGpu,
364*c8dee2aaSAndroid Build Coastguard Worker std::move(pipeline),
365*c8dee2aaSAndroid Build Coastguard Worker samplerDSHandle,
366*c8dee2aaSAndroid Build Coastguard Worker fUniformHandles,
367*c8dee2aaSAndroid Build Coastguard Worker fUniformHandler.fUniforms,
368*c8dee2aaSAndroid Build Coastguard Worker fUniformHandler.currentOffset(),
369*c8dee2aaSAndroid Build Coastguard Worker fUniformHandler.usePushConstants(),
370*c8dee2aaSAndroid Build Coastguard Worker fUniformHandler.fSamplers,
371*c8dee2aaSAndroid Build Coastguard Worker std::move(fGPImpl),
372*c8dee2aaSAndroid Build Coastguard Worker std::move(fXPImpl),
373*c8dee2aaSAndroid Build Coastguard Worker std::move(fFPImpls));
374*c8dee2aaSAndroid Build Coastguard Worker }
375