GLSL: Separate out swizzle handling (potentially fixing bugs).
authorJohn Kessenich <cepheus@frii.com>
Fri, 1 May 2020 09:07:54 +0000 (03:07 -0600)
committerJohn Kessenich <cepheus@frii.com>
Fri, 1 May 2020 13:35:30 +0000 (07:35 -0600)
Noticed this when looking at swizzles.  It's at least better structure,
removing hard-to-see early returns, which might be contributing to bugs.

glslang/MachineIndependent/ParseHelper.cpp
glslang/MachineIndependent/ParseHelper.h

index ddb3e3a..ea89e43 100644 (file)
@@ -822,50 +822,7 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm
     TIntermTyped* result = base;
     if ((base->isVector() || base->isScalar()) &&
         (base->isFloatingDomain() || base->isIntegerDomain() || base->getBasicType() == EbtBool)) {
-        if (base->isScalar()) {
-            const char* dotFeature = "scalar swizzle";
-            requireProfile(loc, ~EEsProfile, dotFeature);
-            profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, dotFeature);
-        }
-
-        TSwizzleSelectors<TVectorSelector> selectors;
-        parseSwizzleSelector(loc, field, base->getVectorSize(), selectors);
-
-        if (base->isVector() && selectors.size() != 1 && base->getType().contains16BitFloat())
-            requireFloat16Arithmetic(loc, ".", "can't swizzle types containing float16");
-        if (base->isVector() && selectors.size() != 1 && base->getType().contains16BitInt())
-            requireInt16Arithmetic(loc, ".", "can't swizzle types containing (u)int16");
-        if (base->isVector() && selectors.size() != 1 && base->getType().contains8BitInt())
-            requireInt8Arithmetic(loc, ".", "can't swizzle types containing (u)int8");
-
-        if (base->isScalar()) {
-            if (selectors.size() == 1)
-                return result;
-            else {
-                TType type(base->getBasicType(), EvqTemporary, selectors.size());
-                // Swizzle operations propagate specialization-constantness
-                if (base->getQualifier().isSpecConstant())
-                    type.getQualifier().makeSpecConstant();
-                return addConstructor(loc, base, type);
-            }
-        }
-
-        if (base->getType().getQualifier().isFrontEndConstant())
-            result = intermediate.foldSwizzle(base, selectors, loc);
-        else {
-            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 {
-                TIntermTyped* index = intermediate.addSwizzle(selectors, loc);
-                result = intermediate.addIndex(EOpVectorSwizzle, base, index, loc);
-                result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, selectors.size()));
-            }
-            // Swizzle operations propagate specialization-constantness
-            if (base->getType().getQualifier().isSpecConstant())
-                result->getWritableType().getQualifier().makeSpecConstant();
-        }
+        result = handleDotSwizzle(loc, base, field);
     } else if (base->isStruct() || base->isReference()) {
         const TTypeList* fields = base->isReference() ?
                                   base->getType().getReferentType()->getStruct() :
@@ -906,6 +863,60 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm
     return result;
 }
 
+//
+// Handle seeing a base.swizzle, a subset of base.identifier in the grammar.
+//
+TIntermTyped* TParseContext::handleDotSwizzle(const TSourceLoc& loc, TIntermTyped* base, const TString& field)
+{
+    TIntermTyped* result = base;
+    if (base->isScalar()) {
+        const char* dotFeature = "scalar swizzle";
+        requireProfile(loc, ~EEsProfile, dotFeature);
+        profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, dotFeature);
+    }
+
+    TSwizzleSelectors<TVectorSelector> selectors;
+    parseSwizzleSelector(loc, field, base->getVectorSize(), selectors);
+
+    if (base->isVector() && selectors.size() != 1 && base->getType().contains16BitFloat())
+        requireFloat16Arithmetic(loc, ".", "can't swizzle types containing float16");
+    if (base->isVector() && selectors.size() != 1 && base->getType().contains16BitInt())
+        requireInt16Arithmetic(loc, ".", "can't swizzle types containing (u)int16");
+    if (base->isVector() && selectors.size() != 1 && base->getType().contains8BitInt())
+        requireInt8Arithmetic(loc, ".", "can't swizzle types containing (u)int8");
+
+    if (base->isScalar()) {
+        if (selectors.size() == 1)
+            return result;
+        else {
+            TType type(base->getBasicType(), EvqTemporary, selectors.size());
+            // Swizzle operations propagate specialization-constantness
+            if (base->getQualifier().isSpecConstant())
+                type.getQualifier().makeSpecConstant();
+            return addConstructor(loc, base, type);
+        }
+    }
+
+    if (base->getType().getQualifier().isFrontEndConstant())
+        result = intermediate.foldSwizzle(base, selectors, loc);
+    else {
+        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 {
+            TIntermTyped* index = intermediate.addSwizzle(selectors, loc);
+            result = intermediate.addIndex(EOpVectorSwizzle, base, index, loc);
+            result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, selectors.size()));
+        }
+        // Swizzle operations propagate specialization-constantness
+        if (base->getType().getQualifier().isSpecConstant())
+            result->getWritableType().getQualifier().makeSpecConstant();
+    }
+
+    return result;
+}
+
 void TParseContext::blockMemberExtensionCheck(const TSourceLoc& loc, const TIntermTyped* base, int member, const TString& memberName)
 {
     // a block that needs extension checking is either 'base', or if arrayed,
index 20df640..9c5fdc7 100644 (file)
@@ -315,6 +315,7 @@ public:
     TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right);
     TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode);
     TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field);
+    TIntermTyped* handleDotSwizzle(const TSourceLoc&, TIntermTyped* base, const TString& field);
     void blockMemberExtensionCheck(const TSourceLoc&, const TIntermTyped* base, int member, const TString& memberName);
     TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
     TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&);