Commit c342647f by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Refactor gl_PerVertex trimming out of SPIR-V transformer

The SPIR-V transformer performs multiple transformations in one pass. This is part of a series of refactoring changes that detangle these transformations and encapsulate them, while allowing the transformation to remain single-pass. Bug: angleproject:4888 Change-Id: I41ba9165336487819dcf915af0d1ed868f73f724 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2703791 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarCharlie Lao <cclao@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 8f65bb39
...@@ -1636,6 +1636,74 @@ void SpirvIDDiscoverer::writePendingDeclarations(SpirvTransformerBase *transform ...@@ -1636,6 +1636,74 @@ void SpirvIDDiscoverer::writePendingDeclarations(SpirvTransformerBase *transform
spirv::LiteralContextDependentNumber(kFloatHalfAsUint)); spirv::LiteralContextDependentNumber(kFloatHalfAsUint));
} }
// Helper class that trims input and output gl_PerVertex declarations to remove inactive builtins.
class SpirvPerVertexTrimmer final : angle::NonCopyable
{
public:
SpirvPerVertexTrimmer() {}
TransformationState transformMemberDecorate(const SpirvIDDiscoverer &ids,
spirv::IdRef typeId,
spirv::LiteralInteger member,
spv::Decoration decoration);
TransformationState transformMemberName(const SpirvIDDiscoverer &ids,
spirv::IdRef id,
spirv::LiteralInteger member,
const spirv::LiteralString &name);
TransformationState transformTypeStruct(const SpirvIDDiscoverer &ids,
spirv::IdResult id,
spirv::IdRefList *memberList,
SpirvBlob *blobOut);
};
TransformationState SpirvPerVertexTrimmer::transformMemberDecorate(const SpirvIDDiscoverer &ids,
spirv::IdRef typeId,
spirv::LiteralInteger member,
spv::Decoration decoration)
{
// Transform only OpMemberDecorate %gl_PerVertex N BuiltIn B
if (!ids.isPerVertex(typeId) || decoration != spv::DecorationBuiltIn)
{
return TransformationState::Unchanged;
}
// Drop stripped fields.
return member > ids.getPerVertexMaxActiveMember(typeId) ? TransformationState::Transformed
: TransformationState::Unchanged;
}
TransformationState SpirvPerVertexTrimmer::transformMemberName(const SpirvIDDiscoverer &ids,
spirv::IdRef id,
spirv::LiteralInteger member,
const spirv::LiteralString &name)
{
// Remove the instruction if it's a stripped member of gl_PerVertex.
return ids.isPerVertex(id) && member > ids.getPerVertexMaxActiveMember(id)
? TransformationState::Transformed
: TransformationState::Unchanged;
}
TransformationState SpirvPerVertexTrimmer::transformTypeStruct(const SpirvIDDiscoverer &ids,
spirv::IdResult id,
spirv::IdRefList *memberList,
SpirvBlob *blobOut)
{
if (!ids.isPerVertex(id))
{
return TransformationState::Unchanged;
}
const uint32_t maxMembers = ids.getPerVertexMaxActiveMember(id);
// Change the definition of the gl_PerVertex struct by stripping unused fields at the end.
const uint32_t memberCount = maxMembers + 1;
memberList->resize(memberCount);
spirv::WriteTypeStruct(blobOut, id, *memberList);
return TransformationState::Transformed;
}
// A SPIR-V transformer. It walks the instructions and modifies them as necessary, for example to // A SPIR-V transformer. It walks the instructions and modifies them as necessary, for example to
// assign bindings or locations. // assign bindings or locations.
class SpirvTransformer final : public SpirvTransformerBase class SpirvTransformer final : public SpirvTransformerBase
...@@ -1712,6 +1780,8 @@ class SpirvTransformer final : public SpirvTransformerBase ...@@ -1712,6 +1780,8 @@ class SpirvTransformer final : public SpirvTransformerBase
// Transformation state: // Transformation state:
SpirvPerVertexTrimmer mPerVertexTrimmer;
// Each OpTypePointer instruction that defines a type with the Output storage class is // Each OpTypePointer instruction that defines a type with the Output storage class is
// duplicated with a similar instruction but which defines a type with the Private storage // duplicated with a similar instruction but which defines a type with the Private storage
// class. If inactive varyings are encountered, its type is changed to the Private one. The // class. If inactive varyings are encountered, its type is changed to the Private one. The
...@@ -2503,15 +2573,7 @@ TransformationState SpirvTransformer::transformMemberDecorate(const uint32_t *in ...@@ -2503,15 +2573,7 @@ TransformationState SpirvTransformer::transformMemberDecorate(const uint32_t *in
spv::Decoration decoration; spv::Decoration decoration;
spirv::ParseMemberDecorate(instruction, &typeId, &member, &decoration, nullptr); spirv::ParseMemberDecorate(instruction, &typeId, &member, &decoration, nullptr);
// Transform only OpMemberDecorate %gl_PerVertex N BuiltIn B return mPerVertexTrimmer.transformMemberDecorate(mIds, typeId, member, decoration);
if (!mIds.isPerVertex(typeId) || decoration != spv::DecorationBuiltIn)
{
return TransformationState::Unchanged;
}
// Drop stripped fields.
return member > mIds.getPerVertexMaxActiveMember(typeId) ? TransformationState::Transformed
: TransformationState::Unchanged;
} }
TransformationState SpirvTransformer::transformCapability(const uint32_t *instruction, TransformationState SpirvTransformer::transformCapability(const uint32_t *instruction,
...@@ -2561,10 +2623,7 @@ TransformationState SpirvTransformer::transformDebugInfo(const uint32_t *instruc ...@@ -2561,10 +2623,7 @@ TransformationState SpirvTransformer::transformDebugInfo(const uint32_t *instruc
spirv::LiteralString name; spirv::LiteralString name;
spirv::ParseMemberName(instruction, &id, &member, &name); spirv::ParseMemberName(instruction, &id, &member, &name);
// Remove the instruction if it's a stripped member of gl_PerVertex. return mPerVertexTrimmer.transformMemberName(mIds, id, member, name);
return mIds.isPerVertex(id) && member > mIds.getPerVertexMaxActiveMember(id)
? TransformationState::Transformed
: TransformationState::Unchanged;
} }
// In the case of ANGLEXfbN, unconditionally remove the variable names. If transform // In the case of ANGLEXfbN, unconditionally remove the variable names. If transform
...@@ -2695,20 +2754,7 @@ TransformationState SpirvTransformer::transformTypeStruct(const uint32_t *instru ...@@ -2695,20 +2754,7 @@ TransformationState SpirvTransformer::transformTypeStruct(const uint32_t *instru
spirv::IdRefList memberList; spirv::IdRefList memberList;
ParseTypeStruct(instruction, &id, &memberList); ParseTypeStruct(instruction, &id, &memberList);
if (!mIds.isPerVertex(id)) return mPerVertexTrimmer.transformTypeStruct(mIds, id, &memberList, mSpirvBlobOut);
{
return TransformationState::Unchanged;
}
const uint32_t maxMembers = mIds.getPerVertexMaxActiveMember(id);
// Change the definition of the gl_PerVertex struct by stripping unused fields at the end.
const uint32_t memberCount = maxMembers + 1;
memberList.resize(memberCount);
spirv::WriteTypeStruct(mSpirvBlobOut, id, memberList);
return TransformationState::Transformed;
} }
TransformationState SpirvTransformer::transformReturn(const uint32_t *instruction) TransformationState SpirvTransformer::transformReturn(const uint32_t *instruction)
......
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