Commit 65c78a0b by John Kessenich

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.
parent b3548358
......@@ -953,7 +953,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
{
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::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
spv::MissingFunctionality("Unsized array");
arraySize = 8;
} else
arraySize = type.getArraySize();
arraySize = type.getOuterArraySize();
spvType = builder.makeArrayType(spvType, arraySize);
}
......@@ -2637,15 +2637,11 @@ spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TType& glslangT
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()) {
......
#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
}
......@@ -17,7 +17,6 @@ ERROR: 0:34: '.' : cannot apply to an array: flizbit
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
......
......@@ -21,7 +21,6 @@ ERROR: 0:85: 'double vector' : not supported with this profile: es
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
......
......@@ -37,7 +37,6 @@ ERROR: 0:111: '' : image variables not declared 'writeonly' must have a format l
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
......
......@@ -9,7 +9,6 @@ ERROR: 0:58: 'sampler/image' : type requires declaration of default precision qu
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
......
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
......
......@@ -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.
......
......@@ -17,10 +17,6 @@ ERROR: 0:102: 'color' : redefinition
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:226: 'in' : not allowed in nested scope
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 @@ ERROR: node is still EOpNull!
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 @@ ERROR: node is still EOpNull!
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 @@ ERROR: node is still EOpNull!
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 @@ ERROR: node is still EOpNull!
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:
......
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:134: '' : function does not return a value: funcA
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 @@ ERROR: node is still EOpNull!
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 @@ ERROR: node is still EOpNull!
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})
......
......@@ -20,7 +20,7 @@ uniform Transform { // API uses “Transform[2]” to refer to instance 2
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;
......
......@@ -76,6 +76,7 @@ numeral.frag
410.geom
430.vert
430.comp
430AofA.frag
440.vert
440.frag
450.vert
......
......@@ -896,15 +896,32 @@ public:
// 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 @@ public:
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 @@ public:
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 @@ public:
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 addArrayOuterSizes(const TArraySizes& s)
{
if (arraySizes == nullptr)
newArraySizes(s);
else
arraySizes->addOuterSizes(s);
}
void setArraySizes(const TType& type) { setArraySizes(type.arraySizes); }
void changeArraySize(int s) { arraySizes->changeOuterSize(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 @@ public:
{
return TType::getBasicString(basicType);
}
static const char* getBasicString(TBasicType t)
{
switch (t) {
......@@ -1242,12 +1252,12 @@ public:
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 @@ public:
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 @@ public:
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
......
......@@ -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 @@ struct TSmallArrayVector {
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 @@ struct TSmallArrayVector {
return false;
return *sizes == *rhs.sizes;
}
bool operator!=(const TSmallArrayVector& rhs) const { return ! operator==(rhs); }
protected:
TSmallArrayVector(const TSmallArrayVector&);
......@@ -127,6 +162,7 @@ protected:
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 @@ protected:
//
// 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 @@ struct TArraySizes {
// 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;
......
......@@ -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"
......@@ -3276,9 +3276,9 @@ void IdentifyBuiltIns(int version, EProfile profile, EShLanguage language, TSymb
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);
}
......
......@@ -138,10 +138,11 @@ public:
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 @@ public:
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&);
......
......@@ -113,7 +113,7 @@ void TType::buildMangledName(TString& mangledName)
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 += ']';
......
......@@ -691,7 +691,7 @@ declaration
// 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 @@ array_specifier
: 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 @@ array_specifier
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 @@ precision_qualifier
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 @@ struct_declarator
$$.type = new TType(EbtVoid);
$$.loc = $1.loc;
$$.type->setFieldName(*$1.string);
$$.type->setArraySizes($2.arraySizes);
$$.type->newArraySizes(*$2.arraySizes);
}
;
......@@ -2354,7 +2354,7 @@ jump_statement
$$ = 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");
......
......@@ -240,9 +240,7 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin
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 TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ
int size;
if (qualifier.isUniformOrBuffer()) {
if (type.isArray())
size = type.getArraySize();
size = type.getCumulativeArraySize();
else
size = 1;
} else {
......@@ -693,12 +691,13 @@ int TIntermediate::computeTypeLocationSize(const TType& type) const
// "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 @@ unsigned int TIntermediate::computeTypeXfbSize(const TType& type, bool& contains
// 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 @@ int TIntermediate::getBaseAlignment(const TType& type, int& size, bool std140)
// 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;
}
......
......@@ -166,7 +166,7 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
int mapToGlArraySize(const TType& type)
{
return type.isArray() ? type.getArraySize() : 1;
return type.isArray() ? type.getOuterArraySize() : 1;
}
typedef std::list<TIntermAggregate*> TFunctionStack;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment