Add support for GL_EXT_buffer_reference2
authorJeff Bolz <jbolz@nvidia.com>
Fri, 8 Mar 2019 16:42:49 +0000 (10:42 -0600)
committerJeff Bolz <jbolz@nvidia.com>
Wed, 1 May 2019 21:13:26 +0000 (16:13 -0500)
12 files changed:
Test/baseResults/spv.bufferhandle18.frag.out [new file with mode: 0644]
Test/baseResults/spv.bufferhandle19_Errors.frag.out [new file with mode: 0644]
Test/spv.bufferhandle18.frag [new file with mode: 0644]
Test/spv.bufferhandle19_Errors.frag [new file with mode: 0644]
glslang/MachineIndependent/Intermediate.cpp
glslang/MachineIndependent/ParseHelper.cpp
glslang/MachineIndependent/Versions.cpp
glslang/MachineIndependent/Versions.h [changed mode: 0755->0644]
glslang/MachineIndependent/linkValidate.cpp [changed mode: 0755->0644]
glslang/MachineIndependent/localintermediate.h
glslang/MachineIndependent/reflection.cpp
gtests/Spv.FromFile.cpp

diff --git a/Test/baseResults/spv.bufferhandle18.frag.out b/Test/baseResults/spv.bufferhandle18.frag.out
new file mode 100644 (file)
index 0000000..a36ae67
--- /dev/null
@@ -0,0 +1,274 @@
+spv.bufferhandle18.frag
+// Module Version 10000
+// Generated by (magic number): 80007
+// Id's are bound by 196
+
+                              Capability Shader
+                              Capability Int64
+                              Capability CapabilityPhysicalStorageBufferAddressesEXT
+                              Extension  "SPV_EXT_physical_storage_buffer"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel PhysicalStorageBuffer64EXT GLSL450
+                              EntryPoint Fragment 4  "main"
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 450
+                              SourceExtension  "GL_EXT_buffer_reference"
+                              SourceExtension  "GL_EXT_buffer_reference2"
+                              SourceExtension  "GL_EXT_scalar_block_layout"
+                              SourceExtension  "GL_EXT_shader_explicit_arithmetic_types_int64"
+                              Name 4  "main"
+                              Name 9  "T1"
+                              MemberName 9(T1) 0  "x"
+                              MemberName 9(T1) 1  "y"
+                              Name 11  "a"
+                              Name 15  "b"
+                              Name 18  "c"
+                              Name 24  "d"
+                              Name 26  "e"
+                              Name 29  "f"
+                              Name 59  "arr"
+                              Name 71  "i"
+                              Name 130  "j"
+                              Name 153  "k"
+                              Name 160  "x"
+                              Name 171  "y"
+                              Name 178  "T2"
+                              MemberName 178(T2) 0  "x"
+                              Name 180  "m"
+                              Name 190  "x"
+                              Name 195  "buf"
+                              MemberDecorate 9(T1) 0 Offset 0
+                              MemberDecorate 9(T1) 1 Offset 4
+                              Decorate 9(T1) Block
+                              Decorate 11(a) DecorationAliasedPointerEXT
+                              Decorate 15(b) DecorationAliasedPointerEXT
+                              Decorate 18(c) DecorationAliasedPointerEXT
+                              Decorate 24(d) DecorationAliasedPointerEXT
+                              Decorate 26(e) DecorationAliasedPointerEXT
+                              Decorate 29(f) DecorationAliasedPointerEXT
+                              Decorate 59(arr) DecorationAliasedPointerEXT
+                              Decorate 130(j) DecorationAliasedPointerEXT
+                              Decorate 153(k) DecorationAliasedPointerEXT
+                              MemberDecorate 178(T2) 0 Offset 0
+                              Decorate 178(T2) Block
+                              Decorate 180(m) DecorationAliasedPointerEXT
+               2:             TypeVoid
+               3:             TypeFunction 2
+                              TypeForwardPointer 6 PhysicalStorageBufferEXT
+               7:             TypeInt 32 1
+               8:             TypeInt 32 0
+           9(T1):             TypeStruct 7(int) 8(int)
+               6:             TypePointer PhysicalStorageBufferEXT 9(T1)
+              10:             TypePointer Function 6(ptr)
+              12:             TypeInt 64 0
+              13: 12(int64_t) Constant 4 0
+              16: 12(int64_t) Constant 5 0
+              19:             TypeBool
+              20:    19(bool) ConstantTrue
+              27: 12(int64_t) Constant 6 0
+              31:      7(int) Constant 1
+              32:             TypePointer PhysicalStorageBufferEXT 8(int)
+              35:      8(int) Constant 0
+              37: 12(int64_t) Constant 8 0
+              39: 12(int64_t) Constant 9 0
+              44: 12(int64_t) Constant 24 0
+              47:      7(int) Constant 0
+              48:             TypePointer PhysicalStorageBufferEXT 7(int)
+              52: 12(int64_t) Constant 40 0
+              56:      8(int) Constant 2
+              57:             TypeArray 6(ptr) 56
+              58:             TypePointer Function 57
+              66: 12(int64_t) Constant 56 0
+              70:             TypePointer Function 7(int)
+              77:             TypeInt 64 1
+             137: 12(int64_t) Constant 16 0
+             146: 12(int64_t) Constant 32 0
+             156: 12(int64_t) Constant 48 0
+             159:             TypePointer Function 77(int64_t)
+             168: 77(int64_t) Constant 8 0
+             170:             TypePointer Function 12(int64_t)
+             174: 12(int64_t) Constant 4294967288 4294967295
+                              TypeForwardPointer 177 PhysicalStorageBufferEXT
+         178(T2):             TypeStruct 7(int)
+             177:             TypePointer PhysicalStorageBufferEXT 178(T2)
+             179:             TypePointer Function 177(ptr)
+             183: 12(int64_t) Constant 64 0
+             186:      7(int) Constant 3
+             187:      8(int) Constant 3
+             188:             TypeArray 7(int) 187
+             189:             TypePointer Private 188
+          190(x):    189(ptr) Variable Private
+             191: 12(int64_t) Constant 10 0
+             192:      8(int) Constant 8
+             193:             TypeArray 8(int) 192
+             194:             TypePointer Private 193
+        195(buf):    194(ptr) Variable Private
+         4(main):           2 Function None 3
+               5:             Label
+           11(a):     10(ptr) Variable Function
+           15(b):     10(ptr) Variable Function
+           18(c):     10(ptr) Variable Function
+           24(d):     10(ptr) Variable Function
+           26(e):     10(ptr) Variable Function
+           29(f):     10(ptr) Variable Function
+         59(arr):     58(ptr) Variable Function
+           71(i):     70(ptr) Variable Function
+          130(j):     10(ptr) Variable Function
+          153(k):     10(ptr) Variable Function
+          160(x):    159(ptr) Variable Function
+          171(y):    170(ptr) Variable Function
+          180(m):    179(ptr) Variable Function
+              14:      6(ptr) Bitcast 13
+                              Store 11(a) 14
+              17:      6(ptr) Bitcast 16
+                              Store 15(b) 17
+              21:      6(ptr) Load 11(a)
+              22:      6(ptr) Load 15(b)
+              23:      6(ptr) Select 20 21 22
+                              Store 18(c) 23
+              25:      6(ptr) Load 15(b)
+                              Store 24(d) 25
+              28:      6(ptr) Bitcast 27
+                              Store 26(e) 28
+              30:      6(ptr) Load 11(a)
+              33:     32(ptr) AccessChain 30 31
+              34:      8(int) Load 33 Aligned 4
+              36:    19(bool) INotEqual 34 35
+              38:      6(ptr) Bitcast 37
+              40:      6(ptr) Bitcast 39
+              41:      6(ptr) Select 36 38 40
+                              Store 29(f) 41
+              42:      6(ptr) Load 29(f)
+              43: 12(int64_t) ConvertPtrToU 42
+              45: 12(int64_t) IAdd 43 44
+              46:      6(ptr) ConvertUToPtr 45
+              49:     48(ptr) AccessChain 46 47
+                              Store 49 31 Aligned 8
+              50:      6(ptr) Load 29(f)
+              51: 12(int64_t) ConvertPtrToU 50
+              53: 12(int64_t) IAdd 51 52
+              54:      6(ptr) ConvertUToPtr 53
+              55:     48(ptr) AccessChain 54 47
+                              Store 55 31 Aligned 8
+              60:      6(ptr) Load 11(a)
+              61:      6(ptr) Load 29(f)
+              62:          57 CompositeConstruct 60 61
+                              Store 59(arr) 62
+              63:     10(ptr) AccessChain 59(arr) 31
+              64:      6(ptr) Load 63
+              65: 12(int64_t) ConvertPtrToU 64
+              67: 12(int64_t) IAdd 65 66
+              68:      6(ptr) ConvertUToPtr 67
+              69:     48(ptr) AccessChain 68 47
+                              Store 69 31 Aligned 8
+              72:      7(int) Load 71(i)
+              73:     10(ptr) AccessChain 59(arr) 72
+              74:      6(ptr) Load 73
+              75: 12(int64_t) ConvertPtrToU 74
+              76:      7(int) Load 71(i)
+              78: 77(int64_t) SConvert 76
+              79: 12(int64_t) Bitcast 78
+              80: 12(int64_t) IMul 79 37
+              81: 12(int64_t) IAdd 75 80
+              82:      6(ptr) ConvertUToPtr 81
+              83:     48(ptr) AccessChain 82 47
+                              Store 83 31 Aligned 8
+              84:      7(int) Load 71(i)
+              85:     10(ptr) AccessChain 59(arr) 84
+              86:      6(ptr) Load 85
+              87: 12(int64_t) ConvertPtrToU 86
+              88:      7(int) Load 71(i)
+              89: 77(int64_t) SConvert 88
+              90: 12(int64_t) Bitcast 89
+              91: 12(int64_t) IMul 90 37
+              92: 12(int64_t) IAdd 87 91
+              93:      6(ptr) ConvertUToPtr 92
+              94: 12(int64_t) ConvertPtrToU 93
+              95:      7(int) Load 71(i)
+              96: 77(int64_t) SConvert 95
+              97: 12(int64_t) Bitcast 96
+              98: 12(int64_t) IMul 97 37
+              99: 12(int64_t) IAdd 94 98
+             100:      6(ptr) ConvertUToPtr 99
+             101: 12(int64_t) ConvertPtrToU 100
+             102:      7(int) Load 71(i)
+             103: 77(int64_t) SConvert 102
+             104: 12(int64_t) Bitcast 103
+             105: 12(int64_t) IMul 104 37
+             106: 12(int64_t) IAdd 101 105
+             107:      6(ptr) ConvertUToPtr 106
+             108: 12(int64_t) ConvertPtrToU 107
+             109:      7(int) Load 71(i)
+             110: 77(int64_t) SConvert 109
+             111: 12(int64_t) Bitcast 110
+             112: 12(int64_t) IMul 111 37
+             113: 12(int64_t) IAdd 108 112
+             114:      6(ptr) ConvertUToPtr 113
+             115: 12(int64_t) ConvertPtrToU 114
+             116:      7(int) Load 71(i)
+             117: 77(int64_t) SConvert 116
+             118: 12(int64_t) Bitcast 117
+             119: 12(int64_t) IMul 118 37
+             120: 12(int64_t) IAdd 115 119
+             121:      6(ptr) ConvertUToPtr 120
+             122: 12(int64_t) ConvertPtrToU 121
+             123:      7(int) Load 71(i)
+             124: 77(int64_t) SConvert 123
+             125: 12(int64_t) Bitcast 124
+             126: 12(int64_t) IMul 125 37
+             127: 12(int64_t) IAdd 122 126
+             128:      6(ptr) ConvertUToPtr 127
+             129:     48(ptr) AccessChain 128 47
+                              Store 129 31 Aligned 8
+             131:      6(ptr) Load 130(j)
+             132: 12(int64_t) ConvertPtrToU 131
+             133: 12(int64_t) IAdd 132 37
+             134:      6(ptr) ConvertUToPtr 133
+                              Store 130(j) 134
+             135:      6(ptr) Load 130(j)
+             136: 12(int64_t) ConvertPtrToU 135
+             138: 12(int64_t) ISub 136 137
+             139:      6(ptr) ConvertUToPtr 138
+                              Store 130(j) 139
+             140:      6(ptr) Load 130(j)
+             141: 12(int64_t) ConvertPtrToU 140
+             142: 12(int64_t) IAdd 141 44
+             143:      6(ptr) ConvertUToPtr 142
+                              Store 130(j) 143
+             144:      6(ptr) Load 130(j)
+             145: 12(int64_t) ConvertPtrToU 144
+             147: 12(int64_t) ISub 145 146
+             148:      6(ptr) ConvertUToPtr 147
+                              Store 130(j) 148
+             149:      6(ptr) Load 130(j)
+             150: 12(int64_t) ConvertPtrToU 149
+             151: 12(int64_t) IAdd 52 150
+             152:      6(ptr) ConvertUToPtr 151
+                              Store 130(j) 152
+             154:      6(ptr) Load 130(j)
+             155: 12(int64_t) ConvertPtrToU 154
+             157: 12(int64_t) IAdd 155 156
+             158:      6(ptr) ConvertUToPtr 157
+                              Store 153(k) 158
+             161:      6(ptr) Load 153(k)
+             162: 12(int64_t) ConvertPtrToU 161
+             163: 77(int64_t) Bitcast 162
+             164:      6(ptr) Load 130(j)
+             165: 12(int64_t) ConvertPtrToU 164
+             166: 77(int64_t) Bitcast 165
+             167: 77(int64_t) ISub 163 166
+             169: 77(int64_t) SDiv 167 168
+                              Store 160(x) 169
+                              Store 171(y) 37
+             172:      6(ptr) Load 153(k)
+             173: 12(int64_t) ConvertPtrToU 172
+             175: 12(int64_t) IAdd 173 174
+             176:      6(ptr) ConvertUToPtr 175
+                              Store 153(k) 176
+             181:    177(ptr) Load 180(m)
+             182: 12(int64_t) ConvertPtrToU 181
+             184: 12(int64_t) IAdd 182 183
+             185:    177(ptr) ConvertUToPtr 184
+                              Store 180(m) 185
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/spv.bufferhandle19_Errors.frag.out b/Test/baseResults/spv.bufferhandle19_Errors.frag.out
new file mode 100644 (file)
index 0000000..930e5a4
--- /dev/null
@@ -0,0 +1,17 @@
+spv.bufferhandle19_Errors.frag
+ERROR: 0:18: '+' :  wrong operand types: no operation '+' exists that takes a left-hand operand of type ' temp reference' and a right operand of type ' const int' (or there is no acceptable conversion)
+ERROR: 0:19: '-' :  wrong operand types: no operation '-' exists that takes a left-hand operand of type ' temp reference' and a right operand of type ' const int' (or there is no acceptable conversion)
+ERROR: 0:20: '+' :  wrong operand types: no operation '+' exists that takes a left-hand operand of type ' const int' and a right operand of type ' temp reference' (or there is no acceptable conversion)
+ERROR: 0:21: '-' :  wrong operand types: no operation '-' exists that takes a left-hand operand of type ' temp reference' and a right operand of type ' temp reference' (or there is no acceptable conversion)
+ERROR: 0:22: 'assign' :  cannot convert from ' const int' to ' temp reference'
+ERROR: 0:23: 'assign' :  cannot convert from ' const int' to ' temp reference'
+ERROR: 0:24: 'assign' :  cannot convert from ' temp reference' to ' temp reference'
+ERROR: 0:25: 'assign' :  cannot convert from ' temp reference' to ' temp reference'
+ERROR: 0:28: 'assign' :  cannot convert from ' temp reference' to ' temp reference'
+ERROR: 0:29: 'assign' :  cannot convert from ' temp reference' to ' temp reference'
+ERROR: 0:30: '+' :  wrong operand types: no operation '+' exists that takes a left-hand operand of type ' temp reference' and a right operand of type ' temp reference' (or there is no acceptable conversion)
+ERROR: 0:31: '-' :  wrong operand types: no operation '-' exists that takes a left-hand operand of type ' const int' and a right operand of type ' temp reference' (or there is no acceptable conversion)
+ERROR: 12 compilation errors.  No code generated.
+
+
+SPIR-V is not generated for failed compile or link
diff --git a/Test/spv.bufferhandle18.frag b/Test/spv.bufferhandle18.frag
new file mode 100644 (file)
index 0000000..64517fe
--- /dev/null
@@ -0,0 +1,59 @@
+#version 450\r
+\r
+#extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable\r
+#extension GL_EXT_buffer_reference2 : enable\r
+#extension GL_EXT_scalar_block_layout : enable\r
+\r
+layout(buffer_reference, buffer_reference_align = 8) buffer T1 {\r
+    int x;\r
+    bool y;\r
+};\r
+layout(buffer_reference, buffer_reference_align = 64) buffer T2 {\r
+    int x;\r
+};\r
+\r
+const int s = int(uint64_t(T1(T2(uint64_t(3)))));\r
+int x[s];\r
+const uint64_t t = uint64_t(true ? T2(uint64_t(10)) : T2(uint64_t(11)));\r
+\r
+\r
+#define sizeof(T) (uint64_t(T(uint64_t(0))+1))\r
+\r
+const uint64_t s2 = sizeof(T1);\r
+uint buf[int(s2)];\r
+\r
+\r
+void main()\r
+{\r
+    T1 a = T1(uint64_t(4)), b = T1(uint64_t(5));\r
+    T1 c = true ? a : b;\r
+    T1 d = (a,b);\r
+    T1 e = true ? T1(uint64_t(6)) : T1(uint64_t(7));\r
+    T1 f = a.y ? T1(uint64_t(8)) : T1(uint64_t(9));\r
+\r
+    f[3].x = 1;\r
+    (f+5).x = 1;\r
+\r
+    T1 arr[2] = {a, f};\r
+    arr[1][7].x = 1;\r
+    int i;\r
+    arr[i][i].x = 1;\r
+    // Since we don't distinguish between "pointer" and "reference" type,\r
+    // a reference type can have [] applied to it repeatedly and it has\r
+    // the effect of adding up the indices.\r
+    arr[i][i][i][i][i][i][i].x = 1;\r
+\r
+    T1 j;\r
+    j = j+1;\r
+    j = j-2;\r
+    j += 3;\r
+    j -= 4;\r
+    j = 5+j;\r
+    T1 k = j + 6;\r
+    int64_t x = k - j;\r
+    uint64_t y = sizeof(T1);\r
+    k = k + (-1);\r
+\r
+    T2 m;\r
+    m = m+1;\r
+}\r
diff --git a/Test/spv.bufferhandle19_Errors.frag b/Test/spv.bufferhandle19_Errors.frag
new file mode 100644 (file)
index 0000000..75f53e6
--- /dev/null
@@ -0,0 +1,32 @@
+#version 450\r
+\r
+#extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable\r
+#extension GL_EXT_buffer_reference2 : enable\r
+#extension GL_EXT_scalar_block_layout : enable\r
+\r
+layout(buffer_reference) buffer T1 {\r
+    int x[];\r
+};\r
+\r
+layout(buffer_reference) buffer T2 {\r
+    int x[2];\r
+};\r
+\r
+void main()\r
+{\r
+    T1 a;\r
+    a+1;\r
+    a-1;\r
+    1+a;\r
+    a-a;\r
+    a+=1;\r
+    a-=1;\r
+    a+=a;\r
+    a-=a;\r
+\r
+    T2 b;\r
+    b+=b;\r
+    b-=b;\r
+    b+b;\r
+    1-b;\r
+}\r
index 4ec728d..49c7b1e 100644 (file)
@@ -119,6 +119,62 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
     if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock)
         return nullptr;
 
