Commit e9f8f5b1 by Chris Forbes

Implement some common forms of OpLoad

Bug: b/124388146 Change-Id: I79b4c3bc59631332f4748394a166612ad5d975de Reviewed-on: https://swiftshader-review.googlesource.com/c/24600Reviewed-by: 's avatarBen Clayton <bclayton@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Tested-by: 's avatarChris Forbes <chrisforbes@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
parent b8fb08a7
......@@ -166,6 +166,7 @@ namespace sw
// 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 @@ namespace sw
// 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 @@ namespace sw
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 @@ namespace sw
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;
......
......@@ -33,9 +33,15 @@ namespace sw
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
......
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