Hash :
dee4d7a5
Author :
Date :
2020-04-10T10:22:56
Vulkan: Early fragment tests optimization Checks if early fragment tests as an optimization is feasible and enable it if we can. In the link time, if context state diagrees with optimization (in rare case), then remove the ExecutionModeEarlyFragmentTests sprv op code. Bug: angleproject:4508 Change-Id: Ifbb06c0ffb050a9f3ddb16ab50362e908b4b9cf6 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2136490 Commit-Queue: Charlie Lao <cclao@google.com> Reviewed-by: Tim Van Patten <timvp@google.com> Reviewed-by: Courtney Goeltzenleuchter <courtneygo@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
//
// 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(), glProgram->getResources(),
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;
}
if (anyNewBufferAllocated)
{
// 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