+    // Convert "reference +/- int" and "reference - reference" to integer math
+    if ((op == EOpAdd || op == EOpSub) && extensionRequested(E_GL_EXT_buffer_reference2)) {
+
+        // No addressing math on struct with unsized array.
+        if ((left->getBasicType() == EbtReference && left->getType().getReferentType()->containsUnsizedArray()) ||
+            (right->getBasicType() == EbtReference && right->getType().getReferentType()->containsUnsizedArray())) {
+            return nullptr;
+        }
+
+        if (left->getBasicType() == EbtReference && isTypeInt(right->getBasicType())) {
+            const TType& referenceType = left->getType();
+            TIntermConstantUnion* size = addConstantUnion((unsigned long long)computeBufferReferenceTypeSize(left->getType()), loc, true);
+            left  = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, left, TType(EbtUint64));
+
+            right = createConversion(EbtInt64, right);
+            right = addBinaryMath(EOpMul, right, size, loc);
+
+            TIntermTyped *node = addBinaryMath(op, left, right, loc);
+            node = addBuiltInFunctionCall(loc, EOpConvUint64ToPtr, true, node, referenceType);
+            return node;
+        }
+
+        if (op == EOpAdd && right->getBasicType() == EbtReference && isTypeInt(left->getBasicType())) {
+            const TType& referenceType = right->getType();
+            TIntermConstantUnion* size = addConstantUnion((unsigned long long)computeBufferReferenceTypeSize(right->getType()), loc, true);
+            right = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, right, TType(EbtUint64));
+
+            left  = createConversion(EbtInt64, left);
+            left  = addBinaryMath(EOpMul, left, size, loc);
+
+            TIntermTyped *node = addBinaryMath(op, left, right, loc);
+            node = addBuiltInFunctionCall(loc, EOpConvUint64ToPtr, true, node, referenceType);
+            return node;
+        }
+
+        if (op == EOpSub && left->getBasicType() == EbtReference && right->getBasicType() == EbtReference) {
+            TIntermConstantUnion* size = addConstantUnion((long long)computeBufferReferenceTypeSize(left->getType()), loc, true);
+
+            left = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, left, TType(EbtUint64));
+            right = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, right, TType(EbtUint64));
+
+            left = addBuiltInFunctionCall(loc, EOpConvUint64ToInt64, true, left, TType(EbtInt64));
+            right = addBuiltInFunctionCall(loc, EOpConvUint64ToInt64, true, right, TType(EbtInt64));
+
+            left = addBinaryMath(EOpSub, left, right, loc);
+
+            TIntermTyped *node = addBinaryMath(EOpDiv, left, size, loc);
+            return node;
+        }
+
+        // No other math operators supported on references
+        if (left->getBasicType() == EbtReference || right->getBasicType() == EbtReference) {
+            return nullptr;
+        }
+    }
+
     // Try converting the children's base types to compatible types.
     auto children = addConversion(op, left, right);
     left = std::get<0>(children);
