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