SPV 1.4: Lookup tables: Use variable initializer and NonWritable...
authorJohn Kessenich <cepheus@frii.com>
Thu, 7 Feb 2019 15:04:12 +0000 (08:04 -0700)
committerJohn Kessenich <cepheus@frii.com>
Fri, 10 May 2019 06:02:45 +0000 (00:02 -0600)
...when doing a variable lookup on an array of constants.

SPIRV/GlslangToSpv.cpp
SPIRV/SpvBuilder.cpp
SPIRV/SpvBuilder.h
Test/baseResults/spv.1.4.NonWritable.frag.out [new file with mode: 0755]
Test/spv.1.4.NonWritable.frag [new file with mode: 0755]
gtests/Spv.FromFile.cpp

index c12f5bf..f5cbb88 100644 (file)
@@ -1711,6 +1711,7 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
     case glslang::EOpIndexDirect:
     case glslang::EOpIndexDirectStruct:
         {
+            // Structure, array, matrix, or vector indirection with statically known index.
             // Get the left part of the access chain.
             node->getLeft()->traverse(this);
 
@@ -1765,8 +1766,8 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
         return false;
     case glslang::EOpIndexIndirect:
         {
-            // Structure or array or vector indirection.
-            // Will use native SPIR-V access-chain for struct and array indirection;
+            // Array, matrix, or vector indirection with variable index.
+            // Will use native SPIR-V access-chain for and array indirection;
             // matrices are arrays of vectors, so will also work for a matrix.
             // Will use the access chain's 'component' for variable index into a vector.
 
index 6eb18d0..773e5f1 100644 (file)
@@ -1306,11 +1306,13 @@ void Builder::makeDiscard()
 }
 
 // Comments in header
-Id Builder::createVariable(StorageClass storageClass, Id type, const char* name)
+Id Builder::createVariable(StorageClass storageClass, Id type, const char* name, Id initializer)
 {
     Id pointerType = makePointer(storageClass, type);
     Instruction* inst = new Instruction(getUniqueId(), pointerType, OpVariable);
     inst->addImmediateOperand(storageClass);
+    if (initializer != NoResult)
+        inst->addIdOperand(initializer);
 
     switch (storageClass) {
     case StorageClassFunction:
@@ -2649,12 +2651,19 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
             if (constant) {
                 id = createCompositeExtract(accessChain.base, swizzleBase, indexes);
             } else {
-                // make a new function variable for this r-value
-                Id lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable");
-
-                // store into it
-                createStore(accessChain.base, lValue);
-
+                Id lValue = NoResult;
+                if (spvVersion >= Spv_1_4) {
+                    // make a new function variable for this r-value, using an initializer,
+                    // and mark it as NonWritable so that downstream it can be detected as a lookup
+                    // table
+                    lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable",
+                        accessChain.base);
+                    addDecoration(lValue, DecorationNonWritable);
+                } else {
+                    lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable");
+                    // store into it
+                    createStore(accessChain.base, lValue);
+                }
                 // move base to the new variable
                 accessChain.base = lValue;
                 accessChain.isRValue = false;
index 72018a3..aee9781 100644 (file)
 
 namespace spv {
 
+typedef enum {
+    Spv_1_0 = (1 << 16),
+    Spv_1_1 = (1 << 16) | (1 << 8),
+    Spv_1_2 = (1 << 16) | (2 << 8),
+    Spv_1_3 = (1 << 16) | (3 << 8),
+    Spv_1_4 = (1 << 16) | (4 << 8),
+} SpvVersion;
+
 class Builder {
 public:
     Builder(unsigned int spvVersion, unsigned int userNumber, SpvBuildLogger* logger);
@@ -300,7 +308,7 @@ public:
     void makeDiscard();
 
     // Create a global or function local or IO variable.
-    Id createVariable(StorageClass, Id type, const char* name = 0);
+    Id createVariable(StorageClass, Id type, const char* name = 0, Id initializer = NoResult);
 
     // Create an intermediate with an undefined value.
     Id createUndefined(Id type);
diff --git a/Test/baseResults/spv.1.4.NonWritable.frag.out b/Test/baseResults/spv.1.4.NonWritable.frag.out
new file mode 100755 (executable)
index 0000000..4f92426
--- /dev/null
@@ -0,0 +1,59 @@
+spv.1.4.NonWritable.frag
+Validation failed
+// Module Version 10400
+// Generated by (magic number): 80007
+// Id's are bound by 38
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main" 8 31
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 450
+                              Name 4  "main"
+                              Name 8  "color"
+                              Name 31  "index"
+                              Name 34  "indexable"
+                              Decorate 8(color) Location 0
+                              Decorate 31(index) Flat
+                              Decorate 31(index) Location 0
+                              Decorate 34(indexable) NonWritable
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypePointer Output 6(float)
+        8(color):      7(ptr) Variable Output
+               9:             TypeInt 32 0
+              10:      9(int) Constant 16
+              11:             TypeArray 6(float) 10
+              12:    6(float) Constant 1065353216
+              13:    6(float) Constant 1073741824
+              14:    6(float) Constant 1077936128
+              15:    6(float) Constant 1082130432
+              16:    6(float) Constant 1084227584
+              17:    6(float) Constant 1086324736
+              18:    6(float) Constant 1088421888
+              19:    6(float) Constant 1090519040
+              20:    6(float) Constant 1091567616
+              21:    6(float) Constant 1092616192
+              22:    6(float) Constant 1093664768
+              23:    6(float) Constant 1094713344
+              24:    6(float) Constant 1095761920
+              25:    6(float) Constant 1096810496
+              26:    6(float) Constant 1097859072
+              27:    6(float) Constant 1098907648
+              28:          11 ConstantComposite 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
+              29:             TypeInt 32 1
+              30:             TypePointer Input 29(int)
+       31(index):     30(ptr) Variable Input
+              33:             TypePointer Function 11
+              35:             TypePointer Function 6(float)
+         4(main):           2 Function None 3
+               5:             Label
+   34(indexable):     33(ptr) Variable Function 28
+              32:     29(int) Load 31(index)
+              36:     35(ptr) AccessChain 34(indexable) 32
+              37:    6(float) Load 36
+                              Store 8(color) 37
+                              Return
+                              FunctionEnd
diff --git a/Test/spv.1.4.NonWritable.frag b/Test/spv.1.4.NonWritable.frag
new file mode 100755 (executable)
index 0000000..386b446
--- /dev/null
@@ -0,0 +1,13 @@
+#version 450
+
+layout(location = 0) flat in int index;
+
+layout(location = 0) out float color;
+
+// lookup table
+const float table[16] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
+
+void main()
+{
+    color = table[index];
+}
index 25abf3a..308bab6 100755 (executable)
@@ -465,9 +465,10 @@ INSTANTIATE_TEST_CASE_P(
 INSTANTIATE_TEST_CASE_P(
     Glsl, CompileToSpirv14Test,
     ::testing::ValuesIn(std::vector<std::string>({
+        "spv.1.4.LoopControl.frag",
+        "spv.1.4.NonWritable.frag",
         "spv.1.4.OpEntryPoint.frag",
         "spv.1.4.OpSelect.frag",
-        "spv.1.4.LoopControl.frag",
         "spv.1.4.OpCopyLogical.comp",
         "spv.1.4.OpCopyLogicalBool.comp",
         "spv.1.4.OpCopyLogical.funcall.frag",