diff --git a/Test/baseResults/array.frag.out b/Test/baseResults/array.frag.out index dd3fab12..e2046f8a 100644 --- a/Test/baseResults/array.frag.out +++ b/Test/baseResults/array.frag.out @@ -6,12 +6,12 @@ ERROR: 0:31: 'assign' : cannot convert from '4-element array of float' to 'unsi ERROR: 0:33: 'foo' : no matching overloaded function found ERROR: 0:42: '[' : array index out of range '5' ERROR: 0:45: '[' : array index out of range '1000' -ERROR: 0:46: '[' : array index out of range '-1' -ERROR: 0:52: '[' : array index '2' out of range +ERROR: 0:46: '[' : index out of range '-1' +ERROR: 0:52: '[' : array index out of range '2' ERROR: 0:54: 'const' : non-matching or non-convertible constant type for const initializer ERROR: 0:56: '=' : cannot convert from 'const 2-element array of int' to '3-element array of int' ERROR: 0:57: '[]' : scalar integer expression required -ERROR: 0:57: '[' : array index out of range '-858993459' +ERROR: 0:57: '[' : index out of range '-858993459' ERROR: 0:58: '[]' : scalar integer expression required ERROR: 14 compilation errors. No code generated. @@ -157,7 +157,7 @@ ERROR: node is still EOpNull! 0:52 add second child into first child (int) 0:52 'sum' (int) 0:52 Constant: -0:52 3 (const int) +0:52 2 (const int) 0:55 Sequence 0:55 move second child to first child (2-element array of int) 0:55 'ica' (2-element array of int) diff --git a/Test/baseResults/array100.frag.out b/Test/baseResults/array100.frag.out index 400b097e..a7e0c5b5 100644 --- a/Test/baseResults/array100.frag.out +++ b/Test/baseResults/array100.frag.out @@ -14,7 +14,7 @@ ERROR: 0:31: 'arrayed constructor' : not supported for this version or the enabl ERROR: 0:31: 'array comparison' : not supported for this version or the enabled extensions ERROR: 0:35: '[' : array index out of range '5' ERROR: 0:38: '[' : array index out of range '1000' -ERROR: 0:39: '[' : array index out of range '-1' +ERROR: 0:39: '[' : index out of range '-1' ERROR: 17 compilation errors. No code generated. ERROR: node is still EOpNull! diff --git a/Test/baseResults/constFold.frag.out b/Test/baseResults/constFold.frag.out index e70ee559..ba751b36 100644 --- a/Test/baseResults/constFold.frag.out +++ b/Test/baseResults/constFold.frag.out @@ -1,5 +1,13 @@ Warning, version 430 is not yet complete; some version-specific features are present, but many are missing. -0:? Sequence +ERROR: 0:109: '[' : index out of range '-1' +ERROR: 0:110: '[' : vector index out of range '4' +ERROR: 0:111: '[' : index out of range '-2' +ERROR: 0:112: '[' : index out of range '-1' +ERROR: 0:113: '[' : vector index out of range '3' +ERROR: 0:114: '[' : matrix index out of range '3' +ERROR: 6 compilation errors. No code generated. + +ERROR: node is still EOpNull! 0:28 Function Definition: main( (void) 0:28 Function Parameters: 0:30 Sequence @@ -163,6 +171,51 @@ Warning, version 430 is not yet complete; some version-specific features are pre 0:81 0 (const int) 0:81 Constant: 0:81 7.000000 +0:82 Constant: +0:82 2 (const int) +0:83 Constant: +0:83 2147483647 (const int) +0:84 Constant: +0:84 1.#INF00 +0:88 Constant: +0:88 2 (const uint) +0:88 3 (const uint) +0:89 Constant: +0:89 0 (const uint) +0:90 Constant: +0:90 6 (const uint) +0:90 7 (const uint) +0:103 Function Definition: foo2( (void) +0:103 Function Parameters: +0:105 Sequence +0:105 direct index (float) +0:105 'a1' (1-element array of float) +0:105 Constant: +0:105 0 (const int) +0:106 direct index (float) +0:106 'a2' (2-element array of float) +0:106 Constant: +0:106 0 (const int) +0:107 direct index (float) +0:107 'a3' (4-element array of float) +0:107 Constant: +0:107 0 (const int) +0:108 direct index (float) +0:108 'a4' (2-element array of float) +0:108 Constant: +0:108 0 (const int) +0:109 Constant: +0:109 1.000000 +0:110 Constant: +0:110 5.000000 +0:111 Constant: +0:111 2.000000 +0:112 Constant: +0:112 3.000000 +0:113 Constant: +0:113 0.000000 +0:114 Constant: +0:114 0.000000 0:? Linker Objects 0:? 'a' (const int) 0:? 1 (const int) @@ -209,4 +262,32 @@ Warning, version 430 is not yet complete; some version-specific features are pre 0:? 6.000000 0:? 7.000000 0:? 8.000000 +0:? 'm2' (const 2X2 matrix of float) +0:? 2.000000 +0:? 3.000000 +0:? 4.000000 +0:? 5.000000 +0:? 'm3' (const 3X3 matrix of float) +0:? 2.000000 +0:? 3.000000 +0:? 0.000000 +0:? 4.000000 +0:? 5.000000 +0:? 0.000000 +0:? 0.000000 +0:? 0.000000 +0:? 1.000000 +0:? 'mc' (const int) +0:? 1 (const int) +0:? 'a1' (1-element array of float) +0:? 'a2' (2-element array of float) +0:? 'a3' (4-element array of float) +0:? 'v2' (const 2-component vector of float) +0:? 1.000000 +0:? 2.000000 +0:? 'v3' (const 3-component vector of float) +0:? 3.000000 +0:? 4.000000 +0:? 5.000000 +0:? 'a4' (2-element array of float) diff --git a/Test/baseResults/matrixError.vert.out b/Test/baseResults/matrixError.vert.out index 70bdae84..1ac11f13 100644 --- a/Test/baseResults/matrixError.vert.out +++ b/Test/baseResults/matrixError.vert.out @@ -3,8 +3,8 @@ ERROR: 0:7: 'const' : non-matching or non-convertible constant type for const in ERROR: 0:17: 'assign' : cannot convert from '2-component vector of float' to '3-component vector of float' ERROR: 0:18: 'assign' : cannot convert from '2-component vector of float' to '3-component vector of float' ERROR: 0:19: '.' : field selection not allowed on matrix -ERROR: 0:21: '[' : index out of range '2' -ERROR: 0:21: '[' : index out of range '4' +ERROR: 0:21: '[' : matrix index out of range '2' +ERROR: 0:21: '[' : vector index out of range '4' ERROR: 7 compilation errors. No code generated. ERROR: node is still EOpNull! diff --git a/Test/constFold.frag b/Test/constFold.frag index e5a007df..824d6302 100644 --- a/Test/constFold.frag +++ b/Test/constFold.frag @@ -79,4 +79,37 @@ void foo() { float a[s.iv2.y]; // 3 element array a[0] = s.m[1].z; // 7.0 + b % 0; // int + b / 0; + e / 0; + const uint ua = 5; + const uvec2 ub = uvec2(6, 7); + const uint uc = 8; + ub % 4u; + 0u % uc; + ub % 0u; } + +const mat2 m2 = mat2(2, 3, 4, 5); +const mat3 m3 = mat3(m2); +const int mc = int(m3[2][2]); +float a1[mc]; +float a2[int(m3[2][1]) + 2]; // size 2 +float a3[int(m3[1][0])]; // size 4 +const vec2 v2 = vec2(1, 2); +const vec3 v3 = vec3(3, 4, 5); +float a4[uint(mat3(v2, v3, v2, v2)[2][2])]; // size 2 + +void foo2() +{ + a1[0]; // array size 1 + a2[0]; // array size 2 + a3[0]; // array size 4 + a4[0]; // array size 2 + v2[-1]; // ERROR + v3[4]; // ERROR + m3[0][-2]; // ERROR + m2[-1][1]; // ERROR + m3[1][3]; // ERROR + m3[3][1]; // ERROR +} \ No newline at end of file diff --git a/glslang/MachineIndependent/Constant.cpp b/glslang/MachineIndependent/Constant.cpp index 67b90c8e..b5c2b4fd 100644 --- a/glslang/MachineIndependent/Constant.cpp +++ b/glslang/MachineIndependent/Constant.cpp @@ -166,7 +166,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod case EbtInt: if (rightUnionArray[i] == 0) { - newConstArray[i].setIConst(0xEFFFFFFF); + newConstArray[i].setIConst(0x7FFFFFFF); } else newConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst()); break; @@ -207,8 +207,12 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod break; case EOpMod: - for (int i = 0; i < objectSize; i++) - newConstArray[i] = unionArray[i] % rightUnionArray[i]; + for (int i = 0; i < objectSize; i++) { + if (rightUnionArray[i] == 0) + newConstArray[i] = unionArray[i]; + else + newConstArray[i] = unionArray[i] % rightUnionArray[i]; + } break; case EOpRightShift: diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 565abba2..9adb2eb8 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -437,6 +437,12 @@ TIntermTyped* TParseContext::handleBracketDereference(TSourceLoc loc, TIntermTyp { TIntermTyped* result = 0; + int indexValue = 0; + if (index->getQualifier().storage == EvqConst) { + indexValue = index->getAsConstantUnion()->getConstArray()[0].getIConst(); + checkIndex(loc, base->getType(), indexValue); + } + variableCheck(base); if (! base->isArray() && ! base->isMatrix() && ! base->isVector()) { if (base->getAsSymbolNode()) @@ -446,31 +452,22 @@ TIntermTyped* TParseContext::handleBracketDereference(TSourceLoc loc, TIntermTyp } else if (base->getType().getQualifier().storage == EvqConst && index->getQualifier().storage == EvqConst) { if (base->isArray()) { // constant folding for arrays - result = addConstArrayNode(index->getAsConstantUnion()->getConstArray()[0].getIConst(), base, loc); + result = addConstArrayNode(loc, indexValue, base); } else if (base->isVector()) { // constant folding for vectors - TVectorFields fields; + TVectorFields fields; // need to do it this way because v.xy sends fields integer array fields.num = 1; - fields.offsets[0] = index->getAsConstantUnion()->getConstArray()[0].getIConst(); // need to do it this way because v.xy sends fields integer array - result = addConstVectorNode(fields, base, loc); + fields.offsets[0] = indexValue; + result = addConstVectorNode(loc, fields, base); } else if (base->isMatrix()) { // constant folding for matrices - result = addConstMatrixNode(index->getAsConstantUnion()->getConstArray()[0].getIConst(), base, loc); + result = addConstMatrixNode(loc, indexValue, base); } } else { // at least one of base and index is variable... if (index->getQualifier().storage == EvqConst) { - int indexValue = index->getAsConstantUnion()->getConstArray()[0].getIConst(); - if (! base->isArray() && ((base->isVector() && base->getType().getVectorSize() <= indexValue) || - (base->isMatrix() && base->getType().getMatrixCols() <= indexValue))) - error(loc, "", "[", "index out of range '%d'", index->getAsConstantUnion()->getConstArray()[0].getIConst()); - if (base->isArray()) { - if (base->getType().getArraySize() == 0) - updateMaxArraySize(loc, base, index->getAsConstantUnion()->getConstArray()[0].getIConst()); - else if (index->getAsConstantUnion()->getConstArray()[0].getIConst() >= base->getType().getArraySize() || - index->getAsConstantUnion()->getConstArray()[0].getIConst() < 0) - error(loc, "", "[", "array index out of range '%d'", index->getAsConstantUnion()->getConstArray()[0].getIConst()); - } + if (base->isArray() && base->getType().getArraySize() == 0) + updateMaxArraySize(loc, base, indexValue); result = intermediate.addIndex(EOpIndexDirect, base, index, loc); } else { if (base->isArray() && base->getType().getArraySize() == 0) @@ -490,10 +487,12 @@ TIntermTyped* TParseContext::handleBracketDereference(TSourceLoc loc, TIntermTyp } if (result == 0) { + // Insert dummy error-recovery result TConstUnionArray unionArray(1); unionArray[0].setDConst(0.0); result = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), loc); } else { + // Insert valid dereferenced result TType newType; newType.shallowCopy(base->getType()); if (base->getType().getQualifier().storage == EvqConst && index->getQualifier().storage == EvqConst) @@ -513,6 +512,29 @@ TIntermTyped* TParseContext::handleBracketDereference(TSourceLoc loc, TIntermTyp return result; } +void TParseContext::checkIndex(TSourceLoc loc, const TType& type, int& index) +{ + if (index < 0) { + error(loc, "", "[", "index out of range '%d'", index); + index = 0; + } else if (type.isArray()) { + if (type.getArraySize() != 0 && index >= type.getArraySize()) { + error(loc, "", "[", "array index out of range '%d'", index); + index = type.getArraySize() - 1; + } + } else if (type.isVector()) { + if (index >= type.getVectorSize()) { + error(loc, "", "[", "vector index out of range '%d'", index); + index = type.getVectorSize() - 1; + } + } else if (type.isMatrix()) { + if (index >= type.getMatrixCols()) { + error(loc, "", "[", "matrix index out of range '%d'", index); + index = type.getMatrixCols() - 1; + } + } +} + // for ES 2.0 (version 100) limitations for almost all index operations except vertex-shader uniforms void TParseContext::handleIndexLimits(TSourceLoc loc, TIntermTyped* base, TIntermTyped* index) { @@ -632,7 +654,7 @@ TIntermTyped* TParseContext::handleDotDereference(TSourceLoc loc, TIntermTyped* } if (base->getType().getQualifier().storage == EvqConst) { // constant folding for vector fields - result = addConstVectorNode(fields, base, loc); + result = addConstVectorNode(loc, fields, base); if (result == 0) result = base; else @@ -668,7 +690,7 @@ TIntermTyped* TParseContext::handleDotDereference(TSourceLoc loc, TIntermTyped* } if (fieldFound) { if (base->getType().getQualifier().storage == EvqConst) { - result = addConstStruct(field, base, loc); + result = addConstStruct(loc, field, base); if (result == 0) result = base; else { @@ -3600,26 +3622,18 @@ TIntermNode* TParseContext::addSwitch(TSourceLoc loc, TIntermTyped* expression, // TODO: simplification: constant folding: these should use a follow a fully folded model now, and probably move to Constant.cpp scheme. // -// This function returns the tree representation for the vector field(s) being accessed from a constant vector. -// If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is -// returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol -// node or it could be the intermediate tree representation of accessing fields in a constant structure or column of -// a constant matrix. +// Make a constant scalar or vector node, representing a given constant vector and constant swizzle into it. // -TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, TSourceLoc loc) +// The type of the returned node is still the original vector type; it needs to be corrected by the caller. +// +TIntermTyped* TParseContext::addConstVectorNode(TSourceLoc loc, TVectorFields& fields, TIntermTyped* node) { - TIntermTyped* typedNode; - TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); - - TConstUnionArray unionArray; - if (tempConstantNode) - unionArray = tempConstantNode->getConstArray(); - else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error + if (! node->getAsConstantUnion()) { error(loc, "Cannot offset into the vector", "Error", ""); - return 0; } + const TConstUnionArray& unionArray = node->getAsConstantUnion()->getConstArray(); TConstUnionArray constArray(fields.num); for (int i = 0; i < fields.num; i++) { @@ -3630,52 +3644,45 @@ TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTy constArray[i] = unionArray[fields.offsets[i]]; } - typedNode = intermediate.addConstantUnion(constArray, node->getType(), loc); - return typedNode; + return intermediate.addConstantUnion(constArray, node->getType(), loc); } // -// This function returns the column being accessed from a constant matrix. The values are retrieved from -// the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input -// to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a -// constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure) +// Make a constant vector node, representing a given constant column +// from the given constant matrix. // -TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, TSourceLoc loc) +// The type of the returned node is still the original matrix type; +// which needs to be corrected (dereferenced) by the caller. +// +TIntermTyped* TParseContext::addConstMatrixNode(TSourceLoc loc, int index, TIntermTyped* node) { - TIntermTyped* typedNode; - TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); + TIntermConstantUnion* constNode = node->getAsConstantUnion(); if (index >= node->getType().getMatrixCols()) { error(loc, "", "[", "matrix field selection out of range '%d'", index); index = 0; } - if (tempConstantNode) { - const TConstUnionArray& unionArray = tempConstantNode->getConstArray(); - int size = tempConstantNode->getType().getMatrixRows(); - // Note: the type is corrected (dereferenced) by the caller - typedNode = intermediate.addConstantUnion(TConstUnionArray(unionArray, size * index, size), tempConstantNode->getType(), loc); + if (constNode) { + const TConstUnionArray& unionArray = constNode->getConstArray(); + int size = constNode->getType().getMatrixRows(); + return intermediate.addConstantUnion(TConstUnionArray(unionArray, size * index, size), constNode->getType(), loc); } else { error(loc, "Cannot offset into the matrix", "Error", ""); - return 0; } - - return typedNode; } // -// This function returns an element of an array accessed from a constant array. The values are retrieved from -// the symbol table and parse-tree is built for the type of the element. The input -// to the function could either be a symbol node (a[0] where a is a constant array)that represents a -// constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure) +// Make a constant node, representing the constant element of the constant array. // -TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TSourceLoc loc) +// The type of the returned node is still the original array type; +// which needs to be corrected (dereferenced) by the caller. +// +TIntermTyped* TParseContext::addConstArrayNode(TSourceLoc loc, int index, TIntermTyped* node) { - TIntermTyped* typedNode; - TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); TType arrayElementType; arrayElementType.shallowCopy(node->getType()); // TODO: 4.3 simplification: arrays of arrays: combine this with deref. arrayElementType.dereference(); @@ -3685,18 +3692,14 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS index = 0; } - int arrayElementSize = arrayElementType.getObjectSize(); - - if (tempConstantNode) { - typedNode = intermediate.addConstantUnion(TConstUnionArray(tempConstantNode->getConstArray(), arrayElementSize * index, arrayElementSize), - tempConstantNode->getType(), loc); + if (node->getAsConstantUnion()) { + int arrayElementSize = arrayElementType.getObjectSize(); + return intermediate.addConstantUnion(TConstUnionArray(node->getAsConstantUnion()->getConstArray(), arrayElementSize * index, arrayElementSize), + node->getType(), loc); } else { error(loc, "Cannot offset into the array", "Error", ""); - return 0; } - - return typedNode; } @@ -3705,16 +3708,13 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS // If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr // function and returns the parse-tree with the values of the embedded/nested struct. // -TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, TSourceLoc loc) +TIntermTyped* TParseContext::addConstStruct(TSourceLoc loc, TString& identifier, TIntermTyped* node) { TTypeList* fields = node->getType().getStruct(); - TIntermTyped *typedNode; int instanceOffset = 0; int instanceSize; - unsigned int index = 0; - TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion(); - for ( index = 0; index < fields->size(); ++index) { + for (size_t index = 0; index < fields->size(); ++index) { instanceSize = (*fields)[index].type->getObjectSize(); if ((*fields)[index].type->getFieldName() == identifier) @@ -3723,17 +3723,14 @@ TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* n instanceOffset += instanceSize; } - if (tempConstantNode) { - typedNode = intermediate.addConstantUnion(TConstUnionArray(tempConstantNode->getConstArray(), instanceOffset, instanceSize), - tempConstantNode->getType(), loc); + if (node->getAsConstantUnion()) { + return intermediate.addConstantUnion(TConstUnionArray(node->getAsConstantUnion()->getConstArray(), instanceOffset, instanceSize), + node->getType(), loc); // type will be changed in the calling function } else { error(loc, "Cannot offset into the structure", "Error", ""); - return 0; } - - return typedNode; } } // end namespace glslang diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index 6ae64569..2bade69e 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -81,6 +81,7 @@ public: void handlePragma(const char **tokens, int numTokens); TIntermTyped* handleVariable(TSourceLoc, TSymbol* symbol, TString* string); TIntermTyped* handleBracketDereference(TSourceLoc, TIntermTyped* base, TIntermTyped* index); + void checkIndex(TSourceLoc, const TType&, int& index); void handleIndexLimits(TSourceLoc, TIntermTyped* base, TIntermTyped* index); void handleInputArrayAccess(TSourceLoc, TIntermTyped* base); void checkInputArrayConsistency(TSourceLoc, bool tailOnly = false); @@ -159,10 +160,10 @@ public: void updateTypedDefaults(TSourceLoc, const TQualifier&, const TString* id); void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode); TIntermNode* addSwitch(TSourceLoc, TIntermTyped* expression, TIntermAggregate* body); - TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, TSourceLoc); - TIntermTyped* addConstMatrixNode(int , TIntermTyped*, TSourceLoc); - TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, TSourceLoc); - TIntermTyped* addConstStruct(TString& , TIntermTyped*, TSourceLoc); + TIntermTyped* addConstVectorNode(TSourceLoc, TVectorFields&, TIntermTyped*); + TIntermTyped* addConstMatrixNode(TSourceLoc, int index, TIntermTyped*); + TIntermTyped* addConstArrayNode(TSourceLoc, int index, TIntermTyped* node); + TIntermTyped* addConstStruct(TSourceLoc, TString& , TIntermTyped*); void updateMaxArraySize(TSourceLoc, TIntermNode*, int index); diff --git a/glslang/MachineIndependent/parseConst.cpp b/glslang/MachineIndependent/parseConst.cpp index 872607b7..342fca51 100644 --- a/glslang/MachineIndependent/parseConst.cpp +++ b/glslang/MachineIndependent/parseConst.cpp @@ -118,28 +118,23 @@ void ParseConstantUnion(TIntermConstantUnion* node, TIntermTraverser* it) if (oit->index >= instanceSize) return; - if (!oit->singleConstantParam) { + if (! oit->singleConstantParam) { int size = node->getType().getObjectSize(); const TConstUnionArray& rightUnionArray = node->getConstArray(); - for (int i=0; i < size; i++) { + for (int i = 0; i < size; i++) { if (oit->index >= instanceSize) return; leftUnionArray[oit->index] = rightUnionArray[i]; - (oit->index)++; + oit->index++; } } else { - int size, totalSize, matrixRows; - bool isMatrix = false; - size = oit->size; - matrixRows = oit->matrixRows; - isMatrix = oit->isMatrix; - totalSize = oit->index + size; + int endIndex = oit->index + oit->size; const TConstUnionArray& rightUnionArray = node->getConstArray(); - if (! isMatrix) { + if (! oit->isMatrix) { int count = 0; - for (int i = oit->index; i < totalSize; i++) { + for (int i = oit->index; i < endIndex; i++) { if (i >= instanceSize) return; @@ -150,21 +145,41 @@ void ParseConstantUnion(TIntermConstantUnion* node, TIntermTraverser* it) if (node->getType().getObjectSize() > 1) count++; } - } else { // for matrix constructors - int count = 0; - int index = oit->index; - for (int i = index; i < totalSize; i++) { - if (i >= instanceSize) - return; - if (index - i == 0 || (i - index) % (matrixRows + 1) == 0 ) - leftUnionArray[i] = rightUnionArray[count]; - else - leftUnionArray[i].setDConst(0.0); + } else { + // constructing a matrix, but from what? + if (node->isMatrix()) { + // Matrix from a matrix; oit has the outer matrix, node is the argument matrix. + // Traverse the outer, potentially bigger matrix, fill in missing pieces with the + // identity matrix. + for (int c = 0; c < oit->matrixCols; ++c) { + for (int r = 0; r < oit->matrixRows; ++r) { + int targetOffset = oit->index + c * oit->matrixRows + r; + if (r < node->getType().getMatrixRows() && c < node->getType().getMatrixCols()) { + int srcOffset = c * node->getType().getMatrixRows() + r; + leftUnionArray[targetOffset] = rightUnionArray[srcOffset]; + } else if (r == c) + leftUnionArray[targetOffset].setDConst(1.0); + else + leftUnionArray[targetOffset].setDConst(0.0); + } + } + } else { + // matrix from vector + int count = 0; + int index = oit->index; + for (int i = index; i < endIndex; i++) { + if (i >= instanceSize) + return; + if (i == index || (i - index) % (oit->matrixRows + 1) == 0 ) + leftUnionArray[i] = rightUnionArray[count]; + else + leftUnionArray[i].setDConst(0.0); - (oit->index)++; + oit->index++; - if (node->getType().getObjectSize() > 1) - count++; + if (node->getType().getObjectSize() > 1) + count++; + } } } }