Implement some common forms of OpLoad Bug: b/124388146 Change-Id: I79b4c3bc59631332f4748394a166612ad5d975de Reviewed-on: https://swiftshader-review.googlesource.com/c/24600 Reviewed-by: Ben Clayton <bclayton@google.com> Reviewed-by: Nicolas Capens <nicolascapens@google.com> Tested-by: Chris Forbes <chrisforbes@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp index 86c1a20..3b2fac8 100644 --- a/src/Pipeline/SpirvShader.cpp +++ b/src/Pipeline/SpirvShader.cpp
@@ -166,6 +166,7 @@ // OpVariable's "size" is the size of the allocation required (the size of the pointee) object.sizeInComponents = pointeeType.sizeInComponents; object.isBuiltInBlock = type.isBuiltInBlock; + object.pointerBase = insn.word(2); // base is itself // Register builtins @@ -233,7 +234,7 @@ // interior ptr has two parts: // - logical base ptr, common across all lanes and known at compile time // - per-lane offset - object.pointerBase = insn.word(3); + object.pointerBase = getObject(insn.word(3)).pointerBase; } break; } @@ -597,13 +598,12 @@ if (object.kind != Object::Kind::InterfaceVariable && object.sizeInComponents > 0) { // any variable not in a location-oriented interface - routine->lvalues.emplace(insn.word(2), std::unique_ptr<Array<Float4>>( - new Array<Float4>(object.sizeInComponents))); + routine->createLvalue(insn.word(2), object.sizeInComponents); } break; } default: - printf("emitEarly: ignoring opcode %d\n", insn.opcode()); + // Nothing else produces interface variables, so can all be safely ignored. break; } } @@ -611,12 +611,55 @@ void SpirvShader::emit(SpirvRoutine *routine) const { - (void) routine; - for (auto insn : *this) { switch (insn.opcode()) { + case spv::OpLoad: + { + auto &object = getObject(insn.word(2)); + auto &type = getType(insn.word(1)); + auto &pointer = getObject(insn.word(3)); + routine->createLvalue(insn.word(2), type.sizeInComponents); // TODO: this should be an ssavalue! + auto &pointerBase = getObject(pointer.pointerBase); + + if (pointerBase.kind == Object::Kind::InterfaceVariable) + { + UNIMPLEMENTED("Location-based load not yet implemented"); + } + + if (pointerBase.storageClass == spv::StorageClassImage || + pointerBase.storageClass == spv::StorageClassUniform || + pointerBase.storageClass == spv::StorageClassUniformConstant) + { + UNIMPLEMENTED("Descriptor-backed load not yet implemented"); + } + + SpirvRoutine::Value& ptrBase = *(routine->lvalues)[pointer.pointerBase]; + auto & dst = *(routine->lvalues)[insn.word(2)]; + + if (pointer.kind == Object::Kind::Value) + { + auto offsets = As<Int4>(*(routine->lvalues)[insn.word(3)]); + for (auto i = 0u; i < object.sizeInComponents; i++) + { + // i wish i had a Float,Float,Float,Float constructor here.. + Float4 v; + for (int j = 0; j < 4; j++) + v = Insert(v, Extract(ptrBase[Int(i) + Extract(offsets, j)], j), j); + dst[i] = v; + } + } + else + { + // no divergent offsets to worry about + for (auto i = 0u; i < object.sizeInComponents; i++) + { + dst[i] = ptrBase[i]; + } + } + break; + } default: printf("emit: ignoring opcode %d\n", insn.opcode()); break;
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp index 1419004..ec8f308 100644 --- a/src/Pipeline/SpirvShader.hpp +++ b/src/Pipeline/SpirvShader.hpp
@@ -33,9 +33,15 @@ class SpirvRoutine { public: - std::unordered_map<uint32_t, std::unique_ptr<Array<Float4>>> lvalues; - std::unique_ptr<Array<Float4>> inputs = std::unique_ptr<Array<Float4>>(new Array<Float4>(MAX_INTERFACE_COMPONENTS)); - std::unique_ptr<Array<Float4>> outputs = std::unique_ptr<Array<Float4>>(new Array<Float4>(MAX_INTERFACE_COMPONENTS)); + using Value = Array<Float4>; + std::unordered_map<uint32_t, std::unique_ptr<Value>> lvalues; + std::unique_ptr<Value> inputs = std::unique_ptr<Value>(new Value(MAX_INTERFACE_COMPONENTS)); + std::unique_ptr<Value> outputs = std::unique_ptr<Value>(new Value(MAX_INTERFACE_COMPONENTS)); + + void createLvalue(uint32_t id, uint32_t size) + { + lvalues.emplace(id, std::unique_ptr<Value>(new Value(size))); + } }; class SpirvShader