Front-ends: Non-functional: Rationalize vector and matrix swizzles.
authorJohn Kessenich <cepheus@frii.com>
Sat, 14 Jan 2017 02:34:22 +0000 (19:34 -0700)
committerJohn Kessenich <cepheus@frii.com>
Sat, 14 Jan 2017 02:35:29 +0000 (19:35 -0700)
This reduces code duplication in a few ways, and better encapsulates
vector swizzle representation.

12 files changed:
Test/baseResults/120.frag.out
Test/baseResults/420.vert.out
Test/baseResults/cppComplexExpr.vert.out
Test/baseResults/specExamples.frag.out
glslang/MachineIndependent/Constant.cpp
glslang/MachineIndependent/Intermediate.cpp
glslang/MachineIndependent/ParseContextBase.cpp
glslang/MachineIndependent/ParseHelper.cpp
glslang/MachineIndependent/ParseHelper.h
glslang/MachineIndependent/localintermediate.h
hlsl/hlslParseHelper.cpp
hlsl/hlslParseHelper.h

index 79898aa..5df3f98 100644 (file)
@@ -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:
index a70b44e..b8e1306 100644 (file)
@@ -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
index 352dcac..90d62c1 100644 (file)
@@ -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
index a66144a..f660e66 100644 (file)
@@ -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 
index c709a78..fff8fd2 100644 (file)
@@ -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<TVectorSelector>& 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;
 }
index 3363d67..8d68517 100644 (file)
@@ -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);
-    }
+    TIntermConstantUnion* constIntNode = addConstantUnion(selector, loc);
+    sequence.push_back(constIntNode);
+}
 
-    return node;
+// 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);
 }
 
-// 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)
+// Make an aggregate node that has a sequence of all selectors.
+template TIntermTyped* TIntermediate::addSwizzle<TVectorSelector>(TSwizzleSelectors<TVectorSelector>& selector, const TSourceLoc& loc);
+template TIntermTyped* TIntermediate::addSwizzle<TMatrixSelector>(TSwizzleSelectors<TMatrixSelector>& selector, const TSourceLoc& loc);
+template<typename selectorType>
+TIntermTyped* TIntermediate::addSwizzle(TSwizzleSelectors<selectorType>& 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;
 }
index a5be351..83a9fdf 100644 (file)
@@ -434,6 +434,108 @@ const TFunction* TParseContextBase::selectFunction(
 }
 
 //
+// 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<TVectorSelector>& selector)
+{
+    // Too long?
+    if (compString.size() > TSwizzleSelectors<TVectorSelector>::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<TVectorSelector>::maxSelectors];
+
+    // Decode the swizzle string.
+    int size = std::min(TSwizzleSelectors<TVectorSelector>::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.
 //
index cfb56b0..b0ac3bb 100644 (file)
@@ -258,106 +258,6 @@ void TParseContext::handlePragma(const TSourceLoc& loc, const TVector<TString>&
     }
 }
 
-///////////////////////////////////////////////////////////////////////
-//
-// 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<TVectorSelector> 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())
index 8d169e4..2e09a5a 100644 (file)
@@ -170,6 +170,9 @@ protected:
         std::function<bool(const TType&, const TType&, const TType&)>,
         /* output */ bool& tie);
 
+    virtual void parseSwizzleSelector(const TSourceLoc&, const TString&, int size,
+                                      TSwizzleSelectors<TVectorSelector>&);
+
     // 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);
index cb790af..812d4a3 100644 (file)
@@ -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 {
+typedef int TVectorSelector;
+
+template<typename selectorType>
+class TSwizzleSelectors {
 public:
-    static const int maxMatrixComponents = 4;
-    struct tMatrixComponent {
-        int coord1;  // stay agnostic about column/row; this is parse order
-        int coord2;
-    };
-
-    TMatrixComponents() : size_(0) { }
-    void push_back(tMatrixComponent comp)
+    static const int maxSelectors = 4;
+    TSwizzleSelectors() : size_(0) { }
+
+    void push_back(selectorType comp)
     {
-        if (size_ < maxMatrixComponents)
+        if (size_ < maxSelectors)
             components[size_++] = comp;
     }
+    void resize(int s)
+    {
+        assert(s <= size_);
+        size_ = s;
+    }
     int size() const { return size_; }
-    tMatrixComponent get(int i) const
+    selectorType operator[](int i) const
     {
-        assert(i < maxMatrixComponents);
+        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<typename selectorType> TIntermTyped* addSwizzle(TSwizzleSelectors<selectorType>&, 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<TVectorSelector>& 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
index 7477e03..de1275c 100755 (executable)
@@ -502,101 +502,7 @@ void HlslParseContext::handlePragma(const TSourceLoc& loc, const TVector<TString
 }
 
 //
-// Look at a '.' field selector string and change it into offsets
-// for a vector or scalar
-//
-// Returns true if there is no error.
-//
-bool HlslParseContext::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;
-}
-
-//
-// 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<TMatrixSelector>& components)
 {
-    int startPos[TMatrixComponents::maxMatrixComponents];
+    int startPos[TSwizzleSelectors<TVectorSelector>::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<TVectorSelector>::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<TMatrixSelector>& 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<TVectorSelector> 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<TMatrixSelector> 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<TVectorSelector> 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<TVectorSelector> 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();
index ebeac0a..cd3ac95 100755 (executable)
@@ -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<TMatrixSelector>&);
+    int getMatrixComponentsColumn(int rows, const TSwizzleSelectors<TMatrixSelector>&);
     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);