Hash :
d10ba166
Author :
Date :
2020-05-19T18:00:38
Rename ProgramState::getProgramExecutable() to getExecutable() The "Program" part of ProgramState::getProgramExecutable() is already implied by being part of a ProgramState, so it can be removed. Bug: angleproject:3570 Change-Id: I35ffb2af81196fa7f189f7d3a37158f5f1951141 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2209317 Reviewed-by: Jamie Madill <jmadill@chromium.org> Commit-Queue: Tim Van Patten <timvp@google.com>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
//
// 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)
{
mExecutable.setProgramPipeline(this);
}
ProgramPipelineVk::~ProgramPipelineVk() {}
void ProgramPipelineVk::destroy(const gl::Context *context)
{
ContextVk *contextVk = vk::GetImpl(context);
reset(contextVk);
}
void ProgramPipelineVk::reset(ContextVk *contextVk)
{
mExecutable.reset(contextVk);
}
// TODO: http://anglebug.com/3570: Move/Copy all of the necessary information into
// the ProgramExecutable, so this function can be removed.
void ProgramPipelineVk::fillProgramStateMap(
const ContextVk *contextVk,
gl::ShaderMap<const gl::ProgramState *> *programStatesOut)
{
for (gl::ShaderType shaderType : gl::AllShaderTypes())
{
(*programStatesOut)[shaderType] = nullptr;
ProgramVk *programVk = getShaderProgram(contextVk->getState(), shaderType);
if (programVk)
{
(*programStatesOut)[shaderType] = &programVk->getState();
}
}
}
angle::Result ProgramPipelineVk::link(const gl::Context *glContext)
{
ContextVk *contextVk = vk::GetImpl(glContext);
const gl::State &glState = glContext->getState();
const gl::ProgramPipeline *glPipeline = glState.getProgramPipeline();
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.
for (const gl::ShaderType shaderType : glPipeline->getExecutable().getLinkedShaderStages())
{
gl::Program *glProgram =
const_cast<gl::Program *>(glPipeline->getShaderProgram(shaderType));
if (glProgram)
{
// The program interface info must survive across shaders, except
// for some program-specific values.
ProgramVk *programVk = vk::GetImpl(glProgram);
GlslangProgramInterfaceInfo &programProgramInterfaceInfo =
programVk->getGlslangProgramInterfaceInfo();
glslangProgramInterfaceInfo.locationsUsedForXfbExtension =
programProgramInterfaceInfo.locationsUsedForXfbExtension;
GlslangAssignLocations(options, glProgram->getState().getExecutable(), shaderType,
&glslangProgramInterfaceInfo,
&mExecutable.getShaderInterfaceVariableInfoMap());
}
}
ANGLE_TRY(transformShaderSpirV(glContext));
return mExecutable.createPipelineLayout(glContext);
}
angle::Result ProgramPipelineVk::transformShaderSpirV(const gl::Context *glContext)
{
ContextVk *contextVk = vk::GetImpl(glContext);
const gl::ProgramExecutable *executable = contextVk->getState().getProgramExecutable();
ASSERT(executable);
for (const gl::ShaderType shaderType : executable->getLinkedShaderStages())
{
ProgramVk *programVk = getShaderProgram(contextVk->getState(), shaderType);
if (programVk)
{
ShaderInterfaceVariableInfoMap &variableInfoMap =
mExecutable.mVariableInfoMap[shaderType];
std::vector<uint32_t> transformedSpirvBlob;
// We skip early fragment tests optimization modification here since we need to keep
// original spriv blob here.
ANGLE_TRY(GlslangWrapperVk::TransformSpirV(
contextVk, shaderType, false, variableInfoMap,
programVk->getShaderInfo().getSpirvBlobs()[shaderType], &transformedSpirvBlob));
// Save the newly transformed SPIR-V
// TODO: http://anglebug.com/4513: Keep the original SPIR-V and
// translated SPIR-V in separate buffers in ShaderInfo to avoid the
// extra copy here.
programVk->getShaderInfo().getSpirvBlobs()[shaderType] = transformedSpirvBlob;
}
}
return angle::Result::Continue;
}
angle::Result ProgramPipelineVk::updateUniforms(ContextVk *contextVk)
{
uint32_t offsetIndex = 0;
bool anyNewBufferAllocated = false;
const gl::ProgramExecutable *glExecutable = contextVk->getState().getProgramExecutable();
for (const gl::ShaderType shaderType : glExecutable->getLinkedShaderStages())
{
ProgramVk *programVk = getShaderProgram(contextVk->getState(), shaderType);
if (programVk && programVk->dirtyUniforms())
{
ANGLE_TRY(programVk->updateShaderUniforms(
contextVk, shaderType, &mExecutable.mDynamicBufferOffsets[offsetIndex],
&anyNewBufferAllocated));
}
++offsetIndex;
}
// The PPO's list of descriptor sets being empty without a new buffer being allocated indicates
// a Program that was already used in a draw command (and thus already allocated uniform
// buffers) has been bound to this PPO.
if (anyNewBufferAllocated || mExecutable.mDescriptorSets.empty())
{
// We need to reinitialize the descriptor sets if we newly allocated buffers since we can't
// modify the descriptor sets once initialized.
ANGLE_TRY(mExecutable.allocateDescriptorSet(contextVk, kUniformsAndXfbDescriptorSetIndex));
mExecutable.mDescriptorBuffersCache.clear();
for (const gl::ShaderType shaderType : glExecutable->getLinkedShaderStages())
{
ProgramVk *programVk = getShaderProgram(contextVk->getState(), shaderType);
if (programVk)
{
mExecutable.updateDefaultUniformsDescriptorSet(
shaderType, programVk->getDefaultUniformBlocks(), contextVk);
mExecutable.updateTransformFeedbackDescriptorSetImpl(programVk->getState(),
contextVk);
}
}
}
return angle::Result::Continue;
}
bool ProgramPipelineVk::dirtyUniforms(const gl::State &glState)
{
for (const gl::ShaderType shaderType : gl::AllShaderTypes())
{
const ProgramVk *program = getShaderProgram(glState, shaderType);
if (program && program->dirtyUniforms())
{
return true;
}
}
return false;
}
} // namespace rx