Commit 484e08e0 by Ben Clayton

SpirvShader: Rework pointer types

Previously Objects of the Variable kind would hold an Object::ID to another pointerBase object, which was combined with a per-lane offset in SpirvRoutine::intermediates. This is almost exactly the same as PhysicalPointer - except the base address was taken from SpirvRoutine::physicalPointers. With descriptor indices, we need a dynamic base pointer (only known at emit time) with per lane offsets. This change transforms the Kind::Variable and Kind::PhysicalPointer kinds into Kind::DivergentPointer and Kind::NonDivergentPointer. This reduces complexity in loads and stores, and better represents the various forms of pointer we care about. Bug: b/126330097 Change-Id: I514af5962b9cad4109197893066eda6f996be107 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/28390Tested-by: 's avatarBen Clayton <bclayton@google.com> Reviewed-by: 's avatarChris Forbes <chrisforbes@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Presubmit-Ready: Ben Clayton <bclayton@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
parent bd3af855
......@@ -233,17 +233,36 @@ namespace sw
InsnIterator definition;
Type::ID type;
ID pointerBase;
std::unique_ptr<uint32_t[]> constantValue = nullptr;
enum class Kind
{
Unknown, /* for paranoia -- if we get left with an object in this state, the module was broken */
Variable, // TODO: Document
InterfaceVariable, // TODO: Document
Constant, // Values held by Object::constantValue
Intermediate, // Values held by SpirvRoutine::intermediates
PhysicalPointer, // Pointer held by SpirvRoutine::physicalPointers
// Invalid default kind.
// If we get left with an object in this state, the module was
// broken.
Unknown,
// TODO: Better document this kind.
// A shader interface variable pointer.
// Pointer with uniform address across all lanes.
// Pointer held by SpirvRoutine::pointers
InterfaceVariable,
// Constant value held by Object::constantValue.
Constant,
// Value held by SpirvRoutine::intermediates.
Intermediate,
// DivergentPointer formed from a base pointer and per-lane offset.
// Base pointer held by SpirvRoutine::pointers
// Per-lane offset held by SpirvRoutine::intermediates.
DivergentPointer,
// Pointer with uniform address across all lanes.
// Pointer held by SpirvRoutine::pointers
NonDivergentPointer,
} kind = Kind::Unknown;
};
......@@ -539,7 +558,15 @@ namespace sw
void ProcessInterfaceVariable(Object &object);
SIMD::Int WalkExplicitLayoutAccessChain(Object::ID id, uint32_t numIndexes, uint32_t const *indexIds, SpirvRoutine *routine) const;
// Returns a base pointer and per-lane offset to the underlying data for
// the given pointer object. Handles objects of the following kinds:
// • DivergentPointer
// • InterfaceVariable
// • NonDivergentPointer
// Calling GetPointerToData with objects of any other kind will assert.
std::pair<Pointer<Byte>, SIMD::Int> GetPointerToData(Object::ID id, int arrayIndex, SpirvRoutine *routine) const;
std::pair<Pointer<Byte>, SIMD::Int> WalkExplicitLayoutAccessChain(Object::ID id, uint32_t numIndexes, uint32_t const *indexIds, SpirvRoutine *routine) const;
SIMD::Int WalkAccessChain(Object::ID id, uint32_t numIndexes, uint32_t const *indexIds, SpirvRoutine *routine) const;
uint32_t WalkLiteralAccessChain(Type::ID id, uint32_t numIndexes, uint32_t const *indexes) const;
......@@ -655,7 +682,7 @@ namespace sw
std::unordered_map<SpirvShader::Object::ID, Intermediate> intermediates;
std::unordered_map<SpirvShader::Object::ID, Pointer<Byte> > physicalPointers;
std::unordered_map<SpirvShader::Object::ID, Pointer<Byte> > pointers;
Variable inputs = Variable{MAX_INTERFACE_COMPONENTS};
Variable outputs = Variable{MAX_INTERFACE_COMPONENTS};
......@@ -671,6 +698,25 @@ namespace sw
ASSERT_MSG(added, "Variable %d created twice", id.value());
}
template <typename T>
void createPointer(SpirvShader::Object::ID id, Pointer<T> ptrBase)
{
bool added = pointers.emplace(id, ptrBase).second;
ASSERT_MSG(added, "Pointer %d created twice", id.value());
}
template <typename T>
void createPointer(SpirvShader::Object::ID id, RValue<Pointer<T>> ptrBase)
{
createPointer(id, Pointer<T>(ptrBase));
}
template <typename T>
void createPointer(SpirvShader::Object::ID id, Reference<Pointer<T>> ptrBase)
{
createPointer(id, Pointer<T>(ptrBase));
}
Intermediate& createIntermediate(SpirvShader::Object::ID id, uint32_t size)
{
auto it = intermediates.emplace(std::piecewise_construct,
......@@ -694,10 +740,10 @@ namespace sw
return it->second;
}
Pointer<Byte>& getPhysicalPointer(SpirvShader::Object::ID id)
Pointer<Byte>& getPointer(SpirvShader::Object::ID id)
{
auto it = physicalPointers.find(id);
ASSERT_MSG(it != physicalPointers.end(), "Unknown physical pointer %d", id.value());
auto it = pointers.find(id);
ASSERT_MSG(it != pointers.end(), "Unknown pointer %d", id.value());
return it->second;
}
};
......
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