// // Copyright 2017 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // ProgramPipelineVk.cpp: // Implements the class methods for ProgramPipelineVk. // #include "libANGLE/renderer/vulkan/ProgramPipelineVk.h" namespace rx { ProgramPipelineVk::ProgramPipelineVk(const gl::ProgramPipelineState &state) : ProgramPipelineImpl(state) {} ProgramPipelineVk::~ProgramPipelineVk() {} void ProgramPipelineVk::destroy(const gl::Context *context) { ContextVk *contextVk = vk::GetImpl(context); reset(contextVk); } void ProgramPipelineVk::reset(ContextVk *contextVk) { getExecutable()->reset(contextVk); } angle::Result ProgramPipelineVk::link(const gl::Context *glContext, const gl::ProgramMergedVaryings &mergedVaryings, const gl::ProgramVaryingPacking &varyingPacking) { ContextVk *contextVk = vk::GetImpl(glContext); vk::Renderer *renderer = contextVk->getRenderer(); const gl::ProgramExecutable &glExecutable = mState.getExecutable(); ProgramExecutableVk *executableVk = vk::GetImpl(&glExecutable); SpvSourceOptions options = SpvCreateSourceOptions(contextVk->getFeatures(), renderer->getMaxColorInputAttachmentCount()); SpvProgramInterfaceInfo spvProgramInterfaceInfo = {}; reset(contextVk); executableVk->clearVariableInfoMap(); // Now that the program pipeline has all of the programs attached, the various descriptor // set/binding locations need to be re-assigned to their correct values. const gl::ShaderType linkedTransformFeedbackStage = glExecutable.getLinkedTransformFeedbackStage(); // This should be done before assigning varying locations. Otherwise, we can encounter shader // interface mismatching problems when the transform feedback stage is not the vertex stage. if (options.supportsTransformFeedbackExtension) { for (const gl::ShaderType shaderType : glExecutable.getLinkedShaderStages()) { const gl::SharedProgramExecutable &glShaderExecutable = mState.getShaderProgramExecutable(shaderType); if (glShaderExecutable && gl::ShaderTypeSupportsTransformFeedback(shaderType)) { const bool isTransformFeedbackStage = shaderType == linkedTransformFeedbackStage && !glShaderExecutable->getLinkedTransformFeedbackVaryings().empty(); SpvAssignTransformFeedbackLocations( shaderType, *glShaderExecutable.get(), isTransformFeedbackStage, &spvProgramInterfaceInfo, &executableVk->mVariableInfoMap); } } } executableVk->mOriginalShaderInfo.clear(); SpvAssignLocations(options, glExecutable, varyingPacking, linkedTransformFeedbackStage, &spvProgramInterfaceInfo, &executableVk->mVariableInfoMap); for (const gl::ShaderType shaderType : glExecutable.getLinkedShaderStages()) { const gl::SharedProgramExecutable &glShaderExecutable = mState.getShaderProgramExecutable(shaderType); ProgramExecutableVk *programExecutableVk = vk::GetImpl(glShaderExecutable.get()); executableVk->mDefaultUniformBlocks[shaderType] = programExecutableVk->getSharedDefaultUniformBlock(shaderType); executableVk->mOriginalShaderInfo.initShaderFromProgram( shaderType, programExecutableVk->mOriginalShaderInfo); } executableVk->setAllDefaultUniformsDirty(); if (contextVk->getFeatures().varyingsRequireMatchingPrecisionInSpirv.enabled && contextVk->getFeatures().enablePrecisionQualifiers.enabled) { executableVk->resolvePrecisionMismatch(mergedVaryings); } executableVk->resetLayout(contextVk); ANGLE_TRY(executableVk->createPipelineLayout(contextVk, &contextVk->getPipelineLayoutCache(), &contextVk->getDescriptorSetLayoutCache(), nullptr)); ANGLE_TRY(executableVk->initializeDescriptorPools(contextVk, &contextVk->getDescriptorSetLayoutCache(), &contextVk->getMetaDescriptorPools())); angle::Result result = angle::Result::Continue; if (contextVk->getFeatures().warmUpPipelineCacheAtLink.enabled) { ANGLE_TRY(executableVk->warmUpPipelineCache(renderer, contextVk->pipelineRobustness(), contextVk->pipelineProtectedAccess())); } return result; } // namespace rx } // namespace rx