@@ -231,6 +287,26 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm
     if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock)
         return nullptr;
 
+    // Convert "reference += int" to "reference = reference + int". We need this because the
+    // "reference + int" calculation involves a cast back to the original type, which makes it
+    // not an lvalue.
+    if ((op == EOpAddAssign || op == EOpSubAssign) && left->getBasicType() == EbtReference &&
+        extensionRequested(E_GL_EXT_buffer_reference2)) {
+
+        if (!(right->getType().isScalar() && right->getType().isIntegerDomain()))
+            return nullptr;
+
+        TIntermTyped* node = addBinaryMath(op == EOpAddAssign ? EOpAdd : EOpSub, left, right, loc);
+        if (!node)
+            return nullptr;
+
+        TIntermSymbol* symbol = left->getAsSymbolNode();
+        left = addSymbol(*symbol);
+
+        node = addAssign(EOpAssign, left, node, loc);
+        return node;
+    }
+
     //
     // Like adding binary math, except the conversion can only go
     // from right to left.
index 8f575fb..e04600a 100644 (file)
@@ -377,7 +377,8 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn
     // basic type checks...
     variableCheck(base);
 
-    if (! base->isArray() && ! base->isMatrix() && ! base->isVector() && ! base->getType().isCoopMat()) {
+    if (! base->isArray() && ! base->isMatrix() && ! base->isVector() && ! base->getType().isCoopMat() &&
+        base->getBasicType() != EbtReference) {
         if (base->getAsSymbolNode())
             error(loc, " left of '[' is not of type array, matrix, or vector ", base->getAsSymbolNode()->getName().c_str(), "");
         else
@@ -405,6 +406,14 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn
 
     // at least one of base and index is not a front-end constant variable...
     TIntermTyped* result = nullptr;
+
+    if (base->getBasicType() == EbtReference && ! base->isArray()) {
+        requireExtensions(loc, 1, &E_GL_EXT_buffer_reference2, "buffer reference indexing");
+        result = intermediate.addBinaryMath(EOpAdd, base, index, loc);
+        result->setType(base->getType());
+        return result;
+    }
+
     if (index->getQualifier().isFrontEndConstant())
         checkIndex(loc, base->getType(), indexValue);
 
index 0d4b994..f19c385 100644 (file)
@@ -209,6 +209,7 @@ void TParseVersions::initializeExtensionBehavior()
     extensionBehavior[E_GL_EXT_scalar_block_layout]                     = EBhDisable;
     extensionBehavior[E_GL_EXT_fragment_invocation_density]             = EBhDisable;
     extensionBehavior[E_GL_EXT_buffer_reference]                        = EBhDisable;
+    extensionBehavior[E_GL_EXT_buffer_reference2]                       = EBhDisable;
 
     extensionBehavior[E_GL_EXT_shader_16bit_storage]                    = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_8bit_storage]                     = EBhDisable;
@@ -389,6 +390,7 @@ void TParseVersions::getPreamble(std::string& preamble)
             "#define GL_EXT_scalar_block_layout 1\n"
             "#define GL_EXT_fragment_invocation_density 1\n"
             "#define GL_EXT_buffer_reference 1\n"
+            "#define GL_EXT_buffer_reference2 1\n"
 
             // GL_KHR_shader_subgroup
             "#define GL_KHR_shader_subgroup_basic 1\n"
@@ -808,6 +810,8 @@ void TParseVersions::updateExtensionBehavior(int line, const char* extension, co
     else if (strcmp(extension, "GL_NV_shader_subgroup_partitioned") == 0)
         updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString);
 #endif
+    else if (strcmp(extension, "GL_EXT_buffer_reference2") == 0)
+        updateExtensionBehavior(line, "GL_EXT_buffer_reference", behaviorString);
 }
 
 void TParseVersions::updateExtensionBehavior(const char* extension, TExtensionBehavior behavior)
old mode 100755 (executable)
new mode 100644 (file)
index e571b51..bff0827
@@ -171,6 +171,7 @@ const char* const E_GL_EXT_samplerless_texture_functions    = "GL_EXT_samplerles
 const char* const E_GL_EXT_scalar_block_layout              = "GL_EXT_scalar_block_layout";
 const char* const E_GL_EXT_fragment_invocation_density      = "GL_EXT_fragment_invocation_density";
 const char* const E_GL_EXT_buffer_reference                 = "GL_EXT_buffer_reference";
+const char* const E_GL_EXT_buffer_reference2                = "GL_EXT_buffer_reference2";
 
 // Arrays of extensions for the above viewportEXTs duplications
 
old mode 100755 (executable)
new mode 100644 (file)
index 0cf2d36..f935d4a
@@ -1683,4 +1683,74 @@ int TIntermediate::getMemberAlignment(const TType& type, int& size, int& stride,
     }
 }
 
+// shared calculation by getOffset and getOffsets
+void TIntermediate::updateOffset(const TType& parentType, const TType& memberType, int& offset, int& memberSize)
+{
+    int dummyStride;
+
+    // modify just the children's view of matrix layout, if there is one for this member
+    TLayoutMatrix subMatrixLayout = memberType.getQualifier().layoutMatrix;
+    int memberAlignment = getMemberAlignment(memberType, memberSize, dummyStride,
+                                             parentType.getQualifier().layoutPacking,
+                                             subMatrixLayout != ElmNone
+                                                 ? subMatrixLayout == ElmRowMajor
+                                                 : parentType.getQualifier().layoutMatrix == ElmRowMajor);
+    RoundToPow2(offset, memberAlignment);
+}
+
+// Lookup or calculate the offset of a block member, using the recursively
+// defined block offset rules.
+int TIntermediate::getOffset(const TType& type, int index)
+{
+    const TTypeList& memberList = *type.getStruct();
+
+    // Don't calculate offset if one is present, it could be user supplied
+    // and different than what would be calculated.  That is, this is faster,
+    // but not just an optimization.
+    if (memberList[index].type->getQualifier().hasOffset())
+        return memberList[index].type->getQualifier().layoutOffset;
+
+    int memberSize = 0;
+    int offset = 0;
+    for (int m = 0; m <= index; ++m) {
+        updateOffset(type, *memberList[m].type, offset, memberSize);
+
+        if (m < index)
+            offset += memberSize;
+    }
+
+    return offset;
+}
+
+// Calculate the block data size.
+// Block arrayness is not taken into account, each element is backed by a separate buffer.
+int TIntermediate::getBlockSize(const TType& blockType)
+{
+    const TTypeList& memberList = *blockType.getStruct();
+    int lastIndex = (int)memberList.size() - 1;
+    int lastOffset = getOffset(blockType, lastIndex);
+
+    int lastMemberSize;
+    int dummyStride;
+    getMemberAlignment(*memberList[lastIndex].type, lastMemberSize, dummyStride,
+                       blockType.getQualifier().layoutPacking,
+                       blockType.getQualifier().layoutMatrix == ElmRowMajor);
+
+    return lastOffset + lastMemberSize;
+}
+
+int TIntermediate::computeBufferReferenceTypeSize(const TType& type)
+{
+    assert(type.getBasicType() == EbtReference);
+    int size = getBlockSize(*type.getReferentType());
+
+    int align = type.getBufferReferenceAlignment();
+
+    if (align) {
+        size = (size + align - 1) & ~(align-1);
+    }
+
+    return size;
+}
+
 } // end namespace glslang
index ba17725..f29c93c 100644 (file)
@@ -696,6 +696,10 @@ public:
     static int getScalarAlignment(const TType&, int& size, int& stride, bool rowMajor);
     static int getMemberAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor);
     static bool improperStraddle(const TType& type, int size, int offset);
+    static void updateOffset(const TType& parentType, const TType& memberType, int& offset, int& memberSize);
+    static int getOffset(const TType& type, int index);
+    static int getBlockSize(const TType& blockType);
+    static int computeBufferReferenceTypeSize(const TType&);
     bool promote(TIntermOperator*);
 
 #ifdef NV_EXTENSIONS
index 2b28403..a09a048 100644 (file)
@@ -143,45 +143,6 @@ public:
         }
     }
 
-    // shared calculation by getOffset and getOffsets
-    void updateOffset(const TType& parentType, const TType& memberType, int& offset, int& memberSize)
-    {
-        int dummyStride;
-
-        // modify just the children's view of matrix layout, if there is one for this member
-        TLayoutMatrix subMatrixLayout = memberType.getQualifier().layoutMatrix;
-        int memberAlignment = intermediate.getMemberAlignment(memberType, memberSize, dummyStride,
-                                                              parentType.getQualifier().layoutPacking,
-                                                              subMatrixLayout != ElmNone
-                                                                  ? subMatrixLayout == ElmRowMajor
-                                                                  : parentType.getQualifier().layoutMatrix == ElmRowMajor);
-        RoundToPow2(offset, memberAlignment);
-    }
-
-    // Lookup or calculate the offset of a block member, using the recursively
-    // defined block offset rules.
-    int getOffset(const TType& type, int index)
-    {
-        const TTypeList& memberList = *type.getStruct();
-
-        // Don't calculate offset if one is present, it could be user supplied
-        // and different than what would be calculated.  That is, this is faster,
-        // but not just an optimization.
-        if (memberList[index].type->getQualifier().hasOffset())
-            return memberList[index].type->getQualifier().layoutOffset;
-
-        int memberSize = 0;
-        int offset = 0;
-        for (int m = 0; m <= index; ++m) {
-            updateOffset(type, *memberList[m].type, offset, memberSize);
-
-            if (m < index)
-                offset += memberSize;
-        }
-
-        return offset;
-    }
-
     // Lookup or calculate the offset of all block members at once, using the recursively
     // defined block offset rules.
     void getOffsets(const TType& type, TVector<int>& offsets)
@@ -196,7 +157,7 @@ public:
                 offset = memberList[m].type->getQualifier().layoutOffset;
 
             // calculate the offset of the next member and align the current offset to this member
-            updateOffset(type, *memberList[m].type, offset, memberSize);
+            intermediate.updateOffset(type, *memberList[m].type, offset, memberSize);
 
             // save the offset of this member
             offsets[m] = offset;
@@ -226,23 +187,6 @@ public:
         return stride;
     }
 
-    // Calculate the block data size.
-    // Block arrayness is not taken into account, each element is backed by a separate buffer.
-    int getBlockSize(const TType& blockType)
-    {
-        const TTypeList& memberList = *blockType.getStruct();
-        int lastIndex = (int)memberList.size() - 1;
-        int lastOffset = getOffset(blockType, lastIndex);
-
-        int lastMemberSize;
-        int dummyStride;
-        intermediate.getMemberAlignment(*memberList[lastIndex].type, lastMemberSize, dummyStride,
-                                        blockType.getQualifier().layoutPacking,
-                                        blockType.getQualifier().layoutMatrix == ElmRowMajor);
-
-        return lastOffset + lastMemberSize;
-    }
-
     // count the total number of leaf members from iterating out of a block type
     int countAggregateMembers(const TType& parentType)
     {
@@ -349,7 +293,7 @@ public:
             case EOpIndexDirectStruct:
                 index = visitNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
                 if (offset >= 0)
-                    offset += getOffset(visitNode->getLeft()->getType(), index);
+                    offset += intermediate.getOffset(visitNode->getLeft()->getType(), index);
                 if (name.size() > 0)
                     name.append(".");
                 name.append((*visitNode->getLeft()->getType().getStruct())[index].type->getFieldName());
@@ -592,10 +536,10 @@ public:
                 assert(! anonymous);
                 for (int e = 0; e < base->getType().getCumulativeArraySize(); ++e)
                     blockIndex = addBlockName(blockName + "[" + String(e) + "]", derefType,
-                                              getBlockSize(base->getType()));
+                                              intermediate.getBlockSize(base->getType()));
                 baseName.append(TString("[0]"));
             } else
-                blockIndex = addBlockName(blockName, base->getType(), getBlockSize(base->getType()));
+                blockIndex = addBlockName(blockName, base->getType(), intermediate.getBlockSize(base->getType()));
 
             if (reflection.options & EShReflectionAllBlockVariables) {
                 // Use a degenerate (empty) set of dereferences to immediately put as at the end of
index 4663df6..7be692d 100644 (file)
@@ -274,6 +274,8 @@ INSTANTIATE_TEST_CASE_P(
         "spv.bufferhandle15.frag",
         "spv.bufferhandle16.frag",
         "spv.bufferhandle17_Errors.frag",
+        "spv.bufferhandle18.frag",
+        "spv.bufferhandle19_Errors.frag",
         "spv.bufferhandle2.frag",
         "spv.bufferhandle3.frag",
         "spv.bufferhandle4.frag",