blob: 446c051f189f427d5d078910ec080fb6adf05e27 [file] [log] [blame]
//
// 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"
#include "libANGLE/renderer/glslang_wrapper_utils.h"
#include "libANGLE/renderer/vulkan/GlslangWrapperVk.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)
{
mExecutable.reset(contextVk);
}
angle::Result ProgramPipelineVk::link(const gl::Context *glContext,
const gl::ProgramMergedVaryings &mergedVaryings,
const gl::ProgramVaryingPacking &varyingPacking)
{
ContextVk *contextVk = vk::GetImpl(glContext);
const gl::ProgramExecutable &glExecutable = mState.getExecutable();
GlslangSourceOptions options =
GlslangWrapperVk::CreateSourceOptions(contextVk->getRenderer()->getFeatures());
GlslangProgramInterfaceInfo glslangProgramInterfaceInfo;
GlslangWrapperVk::ResetGlslangProgramInterfaceInfo(&glslangProgramInterfaceInfo);
mExecutable.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::Program *glProgram = mState.getShaderProgram(shaderType);
if (glProgram && gl::ShaderTypeSupportsTransformFeedback(shaderType))
{
const bool isTransformFeedbackStage =
shaderType == linkedTransformFeedbackStage &&
!glProgram->getState().getLinkedTransformFeedbackVaryings().empty();
GlslangAssignTransformFeedbackLocations(
shaderType, glProgram->getState(), isTransformFeedbackStage,
&glslangProgramInterfaceInfo, &mExecutable.mVariableInfoMap);
}
}
}
mExecutable.mOriginalShaderInfo.clear();
gl::ShaderType frontShaderType = gl::ShaderType::InvalidEnum;
UniformBindingIndexMap uniformBindingIndexMap;
for (const gl::ShaderType shaderType : glExecutable.getLinkedShaderStages())
{
const gl::Program *glProgram = mState.getShaderProgram(shaderType);
if (glProgram)
{
const bool isTransformFeedbackStage =
shaderType == linkedTransformFeedbackStage &&
!glProgram->getState().getLinkedTransformFeedbackVaryings().empty();
GlslangAssignLocations(options, glProgram->getState(), varyingPacking, shaderType,
frontShaderType, isTransformFeedbackStage,
&glslangProgramInterfaceInfo, &uniformBindingIndexMap,
&mExecutable.mVariableInfoMap);
frontShaderType = shaderType;
ProgramVk *programVk = vk::GetImpl(glProgram);
ProgramExecutableVk &programExecutableVk = programVk->getExecutable();
mExecutable.mDefaultUniformBlocks[shaderType] =
programExecutableVk.getSharedDefaultUniformBlock(shaderType);
mExecutable.mOriginalShaderInfo.initShaderFromProgram(
shaderType, programExecutableVk.mOriginalShaderInfo);
}
}
mExecutable.setAllDefaultUniformsDirty(glExecutable);
if (contextVk->getFeatures().enablePrecisionQualifiers.enabled)
{
mExecutable.resolvePrecisionMismatch(mergedVaryings);
}
return mExecutable.createPipelineLayout(contextVk, mState.getExecutable(), nullptr);
}
void ProgramPipelineVk::onProgramUniformUpdate(gl::ShaderType shaderType)
{
mExecutable.mDefaultUniformBlocksDirty.set(shaderType);
}
} // namespace rx