SPV arrays: Add support for runtime-sized array types and arrays of arrays.
authorJohn Kessenich <cepheus@frii.com>
Sat, 12 Sep 2015 18:17:44 +0000 (12:17 -0600)
committerJohn Kessenich <cepheus@frii.com>
Sun, 13 Sep 2015 16:18:19 +0000 (10:18 -0600)
This includes run-time block.member.length() (OpArrayLength).

SPIRV/GlslangToSpv.cpp
SPIRV/SpvBuilder.cpp
SPIRV/SpvBuilder.h
Test/baseResults/spv.310.comp.out
Test/baseResults/spv.AofA.frag.out [new file with mode: 0644]
Test/spv.310.comp
Test/spv.AofA.frag [new file with mode: 0644]
Test/test-spirv-list
glslang/Include/revision.h

index cc02738..4c7c17c 100755 (executable)
@@ -680,6 +680,24 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
     }
 
     // Non-texturing.
+
+    if (node->getOp() == glslang::EOpArrayLength) {
+        // Quite special; won't want to evaluate the operand.
+
+        // Normal .length() would have been constant folded by the front-end.
+        // So, this has to be block.lastMember.length().
+        // SPV wants "block" as the operand, go get it.
+        assert(node->getOperand()->getType().isRuntimeSizedArray());
+        glslang::TIntermTyped* block = node->getOperand()->getAsBinaryNode()->getLeft();
+        block->traverse(this);
+        spv::Id length = builder.createUnaryOp(spv::OpArrayLength, builder.makeIntType(32), builder.accessChainGetLValue());
+
+        builder.clearAccessChain();
+        builder.setAccessChainRValue(length);
+
+        return false;
+    }
+
     // Start by evaluating the operand
 
     builder.clearAccessChain();
@@ -967,17 +985,6 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
         // which can be emitted by the one in createBinaryOperation()
         binOp = glslang::EOpMod;
         break;
-    case glslang::EOpArrayLength:
-    {
-        glslang::TIntermTyped* typedNode = node->getSequence()[0]->getAsTyped();
-        assert(typedNode);
-        spv::Id length = builder.makeIntConstant(typedNode->getType().getOuterArraySize());
-
-        builder.clearAccessChain();
-        builder.setAccessChainRValue(length);
-
-        return false;
-    }
     case glslang::EOpEmitVertex:
     case glslang::EOpEndPrimitive:
     case glslang::EOpBarrier:
@@ -1468,14 +1475,23 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
     }
 
     if (type.isArray()) {
-        unsigned arraySize;
-        if (! type.isExplicitlySizedArray()) {
-            spv::MissingFunctionality("Unsized array");
-            arraySize = 8;
-        } else
-            arraySize = type.getOuterArraySize();
-        spvType = builder.makeArrayType(spvType, arraySize);
+        // Do all but the outer dimension
+        for (int dim = type.getArraySizes()->getNumDims() - 1; dim > 0; --dim) {
+            assert(type.getArraySizes()->getDimSize(dim) > 0);
+            spvType = builder.makeArrayType(spvType, type.getArraySizes()->getDimSize(dim));
+        }
+
+        // Do the outer dimension, which might not be known for a runtime-sized array
+        if (type.isRuntimeSizedArray()) {
+            spvType = builder.makeRuntimeArray(spvType);
+        } else {
+            assert(type.getOuterArraySize() > 0);
+            spvType = builder.makeArrayType(spvType, type.getOuterArraySize());
+        }
 
+        // TODO: layout still needs to be done hierarchically for arrays of arrays, which 
+        // may still require additional "link time" support from the front-end 
+        // for arrays of arrays
         if (explicitLayout)
             builder.addDecoration(spvType, spv::DecorationArrayStride, getArrayStride(type));
     }
index f544f21..953b604 100755 (executable)
@@ -264,6 +264,16 @@ Id Builder::makeArrayType(Id element, unsigned size)
     return type->getResultId();
 }
 
+Id Builder::makeRuntimeArray(Id element)
+{
+    Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeRuntimeArray);
+    type->addIdOperand(element);
+    constantsTypesGlobals.push_back(type);
+    module.mapInstruction(type);
+
+    return type->getResultId();
+}
+
 Id Builder::makeFunctionType(Id returnType, std::vector<Id>& paramTypes)
 {
     // try to find it
@@ -280,7 +290,7 @@ Id Builder::makeFunctionType(Id returnType, std::vector<Id>& paramTypes)
             }
         }
         if (! mismatch)
