Commit 454194e4 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Refactor inactive varying removal 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: Ifd52be302c25392d3e8fc1c589795c113e44d354 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2703792 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarCharlie Lao <cclao@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent c342647f
...@@ -1163,6 +1163,7 @@ class SpirvTransformerBase : angle::NonCopyable ...@@ -1163,6 +1163,7 @@ class SpirvTransformerBase : angle::NonCopyable
return mVariableInfoById; return mVariableInfoById;
} }
static spirv::IdRef GetNewId(SpirvBlob *blob);
spirv::IdRef getNewId(); spirv::IdRef getNewId();
protected: protected:
...@@ -1243,9 +1244,14 @@ void SpirvTransformerBase::copyInstruction(const uint32_t *instruction, size_t w ...@@ -1243,9 +1244,14 @@ void SpirvTransformerBase::copyInstruction(const uint32_t *instruction, size_t w
mSpirvBlobOut->insert(mSpirvBlobOut->end(), instruction, instruction + wordCount); mSpirvBlobOut->insert(mSpirvBlobOut->end(), instruction, instruction + wordCount);
} }
spirv::IdRef SpirvTransformerBase::GetNewId(SpirvBlob *blob)
{
return spirv::IdRef((*blob)[kHeaderIndexIndexBound]++);
}
spirv::IdRef SpirvTransformerBase::getNewId() spirv::IdRef SpirvTransformerBase::getNewId()
{ {
return spirv::IdRef((*mSpirvBlobOut)[kHeaderIndexIndexBound]++); return GetNewId(mSpirvBlobOut);
} }
enum class SpirvVariableType enum class SpirvVariableType
...@@ -1294,7 +1300,7 @@ class SpirvIDDiscoverer final : angle::NonCopyable ...@@ -1294,7 +1300,7 @@ class SpirvIDDiscoverer final : angle::NonCopyable
// Helpers: // Helpers:
void visitTypeHelper(spirv::IdResult id, spirv::IdRef typeId); void visitTypeHelper(spirv::IdResult id, spirv::IdRef typeId);
void visitTransformFeedbackVariable(spirv::IdResult id, const spirv::LiteralString &name); void visitTransformFeedbackVariable(spirv::IdResult id, const spirv::LiteralString &name);
void writePendingDeclarations(SpirvTransformerBase *transformer, SpirvBlob *blobOut); void writePendingDeclarations(SpirvBlob *blobOut);
// Getters: // Getters:
const spirv::LiteralString &getName(spirv::IdRef id) const { return mNamesById[id]; } const spirv::LiteralString &getName(spirv::IdRef id) const { return mNamesById[id]; }
...@@ -1597,41 +1603,40 @@ void SpirvIDDiscoverer::visitTransformFeedbackVariable(spirv::IdResult id, ...@@ -1597,41 +1603,40 @@ void SpirvIDDiscoverer::visitTransformFeedbackVariable(spirv::IdResult id,
} }
} }
void SpirvIDDiscoverer::writePendingDeclarations(SpirvTransformerBase *transformer, void SpirvIDDiscoverer::writePendingDeclarations(SpirvBlob *blobOut)
SpirvBlob *blobOut)
{ {
if (!mFloatId.valid()) if (!mFloatId.valid())
{ {
mFloatId = transformer->getNewId(); mFloatId = SpirvTransformerBase::GetNewId(blobOut);
spirv::WriteTypeFloat(blobOut, mFloatId, spirv::LiteralInteger(32)); spirv::WriteTypeFloat(blobOut, mFloatId, spirv::LiteralInteger(32));
} }
if (!mVec4Id.valid()) if (!mVec4Id.valid())
{ {
mVec4Id = transformer->getNewId(); mVec4Id = SpirvTransformerBase::GetNewId(blobOut);
spirv::WriteTypeVector(blobOut, mVec4Id, mFloatId, spirv::LiteralInteger(4)); spirv::WriteTypeVector(blobOut, mVec4Id, mFloatId, spirv::LiteralInteger(4));
} }
if (!mVec4OutTypePointerId.valid()) if (!mVec4OutTypePointerId.valid())
{ {
mVec4OutTypePointerId = transformer->getNewId(); mVec4OutTypePointerId = SpirvTransformerBase::GetNewId(blobOut);
spirv::WriteTypePointer(blobOut, mVec4OutTypePointerId, spv::StorageClassOutput, mVec4Id); spirv::WriteTypePointer(blobOut, mVec4OutTypePointerId, spv::StorageClassOutput, mVec4Id);
} }
if (!mIntId.valid()) if (!mIntId.valid())
{ {
mIntId = transformer->getNewId(); mIntId = SpirvTransformerBase::GetNewId(blobOut);
spirv::WriteTypeInt(blobOut, mIntId, spirv::LiteralInteger(32), spirv::LiteralInteger(1)); spirv::WriteTypeInt(blobOut, mIntId, spirv::LiteralInteger(32), spirv::LiteralInteger(1));
} }
ASSERT(!mInt0Id.valid()); ASSERT(!mInt0Id.valid());
mInt0Id = transformer->getNewId(); mInt0Id = SpirvTransformerBase::GetNewId(blobOut);
spirv::WriteConstant(blobOut, mIntId, mInt0Id, spirv::LiteralContextDependentNumber(0)); spirv::WriteConstant(blobOut, mIntId, mInt0Id, spirv::LiteralContextDependentNumber(0));
constexpr uint32_t kFloatHalfAsUint = 0x3F00'0000; constexpr uint32_t kFloatHalfAsUint = 0x3F00'0000;
ASSERT(!mFloatHalfId.valid()); ASSERT(!mFloatHalfId.valid());
mFloatHalfId = transformer->getNewId(); mFloatHalfId = SpirvTransformerBase::GetNewId(blobOut);
spirv::WriteConstant(blobOut, mFloatId, mFloatHalfId, spirv::WriteConstant(blobOut, mFloatId, mFloatHalfId,
spirv::LiteralContextDependentNumber(kFloatHalfAsUint)); spirv::LiteralContextDependentNumber(kFloatHalfAsUint));
} }
...@@ -1704,6 +1709,167 @@ TransformationState SpirvPerVertexTrimmer::transformTypeStruct(const SpirvIDDisc ...@@ -1704,6 +1709,167 @@ TransformationState SpirvPerVertexTrimmer::transformTypeStruct(const SpirvIDDisc
return TransformationState::Transformed; return TransformationState::Transformed;
} }
// Helper class that removes inactive varyings and replaces them with Private variables.
class SpirvInactiveVaryingRemover final : angle::NonCopyable
{
public:
SpirvInactiveVaryingRemover() {}
void init(size_t indexCount);
TransformationState transformAccessChain(spirv::IdResultType typeId,
spirv::IdResult id,
spirv::IdRef baseId,
const spirv::IdRefList &indexList,
SpirvBlob *blobOut);
TransformationState transformDecorate(const ShaderInterfaceVariableInfo &info,
gl::ShaderType shaderType,
spirv::IdRef id,
spv::Decoration decoration,
const spirv::LiteralIntegerList &decorationValues,
SpirvBlob *blobOut);
TransformationState transformTypePointer(const SpirvIDDiscoverer &ids,
spirv::IdResult id,
spv::StorageClass storageClass,
spirv::IdRef typeId,
SpirvBlob *blobOut);
TransformationState transformVariable(spirv::IdResultType typeId,
spirv::IdResult id,
spv::StorageClass storageClass,
SpirvBlob *blobOut);
void modifyEntryPointInterfaceList(
const std::vector<const ShaderInterfaceVariableInfo *> &variableInfoById,
gl::ShaderType shaderType,
spirv::IdRefList *interfaceList);
private:
// 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
// class. If inactive varyings are encountered, its type is changed to the Private one. The
// following vector maps the Output type id to the corresponding Private one.
std::vector<spirv::IdRef> mTypePointerTransformedId;
};
void SpirvInactiveVaryingRemover::init(size_t indexBound)
{
// Allocate storage for Output type pointer map. At index i, this vector holds the identical
// type as %i except for its storage class turned to Private.
mTypePointerTransformedId.resize(indexBound);
}
TransformationState SpirvInactiveVaryingRemover::transformAccessChain(
spirv::IdResultType typeId,
spirv::IdResult id,
spirv::IdRef baseId,
const spirv::IdRefList &indexList,
SpirvBlob *blobOut)
{
// Modifiy the instruction to use the private type.
ASSERT(typeId < mTypePointerTransformedId.size());
ASSERT(mTypePointerTransformedId[typeId].valid());
spirv::WriteAccessChain(blobOut, mTypePointerTransformedId[typeId], id, baseId, indexList);
return TransformationState::Transformed;
}
TransformationState SpirvInactiveVaryingRemover::transformDecorate(
const ShaderInterfaceVariableInfo &info,
gl::ShaderType shaderType,
spirv::IdRef id,
spv::Decoration decoration,
const spirv::LiteralIntegerList &decorationValues,
SpirvBlob *blobOut)
{
// If it's an inactive varying, remove the decoration altogether.
return info.activeStages[shaderType] ? TransformationState::Unchanged
: TransformationState::Transformed;
}
void SpirvInactiveVaryingRemover::modifyEntryPointInterfaceList(
const std::vector<const ShaderInterfaceVariableInfo *> &variableInfoById,
gl::ShaderType shaderType,
spirv::IdRefList *interfaceList)
{
// Filter out inactive varyings from entry point interface declaration.
size_t writeIndex = 0;
for (size_t index = 0; index < interfaceList->size(); ++index)
{
spirv::IdRef id((*interfaceList)[index]);
const ShaderInterfaceVariableInfo *info = variableInfoById[id];
ASSERT(info);
if (!info->activeStages[shaderType])
{
continue;
}
(*interfaceList)[writeIndex] = id;
++writeIndex;
}
// Update the number of interface variables.
interfaceList->resize(writeIndex);
}
TransformationState SpirvInactiveVaryingRemover::transformTypePointer(
const SpirvIDDiscoverer &ids,
spirv::IdResult id,
spv::StorageClass storageClass,
spirv::IdRef typeId,
SpirvBlob *blobOut)
{
// If the storage class is output, this may be used to create a variable corresponding to an
// inactive varying, or if that varying is a struct, an Op*AccessChain retrieving a field of
// that inactive varying.
//
// SPIR-V specifies the storage class both on the type and the variable declaration. Otherwise
// it would have been sufficient to modify the OpVariable instruction. For simplicity, duplicate
// every "OpTypePointer Output" and "OpTypePointer Input" instruction except with the Private
// storage class, in case it may be necessary later.
// Cannot create a Private type declaration from builtins such as gl_PerVertex.
if (ids.getName(typeId) != nullptr && gl::IsBuiltInName(ids.getName(typeId)))
{
return TransformationState::Unchanged;
}
if (storageClass != spv::StorageClassOutput && storageClass != spv::StorageClassInput)
{
return TransformationState::Unchanged;
}
const spirv::IdRef newPrivateTypeId(SpirvTransformerBase::GetNewId(blobOut));
// Write OpTypePointer for the new PrivateType.
spirv::WriteTypePointer(blobOut, newPrivateTypeId, spv::StorageClassPrivate, typeId);
// Remember the id of the replacement.
ASSERT(id < mTypePointerTransformedId.size());
mTypePointerTransformedId[id] = newPrivateTypeId;
// The original instruction should still be present as well. At this point, we don't know
// whether we will need the original or Private type.
return TransformationState::Unchanged;
}
TransformationState SpirvInactiveVaryingRemover::transformVariable(spirv::IdResultType typeId,
spirv::IdResult id,
spv::StorageClass storageClass,
SpirvBlob *blobOut)
{
ASSERT(storageClass == spv::StorageClassOutput || storageClass == spv::StorageClassInput);
ASSERT(typeId < mTypePointerTransformedId.size());
ASSERT(mTypePointerTransformedId[typeId].valid());
spirv::WriteVariable(blobOut, mTypePointerTransformedId[typeId], id, spv::StorageClassPrivate,
nullptr);
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
...@@ -1781,17 +1947,9 @@ class SpirvTransformer final : public SpirvTransformerBase ...@@ -1781,17 +1947,9 @@ class SpirvTransformer final : public SpirvTransformerBase
// Transformation state: // Transformation state:
SpirvPerVertexTrimmer mPerVertexTrimmer; SpirvPerVertexTrimmer mPerVertexTrimmer;
SpirvInactiveVaryingRemover mInactiveVaryingRemover;
// Each OpTypePointer instruction that defines a type with the Output storage class is std::vector<spirv::IdRef> mTypePointerTypeId;
// 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
// following vector maps the Output type id to the corresponding Private one.
struct TransformedIDs
{
spirv::IdRef privateID;
spirv::IdRef typeID;
};
std::vector<TransformedIDs> mTypePointerTransformedId;
std::vector<spirv::IdRef> mFixedVaryingId; std::vector<spirv::IdRef> mFixedVaryingId;
std::vector<spirv::IdRef> mFixedVaryingTypeId; std::vector<spirv::IdRef> mFixedVaryingTypeId;
}; };
...@@ -1817,16 +1975,15 @@ void SpirvTransformer::resolveVariableIds() ...@@ -1817,16 +1975,15 @@ void SpirvTransformer::resolveVariableIds()
const size_t indexBound = mSpirvBlobIn[kHeaderIndexIndexBound]; const size_t indexBound = mSpirvBlobIn[kHeaderIndexIndexBound];
mIds.init(indexBound); mIds.init(indexBound);
mInactiveVaryingRemover.init(indexBound);
// Allocate storage for id-to-info map. If %i is the id of a name in mVariableInfoMap, index i // Allocate storage for id-to-info map. If %i is the id of a name in mVariableInfoMap, index i
// in this vector will hold a pointer to the ShaderInterfaceVariableInfo object associated with // in this vector will hold a pointer to the ShaderInterfaceVariableInfo object associated with
// that name in mVariableInfoMap. // that name in mVariableInfoMap.
mVariableInfoById.resize(indexBound, nullptr); mVariableInfoById.resize(indexBound, nullptr);
// Allocate storage for Output type pointer map. At index i, this vector holds the identical // Allocate storage for precision mismatch fix up.
// type as %i except for its storage class turned to Private. mTypePointerTypeId.resize(indexBound);
// Also store a FunctionID and TypeID for when we need to fix a precision mismatch
mTypePointerTransformedId.resize(indexBound);
mFixedVaryingId.resize(indexBound); mFixedVaryingId.resize(indexBound);
mFixedVaryingTypeId.resize(indexBound); mFixedVaryingTypeId.resize(indexBound);
...@@ -2015,7 +2172,7 @@ void SpirvTransformer::writePendingDeclarations() ...@@ -2015,7 +2172,7 @@ void SpirvTransformer::writePendingDeclarations()
return; return;
} }
mIds.writePendingDeclarations(this, mSpirvBlobOut); mIds.writePendingDeclarations(mSpirvBlobOut);
} }
// Called by transformInstruction to insert necessary instructions for casting varyings. // Called by transformInstruction to insert necessary instructions for casting varyings.
...@@ -2041,8 +2198,7 @@ void SpirvTransformer::writeInputPreamble() ...@@ -2041,8 +2198,7 @@ void SpirvTransformer::writeInputPreamble()
// Build OpLoad instruction to load the mediump value into a temporary // Build OpLoad instruction to load the mediump value into a temporary
const spirv::IdRef tempVar(getNewId()); const spirv::IdRef tempVar(getNewId());
const spirv::IdRef tempVarType( const spirv::IdRef tempVarType(mTypePointerTypeId[mFixedVaryingTypeId[id]]);
mTypePointerTransformedId[mFixedVaryingTypeId[id]].typeID);
ASSERT(tempVarType.valid()); ASSERT(tempVarType.valid());
spirv::WriteLoad(mSpirvBlobOut, tempVarType, tempVar, mFixedVaryingId[id], nullptr); spirv::WriteLoad(mSpirvBlobOut, tempVarType, tempVar, mFixedVaryingId[id], nullptr);
...@@ -2076,8 +2232,7 @@ void SpirvTransformer::writeOutputPrologue() ...@@ -2076,8 +2232,7 @@ void SpirvTransformer::writeOutputPrologue()
// Build OpLoad instruction to load the highp value into a temporary // Build OpLoad instruction to load the highp value into a temporary
const spirv::IdRef tempVar(getNewId()); const spirv::IdRef tempVar(getNewId());
const spirv::IdRef tempVarType( const spirv::IdRef tempVarType(mTypePointerTypeId[mFixedVaryingTypeId[id]]);
mTypePointerTransformedId[mFixedVaryingTypeId[id]].typeID);
ASSERT(tempVarType.valid()); ASSERT(tempVarType.valid());
spirv::WriteLoad(mSpirvBlobOut, tempVarType, tempVar, id, nullptr); spirv::WriteLoad(mSpirvBlobOut, tempVarType, tempVar, id, nullptr);
...@@ -2418,8 +2573,9 @@ TransformationState SpirvTransformer::transformDecorate(const uint32_t *instruct ...@@ -2418,8 +2573,9 @@ TransformationState SpirvTransformer::transformDecorate(const uint32_t *instruct
return TransformationState::Unchanged; return TransformationState::Unchanged;
} }
// If it's an inactive varying, remove the decoration altogether. if (mInactiveVaryingRemover.transformDecorate(*info, mOptions.shaderType, id, decoration,
if (!info->activeStages[mOptions.shaderType]) decorationValues, mSpirvBlobOut) ==
TransformationState::Transformed)
{ {
return TransformationState::Transformed; return TransformationState::Transformed;
} }
...@@ -2660,38 +2816,25 @@ TransformationState SpirvTransformer::transformEntryPoint(const uint32_t *instru ...@@ -2660,38 +2816,25 @@ TransformationState SpirvTransformer::transformEntryPoint(const uint32_t *instru
// Should only have one EntryPoint // Should only have one EntryPoint
ASSERT(!mEntryPointId.valid()); ASSERT(!mEntryPointId.valid());
// Remove inactive varyings from the shader interface declaration.
spv::ExecutionModel executionModel; spv::ExecutionModel executionModel;
spirv::LiteralString name; spirv::LiteralString name;
spirv::IdRefList interfaceList; spirv::IdRefList interfaceList;
spirv::ParseEntryPoint(instruction, &executionModel, &mEntryPointId, &name, &interfaceList); spirv::ParseEntryPoint(instruction, &executionModel, &mEntryPointId, &name, &interfaceList);
// Filter out inactive varyings from entry point interface declaration. mInactiveVaryingRemover.modifyEntryPointInterfaceList(mVariableInfoById, mOptions.shaderType,
size_t writeIndex = 0; &interfaceList);
// Modify interface list if any ID was replaced due to varying precision mismatch.
for (size_t index = 0; index < interfaceList.size(); ++index) for (size_t index = 0; index < interfaceList.size(); ++index)
{ {
spirv::IdRef id(interfaceList[index]); spirv::IdRef id(interfaceList[index]);
const ShaderInterfaceVariableInfo *info = mVariableInfoById[id];
ASSERT(info);
if (!info->activeStages[mOptions.shaderType])
{
continue;
}
// If ID is one we had to replace due to varying mismatch, use the fixed ID.
if (mFixedVaryingId[id].valid()) if (mFixedVaryingId[id].valid())
{ {
id = mFixedVaryingId[id]; interfaceList[index] = mFixedVaryingId[id];
} }
interfaceList[writeIndex] = id;
++writeIndex;
} }
// Update the number of interface variables.
interfaceList.resize(writeIndex);
// Write the entry point with the inactive interface variables removed. // Write the entry point with the inactive interface variables removed.
spirv::WriteEntryPoint(mSpirvBlobOut, executionModel, mEntryPointId, name, interfaceList); spirv::WriteEntryPoint(mSpirvBlobOut, executionModel, mEntryPointId, name, interfaceList);
...@@ -2711,41 +2854,11 @@ TransformationState SpirvTransformer::transformTypePointer(const uint32_t *instr ...@@ -2711,41 +2854,11 @@ TransformationState SpirvTransformer::transformTypePointer(const uint32_t *instr
spirv::IdRef typeId; spirv::IdRef typeId;
spirv::ParseTypePointer(instruction, &id, &storageClass, &typeId); spirv::ParseTypePointer(instruction, &id, &storageClass, &typeId);
// If the storage class is output, this may be used to create a variable corresponding to an
// inactive varying, or if that varying is a struct, an Op*AccessChain retrieving a field of
// that inactive varying.
//
// SPIR-V specifies the storage class both on the type and the variable declaration. Otherwise
// it would have been sufficient to modify the OpVariable instruction. For simplicity, duplicate
// every "OpTypePointer Output" and "OpTypePointer Input" instruction except with the Private
// storage class, in case it may be necessary later.
// Cannot create a Private type declaration from builtins such as gl_PerVertex.
if (mIds.getName(typeId) != nullptr && gl::IsBuiltInName(mIds.getName(typeId)))
{
return TransformationState::Unchanged;
}
// Precision fixup needs this typeID // Precision fixup needs this typeID
mTypePointerTransformedId[id].typeID = typeId; mTypePointerTypeId[id] = typeId;
if (storageClass != spv::StorageClassOutput && storageClass != spv::StorageClassInput)
{
return TransformationState::Unchanged;
}
const spirv::IdRef newPrivateTypeId(getNewId());
// Write OpTypePointer for the new PrivateType.
spirv::WriteTypePointer(mSpirvBlobOut, newPrivateTypeId, spv::StorageClassPrivate, typeId);
// Remember the id of the replacement. return mInactiveVaryingRemover.transformTypePointer(mIds, id, storageClass, typeId,
ASSERT(id < mTypePointerTransformedId.size()); mSpirvBlobOut);
mTypePointerTransformedId[id].privateID = newPrivateTypeId;
// The original instruction should still be present as well. At this point, we don't know
// whether we will need the original or Private type.
return TransformationState::Unchanged;
} }
TransformationState SpirvTransformer::transformTypeStruct(const uint32_t *instruction) TransformationState SpirvTransformer::transformTypeStruct(const uint32_t *instruction)
...@@ -2809,11 +2922,8 @@ TransformationState SpirvTransformer::transformVariable(const uint32_t *instruct ...@@ -2809,11 +2922,8 @@ TransformationState SpirvTransformer::transformVariable(const uint32_t *instruct
spirv::WriteVariable(mSpirvBlobOut, typeId, mFixedVaryingId[id], storageClass, nullptr); spirv::WriteVariable(mSpirvBlobOut, typeId, mFixedVaryingId[id], storageClass, nullptr);
// Make original variable a private global // Make original variable a private global
ASSERT(mTypePointerTransformedId[typeId].privateID.valid()); return mInactiveVaryingRemover.transformVariable(typeId, id, storageClass,
spirv::WriteVariable(mSpirvBlobOut, mTypePointerTransformedId[typeId].privateID, id, mSpirvBlobOut);
spv::StorageClassPrivate, nullptr);
return TransformationState::Transformed;
} }
return TransformationState::Unchanged; return TransformationState::Unchanged;
} }
...@@ -2831,17 +2941,9 @@ TransformationState SpirvTransformer::transformVariable(const uint32_t *instruct ...@@ -2831,17 +2941,9 @@ TransformationState SpirvTransformer::transformVariable(const uint32_t *instruct
return TransformationState::Transformed; return TransformationState::Transformed;
} }
ASSERT(storageClass == spv::StorageClassOutput || storageClass == spv::StorageClassInput);
// The variable is inactive. Output a modified variable declaration, where the type is the // The variable is inactive. Output a modified variable declaration, where the type is the
// corresponding type with the Private storage class. // corresponding type with the Private storage class.
ASSERT(typeId < mTypePointerTransformedId.size()); return mInactiveVaryingRemover.transformVariable(typeId, id, storageClass, mSpirvBlobOut);
ASSERT(mTypePointerTransformedId[typeId].privateID.valid());
spirv::WriteVariable(mSpirvBlobOut, mTypePointerTransformedId[typeId].privateID, id,
spv::StorageClassPrivate, nullptr);
return TransformationState::Transformed;
} }
TransformationState SpirvTransformer::transformAccessChain(const uint32_t *instruction) TransformationState SpirvTransformer::transformAccessChain(const uint32_t *instruction)
...@@ -2864,14 +2966,8 @@ TransformationState SpirvTransformer::transformAccessChain(const uint32_t *instr ...@@ -2864,14 +2966,8 @@ TransformationState SpirvTransformer::transformAccessChain(const uint32_t *instr
return TransformationState::Unchanged; return TransformationState::Unchanged;
} }
// Modifiy the instruction to use the private type. return mInactiveVaryingRemover.transformAccessChain(typeId, id, baseId, indexList,
ASSERT(typeId < mTypePointerTransformedId.size()); mSpirvBlobOut);
ASSERT(mTypePointerTransformedId[typeId].privateID.valid());
spirv::WriteAccessChain(mSpirvBlobOut, mTypePointerTransformedId[typeId].privateID, id, baseId,
indexList);
return TransformationState::Transformed;
} }
TransformationState SpirvTransformer::transformExecutionMode(const uint32_t *instruction) TransformationState SpirvTransformer::transformExecutionMode(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