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