Implement some common forms of OpAccessChain
Bug: b/124388146
Change-Id: I948ad5607c1e41be920006aaa4b7d18d210af4a3
Reviewed-on: https://swiftshader-review.googlesource.com/c/24790
Tested-by: Chris Forbes <chrisforbes@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index cdd3a63..aa48093 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -487,6 +487,56 @@
VisitInterfaceInner<F>(def.word(1), d, f);
}
+ Int4 SpirvShader::WalkAccessChain(uint32_t id, uint32_t numIndexes, uint32_t const *indexIds, SpirvRoutine *routine) const
+ {
+ // TODO: think about decorations, to make this work on location based interfaces
+ // TODO: think about explicit layout (UBO/SSBO) storage classes
+ // TODO: avoid doing per-lane work in some cases if we can?
+
+ Int4 res = Int4(0);
+ auto & baseObject = getObject(id);
+ auto typeId = baseObject.definition.word(1);
+
+ if (baseObject.kind == Object::Kind::Value)
+ res += As<Int4>((*routine->lvalues[id])[0]);
+
+ for (auto i = 0u; i < numIndexes; i++)
+ {
+ auto & type = getType(typeId);
+ switch (type.definition.opcode())
+ {
+ case spv::OpTypeStruct:
+ {
+ int memberIndex = GetConstantInt(indexIds[i]);
+ int offsetIntoStruct = 0;
+ for (auto j = 0; j < memberIndex; j++) {
+ offsetIntoStruct += getType(type.definition.word(2 + memberIndex)).sizeInComponents;
+ }
+ res += Int4(offsetIntoStruct);
+ break;
+ }
+
+ case spv::OpTypeVector:
+ case spv::OpTypeMatrix:
+ case spv::OpTypeArray:
+ {
+ auto stride = getType(type.definition.word(2)).sizeInComponents;
+ auto & obj = getObject(indexIds[i]);
+ if (obj.kind == Object::Kind::Constant)
+ res += Int4(stride * GetConstantInt(indexIds[i]));
+ else
+ res += Int4(stride) * As<Int4>((*(routine->lvalues)[indexIds[i]])[0]);
+ break;
+ }
+
+ default:
+ UNIMPLEMENTED("Unexpected type in WalkAccessChain");
+ }
+ }
+
+ return res;
+ }
+
void SpirvShader::Decorations::Apply(spv::Decoration decoration, uint32_t arg)
{
switch (decoration)
@@ -660,6 +710,32 @@
}
break;
}
+ case spv::OpAccessChain:
+ {
+ auto &object = getObject(insn.word(2));
+ auto &type = getType(insn.word(1));
+ auto &base = getObject(insn.word(3));
+ routine->createLvalue(insn.word(2), type.sizeInComponents); // TODO: this should be an ssavalue!
+ auto &pointerBase = getObject(object.pointerBase);
+ assert(type.sizeInComponents == 1);
+ assert(base.pointerBase == object.pointerBase);
+
+ if (pointerBase.kind == Object::Kind::InterfaceVariable)
+ {
+ UNIMPLEMENTED("Location-based OpAccessChain not yet implemented");
+ }
+
+ if (pointerBase.storageClass == spv::StorageClassImage ||
+ pointerBase.storageClass == spv::StorageClassUniform ||
+ pointerBase.storageClass == spv::StorageClassUniformConstant)
+ {
+ UNIMPLEMENTED("Descriptor-backed OpAccessChain not yet implemented");
+ }
+
+ auto & dst = *(routine->lvalues)[insn.word(2)];
+ dst[0] = As<Float4>(WalkAccessChain(insn.word(3), insn.wordCount() - 4, insn.wordPointer(4), routine));
+ break;
+ }
case spv::OpStore:
{
auto &object = getObject(insn.word(2));