diff --git a/Test/baseResults/120.frag.out b/Test/baseResults/120.frag.out index 79898aaf..5df3f987 100644 --- a/Test/baseResults/120.frag.out +++ b/Test/baseResults/120.frag.out @@ -15,11 +15,9 @@ ERROR: 0:63: 'bitwise-or assign' : not supported for this version or the enabled ERROR: 0:63: 'assign' : cannot convert from 'temp bool' to 'temp float' ERROR: 0:79: ':' : wrong operand types: no operation ':' exists that takes a left-hand operand of type 'temp 4-component vector of float' and a right operand of type 'temp 4X4 matrix of float' (or there is no acceptable conversion) ERROR: 0:79: 'assign' : cannot convert from 'temp 4X4 matrix of float' to 'fragColor 4-component vector of float FragColor' -ERROR: 0:82: 'xr' : illegal - vector component fields not from the same set -ERROR: 0:83: 'xyxyx' : illegal vector field selection -ERROR: 0:83: 'scalar swizzle' : not supported for this version or the enabled extensions -ERROR: 0:83: 'xy' : vector field selection out of range -ERROR: 0:84: 'z' : vector field selection out of range +ERROR: 0:82: 'xr' : vector swizzle selectors not from the same set +ERROR: 0:83: 'xyxyx' : vector swizzle too long +ERROR: 0:84: 'z' : vector swizzle selection out of range ERROR: 0:85: 'assign' : l-value required ERROR: 0:91: 'int' : overloaded functions must have the same return type ERROR: 0:91: 'main' : function already has a body @@ -52,7 +50,7 @@ ERROR: 0:191: 'shadow2DProjGradARB' : required extension not requested: GL_ARB_s ERROR: 0:209: 'shadow2DRectProjGradARB' : no matching overloaded function found ERROR: 0:209: 'assign' : cannot convert from 'const float' to 'temp 4-component vector of float' ERROR: 0:212: 'sampler2DRect' : Reserved word. -ERROR: 53 compilation errors. No code generated. +ERROR: 51 compilation errors. No code generated. Shader version: 120 @@ -251,10 +249,23 @@ ERROR: node is still EOpNull! 0:82 'gl_FragColor' (fragColor 4-component vector of float FragColor) 0:82 Constant: 0:82 0 (const int) -0:83 direct index (temp float) -0:83 'gl_FragColor' (fragColor 4-component vector of float FragColor) -0:83 Constant: -0:83 0 (const int) +0:83 vector swizzle (temp 2-component vector of float) +0:83 vector swizzle (temp 4-component vector of float) +0:83 'gl_FragColor' (fragColor 4-component vector of float FragColor) +0:83 Sequence +0:83 Constant: +0:83 0 (const int) +0:83 Constant: +0:83 1 (const int) +0:83 Constant: +0:83 0 (const int) +0:83 Constant: +0:83 1 (const int) +0:83 Sequence +0:83 Constant: +0:83 0 (const int) +0:83 Constant: +0:83 1 (const int) 0:84 direct index (temp float) 0:84 'centTexCoord' (centroid smooth in 2-component vector of float) 0:84 Constant: diff --git a/Test/baseResults/420.vert.out b/Test/baseResults/420.vert.out index a70b44e7..b8e1306d 100644 --- a/Test/baseResults/420.vert.out +++ b/Test/baseResults/420.vert.out @@ -18,9 +18,9 @@ ERROR: 0:40: 'j' : undeclared identifier ERROR: 0:40: '=' : cannot convert from 'temp float' to 'temp int' ERROR: 0:44: 'jj' : undeclared identifier ERROR: 0:44: '=' : cannot convert from 'temp float' to 'temp int' -ERROR: 0:54: 'y' : vector field selection out of range -ERROR: 0:62: 'xxxxx' : illegal vector field selection -ERROR: 0:63: 'xxy' : vector field selection out of range +ERROR: 0:54: 'y' : vector swizzle selection out of range +ERROR: 0:62: 'xxxxx' : vector swizzle too long +ERROR: 0:63: 'xxy' : vector swizzle selection out of range ERROR: 0:66: 'binding' : cannot declare a default, include a type or full declaration ERROR: 0:69: 'location/component/index' : cannot declare a default, use a full declaration ERROR: 0:70: 'input block' : not supported in this stage: vertex @@ -124,8 +124,10 @@ ERROR: node is still EOpNull! 0:61 'smeared' (temp 3-component vector of float) 0:61 Construct vec3 (temp 3-component vector of float) 0:61 'f' (temp float) -0:62 'f' (temp float) -0:63 'f' (temp float) +0:62 Construct vec4 (temp 4-component vector of float) +0:62 'f' (temp float) +0:63 Construct vec2 (temp 2-component vector of float) +0:63 'f' (temp float) 0:88 Function Definition: bar23444( (global void) 0:88 Function Parameters: 0:? Sequence diff --git a/Test/baseResults/cppComplexExpr.vert.out b/Test/baseResults/cppComplexExpr.vert.out index 352dcac1..90d62c12 100644 --- a/Test/baseResults/cppComplexExpr.vert.out +++ b/Test/baseResults/cppComplexExpr.vert.out @@ -1,6 +1,8 @@ cppComplexExpr.vert -ERROR: 0:46: 'xyxwx' : illegal vector field selection -ERROR: 0:46: 'xyxwx' : illegal vector field selection +ERROR: 0:46: 'xyxwx' : vector swizzle too long +ERROR: 0:46: 'xyxwx' : vector swizzle too long +ERROR: 0:46: 'return' : cannot convert return value to function return type +WARNING: 0:46: 'return' : type conversion on return values was not explicitly allowed until version 420 ERROR: 0:66: '#define' : Macro redefined; different substitutions: BIG ERROR: 0:81: 'preprocessor evaluation' : bad expression ERROR: 0:81: '#if' : unexpected tokens following directive @@ -47,7 +49,7 @@ ERROR: 0:0: 'preprocessor evaluation' : division by 0 ERROR: 0:3: 'preprocessor evaluation' : bad expression ERROR: 0:3: 'preprocessor evaluation' : division by 0 ERROR: 0:10001: '' : missing #endif -ERROR: 48 compilation errors. No code generated. +ERROR: 49 compilation errors. No code generated. Shader version: 300 @@ -80,19 +82,33 @@ ERROR: node is still EOpNull! 0:44 Function Parameters: 0:46 Sequence 0:46 Branch: Return with expression -0:46 add (temp highp float) -0:46 add (temp highp float) -0:46 direct index (temp highp float) +0:46 add (temp highp 4-component vector of float) +0:46 add (temp highp 4-component vector of float) +0:46 vector swizzle (temp highp 4-component vector of float) 0:46 'gl_Position' (gl_Position highp 4-component vector of float Position) -0:46 Constant: -0:46 0 (const int) +0:46 Sequence +0:46 Constant: +0:46 0 (const int) +0:46 Constant: +0:46 1 (const int) +0:46 Constant: +0:46 0 (const int) +0:46 Constant: +0:46 3 (const int) 0:46 Constant: 0:46 3.000000 -0:46 add (temp highp float) -0:46 direct index (temp highp float) +0:46 add (temp highp 4-component vector of float) +0:46 vector swizzle (temp highp 4-component vector of float) 0:46 'gl_Position' (gl_Position highp 4-component vector of float Position) -0:46 Constant: -0:46 0 (const int) +0:46 Sequence +0:46 Constant: +0:46 0 (const int) +0:46 Constant: +0:46 1 (const int) +0:46 Constant: +0:46 0 (const int) +0:46 Constant: +0:46 3 (const int) 0:46 Constant: 0:46 3.000000 0:47 Branch: Return with expression diff --git a/Test/baseResults/specExamples.frag.out b/Test/baseResults/specExamples.frag.out index a66144a7..f660e66f 100644 --- a/Test/baseResults/specExamples.frag.out +++ b/Test/baseResults/specExamples.frag.out @@ -22,14 +22,14 @@ ERROR: 0:172: '[]' : scalar integer expression required ERROR: 0:175: 'x' : undeclared identifier ERROR: 0:175: '[]' : scalar integer expression required ERROR: 0:175: 'b' : left of '[' is not of type array, matrix, or vector -ERROR: 0:175: 'a' : vector field selection out of range +ERROR: 0:175: 'a' : vector swizzle selection out of range ERROR: 0:175: 'length' : does not operate on this type: const float ERROR: 0:175: '' : function call, method, or subroutine call expected ERROR: 0:175: '' : no matching overloaded function found ERROR: 0:178: '[]' : scalar integer expression required ERROR: 0:178: 's' : undeclared identifier ERROR: 0:178: 's' : left of '[' is not of type array, matrix, or vector -ERROR: 0:178: 'a' : vector field selection out of range +ERROR: 0:178: 'a' : vector swizzle selection out of range ERROR: 0:178: 'length' : does not operate on this type: const float ERROR: 0:178: '' : function call, method, or subroutine call expected ERROR: 0:178: '' : no matching overloaded function found diff --git a/glslang/MachineIndependent/Constant.cpp b/glslang/MachineIndependent/Constant.cpp index c709a785..fff8fd26 100644 --- a/glslang/MachineIndependent/Constant.cpp +++ b/glslang/MachineIndependent/Constant.cpp @@ -974,20 +974,20 @@ TIntermTyped* TIntermediate::foldDereference(TIntermTyped* node, int index, cons // Make a constant vector node or constant scalar node, representing a given // constant vector and constant swizzle into it. // -TIntermTyped* TIntermediate::foldSwizzle(TIntermTyped* node, TVectorFields& fields, const TSourceLoc& loc) +TIntermTyped* TIntermediate::foldSwizzle(TIntermTyped* node, TSwizzleSelectors& selectors, const TSourceLoc& loc) { const TConstUnionArray& unionArray = node->getAsConstantUnion()->getConstArray(); - TConstUnionArray constArray(fields.num); + TConstUnionArray constArray(selectors.size()); - for (int i = 0; i < fields.num; i++) - constArray[i] = unionArray[fields.offsets[i]]; + for (int i = 0; i < selectors.size(); i++) + constArray[i] = unionArray[selectors[i]]; TIntermTyped* result = addConstantUnion(constArray, node->getType(), loc); if (result == 0) result = node; else - result->setType(TType(node->getBasicType(), EvqConst, fields.num)); + result->setType(TType(node->getBasicType(), EvqConst, selectors.size())); return result; } diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp index 3363d672..8d68517a 100644 --- a/glslang/MachineIndependent/Intermediate.cpp +++ b/glslang/MachineIndependent/Intermediate.cpp @@ -1392,38 +1392,35 @@ TIntermConstantUnion* TIntermediate::addConstantUnion(double d, TBasicType baseT return addConstantUnion(unionArray, TType(baseType, EvqConst), loc, literal); } -TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc& loc) +// Put vector swizzle selectors onto the given sequence +void TIntermediate::pushSelector(TIntermSequence& sequence, const TVectorSelector& selector, const TSourceLoc& loc) { - TIntermAggregate* node = new TIntermAggregate(EOpSequence); - - node->setLoc(loc); - TIntermConstantUnion* constIntNode; - TIntermSequence &sequenceVector = node->getSequence(); - - for (int i = 0; i < fields.num; i++) { - constIntNode = addConstantUnion(fields.offsets[i], loc); - sequenceVector.push_back(constIntNode); - } - - return node; + TIntermConstantUnion* constIntNode = addConstantUnion(selector, loc); + sequence.push_back(constIntNode); } -// A matrix swizzle is a sequence of nodes, 2N long, where N is the -// number of components in the swizzle, alternating col,row, col,row, ... -TIntermTyped* TIntermediate::addSwizzle(TMatrixComponents& comps, const TSourceLoc& loc) +// Put matrix swizzle selectors onto the given sequence +void TIntermediate::pushSelector(TIntermSequence& sequence, const TMatrixSelector& selector, const TSourceLoc& loc) +{ + TIntermConstantUnion* constIntNode = addConstantUnion(selector.coord1, loc); + sequence.push_back(constIntNode); + constIntNode = addConstantUnion(selector.coord2, loc); + sequence.push_back(constIntNode); +} + +// Make an aggregate node that has a sequence of all selectors. +template TIntermTyped* TIntermediate::addSwizzle(TSwizzleSelectors& selector, const TSourceLoc& loc); +template TIntermTyped* TIntermediate::addSwizzle(TSwizzleSelectors& selector, const TSourceLoc& loc); +template +TIntermTyped* TIntermediate::addSwizzle(TSwizzleSelectors& selector, const TSourceLoc& loc) { TIntermAggregate* node = new TIntermAggregate(EOpSequence); node->setLoc(loc); - TIntermConstantUnion* constIntNode; TIntermSequence &sequenceVector = node->getSequence(); - for (int i = 0; i < comps.size(); i++) { - constIntNode = addConstantUnion(comps.get(i).coord1, loc); - sequenceVector.push_back(constIntNode); - constIntNode = addConstantUnion(comps.get(i).coord2, loc); - sequenceVector.push_back(constIntNode); - } + for (int i = 0; i < selector.size(); i++) + pushSelector(sequenceVector, selector[i], loc); return node; } diff --git a/glslang/MachineIndependent/ParseContextBase.cpp b/glslang/MachineIndependent/ParseContextBase.cpp index a5be3510..83a9fdf5 100644 --- a/glslang/MachineIndependent/ParseContextBase.cpp +++ b/glslang/MachineIndependent/ParseContextBase.cpp @@ -433,6 +433,108 @@ const TFunction* TParseContextBase::selectFunction( return incumbent; } +// +// Look at a '.' field selector string and change it into numerical selectors +// for a vector or scalar. +// +// Always return some form of swizzle, so the result is always usable. +// +void TParseContextBase::parseSwizzleSelector(const TSourceLoc& loc, const TString& compString, int vecSize, + TSwizzleSelectors& selector) +{ + // Too long? + if (compString.size() > TSwizzleSelectors::maxSelectors) + error(loc, "vector swizzle too long", compString.c_str(), ""); + + // Use this to test that all swizzle characters are from the same swizzle-namespace-set + enum { + exyzw, + ergba, + estpq, + } fieldSet[TSwizzleSelectors::maxSelectors]; + + // Decode the swizzle string. + int size = std::min(TSwizzleSelectors::maxSelectors, (int)compString.size()); + for (int i = 0; i < size; ++i) { + switch (compString[i]) { + case 'x': + selector.push_back(0); + fieldSet[i] = exyzw; + break; + case 'r': + selector.push_back(0); + fieldSet[i] = ergba; + break; + case 's': + selector.push_back(0); + fieldSet[i] = estpq; + break; + + case 'y': + selector.push_back(1); + fieldSet[i] = exyzw; + break; + case 'g': + selector.push_back(1); + fieldSet[i] = ergba; + break; + case 't': + selector.push_back(1); + fieldSet[i] = estpq; + break; + + case 'z': + selector.push_back(2); + fieldSet[i] = exyzw; + break; + case 'b': + selector.push_back(2); + fieldSet[i] = ergba; + break; + case 'p': + selector.push_back(2); + fieldSet[i] = estpq; + break; + + case 'w': + selector.push_back(3); + fieldSet[i] = exyzw; + break; + case 'a': + selector.push_back(3); + fieldSet[i] = ergba; + break; + case 'q': + selector.push_back(3); + fieldSet[i] = estpq; + break; + + default: + error(loc, "unknown swizzle selection", compString.c_str(), ""); + break; + } + } + + // Additional error checking. + for (int i = 0; i < selector.size(); ++i) { + if (selector[i] >= vecSize) { + error(loc, "vector swizzle selection out of range", compString.c_str(), ""); + selector.resize(i); + break; + } + + if (i > 0 && fieldSet[i] != fieldSet[i-1]) { + error(loc, "vector swizzle selectors not from the same set", compString.c_str(), ""); + selector.resize(i); + break; + } + } + + // Ensure it is valid. + if (selector.size() == 0) + selector.push_back(0); +} + // // Make the passed-in variable information become a member of the // global uniform block. If this doesn't exist yet, make it. diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index cfb56b04..b0ac3bbd 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -258,106 +258,6 @@ void TParseContext::handlePragma(const TSourceLoc& loc, const TVector& } } -/////////////////////////////////////////////////////////////////////// -// -// Sub- vector and matrix fields -// -//////////////////////////////////////////////////////////////////////// - -// -// Look at a '.' field selector string and change it into offsets -// for a vector or scalar -// -// Returns true if there is no error. -// -bool TParseContext::parseVectorFields(const TSourceLoc& loc, const TString& compString, int vecSize, TVectorFields& fields) -{ - fields.num = (int)compString.size(); - if (fields.num > 4) { - error(loc, "illegal vector field selection", compString.c_str(), ""); - return false; - } - - enum { - exyzw, - ergba, - estpq, - } fieldSet[4]; - - for (int i = 0; i < fields.num; ++i) { - switch (compString[i]) { - case 'x': - fields.offsets[i] = 0; - fieldSet[i] = exyzw; - break; - case 'r': - fields.offsets[i] = 0; - fieldSet[i] = ergba; - break; - case 's': - fields.offsets[i] = 0; - fieldSet[i] = estpq; - break; - case 'y': - fields.offsets[i] = 1; - fieldSet[i] = exyzw; - break; - case 'g': - fields.offsets[i] = 1; - fieldSet[i] = ergba; - break; - case 't': - fields.offsets[i] = 1; - fieldSet[i] = estpq; - break; - case 'z': - fields.offsets[i] = 2; - fieldSet[i] = exyzw; - break; - case 'b': - fields.offsets[i] = 2; - fieldSet[i] = ergba; - break; - case 'p': - fields.offsets[i] = 2; - fieldSet[i] = estpq; - break; - - case 'w': - fields.offsets[i] = 3; - fieldSet[i] = exyzw; - break; - case 'a': - fields.offsets[i] = 3; - fieldSet[i] = ergba; - break; - case 'q': - fields.offsets[i] = 3; - fieldSet[i] = estpq; - break; - default: - error(loc, "illegal vector field selection", compString.c_str(), ""); - return false; - } - } - - for (int i = 0; i < fields.num; ++i) { - if (fields.offsets[i] >= vecSize) { - error(loc, "vector field selection out of range", compString.c_str(), ""); - return false; - } - - if (i > 0) { - if (fieldSet[i] != fieldSet[i-1]) { - error(loc, "illegal - vector component fields not from the same set", compString.c_str(), ""); - return false; - } - } - } - - return true; -} - // // Handle seeing a variable identifier in the grammar. // @@ -781,17 +681,14 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, dotFeature); } - TVectorFields fields; - if (! parseVectorFields(loc, field, base->getVectorSize(), fields)) { - fields.num = 1; - fields.offsets[0] = 0; - } + TSwizzleSelectors selectors; + parseSwizzleSelector(loc, field, base->getVectorSize(), selectors); if (base->isScalar()) { - if (fields.num == 1) + if (selectors.size() == 1) return result; else { - TType type(base->getBasicType(), EvqTemporary, fields.num); + TType type(base->getBasicType(), EvqTemporary, selectors.size()); // Swizzle operations propagate specialization-constantness if (base->getQualifier().isSpecConstant()) type.getQualifier().makeSpecConstant(); @@ -800,17 +697,16 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm } if (base->getType().getQualifier().isFrontEndConstant()) - result = intermediate.foldSwizzle(base, fields, loc); + result = intermediate.foldSwizzle(base, selectors, loc); else { - if (fields.num == 1) { - TIntermTyped* index = intermediate.addConstantUnion(fields.offsets[0], loc); + if (selectors.size() == 1) { + TIntermTyped* index = intermediate.addConstantUnion(selectors[0], loc); result = intermediate.addIndex(EOpIndexDirect, base, index, loc); result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision)); } else { - TString vectorString = field; - TIntermTyped* index = intermediate.addSwizzle(fields, loc); + TIntermTyped* index = intermediate.addSwizzle(selectors, loc); result = intermediate.addIndex(EOpVectorSwizzle, base, index, loc); - result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, (int)vectorString.size())); + result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, selectors.size())); } // Swizzle operations propagate specialization-constantness if (base->getType().getQualifier().isSpecConstant()) diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index 8d169e4e..2e09a5ae 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -170,6 +170,9 @@ protected: std::function, /* output */ bool& tie); + virtual void parseSwizzleSelector(const TSourceLoc&, const TString&, int size, + TSwizzleSelectors&); + // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL) TVariable* globalUniformBlock; // the actual block, inserted into the symbol table int firstNewMember; // the index of the first member not yet inserted into the symbol table @@ -284,7 +287,6 @@ public: void handlePrecisionQualifier(const TSourceLoc&, TQualifier&, TPrecisionQualifier); void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier); - bool parseVectorFields(const TSourceLoc&, const TString&, int vecSize, TVectorFields&); void assignError(const TSourceLoc&, const char* op, TString left, TString right); void unaryOpError(const TSourceLoc&, const char* op, TString operand); void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right); diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index cb790af7..812d4a36 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -47,45 +47,39 @@ class TInfoSink; namespace glslang { -struct TVectorFields { - TVectorFields() { } - - TVectorFields(int c0, int c1, int c2, int c3) : num(4) - { - offsets[0] = c0; - offsets[1] = c1; - offsets[2] = c2; - offsets[3] = c3; - } - - int offsets[4]; - int num; +struct TMatrixSelector { + int coord1; // stay agnostic about column/row; this is parse order + int coord2; }; -class TMatrixComponents { -public: - static const int maxMatrixComponents = 4; - struct tMatrixComponent { - int coord1; // stay agnostic about column/row; this is parse order - int coord2; - }; +typedef int TVectorSelector; - TMatrixComponents() : size_(0) { } - void push_back(tMatrixComponent comp) +template +class TSwizzleSelectors { +public: + static const int maxSelectors = 4; + TSwizzleSelectors() : size_(0) { } + + void push_back(selectorType comp) { - if (size_ < maxMatrixComponents) + if (size_ < maxSelectors) components[size_++] = comp; } - int size() const { return size_; } - tMatrixComponent get(int i) const + void resize(int s) { - assert(i < maxMatrixComponents); + assert(s <= size_); + size_ = s; + } + int size() const { return size_; } + selectorType operator[](int i) const + { + assert(i < maxSelectors); return components[i]; } - + private: int size_; - tMatrixComponent components[4]; + selectorType components[maxSelectors]; }; // @@ -274,8 +268,7 @@ public: TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&); TIntermBranch* addBranch(TOperator, const TSourceLoc&); TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&); - TIntermTyped* addSwizzle(TVectorFields&, const TSourceLoc&); - TIntermTyped* addSwizzle(TMatrixComponents&, const TSourceLoc&); + template TIntermTyped* addSwizzle(TSwizzleSelectors&, const TSourceLoc&); // Low level functions to add nodes (no conversions or other higher level transformations) // If a type is provided, the node's type will be set to it. @@ -291,7 +284,7 @@ public: TIntermTyped* fold(TIntermAggregate* aggrNode); TIntermTyped* foldConstructor(TIntermAggregate* aggrNode); TIntermTyped* foldDereference(TIntermTyped* node, int index, const TSourceLoc&); - TIntermTyped* foldSwizzle(TIntermTyped* node, TVectorFields& fields, const TSourceLoc&); + TIntermTyped* foldSwizzle(TIntermTyped* node, TSwizzleSelectors& fields, const TSourceLoc&); // Tree ops static const TIntermTyped* findLValueBase(const TIntermTyped*, bool swizzleOkay); @@ -444,6 +437,8 @@ protected: bool promoteBinary(TIntermBinary&); void addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable&, const TString&); bool promoteAggregate(TIntermAggregate&); + void pushSelector(TIntermSequence&, const TVectorSelector&, const TSourceLoc&); + void pushSelector(TIntermSequence&, const TMatrixSelector&, const TSourceLoc&); const EShLanguage language; // stage, known at construction time EShSource source; // source language, known a bit later diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index 7477e031..de1275c4 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -502,101 +502,7 @@ void HlslParseContext::handlePragma(const TSourceLoc& loc, const TVector 4) { - error(loc, "illegal vector field selection", compString.c_str(), ""); - return false; - } - - enum { - exyzw, - ergba, - estpq, - } fieldSet[4]; - - for (int i = 0; i < fields.num; ++i) { - switch (compString[i]) { - case 'x': - fields.offsets[i] = 0; - fieldSet[i] = exyzw; - break; - case 'r': - fields.offsets[i] = 0; - fieldSet[i] = ergba; - break; - case 's': - fields.offsets[i] = 0; - fieldSet[i] = estpq; - break; - case 'y': - fields.offsets[i] = 1; - fieldSet[i] = exyzw; - break; - case 'g': - fields.offsets[i] = 1; - fieldSet[i] = ergba; - break; - case 't': - fields.offsets[i] = 1; - fieldSet[i] = estpq; - break; - case 'z': - fields.offsets[i] = 2; - fieldSet[i] = exyzw; - break; - case 'b': - fields.offsets[i] = 2; - fieldSet[i] = ergba; - break; - case 'p': - fields.offsets[i] = 2; - fieldSet[i] = estpq; - break; - - case 'w': - fields.offsets[i] = 3; - fieldSet[i] = exyzw; - break; - case 'a': - fields.offsets[i] = 3; - fieldSet[i] = ergba; - break; - case 'q': - fields.offsets[i] = 3; - fieldSet[i] = estpq; - break; - default: - error(loc, "illegal vector field selection", compString.c_str(), ""); - return false; - } - } - - for (int i = 0; i < fields.num; ++i) { - if (fields.offsets[i] >= vecSize) { - error(loc, "vector field selection out of range", compString.c_str(), ""); - return false; - } - - if (i > 0) { - if (fieldSet[i] != fieldSet[i - 1]) { - error(loc, "illegal - vector component fields not from the same set", compString.c_str(), ""); - return false; - } - } - } - - return true; -} - -// -// Look at a '.' field selector string and change it into components +// Look at a '.' matrix selector string and change it into components // for a matrix. There are two types: // // _21 second row, first column (one based) @@ -604,10 +510,10 @@ bool HlslParseContext::parseVectorFields(const TSourceLoc& loc, const TString& c // // Returns true if there is no error. // -bool HlslParseContext::parseMatrixComponents(const TSourceLoc& loc, const TString& fields, int cols, int rows, - TMatrixComponents& components) +bool HlslParseContext::parseMatrixSwizzleSelector(const TSourceLoc& loc, const TString& fields, int cols, int rows, + TSwizzleSelectors& components) { - int startPos[TMatrixComponents::maxMatrixComponents]; + int startPos[TSwizzleSelectors::maxSelectors]; int numComps = 0; TString compString = fields; @@ -615,7 +521,7 @@ bool HlslParseContext::parseMatrixComponents(const TSourceLoc& loc, const TStrin // recording the first character position after the '_'. for (size_t c = 0; c < compString.size(); ++c) { if (compString[c] == '_') { - if (numComps >= TMatrixComponents::maxMatrixComponents) { + if (numComps >= TSwizzleSelectors::maxSelectors) { error(loc, "matrix component swizzle has too many components", compString.c_str(), ""); return false; } @@ -636,7 +542,7 @@ bool HlslParseContext::parseMatrixComponents(const TSourceLoc& loc, const TStrin bias = 0; ++pos; } - TMatrixComponents::tMatrixComponent comp; + TMatrixSelector comp; comp.coord1 = compString[pos+0] - '0' + bias; comp.coord2 = compString[pos+1] - '0' + bias; if (comp.coord1 < 0 || comp.coord1 >= cols) { @@ -658,21 +564,21 @@ bool HlslParseContext::parseMatrixComponents(const TSourceLoc& loc, const TStrin // // Otherwise, return -1. // -int HlslParseContext::getMatrixComponentsColumn(int rows, const TMatrixComponents& comps) +int HlslParseContext::getMatrixComponentsColumn(int rows, const TSwizzleSelectors& selector) { int col = -1; // right number of comps? - if (comps.size() != rows) + if (selector.size() != rows) return -1; // all comps in the same column? // rows in order? - col = comps.get(0).coord1; + col = selector[0].coord1; for (int i = 0; i < rows; ++i) { - if (col != comps.get(i).coord1) + if (col != selector[i].coord1) return -1; - if (i != comps.get(i).coord2) + if (i != selector[i].coord2) return -1; } @@ -934,63 +840,60 @@ TIntermTyped* HlslParseContext::handleDotDereference(const TSourceLoc& loc, TInt TIntermTyped* result = base; if (base->isVector() || base->isScalar()) { - TVectorFields fields; - if (! parseVectorFields(loc, field, base->getVectorSize(), fields)) { - fields.num = 1; - fields.offsets[0] = 0; - } + TSwizzleSelectors selectors; + parseSwizzleSelector(loc, field, base->getVectorSize(), selectors); if (base->isScalar()) { - if (fields.num == 1) + if (selectors.size() == 1) return result; else { - TType type(base->getBasicType(), EvqTemporary, fields.num); + TType type(base->getBasicType(), EvqTemporary, selectors.size()); return addConstructor(loc, base, type); } } if (base->getVectorSize() == 1) { TType scalarType(base->getBasicType(), EvqTemporary, 1); - if (fields.num == 1) + if (selectors.size() == 1) return addConstructor(loc, base, scalarType); else { - TType vectorType(base->getBasicType(), EvqTemporary, fields.num); + TType vectorType(base->getBasicType(), EvqTemporary, selectors.size()); return addConstructor(loc, addConstructor(loc, base, scalarType), vectorType); } } if (base->getType().getQualifier().isFrontEndConstant()) - result = intermediate.foldSwizzle(base, fields, loc); + result = intermediate.foldSwizzle(base, selectors, loc); else { - if (fields.num == 1) { - TIntermTyped* index = intermediate.addConstantUnion(fields.offsets[0], loc); + if (selectors.size() == 1) { + TIntermTyped* index = intermediate.addConstantUnion(selectors[0], loc); result = intermediate.addIndex(EOpIndexDirect, base, index, loc); result->setType(TType(base->getBasicType(), EvqTemporary)); } else { - TIntermTyped* index = intermediate.addSwizzle(fields, loc); + TIntermTyped* index = intermediate.addSwizzle(selectors, loc); result = intermediate.addIndex(EOpVectorSwizzle, base, index, loc); - result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, fields.num)); + result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, selectors.size())); } } } else if (base->isMatrix()) { - TMatrixComponents comps; - if (! parseMatrixComponents(loc, field, base->getMatrixCols(), base->getMatrixRows(), comps)) + TSwizzleSelectors selectors; + if (! parseMatrixSwizzleSelector(loc, field, base->getMatrixCols(), base->getMatrixRows(), selectors)) return result; - if (comps.size() == 1) { + if (selectors.size() == 1) { // Representable by m[c][r] if (base->getType().getQualifier().isFrontEndConstant()) { - result = intermediate.foldDereference(base, comps.get(0).coord1, loc); - result = intermediate.foldDereference(result, comps.get(1).coord2, loc); + result = intermediate.foldDereference(base, selectors[0].coord1, loc); + result = intermediate.foldDereference(result, selectors[0].coord2, loc); } else { - result = intermediate.addIndex(EOpIndexDirect, base, intermediate.addConstantUnion(comps.get(0).coord1, loc), loc); + result = intermediate.addIndex(EOpIndexDirect, base, intermediate.addConstantUnion(selectors[0].coord1, loc), loc); TType dereferencedCol(base->getType(), 0); result->setType(dereferencedCol); - result = intermediate.addIndex(EOpIndexDirect, result, intermediate.addConstantUnion(comps.get(0).coord2, loc), loc); + result = intermediate.addIndex(EOpIndexDirect, result, intermediate.addConstantUnion(selectors[0].coord2, loc), loc); TType dereferenced(dereferencedCol, 0); result->setType(dereferenced); } } else { - int column = getMatrixComponentsColumn(base->getMatrixRows(), comps); + int column = getMatrixComponentsColumn(base->getMatrixRows(), selectors); if (column >= 0) { // Representable by m[c] if (base->getType().getQualifier().isFrontEndConstant()) @@ -1002,9 +905,9 @@ TIntermTyped* HlslParseContext::handleDotDereference(const TSourceLoc& loc, TInt } } else { // general case, not a column, not a single component - TIntermTyped* index = intermediate.addSwizzle(comps, loc); + TIntermTyped* index = intermediate.addSwizzle(selectors, loc); result = intermediate.addIndex(EOpMatrixSwizzle, base, index, loc); - result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, comps.size())); + result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, selectors.size())); } } } else if (base->getBasicType() == EbtStruct || base->getBasicType() == EbtBlock) { @@ -2535,14 +2438,16 @@ void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermType coordSwizzle = argCoord; } else { // Extract coordinate - TVectorFields coordFields(0,1,2,3); - coordFields.num = argCoord->getType().getVectorSize() - (isMS ? 0 : 1); + int swizzleSize = argCoord->getType().getVectorSize() - (isMS ? 0 : 1); + TSwizzleSelectors coordFields; + for (int i = 0; i < swizzleSize; ++i) + coordFields.push_back(i); TIntermTyped* coordIdx = intermediate.addSwizzle(coordFields, loc); coordSwizzle = intermediate.addIndex(EOpVectorSwizzle, argCoord, coordIdx, loc); - coordSwizzle->setType(TType(coordBaseType, EvqTemporary, coordFields.num)); + coordSwizzle->setType(TType(coordBaseType, EvqTemporary, coordFields.size())); // Extract LOD - TIntermTyped* lodIdx = intermediate.addConstantUnion(coordFields.num, loc, true); + TIntermTyped* lodIdx = intermediate.addConstantUnion(coordFields.size(), loc, true); lodComponent = intermediate.addIndex(EOpIndexDirect, argCoord, lodIdx, loc); lodComponent->setType(TType(coordBaseType, EvqTemporary, 1)); } @@ -3248,8 +3153,12 @@ void HlslParseContext::decomposeIntrinsic(const TSourceLoc& loc, TIntermTyped*& { // ivec4 ( x.zyxw * 255.001953 ); TIntermTyped* arg0 = node->getAsUnaryNode()->getOperand(); - TVectorFields fields(2,1,0,3); - TIntermTyped* swizzleIdx = intermediate.addSwizzle(fields, loc); + TSwizzleSelectors selectors; + selectors.push_back(2); + selectors.push_back(1); + selectors.push_back(0); + selectors.push_back(3); + TIntermTyped* swizzleIdx = intermediate.addSwizzle(selectors, loc); TIntermTyped* swizzled = intermediate.addIndex(EOpVectorSwizzle, arg0, swizzleIdx, loc); swizzled->setType(arg0->getType()); swizzled->getWritableType().getQualifier().makeTemporary(); diff --git a/hlsl/hlslParseHelper.h b/hlsl/hlslParseHelper.h index ebeac0a1..cd3ac951 100755 --- a/hlsl/hlslParseHelper.h +++ b/hlsl/hlslParseHelper.h @@ -97,9 +97,8 @@ public: TIntermAggregate* handleSamplerTextureCombine(const TSourceLoc& loc, TIntermTyped* argTex, TIntermTyped* argSampler); - bool parseVectorFields(const TSourceLoc&, const TString&, int vecSize, TVectorFields&); - bool parseMatrixComponents(const TSourceLoc&, const TString&, int cols, int rows, TMatrixComponents&); - int getMatrixComponentsColumn(int rows, const TMatrixComponents&); + bool parseMatrixSwizzleSelector(const TSourceLoc&, const TString&, int cols, int rows, TSwizzleSelectors&); + int getMatrixComponentsColumn(int rows, const TSwizzleSelectors&); void assignError(const TSourceLoc&, const char* op, TString left, TString right); void unaryOpError(const TSourceLoc&, const char* op, TString operand); void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right);