-            return type->getResultId();            
+            return type->getResultId();
     }
 
     // not found, make it
index de9686c..1ceb9c6 100755 (executable)
@@ -102,6 +102,7 @@ public:
     Id makeVectorType(Id component, int size);
     Id makeMatrixType(Id component, int cols, int rows);
     Id makeArrayType(Id element, unsigned size);
+    Id makeRuntimeArray(Id element);
     Id makeFunctionType(Id returnType, std::vector<Id>& paramTypes);
     Id makeImageType(Id sampledType, Dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format);
     Id makeSampledImageType(Id imageType);
index d1f8a9a..9fbb2d5 100644 (file)
@@ -5,4 +5,121 @@ Warning, version 310 is not yet complete; most version-specific features are pre
 Linked compute stage:\r
 \r
 \r
-Missing functionality: Unsized array\r
+// Module Version 99\r
+// Generated by (magic number): 51a00bb\r
+// Id's are bound by 72\r
+\r
+                              Source ESSL 310\r
+                              Capability Shader\r
+               1:             ExtInstImport  "GLSL.std.450"\r
+                              MemoryModel Logical GLSL450\r
+                              EntryPoint GLCompute 4  "main"\r
+                              Name 4  "main"\r
+                              Name 14  "outb"\r
+                              MemberName 14(outb) 0  "f"\r
+                              MemberName 14(outb) 1  "g"\r
+                              MemberName 14(outb) 2  "h"\r
+                              MemberName 14(outb) 3  "uns"\r
+                              Name 16  "outbname"\r
+                              Name 20  "s"\r
+                              Name 25  "outbna"\r
+                              MemberName 25(outbna) 0  "k"\r
+                              MemberName 25(outbna) 1  "na"\r
+                              Name 27  "outbnamena"\r
+                              Name 47  "i"\r
+                              Name 53  "outs"\r
+                              MemberName 53(outs) 0  "s"\r
+                              MemberName 53(outs) 1  "va"\r
+                              Name 55  "outnames"\r
+                              Name 59  "gl_LocalInvocationID"\r
+                              Decorate 14(outb) GLSLShared\r
+                              Decorate 14(outb) BufferBlock\r
+                              Decorate 25(outbna) GLSLShared\r
+                              Decorate 25(outbna) BufferBlock\r
+                              Decorate 53(outs) GLSLShared\r
+                              Decorate 53(outs) BufferBlock\r
+                              Decorate 59(gl_LocalInvocationID) BuiltIn LocalInvocationId\r
+                              Decorate 71 BuiltIn WorkgroupSize\r
+                              Decorate 71 NoStaticUse\r
+               2:             TypeVoid\r
+               3:             TypeFunction 2\r
+               7:             TypeInt 32 0\r
+               8:      7(int) Constant 1\r
+               9:      7(int) Constant 1023\r
+              10:      7(int) Constant 0\r
+              11:             TypeFloat 32\r
+              12:             TypeVector 11(float) 3\r
+              13:             TypeRuntimeArray 12(fvec3)\r
+        14(outb):             TypeStruct 11(float) 11(float) 11(float) 13\r
+              15:             TypePointer Uniform 14(outb)\r
+    16(outbname):     15(ptr) Variable Uniform\r
+              17:             TypeInt 32 1\r
+              18:     17(int) Constant 0\r
+              19:             TypePointer WorkgroupLocal 11(float)\r
+           20(s):     19(ptr) Variable WorkgroupLocal\r
+              22:             TypePointer Uniform 11(float)\r
+              24:             TypeVector 11(float) 4\r
+      25(outbna):             TypeStruct 17(int) 24(fvec4)\r
+              26:             TypePointer Uniform 25(outbna)\r
+  27(outbnamena):     26(ptr) Variable Uniform\r
+              28:     17(int) Constant 1\r
+              31:             TypePointer Uniform 24(fvec4)\r
+              33:             TypeRuntimeArray 12(fvec3)\r
+              34:     17(int) Constant 3\r
+              35:     17(int) Constant 18\r
+              36:             TypePointer Uniform 12(fvec3)\r
+              40:             TypeRuntimeArray 12(fvec3)\r
+              41:     17(int) Constant 17\r
+              42:   11(float) Constant 1077936128\r
+              43:   12(fvec3) ConstantComposite 42 42 42\r
+              45:             TypeRuntimeArray 12(fvec3)\r
+              46:             TypePointer WorkgroupLocal 17(int)\r
+           47(i):     46(ptr) Variable WorkgroupLocal\r
+              52:             TypeRuntimeArray 24(fvec4)\r
+        53(outs):             TypeStruct 17(int) 52\r
+              54:             TypePointer Uniform 53(outs)\r
+    55(outnames):     54(ptr) Variable Uniform\r
+              56:             TypeRuntimeArray 24(fvec4)\r
+              57:             TypeVector 7(int) 3\r
+              58:             TypePointer Input 57(ivec3)\r
+59(gl_LocalInvocationID):     58(ptr) Variable Input\r
+              66:             TypePointer Uniform 17(int)\r
+              68:      7(int) Constant 16\r
+              69:      7(int) Constant 32\r
+              70:      7(int) Constant 4\r
+              71:   57(ivec3) ConstantComposite 68 69 70\r
+         4(main):           2 Function None 3\r
+               5:             Label\r
+                              MemoryBarrier 8 9\r
+                              ControlBarrier 8 8 10\r
+              21:   11(float) Load 20(s)\r
+              23:     22(ptr) AccessChain 16(outbname) 18\r
+                              Store 23 21\r
+              29:   11(float) Load 20(s)\r
+              30:   24(fvec4) CompositeConstruct 29 29 29 29\r
+              32:     31(ptr) AccessChain 27(outbnamena) 28\r
+                              Store 32 30\r
+              37:     36(ptr) AccessChain 16(outbname) 34 35\r
+              38:   12(fvec3) Load 37\r
+              39:   11(float) CompositeExtract 38 0\r
+                              Store 20(s) 39\r
+              44:     36(ptr) AccessChain 16(outbname) 34 41\r
+                              Store 44 43\r
+              48:     17(int) Load 47(i)\r
+              49:   11(float) Load 20(s)\r
+              50:   12(fvec3) CompositeConstruct 49 49 49\r
+              51:     36(ptr) AccessChain 16(outbname) 34 48\r
+                              Store 51 50\r
+              60:   57(ivec3) Load 59(gl_LocalInvocationID)\r
+              61:      7(int) CompositeExtract 60 0\r
+              62:   11(float) Load 20(s)\r
+              63:   24(fvec4) CompositeConstruct 62 62 62 62\r
+              64:     31(ptr) AccessChain 55(outnames) 28 61\r
+                              Store 64 63\r
+              65:     17(int) ArrayLength 16(outbname)\r
+              67:     66(ptr) AccessChain 55(outnames) 18\r
+                              Store 67 65\r
+                              Branch 6\r
+               6:             Label\r
+                              Return\r
+                              FunctionEnd\r
diff --git a/Test/baseResults/spv.AofA.frag.out b/Test/baseResults/spv.AofA.frag.out
new file mode 100644 (file)
index 0000000..bda0df3
--- /dev/null
@@ -0,0 +1,154 @@
+spv.AofA.frag\r
+Warning, version 430 is not yet complete; most version-specific features are present, but some are missing.\r
+\r
+\r
+Linked fragment stage:\r
+\r
+\r
+// Module Version 99\r
+// Generated by (magic number): 51a00bb\r
+// Id's are bound by 104\r
+\r
+                              Source GLSL 430\r
+                              Capability Shader\r
+               1:             ExtInstImport  "GLSL.std.450"\r
+                              MemoryModel Logical GLSL450\r
+                              EntryPoint Fragment 4  "main"\r
+                              ExecutionMode 4 OriginLowerLeft\r
+                              Name 4  "main"\r
+                              Name 18  "foo(f1[5][7];"\r
+                              Name 17  "a"\r
+                              Name 21  "r"\r
+                              Name 39  "outfloat"\r
+                              Name 42  "g4"\r
+                              Name 44  "g5"\r
+                              Name 45  "param"\r
+                              Name 48  "u"\r
+                              Name 52  "param"\r
+                              Name 66  "many"\r
+                              Name 68  "i"\r
+                              Name 70  "j"\r
+                              Name 72  "k"\r
+                              Name 78  "infloat"\r
+                              Name 94  "uAofA"\r
+                              MemberName 94(uAofA) 0  "f"\r
+                              Name 98  "nameAofA"\r
+                              Decorate 44(g5) Smooth\r
+                              Decorate 78(infloat) Smooth\r
+                              Decorate 94(uAofA) GLSLShared\r
+                              Decorate 94(uAofA) Block\r
+               2:             TypeVoid\r
+               3:             TypeFunction 2\r
+               7:             TypeFloat 32\r
+               8:             TypeInt 32 0\r
+               9:      8(int) Constant 7\r
+              10:             TypeArray 7(float) 9\r
+              11:      8(int) Constant 5\r
+              12:             TypeArray 10 11\r
+              13:             TypePointer Function 12\r
+              14:      8(int) Constant 4\r
+              15:             TypeArray 10 14\r
+              16:             TypeFunction 15 13(ptr)\r
+              20:             TypePointer Function 10\r
+              22:             TypeInt 32 1\r
+              23:     22(int) Constant 2\r
+              26:     22(int) Constant 0\r
+              29:     22(int) Constant 1\r
+              33:     22(int) Constant 3\r
+              38:             TypePointer Output 7(float)\r
+    39(outfloat):     38(ptr) Variable Output\r
+              40:    7(float) Constant 0\r
+              41:             TypePointer PrivateGlobal 15\r
+          42(g4):     41(ptr) Variable PrivateGlobal\r
+              43:             TypePointer Input 12\r
+          44(g5):     43(ptr) Variable Input\r
+              49:    7(float) Constant 1077936128\r
+              50:             TypePointer Function 7(float)\r
+              55:      8(int) Constant 6\r
+              56:             TypeArray 7(float) 55\r
+              57:             TypeArray 56 11\r
+              58:             TypeArray 57 14\r
+              59:      8(int) Constant 3\r
+              60:             TypeArray 58 59\r
+              61:      8(int) Constant 2\r
+              62:             TypeArray 60 61\r
+              63:      8(int) Constant 1\r
+              64:             TypeArray 62 63\r
+              65:             TypePointer PrivateGlobal 64\r
+        66(many):     65(ptr) Variable PrivateGlobal\r
+              67:             TypePointer UniformConstant 22(int)\r
+           68(i):     67(ptr) Variable UniformConstant\r
+           70(j):     67(ptr) Variable UniformConstant\r
+           72(k):     67(ptr) Variable UniformConstant\r
+              77:             TypePointer Input 7(float)\r
+     78(infloat):     77(ptr) Variable Input\r
+              80:             TypePointer PrivateGlobal 7(float)\r
+              92:             TypeArray 7(float) 14\r
+              93:             TypeArray 92 61\r
+       94(uAofA):             TypeStruct 93\r
+              95:             TypeArray 94(uAofA) 11\r
+              96:             TypeArray 95 59\r
+              97:             TypePointer Uniform 96\r
+    98(nameAofA):     97(ptr) Variable Uniform\r
+              99:             TypePointer Uniform 7(float)\r
+         4(main):           2 Function None 3\r
+               5:             Label\r
+       45(param):     13(ptr) Variable Function\r
+           48(u):     13(ptr) Variable Function\r
+       52(param):     13(ptr) Variable Function\r
+                              Store 39(outfloat) 40\r
+              46:          12 Load 44(g5)\r
+                              Store 45(param) 46\r
+              47:          15 FunctionCall 18(foo(f1[5][7];) 45(param)\r
+                              Store 42(g4) 47\r
+              51:     50(ptr) AccessChain 48(u) 23 23\r
+                              Store 51 49\r
+              53:          12 Load 48(u)\r
+                              Store 52(param) 53\r
+              54:          15 FunctionCall 18(foo(f1[5][7];) 52(param)\r
+              69:     22(int) Load 68(i)\r
+              71:     22(int) Load 70(j)\r
+              73:     22(int) Load 72(k)\r
+              74:     22(int) Load 68(i)\r
+              75:     22(int) Load 70(j)\r
+              76:     22(int) Load 72(k)\r
+              79:    7(float) Load 78(infloat)\r
+              81:     80(ptr) AccessChain 66(many) 69 71 73 74 75 76\r
+                              Store 81 79\r
+              82:     22(int) Load 70(j)\r
+              83:     22(int) Load 70(j)\r
+              84:     22(int) Load 70(j)\r
+              85:     22(int) Load 70(j)\r
+              86:     22(int) Load 70(j)\r
+              87:     22(int) Load 70(j)\r
+              88:     80(ptr) AccessChain 66(many) 82 83 84 85 86 87\r
+              89:    7(float) Load 88\r
+              90:    7(float) Load 39(outfloat)\r
+              91:    7(float) FAdd 90 89\r
+                              Store 39(outfloat) 91\r
+             100:     99(ptr) AccessChain 98(nameAofA) 29 23 26 26 33\r
+             101:    7(float) Load 100\r
+             102:    7(float) Load 39(outfloat)\r
+             103:    7(float) FAdd 102 101\r
+                              Store 39(outfloat) 103\r
+                              Branch 6\r
+               6:             Label\r
+                              Return\r
+                              FunctionEnd\r
+18(foo(f1[5][7];):          15 Function None 16\r
+           17(a):     13(ptr) FunctionParameter\r
+              19:             Label\r
+           21(r):     20(ptr) Variable Function\r
+              24:     20(ptr) AccessChain 17(a) 23\r
+              25:          10 Load 24\r
+                              Store 21(r) 25\r
+              27:     20(ptr) AccessChain 17(a) 26\r
+              28:          10 Load 27\r
+              30:     20(ptr) AccessChain 17(a) 29\r
+              31:          10 Load 30\r
+              32:          10 Load 21(r)\r
+              34:     20(ptr) AccessChain 17(a) 33\r
+              35:          10 Load 34\r
+              36:          15 CompositeConstruct 28 31 32 35\r
+                              ReturnValue 36\r
+                              FunctionEnd\r
index 4511636..bd183e0 100644 (file)
@@ -11,9 +11,7 @@ buffer outb {
     float f;
     float g;
     float h;
-    vec3 uns[];  // this makes it look like the "second" set of 3 floats in a struct, which LLVM
-                 // takes advantage of when optimizing, giving confusing results, like thinking
-                 // &outbname.uns[18].x == &outbname[9].uns.x
+    vec3 uns[];
 } outbname;
 
 buffer outbna {
@@ -22,6 +20,7 @@ buffer outbna {
 } outbnamena;
 
 buffer outs {
+    int s;
     vec4 va[];
 } outnames;
 
@@ -30,8 +29,9 @@ void main()
     barrier();
     outbname.f = s;
     outbnamena.na = vec4(s);
-    s = outbname.uns[18].x;           // TODO: see note above
-    //outbname.uns[17] = vec3(3.0);   // TODO: see note above, this one bitcasts, which isn't handled
+    s = outbname.uns[18].x;
+    outbname.uns[17] = vec3(3.0);
     outbname.uns[i] = vec3(s);
     outnames.va[gl_LocalInvocationID.x] = vec4(s);
+    outnames.s = outbname.uns.length();
 }
diff --git a/Test/spv.AofA.frag b/Test/spv.AofA.frag
new file mode 100644 (file)
index 0000000..606d73b
--- /dev/null
@@ -0,0 +1,43 @@
+#version 430\r
+\r
+in float infloat;\r
+out float outfloat;\r
+\r
+uniform uAofA {\r
+    float f[2][4];\r
+} nameAofA[3][5];\r
+\r
+float[4][5][6] many[1][2][3];\r
+\r
+float g4[4][7];\r
+in float g5[5][7];\r
+\r
+uniform int i, j, k;\r
+\r
+float[4][7] foo(float a[5][7])\r
+{\r
+    float r[7];\r
+    r = a[2];\r
+\r
+    return float[4][7](a[0], a[1], r, a[3]);\r
+}\r
+\r
+void main()\r
+{\r
+    outfloat = 0.0;\r
+\r
+    g4 = foo(g5);\r
+\r
+//    if (foo(g5) == g4)\r
+//        ++outfloat;\r
+\r
+    float u[][7];\r
+    u[2][2] = 3.0;\r
+    float u[5][7];\r
+\r
+    foo(u);\r
+\r
+    many[i][j][k][i][j][k] = infloat;\r
+    outfloat += many[j][j][j][j][j][j];\r
+    outfloat += nameAofA[1][2].f[0][3];\r
+}\r
index ccfa068..a7d8c8d 100644 (file)
@@ -79,3 +79,4 @@ spv.varyingArrayIndirect.frag
 spv.voidFunction.frag
 spv.whileLoop.frag
 spv.atomic.comp
+spv.AofA.frag
index abb7f13..cd2e547 100644 (file)
@@ -2,5 +2,5 @@
 // For the version, it uses the latest git tag followed by the number of commits.
 // For the date, it uses the current date (when then script is run).
 
-#define GLSLANG_REVISION "3.0.748"
-#define GLSLANG_DATE "11-Sep-2015"
+#define GLSLANG_REVISION "3.0.750"
+#define GLSLANG_DATE "13-Sep-2015"