OSDN Git Service

Implement some common forms of OpLoad
authorChris Forbes <chrisforbes@google.com>
Mon, 11 Feb 2019 00:20:16 +0000 (00:20 +0000)
committerChris Forbes <chrisforbes@google.com>
Fri, 15 Feb 2019 19:32:32 +0000 (19:32 +0000)
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>

src/Pipeline/SpirvShader.cpp
src/Pipeline/SpirvShader.hpp

index 86c1a20..3b2fac8 100644 (file)
@@ -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;
index 1419004..ec8f308 100644 (file)
@@ -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