Commit 7993f34d by Tim Van Patten Committed by Commit Bot

Vulkan: Store transformed SPIR-V in ProgramExecutableVk

The original SPIR-V is specific to a ProgramVk while the transformed SPIR-V is specific to a ProgramExecutableVk. This CL keeps the original SPIR-V in the ProgramVk::mOriginalShaderInfo and the transformed SPIR-V in ProgramExecutableVk::mTransformedShaderInfo. This allows us to skip an extra copy that was occurring during PPO link(). Bug: angleproject:4513 Test: CQ Change-Id: I796dcd6bcfb2df08d9b8f1a5295b2821a4096f16 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2265484 Commit-Queue: Tim Van Patten <timvp@google.com> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent e2de2c1c
......@@ -113,22 +113,35 @@ ProgramInfo::~ProgramInfo() = default;
angle::Result ProgramInfo::initProgram(ContextVk *contextVk,
const gl::ShaderType shaderType,
const ShaderInfo &shaderInfo,
const ShaderMapInterfaceVariableInfoMap &variableInfoMap,
ProgramTransformOptionBits optionBits)
ProgramTransformOptionBits optionBits,
ProgramExecutableVk *executableVk)
{
const gl::ShaderMap<SpirvBlob> &spirvBlobs = shaderInfo.getSpirvBlobs();
const ShaderMapInterfaceVariableInfoMap &variableInfoMap =
executableVk->getShaderInterfaceVariableInfoMap();
const gl::ShaderMap<SpirvBlob> &originalSpirvBlobs = shaderInfo.getSpirvBlobs();
const SpirvBlob &originalSpirvBlob = originalSpirvBlobs[shaderType];
const gl::ShaderMap<SpirvBlob> &transformedSpirvBlobs =
executableVk->getTransformedShaderInfo().getSpirvBlobs();
const SpirvBlob &transformedSpirvBlob = transformedSpirvBlobs[shaderType];
const SpirvBlob &spirvBlob = spirvBlobs[shaderType];
if (!spirvBlob.empty())
if (!transformedSpirvBlob.empty())
{
ANGLE_TRY(vk::InitShaderAndSerial(contextVk, &mShaders[shaderType].get(),
transformedSpirvBlob.data(),
transformedSpirvBlob.size() * sizeof(uint32_t)));
}
else
{
if (shaderType == gl::ShaderType::Fragment &&
optionBits[ProgramTransformOption::RemoveEarlyFragmentTestsOptimization])
{
SpirvBlob spirvBlobTransformed;
SpirvBlob &spirvBlobTransformed =
executableVk->getTransformedShaderInfo().getSpirvBlobs()[shaderType];
ANGLE_TRY(GlslangWrapperVk::TransformSpirV(contextVk, shaderType, true,
variableInfoMap[shaderType], spirvBlob,
&spirvBlobTransformed));
variableInfoMap[shaderType],
originalSpirvBlob, &spirvBlobTransformed));
ANGLE_TRY(vk::InitShaderAndSerial(contextVk, &mShaders[shaderType].get(),
spirvBlobTransformed.data(),
spirvBlobTransformed.size() * sizeof(uint32_t)));
......@@ -136,13 +149,13 @@ angle::Result ProgramInfo::initProgram(ContextVk *contextVk,
else
{
ANGLE_TRY(vk::InitShaderAndSerial(contextVk, &mShaders[shaderType].get(),
spirvBlob.data(),
spirvBlob.size() * sizeof(uint32_t)));
originalSpirvBlob.data(),
originalSpirvBlob.size() * sizeof(uint32_t)));
}
mProgramHelper.setShader(shaderType, &mShaders[shaderType]);
}
mProgramHelper.setShader(shaderType, &mShaders[shaderType]);
if (optionBits[ProgramTransformOption::EnableLineRasterEmulation])
{
mProgramHelper.enableSpecializationConstant(
......@@ -166,6 +179,7 @@ ProgramExecutableVk::ProgramExecutableVk()
: mEmptyDescriptorSets{},
mNumDefaultUniformDescriptors(0),
mDynamicBufferOffsets{},
mTransformedShaderInfoSaved(false),
mProgram(nullptr),
mProgramPipeline(nullptr)
{}
......@@ -234,6 +248,12 @@ std::unique_ptr<rx::LinkEvent> ProgramExecutableVk::load(gl::BinaryInputStream *
}
}
mTransformedShaderInfoSaved = stream->readInt<bool>();
if (mTransformedShaderInfoSaved)
{
mTransformedShaderInfo.load(stream);
}
return std::make_unique<LinkEventDone>(angle::Result::Continue);
}
......@@ -256,6 +276,13 @@ void ProgramExecutableVk::save(gl::BinaryOutputStream *stream)
stream->writeInt<uint32_t>(it.second.xfbStride);
}
}
mTransformedShaderInfoSaved = mTransformedShaderInfo.valid();
stream->writeInt(mTransformedShaderInfoSaved);
if (mTransformedShaderInfoSaved)
{
mTransformedShaderInfo.save(stream);
}
}
void ProgramExecutableVk::clearVariableInfoMap()
......@@ -587,8 +614,8 @@ angle::Result ProgramExecutableVk::getGraphicsPipeline(
ProgramVk *programVk = getShaderProgram(glState, shaderType);
if (programVk)
{
ANGLE_TRY(programVk->initGraphicsShaderProgram(contextVk, shaderType,
mTransformOptionBits, programInfo));
ANGLE_TRY(programVk->initGraphicsShaderProgram(
contextVk, shaderType, mTransformOptionBits, &programInfo, this));
}
}
......@@ -611,7 +638,7 @@ angle::Result ProgramExecutableVk::getComputePipeline(ContextVk *contextVk,
ProgramVk *programVk = getShaderProgram(glState, gl::ShaderType::Compute);
ASSERT(programVk);
ProgramInfo &programInfo = getComputeProgramInfo();
ANGLE_TRY(programVk->initComputeProgram(contextVk, programInfo));
ANGLE_TRY(programVk->initComputeProgram(contextVk, &programInfo, this));
vk::ShaderProgramHelper *shaderProgram = programInfo.getShaderProgram();
ASSERT(shaderProgram);
......
......@@ -65,8 +65,8 @@ class ProgramInfo final : angle::NonCopyable
angle::Result initProgram(ContextVk *contextVk,
const gl::ShaderType shaderType,
const ShaderInfo &shaderInfo,
const ShaderMapInterfaceVariableInfoMap &variableInfoMap,
ProgramTransformOptionBits optionBits);
ProgramTransformOptionBits optionBits,
ProgramExecutableVk *executableVk);
void release(ContextVk *contextVk);
ANGLE_INLINE bool valid(const gl::ShaderType shaderType) const
......@@ -163,6 +163,8 @@ class ProgramExecutableVk
mProgramPipeline = pipeline;
}
ShaderInfo &getTransformedShaderInfo() { return mTransformedShaderInfo; }
private:
friend class ProgramVk;
friend class ProgramPipelineVk;
......@@ -246,6 +248,10 @@ class ProgramExecutableVk
ProgramTransformOptionBits mTransformOptionBits;
// We keep the SPIR-V code to use for draw call pipeline creation.
bool mTransformedShaderInfoSaved;
ShaderInfo mTransformedShaderInfo;
ProgramVk *mProgram;
ProgramPipelineVk *mProgramPipeline;
};
......
......@@ -32,6 +32,8 @@ void ProgramPipelineVk::destroy(const gl::Context *context)
void ProgramPipelineVk::reset(ContextVk *contextVk)
{
mExecutable.reset(contextVk);
// Not done in ProgramExecutableVk::reset() since that's called more often.
mExecutable.getTransformedShaderInfo().release(contextVk);
}
// TODO: http://anglebug.com/3570: Move/Copy all of the necessary information into
......@@ -62,6 +64,7 @@ angle::Result ProgramPipelineVk::link(const gl::Context *glContext)
GlslangProgramInterfaceInfo glslangProgramInterfaceInfo;
GlslangWrapperVk::ResetGlslangProgramInterfaceInfo(&glslangProgramInterfaceInfo);
reset(contextVk);
mExecutable.clearVariableInfoMap();
// Now that the program pipeline has all of the programs attached, the various descriptor
......@@ -104,19 +107,16 @@ angle::Result ProgramPipelineVk::transformShaderSpirV(const gl::Context *glConte
{
ShaderInterfaceVariableInfoMap &variableInfoMap =
mExecutable.mVariableInfoMap[shaderType];
std::vector<uint32_t> transformedSpirvBlob;
SpirvBlob &transformedSpirvBlob =
mExecutable.getTransformedShaderInfo().getSpirvBlobs()[shaderType];
ASSERT(transformedSpirvBlob.empty());
// 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;
programVk->getOriginalShaderInfo().getSpirvBlobs()[shaderType],
&transformedSpirvBlob));
}
}
return angle::Result::Continue;
......
......@@ -179,7 +179,7 @@ void ProgramVk::reset(ContextVk *contextVk)
{
RendererVk *renderer = contextVk->getRenderer();
mShaderInfo.release(contextVk);
mOriginalShaderInfo.release(contextVk);
for (auto &uniformBlock : mDefaultUniformBlocks)
{
......@@ -189,6 +189,8 @@ void ProgramVk::reset(ContextVk *contextVk)
GlslangWrapperVk::ResetGlslangProgramInterfaceInfo(&mGlslangProgramInterfaceInfo);
mExecutable.reset(contextVk);
// Not done in ProgramExecutableVk::reset() since that's called more often.
mExecutable.getTransformedShaderInfo().release(contextVk);
}
std::unique_ptr<rx::LinkEvent> ProgramVk::load(const gl::Context *context,
......@@ -201,7 +203,7 @@ std::unique_ptr<rx::LinkEvent> ProgramVk::load(const gl::Context *context,
reset(contextVk);
mShaderInfo.load(stream);
mOriginalShaderInfo.load(stream);
mExecutable.load(stream);
// Deserializes the uniformLayout data of mDefaultUniformBlocks
......@@ -235,7 +237,7 @@ std::unique_ptr<rx::LinkEvent> ProgramVk::load(const gl::Context *context,
void ProgramVk::save(const gl::Context *context, gl::BinaryOutputStream *stream)
{
mShaderInfo.save(stream);
mOriginalShaderInfo.save(stream);
mExecutable.save(stream);
// Serializes the uniformLayout data of mDefaultUniformBlocks
......@@ -302,8 +304,8 @@ std::unique_ptr<LinkEvent> ProgramVk::link(const gl::Context *context,
// Compile the shaders.
angle::Result status =
mShaderInfo.initShaders(contextVk, mState.getExecutable().getLinkedShaderStages(),
shaderSources, mExecutable.mVariableInfoMap);
mOriginalShaderInfo.initShaders(contextVk, mState.getExecutable().getLinkedShaderStages(),
shaderSources, mExecutable.mVariableInfoMap);
if (status != angle::Result::Continue)
{
return std::make_unique<LinkEventDone>(status);
......
......@@ -127,18 +127,22 @@ class ProgramVk : public ProgramImpl
ANGLE_INLINE angle::Result initGraphicsShaderProgram(ContextVk *contextVk,
const gl::ShaderType shaderType,
ProgramTransformOptionBits optionBits,
ProgramInfo &programInfo)
ProgramInfo *programInfo,
ProgramExecutableVk *executableVk)
{
return initProgram(contextVk, shaderType, optionBits, &programInfo);
return initProgram(contextVk, shaderType, optionBits, programInfo, executableVk);
}
ANGLE_INLINE angle::Result initComputeProgram(ContextVk *contextVk, ProgramInfo &programInfo)
ANGLE_INLINE angle::Result initComputeProgram(ContextVk *contextVk,
ProgramInfo *programInfo,
ProgramExecutableVk *executableVk)
{
ProgramTransformOptionBits optionBits;
return initProgram(contextVk, gl::ShaderType::Compute, optionBits, &programInfo);
return initProgram(contextVk, gl::ShaderType::Compute, optionBits, programInfo,
executableVk);
}
ShaderInfo &getShaderInfo() { return mShaderInfo; }
ShaderInfo &getOriginalShaderInfo() { return mOriginalShaderInfo; }
GlslangProgramInterfaceInfo &getGlslangProgramInterfaceInfo()
{
......@@ -171,16 +175,17 @@ class ProgramVk : public ProgramImpl
ANGLE_INLINE angle::Result initProgram(ContextVk *contextVk,
const gl::ShaderType shaderType,
ProgramTransformOptionBits optionBits,
ProgramInfo *programInfo)
ProgramInfo *programInfo,
ProgramExecutableVk *executableVk)
{
ASSERT(mShaderInfo.valid());
ASSERT(mOriginalShaderInfo.valid());
// Create the program pipeline. This is done lazily and once per combination of
// specialization constants.
if (!programInfo->valid(shaderType))
{
ANGLE_TRY(programInfo->initProgram(contextVk, shaderType, mShaderInfo,
mExecutable.mVariableInfoMap, optionBits));
ANGLE_TRY(programInfo->initProgram(contextVk, shaderType, mOriginalShaderInfo,
optionBits, executableVk));
}
ASSERT(programInfo->valid(shaderType));
......@@ -191,7 +196,7 @@ class ProgramVk : public ProgramImpl
gl::ShaderBitSet mDefaultUniformBlocksDirty;
// We keep the SPIR-V code to use for draw call pipeline creation.
ShaderInfo mShaderInfo;
ShaderInfo mOriginalShaderInfo;
GlslangProgramInterfaceInfo mGlslangProgramInterfaceInfo;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment