Array of array: Implement the core functionality: types, constructors, operations.
There will be subsequent commits to refine semantics, esp. version-specific semantics,
as well as I/O functionality and restrictions.
Note: I'm getting white-space differences in the preprocessor test results,
which I'm not checking in. I think they need to be tagged as binary or something.
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index 1d1dcaf..4b8c933 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -953,7 +953,7 @@
{
glslang::TIntermTyped* typedNode = node->getSequence()[0]->getAsTyped();
assert(typedNode);
- spv::Id length = builder.makeIntConstant(typedNode->getType().getArraySize());
+ spv::Id length = builder.makeIntConstant(typedNode->getType().getOuterArraySize());
builder.clearAccessChain();
builder.setAccessChainRValue(length);
@@ -1428,7 +1428,7 @@
spv::MissingFunctionality("Unsized array");
arraySize = 8;
} else
- arraySize = type.getArraySize();
+ arraySize = type.getOuterArraySize();
spvType = builder.makeArrayType(spvType, arraySize);
}
@@ -2637,15 +2637,11 @@
spv::Id typeId = convertGlslangToSpvType(glslangType);
if (glslangType.isArray()) {
- glslang::TType elementType;
- elementType.deepCopy(glslangType);
- elementType.dereference();
- for (int i = 0; i < glslangType.getArraySize(); ++i)
+ glslang::TType elementType(glslangType, 0);
+ for (int i = 0; i < glslangType.getOuterArraySize(); ++i)
spvConsts.push_back(createSpvConstant(elementType, consts, nextConst));
} else if (glslangType.isMatrix()) {
- glslang::TType vectorType;
- vectorType.shallowCopy(glslangType);
- vectorType.dereference();
+ glslang::TType vectorType(glslangType, 0);
for (int col = 0; col < glslangType.getMatrixCols(); ++col)
spvConsts.push_back(createSpvConstant(vectorType, consts, nextConst));
} else if (glslangType.getStruct()) {
diff --git a/Test/430AofA.frag b/Test/430AofA.frag
new file mode 100644
index 0000000..54d0923
--- /dev/null
+++ b/Test/430AofA.frag
@@ -0,0 +1,108 @@
+#version 430
+
+float[4][5][6] many[1][2][3];
+
+float gu[][7];
+float gimp[][]; // ERROR, implicit inner
+float g4[4][7];
+float g5[5][7];
+
+float[4][7] foo(float a[5][7])
+{
+ float r[7];
+ r = a[2];
+ float[](a[0], a[1], r, a[3]); // ERROR, too few dims
+ float[4][7][4](a[0], a[1], r, a[3]); // ERROR, too many dims
+ return float[4][7](a[0], a[1], r, a[3]);
+ return float[][](a[0], a[1], r, a[3]);
+ return float[][7](a[0], a[1], a[2], a[3]);
+}
+
+void bar(float[5][7]) {}
+
+void main()
+{
+ {
+ float gu[3][4][2];
+
+ gu[2][4][1] = 4.0; // ERROR, overflow
+ }
+ vec4 ca4[3][2] = vec4[][](vec4[2](vec4(0.0), vec4(1.0)),
+ vec4[2](vec4(0.0), vec4(1.0)),
+ vec4[2](vec4(0.0), vec4(1.0)));
+ vec4 caim[][2] = vec4[][](vec4[2](vec4(4.0), vec4(2.0)),
+ vec4[2](vec4(4.0), vec4(2.0)),
+ vec4[2](vec4(4.0), vec4(2.0)));
+ vec4 caim2[][] = vec4[][](vec4[2](vec4(4.0), vec4(2.0)),
+ vec4[2](vec4(4.0), vec4(2.0)),
+ vec4[2](vec4(4.0), vec4(2.0)));
+ vec4 caim3[3][] = vec4[][](vec4[2](vec4(4.0), vec4(2.0)),
+ vec4[2](vec4(4.0), vec4(2.0)),
+ vec4[2](vec4(4.0), vec4(2.0)));
+
+ vec4 a4[3][2] = {vec4[](vec4(0.0), vec4(1.0)),
+ vec4[2](vec4(0.0), vec4(1.0)),
+ vec4[2](vec4(0.0), vec4(1.0)) };
+ vec4 aim[][2] = {vec4[2](vec4(4.0), vec4(2.0)),
+ vec4[](vec4(4.0), vec4(2.0)),
+ vec4[2](vec4(4.0), vec4(2.0)) };
+ vec4 aim2[][] = {vec4[2](vec4(4.0), vec4(2.0)),
+ vec4[2](vec4(4.0), vec4(2.0)),
+ vec4[](vec4(4.0), vec4(2.0)) };
+ vec4 aim3[3][] = {vec4[2](vec4(4.0), vec4(2.0)),
+ vec4[2](vec4(4.0), vec4(2.0)),
+ vec4[2](vec4(4.0), vec4(2.0)) };
+
+ vec4 bad2[3][] = {vec4[2](vec4(4.0), vec4(2.0)), // ERROR
+ vec4[3](vec4(4.0), vec4(2.0), vec4(5.0)),
+ vec4[2](vec4(4.0), vec4(2.0)) };
+
+ vec4 bad3[3][] = {vec4[3](vec4(4.0), vec4(2.0), vec4(5.0)), // ERROR
+ vec4[2](vec4(4.0), vec4(2.0)),
+ vec4[2](vec4(4.0), vec4(2.0)) };
+
+ vec4 bad4[4][] = {vec4[2](vec4(4.0), vec4(2.0)), // ERROR
+ vec4[2](vec4(4.0), vec4(2.0)),
+ vec4[2](vec4(4.0), vec4(2.0)) };
+
+
+ g4 = foo(g5);
+ g5 = g4; // ERROR, wrong types
+ gu = g4; // ERROR, not yet sized
+
+ foo(gu); // ERROR, not yet sized
+ bar(g5);
+
+ if (foo(g5) == g4)
+ ;
+ if (foo(g5) == g5) // ERROR, different types
+ ;
+
+ float u[][7];
+ u[2][2] = 3.0;
+ float u[5][7];
+ u[5][2] = 5.0; // ERROR
+ foo(u);
+}
+
+void foo3()
+{
+ float resize1[][5][7];
+ resize1.length(); // ERROR
+ resize1[1][4][5] = 2.0;
+ resize1.length(); // ERROR
+ float resize1[3][5][7];
+ resize1.length(); // 3 in AST
+ resize1[1].length(); // 5 in AST
+ resize1[1][1].length(); // 7 in AST
+ resize1[1][1][1].length(); // ERROR
+
+ float resize2[][5][7];
+ float resize2[3][4][7]; // ERROR, inner dim change
+
+ float resize3[][5][7];
+ float resize3[3][5][9]; // ERROR, inner dim changed
+
+ float resize4[][5][7];
+ int resize4[3][5][7]; // ERROR, element type
+}
diff --git a/Test/baseResults/120.vert.out b/Test/baseResults/120.vert.out
index 8db27da..7b58c8b 100644
--- a/Test/baseResults/120.vert.out
+++ b/Test/baseResults/120.vert.out
@@ -17,7 +17,6 @@
ERROR: 0:34: 'f' : can't use function syntax on variable
ERROR: 0:34: 'a4' : redefinition
ERROR: 0:35: 'arrays of arrays' : not supported with this profile: none
-WARNING: 0:35: 'Not supported yet.' : arrays of arrays
ERROR: 0:36: 'arrays of arrays' : not supported with this profile: none
ERROR: 0:37: 'arrays of arrays' : not supported with this profile: none
ERROR: 0:38: 'arrays of arrays' : not supported with this profile: none
diff --git a/Test/baseResults/300.frag.out b/Test/baseResults/300.frag.out
index 1d1d533..fb050a5 100644
--- a/Test/baseResults/300.frag.out
+++ b/Test/baseResults/300.frag.out
@@ -21,7 +21,6 @@
ERROR: 0:86: 'dvec4' : Reserved word.
ERROR: 0:86: 'double vector' : not supported with this profile: es
ERROR: 0:101: 'arrays of arrays' : not supported for this version or the enabled extensions
-WARNING: 0:101: 'Not supported yet.' : arrays of arrays
ERROR: 0:102: 'arrays of arrays' : not supported for this version or the enabled extensions
ERROR: 0:102: 'arrays of arrays' : not supported for this version or the enabled extensions
ERROR: 0:103: 'arrays of arrays' : not supported for this version or the enabled extensions
diff --git a/Test/baseResults/310.frag.out b/Test/baseResults/310.frag.out
index 7676e70..c74b9f0 100644
--- a/Test/baseResults/310.frag.out
+++ b/Test/baseResults/310.frag.out
@@ -37,7 +37,6 @@
ERROR: 0:112: 'out' : cannot be a matrix
ERROR: 0:114: 'in' : cannot be bool
ERROR: 0:115: 'sampler2D' : sampler/image types can only be used in uniform variables or function parameters: ino
-WARNING: 0:117: 'Not supported yet.' : arrays of arrays
ERROR: 0:117: 'fragment-shader array-of-array input' : not supported with this profile: es
ERROR: 0:120: 'fragment-shader array-of-struct input' : not supported with this profile: es
ERROR: 0:121: 'fragment-shader array-of-struct input' : not supported with this profile: es
diff --git a/Test/baseResults/310.vert.out b/Test/baseResults/310.vert.out
index 82a1311..d6face4 100644
--- a/Test/baseResults/310.vert.out
+++ b/Test/baseResults/310.vert.out
@@ -9,7 +9,6 @@
ERROR: 0:67: 'textureSamples' : no matching overloaded function found
ERROR: 0:72: 'out' : cannot be bool
ERROR: 0:73: 'sampler2D' : sampler/image types can only be used in uniform variables or function parameters: outo
-WARNING: 0:75: 'Not supported yet.' : arrays of arrays
ERROR: 0:75: 'vertex-shader array-of-array output' : not supported with this profile: es
ERROR: 0:78: 'vertex-shader array-of-struct output' : not supported with this profile: es
ERROR: 0:79: 'vertex-shader array-of-struct output' : not supported with this profile: es
diff --git a/Test/baseResults/310AofA.vert.out b/Test/baseResults/310AofA.vert.out
index a8de634..63598fc 100644
--- a/Test/baseResults/310AofA.vert.out
+++ b/Test/baseResults/310AofA.vert.out
@@ -1,6 +1,5 @@
310AofA.vert
Warning, version 310 is not yet complete; most version-specific features are present, but some are missing.
-WARNING: 0:8: 'Not supported yet.' : arrays of arrays
Shader version: 310
0:? Sequence
diff --git a/Test/baseResults/430AofA.frag.out b/Test/baseResults/430AofA.frag.out
new file mode 100644
index 0000000..c6ab950
--- /dev/null
+++ b/Test/baseResults/430AofA.frag.out
@@ -0,0 +1,803 @@
+430AofA.frag
+Warning, version 430 is not yet complete; most version-specific features are present, but some are missing.
+ERROR: 0:6: '[]' : only outermost dimension of an array of arrays can be implicitly sized
+ERROR: 0:14: 'constructor' : constructing non-array constituent from array argument
+ERROR: 0:15: 'constructior' : array constructor argument not correct type to construct array element
+ERROR: 0:28: '[' : array index out of range '4'
+ERROR: 0:56: 'constructor' : cannot convert parameter 2 from 'const 3-element array of 4-component vector of float' to 'temp 2-element array of 4-component vector of float'
+ERROR: 0:60: 'constructor' : cannot convert parameter 2 from 'const 2-element array of 4-component vector of float' to 'temp 3-element array of 4-component vector of float'
+ERROR: 0:64: '=' : cannot convert from 'temp 3-element array of 2-element array of 4-component vector of float' to 'temp 4-element array of 2-element array of 4-component vector of float'
+ERROR: 0:70: 'assign' : cannot convert from 'global 4-element array of 7-element array of float' to 'global 5-element array of 7-element array of float'
+ERROR: 0:71: 'assign' : cannot convert from 'global 4-element array of 7-element array of float' to 'global implicitly-sized array of 7-element array of float'
+ERROR: 0:73: 'foo' : no matching overloaded function found
+ERROR: 0:78: '==' : wrong operand types: no operation '==' exists that takes a left-hand operand of type 'global 4-element array of 7-element array of float' and a right operand of type 'global 5-element array of 7-element array of float' (or there is no acceptable conversion)
+ERROR: 0:84: '[' : array index out of range '5'
+ERROR: 0:91: 'length' : array must be declared with a size before using this method
+ERROR: 0:93: 'length' : array must be declared with a size before using this method
+ERROR: 0:98: 'length' : does not operate on this type: temp float
+ERROR: 0:98: '' : function call, method, or subroutine call expected
+ERROR: 0:98: '' : no matching overloaded function found
+ERROR: 0:101: 'resize2' : redeclaration of array with a different array dimensions or sizes
+ERROR: 0:104: 'resize3' : redeclaration of array with a different array dimensions or sizes
+ERROR: 0:107: 'resize4' : redeclaration of array with a different element type
+ERROR: 20 compilation errors. No code generated.
+
+
+Shader version: 430
+ERROR: node is still EOpNull!
+0:10 Function Definition: foo(f1[5][7]; (global 4-element array of 7-element array of float)
+0:10 Function Parameters:
+0:10 'a' (in 5-element array of 7-element array of float)
+0:? Sequence
+0:13 move second child to first child (temp 7-element array of float)
+0:13 'r' (temp 7-element array of float)
+0:13 direct index (temp 7-element array of float)
+0:13 'a' (in 5-element array of 7-element array of float)
+0:13 Constant:
+0:13 2 (const int)
+0:14 Constant:
+0:14 0.000000
+0:15 Constant:
+0:15 0.000000
+0:16 Branch: Return with expression
+0:16 Construct float (temp 4-element array of 7-element array of float)
+0:16 direct index (temp 7-element array of float)
+0:16 'a' (in 5-element array of 7-element array of float)
+0:16 Constant:
+0:16 0 (const int)
+0:16 direct index (temp 7-element array of float)
+0:16 'a' (in 5-element array of 7-element array of float)
+0:16 Constant:
+0:16 1 (const int)
+0:16 'r' (temp 7-element array of float)
+0:16 direct index (temp 7-element array of float)
+0:16 'a' (in 5-element array of 7-element array of float)
+0:16 Constant:
+0:16 3 (const int)
+0:17 Branch: Return with expression
+0:17 Construct float (temp 4-element array of 7-element array of float)
+0:17 direct index (temp 7-element array of float)
+0:17 'a' (in 5-element array of 7-element array of float)
+0:17 Constant:
+0:17 0 (const int)
+0:17 direct index (temp 7-element array of float)
+0:17 'a' (in 5-element array of 7-element array of float)
+0:17 Constant:
+0:17 1 (const int)
+0:17 'r' (temp 7-element array of float)
+0:17 direct index (temp 7-element array of float)
+0:17 'a' (in 5-element array of 7-element array of float)
+0:17 Constant:
+0:17 3 (const int)
+0:18 Branch: Return with expression
+0:18 Construct float (temp 4-element array of 7-element array of float)
+0:18 direct index (temp 7-element array of float)
+0:18 'a' (in 5-element array of 7-element array of float)
+0:18 Constant:
+0:18 0 (const int)
+0:18 direct index (temp 7-element array of float)
+0:18 'a' (in 5-element array of 7-element array of float)
+0:18 Constant:
+0:18 1 (const int)
+0:18 direct index (temp 7-element array of float)
+0:18 'a' (in 5-element array of 7-element array of float)
+0:18 Constant:
+0:18 2 (const int)
+0:18 direct index (temp 7-element array of float)
+0:18 'a' (in 5-element array of 7-element array of float)
+0:18 Constant:
+0:18 3 (const int)
+0:21 Function Definition: bar(f1[5][7]; (global void)
+0:21 Function Parameters:
+0:21 '' (in 5-element array of 7-element array of float)
+0:23 Function Definition: main( (global void)
+0:23 Function Parameters:
+0:? Sequence
+0:? Sequence
+0:28 move second child to first child (temp float)
+0:28 direct index (temp float)
+0:28 direct index (temp 2-element array of float)
+0:28 direct index (temp 4-element array of 2-element array of float)
+0:28 'gu' (temp 3-element array of 4-element array of 2-element array of float)
+0:28 Constant:
+0:28 2 (const int)
+0:28 Constant:
+0:28 4 (const int)
+0:28 Constant:
+0:28 1 (const int)
+0:28 Constant:
+0:28 4.000000
+0:30 Sequence
+0:30 move second child to first child (temp 3-element array of 2-element array of 4-component vector of float)
+0:30 'ca4' (temp 3-element array of 2-element array of 4-component vector of float)
+0:32 Constant:
+0:32 0.000000
+0:32 0.000000
+0:32 0.000000
+0:32 0.000000
+0:32 1.000000
+0:32 1.000000
+0:32 1.000000
+0:32 1.000000
+0:32 0.000000
+0:32 0.000000
+0:32 0.000000
+0:32 0.000000
+0:32 1.000000
+0:32 1.000000
+0:32 1.000000
+0:32 1.000000
+0:32 0.000000
+0:32 0.000000
+0:32 0.000000
+0:32 0.000000
+0:32 1.000000
+0:32 1.000000
+0:32 1.000000
+0:32 1.000000
+0:33 Sequence
+0:33 move second child to first child (temp 3-element array of 2-element array of 4-component vector of float)
+0:33 'caim' (temp 3-element array of 2-element array of 4-component vector of float)
+0:35 Constant:
+0:35 4.000000
+0:35 4.000000
+0:35 4.000000
+0:35 4.000000
+0:35 2.000000
+0:35 2.000000
+0:35 2.000000
+0:35 2.000000
+0:35 4.000000
+0:35 4.000000
+0:35 4.000000
+0:35 4.000000
+0:35 2.000000
+0:35 2.000000
+0:35 2.000000
+0:35 2.000000
+0:35 4.000000
+0:35 4.000000
+0:35 4.000000
+0:35 4.000000
+0:35 2.000000
+0:35 2.000000
+0:35 2.000000
+0:35 2.000000
+0:36 Sequence
+0:36 move second child to first child (temp 3-element array of 2-element array of 4-component vector of float)
+0:36 'caim2' (temp 3-element array of 2-element array of 4-component vector of float)
+0:38 Constant:
+0:38 4.000000
+0:38 4.000000
+0:38 4.000000
+0:38 4.000000
+0:38 2.000000
+0:38 2.000000
+0:38 2.000000
+0:38 2.000000
+0:38 4.000000
+0:38 4.000000
+0:38 4.000000
+0:38 4.000000
+0:38 2.000000
+0:38 2.000000
+0:38 2.000000
+0:38 2.000000
+0:38 4.000000
+0:38 4.000000
+0:38 4.000000
+0:38 4.000000
+0:38 2.000000
+0:38 2.000000
+0:38 2.000000
+0:38 2.000000
+0:39 Sequence
+0:39 move second child to first child (temp 3-element array of 2-element array of 4-component vector of float)
+0:39 'caim3' (temp 3-element array of 2-element array of 4-component vector of float)
+0:41 Constant:
+0:41 4.000000
+0:41 4.000000
+0:41 4.000000
+0:41 4.000000
+0:41 2.000000
+0:41 2.000000
+0:41 2.000000
+0:41 2.000000
+0:41 4.000000
+0:41 4.000000
+0:41 4.000000
+0:41 4.000000
+0:41 2.000000
+0:41 2.000000
+0:41 2.000000
+0:41 2.000000
+0:41 4.000000
+0:41 4.000000
+0:41 4.000000
+0:41 4.000000
+0:41 2.000000
+0:41 2.000000
+0:41 2.000000
+0:41 2.000000
+0:43 Sequence
+0:43 move second child to first child (temp 3-element array of 2-element array of 4-component vector of float)
+0:43 'a4' (temp 3-element array of 2-element array of 4-component vector of float)
+0:43 Constant:
+0:43 0.000000
+0:43 0.000000
+0:43 0.000000
+0:43 0.000000
+0:43 1.000000
+0:43 1.000000
+0:43 1.000000
+0:43 1.000000
+0:43 0.000000
+0:43 0.000000
+0:43 0.000000
+0:43 0.000000
+0:43 1.000000
+0:43 1.000000
+0:43 1.000000
+0:43 1.000000
+0:43 0.000000
+0:43 0.000000
+0:43 0.000000
+0:43 0.000000
+0:43 1.000000
+0:43 1.000000
+0:43 1.000000
+0:43 1.000000
+0:46 Sequence
+0:46 move second child to first child (temp 3-element array of 2-element array of 4-component vector of float)
+0:46 'aim' (temp 3-element array of 2-element array of 4-component vector of float)
+0:46 Constant:
+0:46 4.000000
+0:46 4.000000
+0:46 4.000000
+0:46 4.000000
+0:46 2.000000
+0:46 2.000000
+0:46 2.000000
+0:46 2.000000
+0:46 4.000000
+0:46 4.000000
+0:46 4.000000
+0:46 4.000000
+0:46 2.000000
+0:46 2.000000
+0:46 2.000000
+0:46 2.000000
+0:46 4.000000
+0:46 4.000000
+0:46 4.000000
+0:46 4.000000
+0:46 2.000000
+0:46 2.000000
+0:46 2.000000
+0:46 2.000000
+0:49 Sequence
+0:49 move second child to first child (temp 3-element array of 2-element array of 4-component vector of float)
+0:49 'aim2' (temp 3-element array of 2-element array of 4-component vector of float)
+0:49 Constant:
+0:49 4.000000
+0:49 4.000000
+0:49 4.000000
+0:49 4.000000
+0:49 2.000000
+0:49 2.000000
+0:49 2.000000
+0:49 2.000000
+0:49 4.000000
+0:49 4.000000
+0:49 4.000000
+0:49 4.000000
+0:49 2.000000
+0:49 2.000000
+0:49 2.000000
+0:49 2.000000
+0:49 4.000000
+0:49 4.000000
+0:49 4.000000
+0:49 4.000000
+0:49 2.000000
+0:49 2.000000
+0:49 2.000000
+0:49 2.000000
+0:52 Sequence
+0:52 move second child to first child (temp 3-element array of 2-element array of 4-component vector of float)
+0:52 'aim3' (temp 3-element array of 2-element array of 4-component vector of float)
+0:52 Constant:
+0:52 4.000000
+0:52 4.000000
+0:52 4.000000
+0:52 4.000000
+0:52 2.000000
+0:52 2.000000
+0:52 2.000000
+0:52 2.000000
+0:52 4.000000
+0:52 4.000000
+0:52 4.000000
+0:52 4.000000
+0:52 2.000000
+0:52 2.000000
+0:52 2.000000
+0:52 2.000000
+0:52 4.000000
+0:52 4.000000
+0:52 4.000000
+0:52 4.000000
+0:52 2.000000
+0:52 2.000000
+0:52 2.000000
+0:52 2.000000
+0:69 move second child to first child (temp 4-element array of 7-element array of float)
+0:69 'g4' (global 4-element array of 7-element array of float)
+0:69 Function Call: foo(f1[5][7]; (global 4-element array of 7-element array of float)
+0:69 'g5' (global 5-element array of 7-element array of float)
+0:70 'g5' (global 5-element array of 7-element array of float)
+0:71 'gu' (global implicitly-sized array of 7-element array of float)
+0:73 Constant:
+0:73 0.000000
+0:74 Function Call: bar(f1[5][7]; (global void)
+0:74 'g5' (global 5-element array of 7-element array of float)
+0:76 Test condition and select (temp void)
+0:76 Condition
+0:76 Compare Equal (temp bool)
+0:76 Function Call: foo(f1[5][7]; (global 4-element array of 7-element array of float)
+0:76 'g5' (global 5-element array of 7-element array of float)
+0:76 'g4' (global 4-element array of 7-element array of float)
+0:76 true case is null
+0:78 Test condition and select (temp void)
+0:78 Condition
+0:78 Constant:
+0:78 false (const bool)
+0:78 true case is null
+0:82 move second child to first child (temp float)
+0:82 direct index (temp float)
+0:82 direct index (temp 7-element array of float)
+0:82 'u' (temp 5-element array of 7-element array of float)
+0:82 Constant:
+0:82 2 (const int)
+0:82 Constant:
+0:82 2 (const int)
+0:82 Constant:
+0:82 3.000000
+0:84 move second child to first child (temp float)
+0:84 direct index (temp float)
+0:84 direct index (temp 7-element array of float)
+0:84 'u' (temp 5-element array of 7-element array of float)
+0:84 Constant:
+0:84 5 (const int)
+0:84 Constant:
+0:84 2 (const int)
+0:84 Constant:
+0:84 5.000000
+0:85 Function Call: foo(f1[5][7]; (global 4-element array of 7-element array of float)
+0:85 'u' (temp 5-element array of 7-element array of float)
+0:88 Function Definition: foo3( (global void)
+0:88 Function Parameters:
+0:? Sequence
+0:91 Constant:
+0:91 1 (const int)
+0:92 move second child to first child (temp float)
+0:92 direct index (temp float)
+0:92 direct index (temp 7-element array of float)
+0:92 direct index (temp 5-element array of 7-element array of float)
+0:92 'resize1' (temp 3-element array of 5-element array of 7-element array of float)
+0:92 Constant:
+0:92 1 (const int)
+0:92 Constant:
+0:92 4 (const int)
+0:92 Constant:
+0:92 5 (const int)
+0:92 Constant:
+0:92 2.000000
+0:93 Constant:
+0:93 1 (const int)
+0:95 Constant:
+0:95 3 (const int)
+0:96 Constant:
+0:96 5 (const int)
+0:97 Constant:
+0:97 7 (const int)
+0:98 Constant:
+0:98 0.000000
+0:? Linker Objects
+0:? 'many' (global 1-element array of 2-element array of 3-element array of 4-element array of 5-element array of 6-element array of float)
+0:? 'gu' (global implicitly-sized array of 7-element array of float)
+0:? 'gimp' (global implicitly-sized array of implicitly-sized array of float)
+0:? 'g4' (global 4-element array of 7-element array of float)
+0:? 'g5' (global 5-element array of 7-element array of float)
+
+
+Linked fragment stage:
+
+
+Shader version: 430
+ERROR: node is still EOpNull!
+0:10 Function Definition: foo(f1[5][7]; (global 4-element array of 7-element array of float)
+0:10 Function Parameters:
+0:10 'a' (in 5-element array of 7-element array of float)
+0:? Sequence
+0:13 move second child to first child (temp 7-element array of float)
+0:13 'r' (temp 7-element array of float)
+0:13 direct index (temp 7-element array of float)
+0:13 'a' (in 5-element array of 7-element array of float)
+0:13 Constant:
+0:13 2 (const int)
+0:14 Constant:
+0:14 0.000000
+0:15 Constant:
+0:15 0.000000
+0:16 Branch: Return with expression
+0:16 Construct float (temp 4-element array of 7-element array of float)
+0:16 direct index (temp 7-element array of float)
+0:16 'a' (in 5-element array of 7-element array of float)
+0:16 Constant:
+0:16 0 (const int)
+0:16 direct index (temp 7-element array of float)
+0:16 'a' (in 5-element array of 7-element array of float)
+0:16 Constant:
+0:16 1 (const int)
+0:16 'r' (temp 7-element array of float)
+0:16 direct index (temp 7-element array of float)
+0:16 'a' (in 5-element array of 7-element array of float)
+0:16 Constant:
+0:16 3 (const int)
+0:17 Branch: Return with expression
+0:17 Construct float (temp 4-element array of 7-element array of float)
+0:17 direct index (temp 7-element array of float)
+0:17 'a' (in 5-element array of 7-element array of float)
+0:17 Constant:
+0:17 0 (const int)
+0:17 direct index (temp 7-element array of float)
+0:17 'a' (in 5-element array of 7-element array of float)
+0:17 Constant:
+0:17 1 (const int)
+0:17 'r' (temp 7-element array of float)
+0:17 direct index (temp 7-element array of float)
+0:17 'a' (in 5-element array of 7-element array of float)
+0:17 Constant:
+0:17 3 (const int)
+0:18 Branch: Return with expression
+0:18 Construct float (temp 4-element array of 7-element array of float)
+0:18 direct index (temp 7-element array of float)
+0:18 'a' (in 5-element array of 7-element array of float)
+0:18 Constant:
+0:18 0 (const int)
+0:18 direct index (temp 7-element array of float)
+0:18 'a' (in 5-element array of 7-element array of float)
+0:18 Constant:
+0:18 1 (const int)
+0:18 direct index (temp 7-element array of float)
+0:18 'a' (in 5-element array of 7-element array of float)
+0:18 Constant:
+0:18 2 (const int)
+0:18 direct index (temp 7-element array of float)
+0:18 'a' (in 5-element array of 7-element array of float)
+0:18 Constant:
+0:18 3 (const int)
+0:21 Function Definition: bar(f1[5][7]; (global void)
+0:21 Function Parameters:
+0:21 '' (in 5-element array of 7-element array of float)
+0:23 Function Definition: main( (global void)
+0:23 Function Parameters:
+0:? Sequence
+0:? Sequence
+0:28 move second child to first child (temp float)
+0:28 direct index (temp float)
+0:28 direct index (temp 2-element array of float)
+0:28 direct index (temp 4-element array of 2-element array of float)
+0:28 'gu' (temp 3-element array of 4-element array of 2-element array of float)
+0:28 Constant:
+0:28 2 (const int)
+0:28 Constant:
+0:28 4 (const int)
+0:28 Constant:
+0:28 1 (const int)
+0:28 Constant:
+0:28 4.000000
+0:30 Sequence
+0:30 move second child to first child (temp 3-element array of 2-element array of 4-component vector of float)
+0:30 'ca4' (temp 3-element array of 2-element array of 4-component vector of float)
+0:32 Constant:
+0:32 0.000000
+0:32 0.000000
+0:32 0.000000
+0:32 0.000000
+0:32 1.000000
+0:32 1.000000
+0:32 1.000000
+0:32 1.000000
+0:32 0.000000
+0:32 0.000000
+0:32 0.000000
+0:32 0.000000
+0:32 1.000000
+0:32 1.000000
+0:32 1.000000
+0:32 1.000000
+0:32 0.000000
+0:32 0.000000
+0:32 0.000000
+0:32 0.000000
+0:32 1.000000
+0:32 1.000000
+0:32 1.000000
+0:32 1.000000
+0:33 Sequence
+0:33 move second child to first child (temp 3-element array of 2-element array of 4-component vector of float)
+0:33 'caim' (temp 3-element array of 2-element array of 4-component vector of float)
+0:35 Constant:
+0:35 4.000000
+0:35 4.000000
+0:35 4.000000
+0:35 4.000000
+0:35 2.000000
+0:35 2.000000
+0:35 2.000000
+0:35 2.000000
+0:35 4.000000
+0:35 4.000000
+0:35 4.000000
+0:35 4.000000
+0:35 2.000000
+0:35 2.000000
+0:35 2.000000
+0:35 2.000000
+0:35 4.000000
+0:35 4.000000
+0:35 4.000000
+0:35 4.000000
+0:35 2.000000
+0:35 2.000000
+0:35 2.000000
+0:35 2.000000
+0:36 Sequence
+0:36 move second child to first child (temp 3-element array of 2-element array of 4-component vector of float)
+0:36 'caim2' (temp 3-element array of 2-element array of 4-component vector of float)
+0:38 Constant:
+0:38 4.000000
+0:38 4.000000
+0:38 4.000000
+0:38 4.000000
+0:38 2.000000
+0:38 2.000000
+0:38 2.000000
+0:38 2.000000
+0:38 4.000000
+0:38 4.000000
+0:38 4.000000
+0:38 4.000000
+0:38 2.000000
+0:38 2.000000
+0:38 2.000000
+0:38 2.000000
+0:38 4.000000
+0:38 4.000000
+0:38 4.000000
+0:38 4.000000
+0:38 2.000000
+0:38 2.000000
+0:38 2.000000
+0:38 2.000000
+0:39 Sequence
+0:39 move second child to first child (temp 3-element array of 2-element array of 4-component vector of float)
+0:39 'caim3' (temp 3-element array of 2-element array of 4-component vector of float)
+0:41 Constant:
+0:41 4.000000
+0:41 4.000000
+0:41 4.000000
+0:41 4.000000
+0:41 2.000000
+0:41 2.000000
+0:41 2.000000
+0:41 2.000000
+0:41 4.000000
+0:41 4.000000
+0:41 4.000000
+0:41 4.000000
+0:41 2.000000
+0:41 2.000000
+0:41 2.000000
+0:41 2.000000
+0:41 4.000000
+0:41 4.000000
+0:41 4.000000
+0:41 4.000000
+0:41 2.000000
+0:41 2.000000
+0:41 2.000000
+0:41 2.000000
+0:43 Sequence
+0:43 move second child to first child (temp 3-element array of 2-element array of 4-component vector of float)
+0:43 'a4' (temp 3-element array of 2-element array of 4-component vector of float)
+0:43 Constant:
+0:43 0.000000
+0:43 0.000000
+0:43 0.000000
+0:43 0.000000
+0:43 1.000000
+0:43 1.000000
+0:43 1.000000
+0:43 1.000000
+0:43 0.000000
+0:43 0.000000
+0:43 0.000000
+0:43 0.000000
+0:43 1.000000
+0:43 1.000000
+0:43 1.000000
+0:43 1.000000
+0:43 0.000000
+0:43 0.000000
+0:43 0.000000
+0:43 0.000000
+0:43 1.000000
+0:43 1.000000
+0:43 1.000000
+0:43 1.000000
+0:46 Sequence
+0:46 move second child to first child (temp 3-element array of 2-element array of 4-component vector of float)
+0:46 'aim' (temp 3-element array of 2-element array of 4-component vector of float)
+0:46 Constant:
+0:46 4.000000
+0:46 4.000000
+0:46 4.000000
+0:46 4.000000
+0:46 2.000000
+0:46 2.000000
+0:46 2.000000
+0:46 2.000000
+0:46 4.000000
+0:46 4.000000
+0:46 4.000000
+0:46 4.000000
+0:46 2.000000
+0:46 2.000000
+0:46 2.000000
+0:46 2.000000
+0:46 4.000000
+0:46 4.000000
+0:46 4.000000
+0:46 4.000000
+0:46 2.000000
+0:46 2.000000
+0:46 2.000000
+0:46 2.000000
+0:49 Sequence
+0:49 move second child to first child (temp 3-element array of 2-element array of 4-component vector of float)
+0:49 'aim2' (temp 3-element array of 2-element array of 4-component vector of float)
+0:49 Constant:
+0:49 4.000000
+0:49 4.000000
+0:49 4.000000
+0:49 4.000000
+0:49 2.000000
+0:49 2.000000
+0:49 2.000000
+0:49 2.000000
+0:49 4.000000
+0:49 4.000000
+0:49 4.000000
+0:49 4.000000
+0:49 2.000000
+0:49 2.000000
+0:49 2.000000
+0:49 2.000000
+0:49 4.000000
+0:49 4.000000
+0:49 4.000000
+0:49 4.000000
+0:49 2.000000
+0:49 2.000000
+0:49 2.000000
+0:49 2.000000
+0:52 Sequence
+0:52 move second child to first child (temp 3-element array of 2-element array of 4-component vector of float)
+0:52 'aim3' (temp 3-element array of 2-element array of 4-component vector of float)
+0:52 Constant:
+0:52 4.000000
+0:52 4.000000
+0:52 4.000000
+0:52 4.000000
+0:52 2.000000
+0:52 2.000000
+0:52 2.000000
+0:52 2.000000
+0:52 4.000000
+0:52 4.000000
+0:52 4.000000
+0:52 4.000000
+0:52 2.000000
+0:52 2.000000
+0:52 2.000000
+0:52 2.000000
+0:52 4.000000
+0:52 4.000000
+0:52 4.000000
+0:52 4.000000
+0:52 2.000000
+0:52 2.000000
+0:52 2.000000
+0:52 2.000000
+0:69 move second child to first child (temp 4-element array of 7-element array of float)
+0:69 'g4' (global 4-element array of 7-element array of float)
+0:69 Function Call: foo(f1[5][7]; (global 4-element array of 7-element array of float)
+0:69 'g5' (global 5-element array of 7-element array of float)
+0:70 'g5' (global 5-element array of 7-element array of float)
+0:71 'gu' (global 1-element array of 7-element array of float)
+0:73 Constant:
+0:73 0.000000
+0:74 Function Call: bar(f1[5][7]; (global void)
+0:74 'g5' (global 5-element array of 7-element array of float)
+0:76 Test condition and select (temp void)
+0:76 Condition
+0:76 Compare Equal (temp bool)
+0:76 Function Call: foo(f1[5][7]; (global 4-element array of 7-element array of float)
+0:76 'g5' (global 5-element array of 7-element array of float)
+0:76 'g4' (global 4-element array of 7-element array of float)
+0:76 true case is null
+0:78 Test condition and select (temp void)
+0:78 Condition
+0:78 Constant:
+0:78 false (const bool)
+0:78 true case is null
+0:82 move second child to first child (temp float)
+0:82 direct index (temp float)
+0:82 direct index (temp 7-element array of float)
+0:82 'u' (temp 5-element array of 7-element array of float)
+0:82 Constant:
+0:82 2 (const int)
+0:82 Constant:
+0:82 2 (const int)
+0:82 Constant:
+0:82 3.000000
+0:84 move second child to first child (temp float)
+0:84 direct index (temp float)
+0:84 direct index (temp 7-element array of float)
+0:84 'u' (temp 5-element array of 7-element array of float)
+0:84 Constant:
+0:84 5 (const int)
+0:84 Constant:
+0:84 2 (const int)
+0:84 Constant:
+0:84 5.000000
+0:85 Function Call: foo(f1[5][7]; (global 4-element array of 7-element array of float)
+0:85 'u' (temp 5-element array of 7-element array of float)
+0:88 Function Definition: foo3( (global void)
+0:88 Function Parameters:
+0:? Sequence
+0:91 Constant:
+0:91 1 (const int)
+0:92 move second child to first child (temp float)
+0:92 direct index (temp float)
+0:92 direct index (temp 7-element array of float)
+0:92 direct index (temp 5-element array of 7-element array of float)
+0:92 'resize1' (temp 3-element array of 5-element array of 7-element array of float)
+0:92 Constant:
+0:92 1 (const int)
+0:92 Constant:
+0:92 4 (const int)
+0:92 Constant:
+0:92 5 (const int)
+0:92 Constant:
+0:92 2.000000
+0:93 Constant:
+0:93 1 (const int)
+0:95 Constant:
+0:95 3 (const int)
+0:96 Constant:
+0:96 5 (const int)
+0:97 Constant:
+0:97 7 (const int)
+0:98 Constant:
+0:98 0.000000
+0:? Linker Objects
+0:? 'many' (global 1-element array of 2-element array of 3-element array of 4-element array of 5-element array of 6-element array of float)
+0:? 'gu' (global 1-element array of 7-element array of float)
+0:? 'gimp' (global 1-element array of implicitly-sized array of float)
+0:? 'g4' (global 4-element array of 7-element array of float)
+0:? 'g5' (global 5-element array of 7-element array of float)
+
diff --git a/Test/baseResults/450.vert.out b/Test/baseResults/450.vert.out
index aecef87..44aff42 100644
--- a/Test/baseResults/450.vert.out
+++ b/Test/baseResults/450.vert.out
@@ -2,7 +2,6 @@
Warning, version 450 is not yet complete; most version-specific features are present, but some are missing.
ERROR: 0:12: 'out' : cannot be bool
ERROR: 0:13: 'sampler2D' : sampler/image types can only be used in uniform variables or function parameters: outo
-WARNING: 0:15: 'Not supported yet.' : arrays of arrays
ERROR: 2 compilation errors. No code generated.
diff --git a/Test/baseResults/specExamples.frag.out b/Test/baseResults/specExamples.frag.out
index bf3ae55..f73c7e3 100644
--- a/Test/baseResults/specExamples.frag.out
+++ b/Test/baseResults/specExamples.frag.out
@@ -17,10 +17,6 @@
ERROR: 0:112: 'redeclaration' : all redeclarations must use the same depth layout on gl_FragDepth
ERROR: 0:118: 'redeclaration' : all redeclarations must use the same depth layout on gl_FragDepth
ERROR: 0:121: 'redeclaration' : all redeclarations must use the same depth layout on gl_FragDepth
-WARNING: 0:146: 'Not supported yet.' : arrays of arrays
-ERROR: 0:150: 'constructor' : constructing from a non-dereferenced array
-ERROR: 0:150: '=' : cannot convert from 'const float' to 'temp 3-element array of 2-element array of 4-component vector of float'
-ERROR: 0:152: 'constructor' : cannot convert parameter 1 from 'const 2-element array of 4-component vector of float' to 'temp 4-component vector of float'
ERROR: 0:172: 'x' : undeclared identifier
ERROR: 0:172: '[]' : scalar integer expression required
ERROR: 0:175: 'x' : undeclared identifier
@@ -42,7 +38,7 @@
ERROR: 0:227: 'in' : not allowed in nested scope
ERROR: 0:228: 'in' : not allowed in nested scope
ERROR: 0:232: 'out' : not allowed in nested scope
-ERROR: 41 compilation errors. No code generated.
+ERROR: 38 compilation errors. No code generated.
Shader version: 430
@@ -164,6 +160,41 @@
0:149 0.100000
0:149 0.100000
0:149 0.100000
+0:150 Sequence
+0:150 move second child to first child (temp 3-element array of 2-element array of 4-component vector of float)
+0:150 'a3' (temp 3-element array of 2-element array of 4-component vector of float)
+0:150 Construct vec4 (temp 3-element array of 2-element array of 4-component vector of float)
+0:150 'b' (temp 2-element array of 4-component vector of float)
+0:150 'b' (temp 2-element array of 4-component vector of float)
+0:150 'b' (temp 2-element array of 4-component vector of float)
+0:152 Sequence
+0:152 move second child to first child (temp 3-element array of 2-element array of 4-component vector of float)
+0:152 'a4' (temp 3-element array of 2-element array of 4-component vector of float)
+0:152 Constant:
+0:152 0.000000
+0:152 0.000000
+0:152 0.000000
+0:152 0.000000
+0:152 1.000000
+0:152 1.000000
+0:152 1.000000
+0:152 1.000000
+0:152 0.000000
+0:152 0.000000
+0:152 0.000000
+0:152 0.000000
+0:152 1.000000
+0:152 1.000000
+0:152 1.000000
+0:152 1.000000
+0:152 0.000000
+0:152 0.000000
+0:152 0.000000
+0:152 0.000000
+0:152 1.000000
+0:152 1.000000
+0:152 1.000000
+0:152 1.000000
0:? Sequence
0:159 Sequence
0:159 Sequence
@@ -191,7 +222,7 @@
0:171 Constant:
0:171 3 (const int)
0:172 Constant:
-0:172 4 (const int)
+0:172 2 (const int)
0:175 Constant:
0:175 0.000000
0:178 Constant:
@@ -418,6 +449,41 @@
0:149 0.100000
0:149 0.100000
0:149 0.100000
+0:150 Sequence
+0:150 move second child to first child (temp 3-element array of 2-element array of 4-component vector of float)
+0:150 'a3' (temp 3-element array of 2-element array of 4-component vector of float)
+0:150 Construct vec4 (temp 3-element array of 2-element array of 4-component vector of float)
+0:150 'b' (temp 2-element array of 4-component vector of float)
+0:150 'b' (temp 2-element array of 4-component vector of float)
+0:150 'b' (temp 2-element array of 4-component vector of float)
+0:152 Sequence
+0:152 move second child to first child (temp 3-element array of 2-element array of 4-component vector of float)
+0:152 'a4' (temp 3-element array of 2-element array of 4-component vector of float)
+0:152 Constant:
+0:152 0.000000
+0:152 0.000000
+0:152 0.000000
+0:152 0.000000
+0:152 1.000000
+0:152 1.000000
+0:152 1.000000
+0:152 1.000000
+0:152 0.000000
+0:152 0.000000
+0:152 0.000000
+0:152 0.000000
+0:152 1.000000
+0:152 1.000000
+0:152 1.000000
+0:152 1.000000
+0:152 0.000000
+0:152 0.000000
+0:152 0.000000
+0:152 0.000000
+0:152 1.000000
+0:152 1.000000
+0:152 1.000000
+0:152 1.000000
0:? Sequence
0:159 Sequence
0:159 Sequence
@@ -445,7 +511,7 @@
0:171 Constant:
0:171 3 (const int)
0:172 Constant:
-0:172 4 (const int)
+0:172 2 (const int)
0:175 Constant:
0:175 0.000000
0:178 Constant:
diff --git a/Test/baseResults/specExamples.vert.out b/Test/baseResults/specExamples.vert.out
index 80e4929..8359f12 100644
--- a/Test/baseResults/specExamples.vert.out
+++ b/Test/baseResults/specExamples.vert.out
@@ -1,6 +1,5 @@
specExamples.vert
Warning, version 430 is not yet complete; most version-specific features are present, but some are missing.
-ERROR: 0:23: 'transforms' : redeclaration of array with size
ERROR: 0:29: 'location' : can only appy to uniform, buffer, in, or out storage qualifiers
ERROR: 0:31: 'triangles' : unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)
ERROR: 0:31: 'invocations' : there is no such layout identifier for this stage taking an assigned value
@@ -35,11 +34,7 @@
ERROR: 0:136: '' : function does not return a value: funcB
ERROR: 0:153: '' : function does not return a value: func3
ERROR: 0:170: 'coherent' : argument cannot drop memory qualifier when passed to formal parameter
-WARNING: 0:192: 'Not supported yet.' : arrays of arrays
-ERROR: 0:192: 'constructor' : constructing from a non-dereferenced array
-ERROR: 0:193: 'constructor' : constructing from a non-dereferenced array
-ERROR: 0:194: 'constructor' : constructing from a non-dereferenced array
-ERROR: 37 compilation errors. No code generated.
+ERROR: 33 compilation errors. No code generated.
Shader version: 430
@@ -269,18 +264,25 @@
0:191 1.000000
0:191 1.000000
0:191 1.000000
-0:192 Constant:
-0:192 0.000000
-0:193 Constant:
-0:193 0.000000
-0:194 Constant:
-0:194 0.000000
+0:192 Construct vec4 (temp 3-element array of 2-element array of 4-component vector of float)
+0:192 'b' (temp 2-element array of 4-component vector of float)
+0:192 'b' (temp 2-element array of 4-component vector of float)
+0:192 'b' (temp 2-element array of 4-component vector of float)
+0:193 Construct vec4 (temp 3-element array of 2-element array of 4-component vector of float)
+0:193 'b' (temp 2-element array of 4-component vector of float)
+0:193 'b' (temp 2-element array of 4-component vector of float)
+0:193 'b' (temp 2-element array of 4-component vector of float)
+0:194 Construct vec4 (temp 3-element array of 2-element array of 4-component vector of float)
+0:194 'b' (temp 2-element array of 4-component vector of float)
+0:194 'b' (temp 2-element array of 4-component vector of float)
+0:194 'b' (temp 2-element array of 4-component vector of float)
0:? Linker Objects
0:? 'Coords' (out block{out 4-component vector of float Position, out 2-component vector of float Texture})
0:? 'anon@0' (out block{out 4-component vector of float Color})
0:? 'transforms' (layout(column_major shared ) uniform 4-element array of block{layout(column_major shared ) uniform 4X4 matrix of float ModelViewMatrix, layout(column_major shared ) uniform 4X4 matrix of float ModelViewProjectionMatrix, layout(column_major shared ) uniform implicitly-sized array of 4-component vector of float a, layout(column_major shared ) uniform float Deformation})
0:? 'normal' (layout(location=3 ) in 4-component vector of float)
0:? 'colors' (layout(location=6 ) in 3-element array of 4-component vector of float)
+0:? 'transforms2' (layout(location=9 ) in 2-element array of 4X4 matrix of float)
0:? 's' (layout(location=3 ) temp structure{global 3-component vector of float a1, global 2X2 matrix of float b, global 2-element array of 4-component vector of float c})
0:? 'var1' (smooth out 4-component vector of float)
0:? 'anon@1' (out block{out 4-component vector of float var2, out 2-component vector of float var3, out 3-component vector of float var4})
@@ -546,18 +548,25 @@
0:191 1.000000
0:191 1.000000
0:191 1.000000
-0:192 Constant:
-0:192 0.000000
-0:193 Constant:
-0:193 0.000000
-0:194 Constant:
-0:194 0.000000
+0:192 Construct vec4 (temp 3-element array of 2-element array of 4-component vector of float)
+0:192 'b' (temp 2-element array of 4-component vector of float)
+0:192 'b' (temp 2-element array of 4-component vector of float)
+0:192 'b' (temp 2-element array of 4-component vector of float)
+0:193 Construct vec4 (temp 3-element array of 2-element array of 4-component vector of float)
+0:193 'b' (temp 2-element array of 4-component vector of float)
+0:193 'b' (temp 2-element array of 4-component vector of float)
+0:193 'b' (temp 2-element array of 4-component vector of float)
+0:194 Construct vec4 (temp 3-element array of 2-element array of 4-component vector of float)
+0:194 'b' (temp 2-element array of 4-component vector of float)
+0:194 'b' (temp 2-element array of 4-component vector of float)
+0:194 'b' (temp 2-element array of 4-component vector of float)
0:? Linker Objects
0:? 'Coords' (out block{out 4-component vector of float Position, out 2-component vector of float Texture})
0:? 'anon@0' (out block{out 4-component vector of float Color})
0:? 'transforms' (layout(column_major shared ) uniform 4-element array of block{layout(column_major shared ) uniform 4X4 matrix of float ModelViewMatrix, layout(column_major shared ) uniform 4X4 matrix of float ModelViewProjectionMatrix, layout(column_major shared ) uniform 1-element array of 4-component vector of float a, layout(column_major shared ) uniform float Deformation})
0:? 'normal' (layout(location=3 ) in 4-component vector of float)
0:? 'colors' (layout(location=6 ) in 3-element array of 4-component vector of float)
+0:? 'transforms2' (layout(location=9 ) in 2-element array of 4X4 matrix of float)
0:? 's' (layout(location=3 ) temp structure{global 3-component vector of float a1, global 2X2 matrix of float b, global 2-element array of 4-component vector of float c})
0:? 'var1' (smooth out 4-component vector of float)
0:? 'anon@1' (out block{out 4-component vector of float var2, out 2-component vector of float var3, out 3-component vector of float var4})
diff --git a/Test/specExamples.vert b/Test/specExamples.vert
index a9c9178..9df1561 100644
--- a/Test/specExamples.vert
+++ b/Test/specExamples.vert
@@ -20,7 +20,7 @@
layout(location = 3) in vec4 normal;
layout(location = 6) in vec4 colors[3];
-layout(location = 9) in mat4 transforms[2];
+layout(location = 9) in mat4 transforms2[2];
layout(location = 3) struct S {
vec3 a1;
diff --git a/Test/testlist b/Test/testlist
index 797dca2..3478040 100644
--- a/Test/testlist
+++ b/Test/testlist
@@ -76,6 +76,7 @@
410.geom
430.vert
430.comp
+430AofA.frag
440.vert
440.frag
450.vert
diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h
index fd12bcc..8900b5b 100644
--- a/glslang/Include/Types.h
+++ b/glslang/Include/Types.h
@@ -896,15 +896,32 @@
// and using only shallow copy
TType(const TType& type, int derefIndex, bool rowMajor = false)
{
- if (! type.isArray() && (type.basicType == EbtStruct || type.basicType == EbtBlock)) {
+ if (type.isArray()) {
+ shallowCopy(type);
+ if (type.getArraySizes()->getNumDims() == 1) {
+ arraySizes = nullptr;
+ } else {
+ // want our own copy of the array, so we can edit it
+ arraySizes = new TArraySizes;
+ arraySizes->copyDereferenced(*type.arraySizes);
+ }
+ } else if (type.basicType == EbtStruct || type.basicType == EbtBlock) {
// do a structure dereference
const TTypeList& memberList = *type.getStruct();
shallowCopy(*memberList[derefIndex].type);
return;
} else {
- // do an array/vector/matrix dereference
+ // do a vector/matrix dereference
shallowCopy(type);
- dereference(rowMajor);
+ if (matrixCols > 0) {
+ if (rowMajor)
+ vectorSize = matrixCols;
+ else
+ vectorSize = matrixRows;
+ matrixCols = 0;
+ matrixRows = 0;
+ } else if (vectorSize > 1)
+ vectorSize = 1;
}
}
// for making structures, ...
@@ -990,28 +1007,13 @@
qualifier = parentType.qualifier;
sampler = parentType.sampler;
if (parentType.arraySizes)
- setArraySizes(parentType.arraySizes);
+ newArraySizes(*parentType.arraySizes);
if (parentType.userDef) {
structure = parentType.userDef->getWritableStruct();
setTypeName(parentType.userDef->getTypeName());
}
}
- virtual void dereference(bool rowMajor = false)
- {
- if (arraySizes)
- arraySizes = nullptr;
- else if (matrixCols > 0) {
- if (rowMajor)
- vectorSize = matrixCols;
- else
- vectorSize = matrixRows;
- matrixCols = 0;
- matrixRows = 0;
- } else if (vectorSize > 1)
- vectorSize = 1;
- }
-
virtual void hideMember() { basicType = EbtVoid; vectorSize = 1; }
virtual bool hiddenMember() const { return basicType == EbtVoid; }
@@ -1038,17 +1040,20 @@
virtual int getVectorSize() const { return vectorSize; }
virtual int getMatrixCols() const { return matrixCols; }
virtual int getMatrixRows() const { return matrixRows; }
- virtual int getArraySize() const { return arraySizes->getOuterSize(); }
+ virtual int getOuterArraySize() const { return arraySizes->getOuterSize(); }
+ virtual int getCumulativeArraySize() const { return arraySizes->getCumulativeSize(); }
virtual bool isArrayOfArrays() const { return arraySizes != nullptr && arraySizes->getNumDims() > 1; }
virtual int getImplicitArraySize() const { return arraySizes->getImplicitSize(); }
+ virtual const TArraySizes* getArraySizes() const { return arraySizes; }
+ virtual TArraySizes& getArraySizes() { assert(arraySizes != nullptr); return *arraySizes; }
virtual bool isScalar() const { return vectorSize == 1 && ! isStruct() && ! isArray(); }
virtual bool isVector() const { return vectorSize > 1; }
virtual bool isMatrix() const { return matrixCols ? true : false; }
virtual bool isArray() const { return arraySizes != nullptr; }
- virtual bool isExplicitlySizedArray() const { return isArray() && getArraySize() != UnsizedArraySize; }
- virtual bool isImplicitlySizedArray() const { return isArray() && getArraySize() == UnsizedArraySize && qualifier.storage != EvqBuffer; }
- virtual bool isRuntimeSizedArray() const { return isArray() && getArraySize() == UnsizedArraySize && qualifier.storage == EvqBuffer; }
+ virtual bool isExplicitlySizedArray() const { return isArray() && getOuterArraySize() != UnsizedArraySize; }
+ virtual bool isImplicitlySizedArray() const { return isArray() && getOuterArraySize() == UnsizedArraySize && qualifier.storage != EvqBuffer; }
+ virtual bool isRuntimeSizedArray() const { return isArray() && getOuterArraySize() == UnsizedArraySize && qualifier.storage == EvqBuffer; }
virtual bool isStruct() const { return structure != nullptr; }
virtual bool isImage() const { return basicType == EbtSampler && getSampler().image; }
@@ -1125,22 +1130,27 @@
assert(type.arraySizes != nullptr);
*arraySizes = *type.arraySizes;
}
- void setArraySizes(TArraySizes* s)
+ void newArraySizes(const TArraySizes& s)
{
// For setting a fresh new set of array sizes, not yet worrying about sharing.
arraySizes = new TArraySizes;
- assert(s != nullptr);
- *arraySizes = *s;
+ *arraySizes = s;
}
- void setArraySizes(const TType& type) { setArraySizes(type.arraySizes); }
- void changeArraySize(int s) { arraySizes->changeOuterSize(s); }
+ void addArrayOuterSizes(const TArraySizes& s)
+ {
+ if (arraySizes == nullptr)
+ newArraySizes(s);
+ else
+ arraySizes->addOuterSizes(s);
+ }
+ void changeOuterArraySize(int s) { arraySizes->changeOuterSize(s); }
void setImplicitArraySize (int s) { arraySizes->setImplicitSize(s); }
// Recursively make the implicit array size the explicit array size, through the type tree.
void adoptImplicitArraySizes()
{
if (isImplicitlySizedArray())
- changeArraySize(getImplicitArraySize());
+ changeOuterArraySize(getImplicitArraySize());
if (isStruct()) {
for (int i = 0; i < (int)structure->size(); ++i)
(*structure)[i].type->adoptImplicitArraySizes();
@@ -1151,7 +1161,7 @@
{
return TType::getBasicString(basicType);
}
-
+
static const char* getBasicString(TBasicType t)
{
switch (t) {
@@ -1242,12 +1252,12 @@
p += snprintf(p, end - p, "writeonly ");
p += snprintf(p, end - p, "%s ", getStorageQualifierString());
if (arraySizes) {
- if (arraySizes->getOuterSize() == UnsizedArraySize) {
- p += snprintf(p, end - p, "implicitly-sized array of ");
- } else {
- for(int i = 0; i < (int)arraySizes->getNumDims() ; ++i) {
- p += snprintf(p, end - p, "%d-element array of ", (*arraySizes)[i]);
- }
+ for(int i = 0; i < (int)arraySizes->getNumDims(); ++i) {
+ int size = arraySizes->getDimSize(i);
+ if (size == 0)
+ p += snprintf(p, end - p, "implicitly-sized array of ");
+ else
+ p += snprintf(p, end - p, "%d-element array of ", arraySizes->getDimSize(i));
}
}
if (qualifier.precision != EpqNone)
@@ -1310,10 +1320,8 @@
else
components = vectorSize;
- if (isArray()) {
- // this function can only be used in paths that have a known array size
- assert(isExplicitlySizedArray());
- components *= getArraySize();
+ if (arraySizes != nullptr) {
+ components *= arraySizes->getCumulativeSize();
}
return components;
@@ -1371,7 +1379,14 @@
bool sameArrayness(const TType& right) const
{
return ((arraySizes == nullptr && right.arraySizes == nullptr) ||
- (arraySizes && right.arraySizes && *arraySizes == *right.arraySizes));
+ (arraySizes != nullptr && right.arraySizes != nullptr && *arraySizes == *right.arraySizes));
+ }
+
+ // See if two type's arrayness match in everything except their outer dimension
+ bool sameInnerArrayness(const TType& right) const
+ {
+ assert(arraySizes != nullptr && right.arraySizes != nullptr);
+ return arraySizes->sameInnerArrayness(*right.arraySizes);
}
// See if two type's elements match in all ways except basic type
diff --git a/glslang/Include/arrays.h b/glslang/Include/arrays.h
index 67f91e9..cc2cdab 100644
--- a/glslang/Include/arrays.h
+++ b/glslang/Include/arrays.h
@@ -43,13 +43,13 @@
namespace glslang {
-// This is used to mean there is no size yet, it is waiting to get a size from somewhere else.
-// Historically, this is not fully encapsulated, trying to catch them all...
+// This is used to mean there is no size yet (unsized), it is waiting to get a size from somewhere else.
const int UnsizedArraySize = 0;
//
// TSmallArrayVector is used as the container for the set of sizes in TArraySizes.
// It has generic-container semantics, while TArraySizes has array-of-array semantics.
+// That is, TSmallArrayVector should be more focused on mechanism and TArraySizes on policy.
//
struct TSmallArrayVector {
//
@@ -101,9 +101,43 @@
sizes->push_back(e);
}
+ void push_front(const TSmallArrayVector& newDims)
+ {
+ alloc();
+ sizes->insert(sizes->begin(), newDims.sizes->begin(), newDims.sizes->end());
+ }
+
+ void pop_front()
+ {
+ assert(sizes != nullptr && sizes->size() > 0);
+ if (sizes->size() == 1)
+ dealloc();
+ else
+ sizes->erase(sizes->begin());
+ }
+
+ // 'this' should currently not be holding anything, and copyNonFront
+ // will make it hold a copy of all but the first element of rhs.
+ // (This would be useful for making a type that is dereferenced by
+ // one dimension.)
+ void copyNonFront(const TSmallArrayVector& rhs)
+ {
+ assert(sizes == nullptr);
+ if (rhs.size() > 1) {
+ alloc();
+ sizes->insert(sizes->begin(), rhs.sizes->begin() + 1, rhs.sizes->end());
+ }
+ }
+
unsigned int operator[](int i) const
{
- assert(sizes && (int)sizes->size() > i);
+ assert(sizes != nullptr && (int)sizes->size() > i);
+ return (*sizes)[i];
+ }
+
+ unsigned int& operator[](int i)
+ {
+ assert(sizes != nullptr && (int)sizes->size() > i);
return (*sizes)[i];
}
@@ -115,6 +149,7 @@
return false;
return *sizes == *rhs.sizes;
}
+ bool operator!=(const TSmallArrayVector& rhs) const { return ! operator==(rhs); }
protected:
TSmallArrayVector(const TSmallArrayVector&);
@@ -127,6 +162,7 @@
void dealloc()
{
delete sizes;
+ sizes = nullptr;
}
TVector<unsigned int>* sizes; // will either hold such a pointer, or in the future, hold the two array sizes
@@ -134,11 +170,17 @@
//
// Represent an array, or array of arrays, to arbitrary depth. This is not
-// done through a hierarchy of types, but localized into this single cumulative object.
+// done through a hierarchy of types in a type tree, rather all contiguous arrayness
+// in the type hierarchy is localized into this single cumulative object.
//
// The arrayness in TTtype is a pointer, so that it can be non-allocated and zero
// for the vast majority of types that are non-array types.
//
+// Order Policy: these are all identical:
+// - left to right order within a contiguous set of ...[..][..][..]... in the source language
+// - index order 0, 1, 2, ... within the 'sizes' member below
+// - outer-most to inner-most
+//
struct TArraySizes {
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
@@ -155,13 +197,57 @@
// translate from array-of-array semantics to container semantics
int getNumDims() const { return sizes.size(); }
+ int getDimSize(int dim) const { return sizes[dim]; }
+ void setDimSize(int dim, int size) { sizes[dim] = size; }
int getOuterSize() const { return sizes.front(); }
- void setOuterSize(int s) { sizes.push_back((unsigned)s); }
+ int getCumulativeSize() const
+ {
+ int size = 1;
+ for (int d = 0; d < sizes.size(); ++d) {
+ // this only makes sense in paths that have a known array size
+ assert(sizes[d] != UnsizedArraySize);
+ size *= sizes[d];
+ }
+ return size;
+ }
+ void addInnerSize() { sizes.push_back((unsigned)UnsizedArraySize); }
+ void addInnerSize(int s) { sizes.push_back((unsigned)s); }
void changeOuterSize(int s) { sizes.changeFront((unsigned)s); }
int getImplicitSize() const { return (int)implicitArraySize; }
void setImplicitSize(int s) { implicitArraySize = s; }
- int operator[](int i) const { return sizes[i]; }
- bool operator==(const TArraySizes& rhs) const { return sizes == rhs.sizes; }
+ bool isInnerImplicit() const
+ {
+ for (int d = 1; d < sizes.size(); ++d) {
+ if (sizes[d] == (unsigned)UnsizedArraySize)
+ return true;
+ }
+
+ return false;
+ }
+ void addOuterSizes(const TArraySizes& s) { sizes.push_front(s.sizes); }
+ void dereference() { sizes.pop_front(); }
+ void copyDereferenced(const TArraySizes& rhs)
+ {
+ assert(sizes.size() == 0);
+ if (rhs.sizes.size() > 1)
+ sizes.copyNonFront(rhs.sizes);
+ }
+
+ bool sameInnerArrayness(const TArraySizes& rhs) const
+ {
+ if (sizes.size() != rhs.sizes.size())
+ return false;
+
+ for (int d = 1; d < sizes.size(); ++d) {
+ if (sizes[d] != rhs.sizes[d])
+ return false;
+ }
+
+ return true;
+ }
+
+ bool operator==(const TArraySizes& rhs) { return sizes == rhs.sizes; }
+ bool operator!=(const TArraySizes& rhs) { return sizes != rhs.sizes; }
protected:
TSmallArrayVector sizes;
diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h
index f129ded..e7d7f4d 100644
--- a/glslang/Include/revision.h
+++ b/glslang/Include/revision.h
@@ -3,4 +3,4 @@
// For the date, it uses the current date (when then script is run).
#define GLSLANG_REVISION "2.3.706"
-#define GLSLANG_DATE "09-Aug-2015"
+#define GLSLANG_DATE "10-Aug-2015"
diff --git a/glslang/MachineIndependent/Initialize.cpp b/glslang/MachineIndependent/Initialize.cpp
index f3620c2..28b8ccd 100644
--- a/glslang/MachineIndependent/Initialize.cpp
+++ b/glslang/MachineIndependent/Initialize.cpp
@@ -3276,9 +3276,9 @@
if (version == 100 || IncludeLegacy(version, profile) || (! ForwardCompatibility && profile != EEsProfile && version < 420)) {
TPrecisionQualifier pq = profile == EEsProfile ? EpqMedium : EpqNone;
TType fragData(EbtFloat, EvqFragColor, pq, 4);
- TArraySizes* arraySizes = new TArraySizes;
- arraySizes->setOuterSize(resources.maxDrawBuffers);
- fragData.setArraySizes(arraySizes);
+ TArraySizes& arraySizes = *new TArraySizes;
+ arraySizes.addInnerSize(resources.maxDrawBuffers);
+ fragData.newArraySizes(arraySizes);
symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"), fragData));
SpecialQualifier("gl_FragData", EvqFragColor, EbvFragData, symbolTable);
}
diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp
index 56f65a6..4f44376 100644
--- a/glslang/MachineIndependent/ParseHelper.cpp
+++ b/glslang/MachineIndependent/ParseHelper.cpp
@@ -558,9 +558,9 @@
error(loc, "", "[", "index out of range '%d'", index);
index = 0;
} else if (type.isArray()) {
- if (type.isExplicitlySizedArray() && index >= type.getArraySize()) {
+ if (type.isExplicitlySizedArray() && index >= type.getOuterArraySize()) {
error(loc, "", "[", "array index out of range '%d'", index);
- index = type.getArraySize() - 1;
+ index = type.getOuterArraySize() - 1;
}
} else if (type.isVector()) {
if (index >= type.getVectorSize()) {
@@ -629,10 +629,10 @@
return;
if (language == EShLangTessControl || language == EShLangTessEvaluation) {
- if (type.getArraySize() != resources.maxPatchVertices) {
+ if (type.getOuterArraySize() != resources.maxPatchVertices) {
if (type.isExplicitlySizedArray())
error(loc, "tessellation input array size must be gl_MaxPatchVertices or implicitly sized", "[]", "");
- type.changeArraySize(resources.maxPatchVertices);
+ type.changeOuterArraySize(resources.maxPatchVertices);
}
}
}
@@ -662,7 +662,7 @@
if (symbolNode->getType().isImplicitlySizedArray()) {
int newSize = getIoArrayImplicitSize();
if (newSize)
- symbolNode->getWritableType().changeArraySize(newSize);
+ symbolNode->getWritableType().changeOuterArraySize(newSize);
}
}
@@ -710,8 +710,8 @@
void TParseContext::checkIoArrayConsistency(const TSourceLoc& loc, int requiredSize, const char* feature, TType& type, const TString& name)
{
if (type.isImplicitlySizedArray())
- type.changeArraySize(requiredSize);
- else if (type.getArraySize() != requiredSize) {
+ type.changeOuterArraySize(requiredSize);
+ else if (type.getOuterArraySize() != requiredSize) {
if (language == EShLangGeometry)
error(loc, "inconsistent input primitive for array size of", feature, name.c_str());
else if (language == EShLangTessControl)
@@ -1203,7 +1203,7 @@
error(loc, "", function->getName().c_str(), "array must be declared with a size before using this method");
}
} else
- length = type.getArraySize();
+ length = type.getOuterArraySize();
} else if (type.isMatrix())
length = type.getMatrixCols();
else if (type.isVector())
@@ -1993,17 +1993,41 @@
error(loc, "array constructor must have at least one argument", "constructor", "");
return true;
}
+
if (type.isImplicitlySizedArray()) {
// auto adapt the constructor type to the number of arguments
- type.changeArraySize(function.getParamCount());
- } else if (type.getArraySize() != function.getParamCount()) {
+ type.changeOuterArraySize(function.getParamCount());
+ } else if (type.getOuterArraySize() != function.getParamCount()) {
error(loc, "array constructor needs one argument per array element", "constructor", "");
return true;
}
+
+ if (type.isArrayOfArrays()) {
+ // Types have to match, but we're still making the type.
+ // Finish making the type, and the comparison is done later
+ // when checking for conversion.
+ TArraySizes& arraySizes = type.getArraySizes();
+
+ // At least the dimensionalities have to match.
+ if (! function[0].type->isArray() || arraySizes.getNumDims() != function[0].type->getArraySizes().getNumDims() + 1) {
+ error(loc, "array constructor argument not correct type to construct array element", "constructior", "");
+ return true;
+ }
+
+ if (arraySizes.isInnerImplicit()) {
+ // "Arrays of arrays ..., and the size for any dimension is optional"
+ // That means we need to adopt (from the first argument) the other array sizes into the type.
+ for (int d = 1; d < arraySizes.getNumDims(); ++d) {
+ if (arraySizes.getDimSize(d) == UnsizedArraySize) {
+ arraySizes.setDimSize(d, function[0].type->getArraySizes().getDimSize(d - 1));
+ }
+ }
+ }
+ }
}
- if (arrayArg && op != EOpConstructStruct) {
- error(loc, "constructing from a non-dereferenced array", "constructor", "");
+ if (arrayArg && op != EOpConstructStruct && ! type.isArrayOfArrays()) {
+ error(loc, "constructing non-array constituent from array argument", "constructor", "");
return true;
}
@@ -2490,13 +2514,13 @@
if (type.getQualifier().storage == EvqVaryingOut && language == EShLangVertex) {
if (type.isArrayOfArrays())
requireProfile(loc, ~EEsProfile, "vertex-shader array-of-array output");
- else if (type.getArraySize() && type.isStruct())
+ else if (type.isStruct())
requireProfile(loc, ~EEsProfile, "vertex-shader array-of-struct output");
}
if (type.getQualifier().storage == EvqVaryingIn && language == EShLangFragment) {
if (type.isArrayOfArrays())
requireProfile(loc, ~EEsProfile, "fragment-shader array-of-array input");
- else if (type.getArraySize() && type.isStruct())
+ else if (type.isStruct())
requireProfile(loc, ~EEsProfile, "fragment-shader array-of-struct input");
}
@@ -2522,11 +2546,24 @@
}
}
-void TParseContext::arrayUnsizedCheck(const TSourceLoc& loc, const TQualifier& qualifier, int size, bool initializer)
+void TParseContext::arrayUnsizedCheck(const TSourceLoc& loc, const TQualifier& qualifier, const TArraySizes* arraySizes, bool initializer)
{
- // desktop always allows unsized variable arrays,
- // ES always allows them if there is an initializer present to get the size from
- if (parsingBuiltins || profile != EEsProfile || initializer)
+ assert(arraySizes);
+
+ // always allow special built-in ins/outs sized to topologies
+ if (parsingBuiltins)
+ return;
+
+ // always allow an initializer to set any unknown array sizes
+ if (initializer)
+ return;
+
+ // No environment lets any non-outer-dimension that's to be implicitly sized
+ if (arraySizes->isInnerImplicit())
+ error(loc, "only outermost dimension of an array of arrays can be implicitly sized", "[]", "");
+
+ // desktop always allows outer-dimension-unsized variable arrays,
+ if (profile != EEsProfile)
return;
// for ES, if size isn't coming from an initializer, it has to be explicitly declared now,
@@ -2553,7 +2590,7 @@
break;
}
- arraySizeRequiredCheck(loc, size);
+ arraySizeRequiredCheck(loc, arraySizes->getOuterSize());
}
void TParseContext::arrayOfArrayVersionCheck(const TSourceLoc& loc)
@@ -2563,15 +2600,9 @@
requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, feature);
profileRequires(loc, EEsProfile, 310, nullptr, feature);
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, feature);
-
- static int once = false;
- if (! once) {
- warn(loc, feature, "Not supported yet.", "");
- once = true;
- }
}
-void TParseContext::arrayDimCheck(const TSourceLoc& loc, TArraySizes* sizes1, TArraySizes* sizes2)
+void TParseContext::arrayDimCheck(const TSourceLoc& loc, const TArraySizes* sizes1, const TArraySizes* sizes2)
{
if ((sizes1 && sizes2) ||
(sizes1 && sizes1->getNumDims() > 1) ||
@@ -2579,13 +2610,28 @@
arrayOfArrayVersionCheck(loc);
}
-void TParseContext::arrayDimCheck(const TSourceLoc& loc, const TType* type, TArraySizes* sizes2)
+void TParseContext::arrayDimCheck(const TSourceLoc& loc, const TType* type, const TArraySizes* sizes2)
{
+ // skip checking for multiple dimensions on the type; it was caught earlier
if ((type && type->isArray() && sizes2) ||
(sizes2 && sizes2->getNumDims() > 1))
arrayOfArrayVersionCheck(loc);
}
+// Merge array dimensions listed in 'sizes' onto the type's array dimensions.
+//
+// From the spec: "vec4[2] a[3]; // size-3 array of size-2 array of vec4"
+//
+// That means, the 'sizes' go in front of the 'type' as outermost sizes.
+// 'type' is the type part of the declaration (to the left)
+// 'sizes' is the arrayness tagged on the identifier (to the right)
+//
+void TParseContext::arrayDimMerge(TType& type, const TArraySizes* sizes)
+{
+ if (sizes)
+ type.addArrayOuterSizes(*sizes);
+}
+
//
// Do all the semantic checking for declaring or redeclaring an array, with and
// without a size, and make the right changes to the symbol table.
@@ -2642,19 +2688,25 @@
error(loc, "redeclaring non-array as array", identifier.c_str(), "");
return;
}
+
+ if (! existingType.sameElementType(type)) {
+ error(loc, "redeclaration of array with a different element type", identifier.c_str(), "");
+ return;
+ }
+
+ if (! existingType.sameInnerArrayness(type)) {
+ error(loc, "redeclaration of array with a different array dimensions or sizes", identifier.c_str(), "");
+ return;
+ }
+
if (existingType.isExplicitlySizedArray()) {
// be more leniant for input arrays to geometry shaders and tessellation control outputs, where the redeclaration is the same size
- if (! (isIoResizeArray(type) && existingType.getArraySize() == type.getArraySize()))
+ if (! (isIoResizeArray(type) && existingType.getOuterArraySize() == type.getOuterArraySize()))
error(loc, "redeclaration of array with size", identifier.c_str(), "");
return;
}
- if (! existingType.sameElementType(type)) {
- error(loc, "redeclaration of array with a different type", identifier.c_str(), "");
- return;
- }
-
- arrayLimitCheck(loc, identifier, type.getArraySize());
+ arrayLimitCheck(loc, identifier, type.getOuterArraySize());
existingType.updateArraySizes(type);
@@ -2954,7 +3006,7 @@
else if (! oldType.sameArrayness(newType) && oldType.isExplicitlySizedArray())
error(memberLoc, "cannot change array size of redeclared block member", member->type->getFieldName().c_str(), "");
else if (newType.isArray())
- arrayLimitCheck(loc, member->type->getFieldName(), newType.getArraySize());
+ arrayLimitCheck(loc, member->type->getFieldName(), newType.getOuterArraySize());
if (newType.getQualifier().isMemory())
error(memberLoc, "cannot add memory qualifier to redeclared block member", member->type->getFieldName().c_str(), "");
if (newType.getQualifier().hasLayout())
@@ -2990,10 +3042,10 @@
else if (type.isArray()) {
if (type.isExplicitlySizedArray() && arraySizes->getOuterSize() == UnsizedArraySize)
error(loc, "block already declared with size, can't redeclare as implicitly-sized", blockName.c_str(), "");
- else if (type.isExplicitlySizedArray() && type.getArraySize() != arraySizes->getOuterSize())
+ else if (type.isExplicitlySizedArray() && type.getArraySizes() != *arraySizes)
error(loc, "cannot change array size of redeclared block", blockName.c_str(), "");
else if (type.isImplicitlySizedArray() && arraySizes->getOuterSize() != UnsizedArraySize)
- type.changeArraySize(arraySizes->getOuterSize());
+ type.changeOuterArraySize(arraySizes->getOuterSize());
}
symbolTable.insert(*block);
@@ -3224,7 +3276,7 @@
inductiveLoopBodyCheck(loop->getBody(), loopIndex, symbolTable);
}
-// Do limit checks against for all built-in arrays.
+// Do limit checks for built-in arrays.
void TParseContext::arrayLimitCheck(const TSourceLoc& loc, const TString& identifier, int size)
{
if (identifier.compare("gl_TexCoord") == 0)
@@ -3806,7 +3858,7 @@
if (type.getBasicType() == EbtSampler) {
int lastBinding = qualifier.layoutBinding;
if (type.isArray())
- lastBinding += type.getArraySize();
+ lastBinding += type.getCumulativeArraySize();
if (lastBinding >= resources.maxCombinedTextureImageUnits)
error(loc, "sampler binding not less than gl_MaxCombinedTextureImageUnits", "binding", type.isArray() ? "(using array)" : "");
}
@@ -3990,7 +4042,7 @@
// Check for overlap
int numOffsets = 4;
if (symbol.getType().isArray())
- numOffsets *= symbol.getType().getArraySize();
+ numOffsets *= symbol.getType().getCumulativeArraySize();
int repeated = intermediate.addUsedOffsets(qualifier.layoutBinding, offset, numOffsets);
if (repeated >= 0)
error(loc, "atomic counters sharing the same offset:", "offset", "%d", repeated);
@@ -4138,6 +4190,9 @@
// Returns a subtree node that computes an initializer, if needed.
// Returns nullptr if there is no code to execute for initialization.
//
+// 'publicType' is the type part of the declaration (to the left)
+// 'arraySizes' is the arrayness tagged on the identifier (to the right)
+//
TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& identifier, const TPublicType& publicType, TArraySizes* arraySizes, TIntermTyped* initializer)
{
TType type(publicType);
@@ -4170,13 +4225,12 @@
if (arraySizes || type.isArray()) {
// Arrayness is potentially coming both from the type and from the
// variable: "int[] a[];" or just one or the other.
- // For now, arrays of arrays aren't supported, so it's just one or the
- // other. Move it to the type, so all arrayness is part of the type.
+ // Merge it all to the type, so all arrayness is part of the type.
arrayDimCheck(loc, &type, arraySizes);
- if (arraySizes)
- type.setArraySizes(arraySizes);
+ arrayDimMerge(type, arraySizes);
- arrayUnsizedCheck(loc, type.getQualifier(), type.getArraySize(), initializer != nullptr);
+ // Check that implicit sizing is only where allowed.
+ arrayUnsizedCheck(loc, type.getQualifier(), &type.getArraySizes(), initializer != nullptr);
if (! arrayQualifierError(loc, type.getQualifier()) && ! arrayError(loc, type))
declareArray(loc, identifier, type, symbol, newDeclaration);
@@ -4299,10 +4353,21 @@
return nullptr;
}
- // Fix arrayness if variable is unsized, getting size from the initializer
- if (initializer->getType().isArray() && initializer->getType().isExplicitlySizedArray() &&
+ // Fix outer arrayness if variable is unsized, getting size from the initializer
+ if (initializer->getType().isExplicitlySizedArray() &&
variable->getType().isImplicitlySizedArray())
- variable->getWritableType().changeArraySize(initializer->getType().getArraySize());
+ variable->getWritableType().changeOuterArraySize(initializer->getType().getOuterArraySize());
+
+ // Inner arrayness can also get set by an initializer
+ if (initializer->getType().isArrayOfArrays() && variable->getType().isArrayOfArrays() &&
+ initializer->getType().getArraySizes()->getNumDims() ==
+ variable->getType().getArraySizes()->getNumDims()) {
+ // adopt unsized sizes from the initializer's sizes
+ for (int d = 1; d < variable->getType().getArraySizes()->getNumDims(); ++d) {
+ if (variable->getType().getArraySizes()->getDimSize(d) == UnsizedArraySize)
+ variable->getWritableType().getArraySizes().setDimSize(d, initializer->getType().getArraySizes()->getDimSize(d));
+ }
+ }
// Uniform and global consts require a constant initializer
if (qualifier == EvqUniform && initializer->getType().getQualifier().storage != EvqConst) {
@@ -4390,9 +4455,20 @@
// The type's array might be unsized, which could be okay, so base sizes on the size of the aggregate.
// Later on, initializer execution code will deal with array size logic.
TType arrayType;
- arrayType.shallowCopy(type);
- arrayType.setArraySizes(type);
- arrayType.changeArraySize((int)initList->getSequence().size());
+ arrayType.shallowCopy(type); // sharing struct stuff is fine
+ arrayType.newArraySizes(*type.getArraySizes()); // but get a fresh copy of the array information, to edit below
+
+ // edit array sizes to fill in unsized dimensions
+ arrayType.changeOuterArraySize((int)initList->getSequence().size());
+ TIntermTyped* firstInit = initList->getSequence()[0]->getAsTyped();
+ if (arrayType.isArrayOfArrays() && firstInit->getType().isArray() &&
+ arrayType.getArraySizes().getNumDims() == firstInit->getType().getArraySizes()->getNumDims() + 1) {
+ for (int d = 1; d < arrayType.getArraySizes().getNumDims(); ++d) {
+ if (arrayType.getArraySizes().getDimSize(d) == UnsizedArraySize)
+ arrayType.getArraySizes().setDimSize(d, firstInit->getType().getArraySizes()->getDimSize(d - 1));
+ }
+ }
+
TType elementType(arrayType, 0); // dereferenced type
for (size_t i = 0; i < initList->getSequence().size(); ++i) {
initList->getSequence()[i] = convertInitializerList(loc, elementType, initList->getSequence()[i]->getAsTyped());
@@ -4455,9 +4531,11 @@
memberTypes = type.getStruct()->begin();
TType elementType;
- elementType.shallowCopy(type);
- if (type.isArray())
- elementType.dereference();
+ if (type.isArray()) {
+ TType dereferenced(type, 0);
+ elementType.shallowCopy(dereferenced);
+ } else
+ elementType.shallowCopy(type);
bool singleArg;
if (aggrNode) {
@@ -4471,11 +4549,11 @@
TIntermTyped *newNode;
if (singleArg) {
// If structure constructor or array constructor is being called
- // for only one parameter inside the structure, we need to call constructStruct function once.
+ // for only one parameter inside the structure, we need to call constructAggregate function once.
if (type.isArray())
- newNode = constructStruct(node, elementType, 1, node->getLoc());
+ newNode = constructAggregate(node, elementType, 1, node->getLoc());
else if (op == EOpConstructStruct)
- newNode = constructStruct(node, *(*memberTypes).type, 1, node->getLoc());
+ newNode = constructAggregate(node, *(*memberTypes).type, 1, node->getLoc());
else
newNode = constructBuiltIn(type, op, node->getAsTyped(), node->getLoc(), false);
@@ -4501,9 +4579,9 @@
for (TIntermSequence::iterator p = sequenceVector.begin();
p != sequenceVector.end(); p++, paramCount++) {
if (type.isArray())
- newNode = constructStruct(*p, elementType, paramCount+1, node->getLoc());
+ newNode = constructAggregate(*p, elementType, paramCount+1, node->getLoc());
else if (op == EOpConstructStruct)
- newNode = constructStruct(*p, *(memberTypes[paramCount]).type, paramCount+1, node->getLoc());
+ newNode = constructAggregate(*p, *(memberTypes[paramCount]).type, paramCount+1, node->getLoc());
else
newNode = constructBuiltIn(type, op, (*p)->getAsTyped(), node->getLoc(), true);
@@ -4610,12 +4688,12 @@
return intermediate.setAggregateOperator(newNode, op, type, loc);
}
-// This function tests for the type of the parameters to the structures constructors. Raises
+// This function tests for the type of the parameters to the structure or array constructor. Raises
// an error message if the expected type does not match the parameter passed to the constructor.
//
// Returns nullptr for an error or the input node itself if the expected and the given parameter types match.
//
-TIntermTyped* TParseContext::constructStruct(TIntermNode* node, const TType& type, int paramCount, const TSourceLoc& loc)
+TIntermTyped* TParseContext::constructAggregate(TIntermNode* node, const TType& type, int paramCount, const TSourceLoc& loc)
{
TIntermTyped* converted = intermediate.addConversion(EOpConstructStruct, type, node->getAsTyped());
if (! converted || converted->getType() != type) {
@@ -4635,9 +4713,10 @@
{
blockStageIoCheck(loc, currentBlockQualifier);
blockQualifierCheck(loc, currentBlockQualifier);
- if (arraySizes)
- arrayUnsizedCheck(loc, currentBlockQualifier, arraySizes->getOuterSize(), false);
- arrayDimCheck(loc, arraySizes, nullptr);
+ if (arraySizes) {
+ arrayUnsizedCheck(loc, currentBlockQualifier, arraySizes, false);
+ arrayDimCheck(loc, arraySizes, 0);
+ }
// fix and check for member storage qualifiers and types that don't belong within a block
for (unsigned int member = 0; member < typeList.size(); ++member) {
@@ -4766,7 +4845,7 @@
TType blockType(&typeList, *blockName, currentBlockQualifier);
if (arraySizes)
- blockType.setArraySizes(arraySizes);
+ blockType.newArraySizes(*arraySizes);
else
ioArrayCheck(loc, blockType, instanceName ? *instanceName : *blockName);
diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h
index e008c0f..81c9eac 100644
--- a/glslang/MachineIndependent/ParseHelper.h
+++ b/glslang/MachineIndependent/ParseHelper.h
@@ -138,10 +138,11 @@
bool arrayError(const TSourceLoc&, const TType&);
void arraySizeRequiredCheck(const TSourceLoc&, int size);
void structArrayCheck(const TSourceLoc&, const TType& structure);
- void arrayUnsizedCheck(const TSourceLoc&, const TQualifier&, int size, bool initializer);
+ void arrayUnsizedCheck(const TSourceLoc&, const TQualifier&, const TArraySizes*, bool initializer);
void arrayOfArrayVersionCheck(const TSourceLoc&);
- void arrayDimCheck(const TSourceLoc&, TArraySizes* sizes1, TArraySizes* sizes2);
- void arrayDimCheck(const TSourceLoc&, const TType*, TArraySizes*);
+ void arrayDimCheck(const TSourceLoc&, const TArraySizes* sizes1, const TArraySizes* sizes2);
+ void arrayDimCheck(const TSourceLoc&, const TType*, const TArraySizes*);
+ void arrayDimMerge(TType& type, const TArraySizes* sizes);
bool voidErrorCheck(const TSourceLoc&, const TString&, TBasicType);
void boolCheck(const TSourceLoc&, const TIntermTyped*);
void boolCheck(const TSourceLoc&, const TPublicType&);
@@ -189,7 +190,7 @@
void declareTypeDefaults(const TSourceLoc&, const TPublicType&);
TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, const TPublicType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0);
TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&, TOperator);
- TIntermTyped* constructStruct(TIntermNode*, const TType&, int, const TSourceLoc&);
+ TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&);
TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset);
void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0);
void blockStageIoCheck(const TSourceLoc&, const TQualifier&);
diff --git a/glslang/MachineIndependent/SymbolTable.cpp b/glslang/MachineIndependent/SymbolTable.cpp
index e07a984..3a401ec 100644
--- a/glslang/MachineIndependent/SymbolTable.cpp
+++ b/glslang/MachineIndependent/SymbolTable.cpp
@@ -113,7 +113,7 @@
const int maxSize = 11;
char buf[maxSize];
for (int i = 0; i < arraySizes->getNumDims(); ++i) {
- snprintf(buf, maxSize, "%d", (*arraySizes)[i]);
+ snprintf(buf, maxSize, "%d", arraySizes->getDimSize(i));
mangledName += '[';
mangledName += buf;
mangledName += ']';
diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y
index 2726014..0c87757 100644
--- a/glslang/MachineIndependent/glslang.y
+++ b/glslang/MachineIndependent/glslang.y
@@ -691,7 +691,7 @@
// lazy setting of the previous scope's defaults, has effect only the first time it is called in a particular scope
parseContext.symbolTable.setPreviousDefaultPrecisions(&parseContext.defaultPrecision[0]);
- parseContext.setDefaultPrecision($1.loc, $3, $2.qualifier.precision);
+ parseContext.setDefaultPrecision($1.loc, $3, $2.qualifier.precision);
$$ = 0;
}
| block_structure SEMICOLON {
@@ -1240,7 +1240,7 @@
: LEFT_BRACKET RIGHT_BRACKET {
$$.loc = $1.loc;
$$.arraySizes = new TArraySizes;
- $$.arraySizes->setOuterSize(0);
+ $$.arraySizes->addInnerSize();
}
| LEFT_BRACKET constant_expression RIGHT_BRACKET {
$$.loc = $1.loc;
@@ -1248,18 +1248,18 @@
int size;
parseContext.arraySizeCheck($2->getLoc(), $2, size);
- $$.arraySizes->setOuterSize(size);
+ $$.arraySizes->addInnerSize(size);
}
| array_specifier LEFT_BRACKET RIGHT_BRACKET {
$$ = $1;
- $$.arraySizes->setOuterSize(0);
+ $$.arraySizes->addInnerSize();
}
| array_specifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
$$ = $1;
int size;
parseContext.arraySizeCheck($3->getLoc(), $3, size);
- $$.arraySizes->setOuterSize(size);
+ $$.arraySizes->addInnerSize(size);
}
;
@@ -1903,19 +1903,19 @@
parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "highp precision qualifier");
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
if (parseContext.profile == EEsProfile)
- $$.qualifier.precision = EpqHigh;
+ $$.qualifier.precision = EpqHigh;
}
| MEDIUM_PRECISION {
parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "mediump precision qualifier");
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
if (parseContext.profile == EEsProfile)
- $$.qualifier.precision = EpqMedium;
+ $$.qualifier.precision = EpqMedium;
}
| LOW_PRECISION {
parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "lowp precision qualifier");
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
if (parseContext.profile == EEsProfile)
- $$.qualifier.precision = EpqLow;
+ $$.qualifier.precision = EpqLow;
}
;
@@ -2020,7 +2020,7 @@
$$.type = new TType(EbtVoid);
$$.loc = $1.loc;
$$.type->setFieldName(*$1.string);
- $$.type->setArraySizes($2.arraySizes);
+ $$.type->newArraySizes(*$2.arraySizes);
}
;
@@ -2354,7 +2354,7 @@
$$ = parseContext.intermediate.addBranch(EOpReturn, $2, $1.loc);
}
} else
- $$ = parseContext.intermediate.addBranch(EOpReturn, $2, $1.loc);
+ $$ = parseContext.intermediate.addBranch(EOpReturn, $2, $1.loc);
}
| DISCARD SEMICOLON {
parseContext.requireStage($1.loc, EShLangFragment, "discard");
diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp
index eafe135..751d0c3 100644
--- a/glslang/MachineIndependent/linkValidate.cpp
+++ b/glslang/MachineIndependent/linkValidate.cpp
@@ -240,9 +240,7 @@
void TIntermediate::mergeImplicitArraySizes(TType& type, const TType& unitType)
{
if (type.isImplicitlySizedArray() && unitType.isArray()) {
- int newImplicitArraySize = unitType.getArraySize();
- if (newImplicitArraySize == 0)
- newImplicitArraySize = unitType.getImplicitArraySize();
+ int newImplicitArraySize = unitType.isImplicitlySizedArray() ? unitType.getImplicitArraySize() : unitType.getOuterArraySize();
if (newImplicitArraySize > type.getImplicitArraySize ())
type.setImplicitArraySize(newImplicitArraySize);
}
@@ -623,7 +621,7 @@
int size;
if (qualifier.isUniformOrBuffer()) {
if (type.isArray())
- size = type.getArraySize();
+ size = type.getCumulativeArraySize();
else
size = 1;
} else {
@@ -693,12 +691,13 @@
// "If the declared input is an array of size n and each element takes m locations, it will be assigned m * n
// consecutive locations..."
if (type.isArray()) {
+ // TODO: perf: this can be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness
TType elementType(type, 0);
if (type.isImplicitlySizedArray()) {
// TODO: are there valid cases of having an implicitly-sized array with a location? If so, running this code too early.
return computeTypeLocationSize(elementType);
} else
- return type.getArraySize() * computeTypeLocationSize(elementType);
+ return type.getOuterArraySize() * computeTypeLocationSize(elementType);
}
// "The locations consumed by block and structure members are determined by applying the rules above
@@ -783,10 +782,11 @@
// that component's size. Aggregate types are flattened down to the component
// level to get this sequence of components."
- if (type.isArray()) {
+ if (type.isArray()) {
+ // TODO: perf: this can be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness
assert(type.isExplicitlySizedArray());
TType elementType(type, 0);
- return type.getArraySize() * computeTypeXfbSize(elementType, containsDouble);
+ return type.getOuterArraySize() * computeTypeXfbSize(elementType, containsDouble);
}
if (type.isStruct()) {
@@ -913,12 +913,13 @@
// rules 4, 6, and 8
if (type.isArray()) {
+ // TODO: perf: this might be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness
TType derefType(type, 0);
alignment = getBaseAlignment(derefType, size, std140);
if (std140)
alignment = std::max(baseAlignmentVec4Std140, alignment);
RoundToPow2(size, alignment);
- size *= type.getArraySize();
+ size *= type.getOuterArraySize();
return alignment;
}
diff --git a/glslang/MachineIndependent/reflection.cpp b/glslang/MachineIndependent/reflection.cpp
index 3d96743..85caff7 100644
--- a/glslang/MachineIndependent/reflection.cpp
+++ b/glslang/MachineIndependent/reflection.cpp
@@ -166,7 +166,7 @@
switch (visitNode->getOp()) {
case EOpIndexIndirect:
// Visit all the indices of this array, and for each one add on the remaining dereferencing
- for (int i = 0; i < visitNode->getLeft()->getType().getArraySize(); ++i) {
+ for (int i = 0; i < visitNode->getLeft()->getType().getOuterArraySize(); ++i) {
TString newBaseName = name;
if (baseType.getBasicType() != EbtBlock)
newBaseName.append(TString("[") + String(i) + "]");
@@ -201,7 +201,7 @@
if (terminalType->isArray()) {
// Visit all the indices of this array, and for each one,
// fully explode the remaining aggregate to dereference
- for (int i = 0; i < terminalType->getArraySize(); ++i) {
+ for (int i = 0; i < terminalType->getOuterArraySize(); ++i) {
TString newBaseName = name;
newBaseName.append(TString("[") + String(i) + "]");
TType derefType(*terminalType, 0);
@@ -286,7 +286,7 @@
anonymous = IsAnonymous(base->getName());
if (base->getType().isArray()) {
assert(! anonymous);
- for (int e = 0; e < base->getType().getArraySize(); ++e)
+ for (int e = 0; e < base->getType().getCumulativeArraySize(); ++e)
blockIndex = addBlockName(base->getType().getTypeName() + "[" + String(e) + "]", getBlockSize(base->getType()));
} else
blockIndex = addBlockName(base->getType().getTypeName(), getBlockSize(base->getType()));
@@ -610,7 +610,7 @@
int mapToGlArraySize(const TType& type)
{
- return type.isArray() ? type.getArraySize() : 1;
+ return type.isArray() ? type.getOuterArraySize() : 1;
}
typedef std::list<TIntermAggregate*> TFunctionStack;