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; ...@@ -113,22 +113,35 @@ ProgramInfo::~ProgramInfo() = default;
angle::Result ProgramInfo::initProgram(ContextVk *contextVk, angle::Result ProgramInfo::initProgram(ContextVk *contextVk,
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
const ShaderInfo &shaderInfo, 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 (!transformedSpirvBlob.empty())
{
if (!spirvBlob.empty()) ANGLE_TRY(vk::InitShaderAndSerial(contextVk, &mShaders[shaderType].get(),
transformedSpirvBlob.data(),
transformedSpirvBlob.size() * sizeof(uint32_t)));
}
else
{ {
if (shaderType == gl::ShaderType::Fragment && if (shaderType == gl::ShaderType::Fragment &&
optionBits[ProgramTransformOption::RemoveEarlyFragmentTestsOptimization]) optionBits[ProgramTransformOption::RemoveEarlyFragmentTestsOptimization])
{ {
SpirvBlob spirvBlobTransformed; SpirvBlob &spirvBlobTransformed =
executableVk->getTransformedShaderInfo().getSpirvBlobs()[shaderType];
ANGLE_TRY(GlslangWrapperVk::TransformSpirV(contextVk, shaderType, true, ANGLE_TRY(GlslangWrapperVk::TransformSpirV(contextVk, shaderType, true,
variableInfoMap[shaderType], spirvBlob, variableInfoMap[shaderType],
&spirvBlobTransformed)); originalSpirvBlob, &spirvBlobTransformed));
ANGLE_TRY(vk::InitShaderAndSerial(contextVk, &mShaders[shaderType].get(), ANGLE_TRY(vk::InitShaderAndSerial(contextVk, &mShaders[shaderType].get(),
spirvBlobTransformed.data(), spirvBlobTransformed.data(),
spirvBlobTransformed.size() * sizeof(uint32_t))); spirvBlobTransformed.size() * sizeof(uint32_t)));
...@@ -136,13 +149,13 @@ angle::Result ProgramInfo::initProgram(ContextVk *contextVk, ...@@ -136,13 +149,13 @@ angle::Result ProgramInfo::initProgram(ContextVk *contextVk,
else else
{ {
ANGLE_TRY(vk::InitShaderAndSerial(contextVk, &mShaders[shaderType].get(), ANGLE_TRY(vk::InitShaderAndSerial(contextVk, &mShaders[shaderType].get(),
spirvBlob.data(), originalSpirvBlob.data(),
spirvBlob.size() * sizeof(uint32_t))); originalSpirvBlob.size() * sizeof(uint32_t)));
} }
mProgramHelper.setShader(shaderType, &mShaders[shaderType]);
} }
mProgramHelper.setShader(shaderType, &mShaders[shaderType]);
if (optionBits[ProgramTransformOption::EnableLineRasterEmulation]) if (optionBits[ProgramTransformOption::EnableLineRasterEmulation])
{ {
mProgramHelper.enableSpecializationConstant( mProgramHelper.enableSpecializationConstant(
...@@ -166,6 +179,7 @@ ProgramExecutableVk::ProgramExecutableVk() ...@@ -166,6 +179,7 @@ ProgramExecutableVk::ProgramExecutableVk()
: mEmptyDescriptorSets{}, : mEmptyDescriptorSets{},
mNumDefaultUniformDescriptors(0), mNumDefaultUniformDescriptors(0),
mDynamicBufferOffsets{}, mDynamicBufferOffsets{},
mTransformedShaderInfoSaved(false),
mProgram(nullptr), mProgram(nullptr),
mProgramPipeline(nullptr) mProgramPipeline(nullptr)
{} {}
...@@ -234,6 +248,12 @@ std::unique_ptr<rx::LinkEvent> ProgramExecutableVk::load(gl::BinaryInputStream * ...@@ -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); return std::make_unique<LinkEventDone>(angle::Result::Continue);
} }
...@@ -256,6 +276,13 @@ void ProgramExecutableVk::save(gl::BinaryOutputStream *stream) ...@@ -256,6 +276,13 @@ void ProgramExecutableVk::save(gl::BinaryOutputStream *stream)
stream->writeInt<uint32_t>(it.second.xfbStride); stream->writeInt<uint32_t>(it.second.xfbStride);
} }
} }
mTransformedShaderInfoSaved = mTransformedShaderInfo.valid();
stream->writeInt(mTransformedShaderInfoSaved);
if (mTransformedShaderInfoSaved)
{
mTransformedShaderInfo.save(stream);
}
} }
void ProgramExecutableVk::clearVariableInfoMap() void ProgramExecutableVk::clearVariableInfoMap()
...@@ -587,8 +614,8 @@ angle::Result ProgramExecutableVk::getGraphicsPipeline( ...@@ -587,8 +614,8 @@ angle::Result ProgramExecutableVk::getGraphicsPipeline(
ProgramVk *programVk = getShaderProgram(glState, shaderType); ProgramVk *programVk = getShaderProgram(glState, shaderType);
if (programVk) if (programVk)
{ {
ANGLE_TRY(programVk->initGraphicsShaderProgram(contextVk, shaderType, ANGLE_TRY(programVk->initGraphicsShaderProgram(
mTransformOptionBits, programInfo)); contextVk, shaderType, mTransformOptionBits, &programInfo, this));
} }
} }
...@@ -611,7 +638,7 @@ angle::Result ProgramExecutableVk::getComputePipeline(ContextVk *contextVk, ...@@ -611,7 +638,7 @@ angle::Result ProgramExecutableVk::getComputePipeline(ContextVk *contextVk,
ProgramVk *programVk = getShaderProgram(glState, gl::ShaderType::Compute); ProgramVk *programVk = getShaderProgram(glState, gl::ShaderType::Compute);
ASSERT(programVk); ASSERT(programVk);
ProgramInfo &programInfo = getComputeProgramInfo(); ProgramInfo &programInfo = getComputeProgramInfo();
ANGLE_TRY(programVk->initComputeProgram(contextVk, programInfo)); ANGLE_TRY(programVk->initComputeProgram(contextVk, &programInfo, this));
vk::ShaderProgramHelper *shaderProgram = programInfo.getShaderProgram(); vk::ShaderProgramHelper *shaderProgram = programInfo.getShaderProgram();
ASSERT(shaderProgram); ASSERT(shaderProgram);
......
...@@ -65,8 +65,8 @@ class ProgramInfo final : angle::NonCopyable ...@@ -65,8 +65,8 @@ class ProgramInfo final : angle::NonCopyable
angle::Result initProgram(ContextVk *contextVk, angle::Result initProgram(ContextVk *contextVk,
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
const ShaderInfo &shaderInfo, const ShaderInfo &shaderInfo,
const ShaderMapInterfaceVariableInfoMap &variableInfoMap, ProgramTransformOptionBits optionBits,
ProgramTransformOptionBits optionBits); ProgramExecutableVk *executableVk);
void release(ContextVk *contextVk); void release(ContextVk *contextVk);
ANGLE_INLINE bool valid(const gl::ShaderType shaderType) const ANGLE_INLINE bool valid(const gl::ShaderType shaderType) const
...@@ -163,6 +163,8 @@ class ProgramExecutableVk ...@@ -163,6 +163,8 @@ class ProgramExecutableVk
mProgramPipeline = pipeline; mProgramPipeline = pipeline;
} }
ShaderInfo &getTransformedShaderInfo() { return mTransformedShaderInfo; }
private: private:
friend class ProgramVk; friend class ProgramVk;
friend class ProgramPipelineVk; friend class ProgramPipelineVk;
...@@ -246,6 +248,10 @@ class ProgramExecutableVk ...@@ -246,6 +248,10 @@ class ProgramExecutableVk
ProgramTransformOptionBits mTransformOptionBits; ProgramTransformOptionBits mTransformOptionBits;
// We keep the SPIR-V code to use for draw call pipeline creation.
bool mTransformedShaderInfoSaved;
ShaderInfo mTransformedShaderInfo;
ProgramVk *mProgram; ProgramVk *mProgram;
ProgramPipelineVk *mProgramPipeline; ProgramPipelineVk *mProgramPipeline;
}; };
......
...@@ -32,6 +32,8 @@ void ProgramPipelineVk::destroy(const gl::Context *context) ...@@ -32,6 +32,8 @@ void ProgramPipelineVk::destroy(const gl::Context *context)
void ProgramPipelineVk::reset(ContextVk *contextVk) void ProgramPipelineVk::reset(ContextVk *contextVk)
{ {
mExecutable.reset(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 // 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) ...@@ -62,6 +64,7 @@ angle::Result ProgramPipelineVk::link(const gl::Context *glContext)
GlslangProgramInterfaceInfo glslangProgramInterfaceInfo; GlslangProgramInterfaceInfo glslangProgramInterfaceInfo;
GlslangWrapperVk::ResetGlslangProgramInterfaceInfo(&glslangProgramInterfaceInfo); GlslangWrapperVk::ResetGlslangProgramInterfaceInfo(&glslangProgramInterfaceInfo);
reset(contextVk);
mExecutable.clearVariableInfoMap(); mExecutable.clearVariableInfoMap();
// Now that the program pipeline has all of the programs attached, the various descriptor // 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 ...@@ -104,19 +107,16 @@ angle::Result ProgramPipelineVk::transformShaderSpirV(const gl::Context *glConte
{ {
ShaderInterfaceVariableInfoMap &variableInfoMap = ShaderInterfaceVariableInfoMap &variableInfoMap =
mExecutable.mVariableInfoMap[shaderType]; 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 // We skip early fragment tests optimization modification here since we need to keep
// original spriv blob here. // original spriv blob here.
ANGLE_TRY(GlslangWrapperVk::TransformSpirV( ANGLE_TRY(GlslangWrapperVk::TransformSpirV(
contextVk, shaderType, false, variableInfoMap, contextVk, shaderType, false, variableInfoMap,
programVk->getShaderInfo().getSpirvBlobs()[shaderType], &transformedSpirvBlob)); programVk->getOriginalShaderInfo().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; return angle::Result::Continue;
......
...@@ -179,7 +179,7 @@ void ProgramVk::reset(ContextVk *contextVk) ...@@ -179,7 +179,7 @@ void ProgramVk::reset(ContextVk *contextVk)
{ {
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
mShaderInfo.release(contextVk); mOriginalShaderInfo.release(contextVk);
for (auto &uniformBlock : mDefaultUniformBlocks) for (auto &uniformBlock : mDefaultUniformBlocks)
{ {
...@@ -189,6 +189,8 @@ void ProgramVk::reset(ContextVk *contextVk) ...@@ -189,6 +189,8 @@ void ProgramVk::reset(ContextVk *contextVk)
GlslangWrapperVk::ResetGlslangProgramInterfaceInfo(&mGlslangProgramInterfaceInfo); GlslangWrapperVk::ResetGlslangProgramInterfaceInfo(&mGlslangProgramInterfaceInfo);
mExecutable.reset(contextVk); 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, 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, ...@@ -201,7 +203,7 @@ std::unique_ptr<rx::LinkEvent> ProgramVk::load(const gl::Context *context,
reset(contextVk); reset(contextVk);
mShaderInfo.load(stream); mOriginalShaderInfo.load(stream);
mExecutable.load(stream); mExecutable.load(stream);
// Deserializes the uniformLayout data of mDefaultUniformBlocks // Deserializes the uniformLayout data of mDefaultUniformBlocks
...@@ -235,7 +237,7 @@ std::unique_ptr<rx::LinkEvent> ProgramVk::load(const gl::Context *context, ...@@ -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) void ProgramVk::save(const gl::Context *context, gl::BinaryOutputStream *stream)
{ {
mShaderInfo.save(stream); mOriginalShaderInfo.save(stream);
mExecutable.save(stream); mExecutable.save(stream);
// Serializes the uniformLayout data of mDefaultUniformBlocks // Serializes the uniformLayout data of mDefaultUniformBlocks
...@@ -302,8 +304,8 @@ std::unique_ptr<LinkEvent> ProgramVk::link(const gl::Context *context, ...@@ -302,8 +304,8 @@ std::unique_ptr<LinkEvent> ProgramVk::link(const gl::Context *context,
// Compile the shaders. // Compile the shaders.
angle::Result status = angle::Result status =
mShaderInfo.initShaders(contextVk, mState.getExecutable().getLinkedShaderStages(), mOriginalShaderInfo.initShaders(contextVk, mState.getExecutable().getLinkedShaderStages(),
shaderSources, mExecutable.mVariableInfoMap); shaderSources, mExecutable.mVariableInfoMap);
if (status != angle::Result::Continue) if (status != angle::Result::Continue)
{ {
return std::make_unique<LinkEventDone>(status); return std::make_unique<LinkEventDone>(status);
......
...@@ -127,18 +127,22 @@ class ProgramVk : public ProgramImpl ...@@ -127,18 +127,22 @@ class ProgramVk : public ProgramImpl
ANGLE_INLINE angle::Result initGraphicsShaderProgram(ContextVk *contextVk, ANGLE_INLINE angle::Result initGraphicsShaderProgram(ContextVk *contextVk,
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
ProgramTransformOptionBits optionBits, 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; 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() GlslangProgramInterfaceInfo &getGlslangProgramInterfaceInfo()
{ {
...@@ -171,16 +175,17 @@ class ProgramVk : public ProgramImpl ...@@ -171,16 +175,17 @@ class ProgramVk : public ProgramImpl
ANGLE_INLINE angle::Result initProgram(ContextVk *contextVk, ANGLE_INLINE angle::Result initProgram(ContextVk *contextVk,
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
ProgramTransformOptionBits optionBits, 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 // Create the program pipeline. This is done lazily and once per combination of
// specialization constants. // specialization constants.
if (!programInfo->valid(shaderType)) if (!programInfo->valid(shaderType))
{ {
ANGLE_TRY(programInfo->initProgram(contextVk, shaderType, mShaderInfo, ANGLE_TRY(programInfo->initProgram(contextVk, shaderType, mOriginalShaderInfo,
mExecutable.mVariableInfoMap, optionBits)); optionBits, executableVk));
} }
ASSERT(programInfo->valid(shaderType)); ASSERT(programInfo->valid(shaderType));
...@@ -191,7 +196,7 @@ class ProgramVk : public ProgramImpl ...@@ -191,7 +196,7 @@ class ProgramVk : public ProgramImpl
gl::ShaderBitSet mDefaultUniformBlocksDirty; gl::ShaderBitSet mDefaultUniformBlocksDirty;
// We keep the SPIR-V code to use for draw call pipeline creation. // We keep the SPIR-V code to use for draw call pipeline creation.
ShaderInfo mShaderInfo; ShaderInfo mOriginalShaderInfo;
GlslangProgramInterfaceInfo mGlslangProgramInterfaceInfo; 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