SPV: For AST interpolateAt* ops consuming a swizzle, invert the order.

Apply the interpolation first, then apply the swizzle to the result,
the inverse of the order requested by the AST.  This fixes issue #411.
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index 0fc5730..26d2f4b 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -118,6 +118,9 @@
     spv::ImageFormat TranslateImageFormat(const glslang::TType& type);
     spv::Id createSpvVariable(const glslang::TIntermSymbol*);
     spv::Id getSampledType(const glslang::TSampler&);
+    spv::Id getInvertedSwizzleType(const glslang::TIntermTyped&);
+    spv::Id createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped&, spv::Id parentResult);
+    void convertSwizzle(const glslang::TIntermAggregate&, std::vector<unsigned>& swizzle);
     spv::Id convertGlslangToSpvType(const glslang::TType& type);
     spv::Id convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking, const glslang::TQualifier&);
     spv::Id convertGlslangStructToSpvType(const glslang::TType&, const glslang::TTypeList* glslangStruct,
@@ -1025,10 +1028,8 @@
     case glslang::EOpVectorSwizzle:
         {
             node->getLeft()->traverse(this);
-            glslang::TIntermSequence& swizzleSequence = node->getRight()->getAsAggregate()->getSequence();
             std::vector<unsigned> swizzle;
-            for (int i = 0; i < (int)swizzleSequence.size(); ++i)
-                swizzle.push_back(swizzleSequence[i]->getAsConstantUnion()->getConstArray()[0].getIConst());
+            convertSwizzle(*node->getRight()->getAsAggregate(), swizzle);
             builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()));
         }
         return false;
@@ -1118,8 +1119,18 @@
 
     // Start by evaluating the operand
 
+    // Does it need a swizzle inversion?  If so, evaluation is inverted;
+    // operate first on the swizzle base, then apply the swizzle.
+    spv::Id invertedType = spv::NoType;
+    auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? invertedType : convertGlslangToSpvType(node->getType()); };
+    if (node->getOp() == glslang::EOpInterpolateAtCentroid)
+        invertedType = getInvertedSwizzleType(*node->getOperand());
+
     builder.clearAccessChain();
-    node->getOperand()->traverse(this);
+    if (invertedType != spv::NoType)
+        node->getOperand()->getAsBinaryNode()->getLeft()->traverse(this);
+    else
+        node->getOperand()->traverse(this);
 
     spv::Id operand = spv::NoResult;
 
@@ -1136,13 +1147,16 @@
 
     // it could be a conversion
     if (! result)
-        result = createConversion(node->getOp(), precision, noContraction, convertGlslangToSpvType(node->getType()), operand, node->getOperand()->getBasicType());
+        result = createConversion(node->getOp(), precision, noContraction, resultType(), operand, node->getOperand()->getBasicType());
 
     // if not, then possibly an operation
     if (! result)
-        result = createUnaryOperation(node->getOp(), precision, noContraction, convertGlslangToSpvType(node->getType()), operand, node->getOperand()->getBasicType());
+        result = createUnaryOperation(node->getOp(), precision, noContraction, resultType(), operand, node->getOperand()->getBasicType());
 
     if (result) {
+        if (invertedType)
+            result = createInvertedSwizzle(precision, *node->getOperand(), result);
+
         builder.clearAccessChain();
         builder.setAccessChainRValue(result);
 
@@ -1210,6 +1224,8 @@
         spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
 
     spv::Id result = spv::NoResult;
+    spv::Id invertedType = spv::NoType;  // to use to override the natural type of the node
+    auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? invertedType : convertGlslangToSpvType(node->getType()); };
 
     // try texturing
     result = createImageTextureFunctionCall(node);
@@ -1366,19 +1382,18 @@
     {
         std::vector<spv::Id> arguments;
         translateArguments(*node, arguments);
-        spv::Id resultTypeId = convertGlslangToSpvType(node->getType());
         spv::Id constructed;
         if (node->getOp() == glslang::EOpConstructTextureSampler)
-            constructed = builder.createOp(spv::OpSampledImage, resultTypeId, arguments);
+            constructed = builder.createOp(spv::OpSampledImage, resultType(), arguments);
         else if (node->getOp() == glslang::EOpConstructStruct || node->getType().isArray()) {
             std::vector<spv::Id> constituents;
             for (int c = 0; c < (int)arguments.size(); ++c)
                 constituents.push_back(arguments[c]);
-            constructed = builder.createCompositeConstruct(resultTypeId, constituents);
+            constructed = builder.createCompositeConstruct(resultType(), constituents);
         } else if (isMatrix)
-            constructed = builder.createMatrixConstructor(precision, arguments, resultTypeId);
+            constructed = builder.createMatrixConstructor(precision, arguments, resultType());
         else
-            constructed = builder.createConstructor(precision, arguments, resultTypeId);
+            constructed = builder.createConstructor(precision, arguments, resultType());
 
         builder.clearAccessChain();
         builder.setAccessChainRValue(constructed);
@@ -1407,7 +1422,7 @@
         break;
     }
     case glslang::EOpMul:
-        // compontent-wise matrix multiply
+        // component-wise matrix multiply
         binOp = glslang::EOpMul;
         break;
     case glslang::EOpOuterProduct:
@@ -1476,7 +1491,7 @@
         spv::Id rightId = accessChainLoad(right->getType());
 
         result = createBinaryOperation(binOp, precision, TranslateNoContractionDecoration(node->getType().getQualifier()),
-                                       convertGlslangToSpvType(node->getType()), leftId, rightId,
+                                       resultType(), leftId, rightId,
                                        left->getType().getBasicType(), reduceComparison);
 
         // code above should only make binOp that exists in createBinaryOperation
@@ -1493,9 +1508,6 @@
     glslang::TIntermSequence& glslangOperands = node->getSequence();
     std::vector<spv::Id> operands;
     for (int arg = 0; arg < (int)glslangOperands.size(); ++arg) {
-        builder.clearAccessChain();
-        glslangOperands[arg]->traverse(this);
-
         // special case l-value operands; there are just a few
         bool lvalue = false;
         switch (node->getOp()) {
@@ -1509,8 +1521,15 @@
 #ifdef AMD_EXTENSIONS
         case glslang::EOpInterpolateAtVertex:
 #endif
-            if (arg == 0)
+            if (arg == 0) {
                 lvalue = true;
+
+                // Does it need a swizzle inversion?  If so, evaluation is inverted;
+                // operate first on the swizzle base, then apply the swizzle.
+                if (glslangOperands[0]->getAsOperator() && 
+                    glslangOperands[0]->getAsOperator()->getOp() == glslang::EOpVectorSwizzle)
+                    invertedType = convertGlslangToSpvType(glslangOperands[0]->getAsBinaryNode()->getLeft()->getType());
+            }
             break;
         case glslang::EOpAtomicAdd:
         case glslang::EOpAtomicMin:
@@ -1536,6 +1555,11 @@
         default:
             break;
         }
+        builder.clearAccessChain();
+        if (invertedType != spv::NoType && arg == 0)
+            glslangOperands[0]->getAsBinaryNode()->getLeft()->traverse(this);
+        else
+            glslangOperands[arg]->traverse(this);
         if (lvalue)
             operands.push_back(builder.accessChainGetLValue());
         else
@@ -1544,24 +1568,26 @@
 
     if (atomic) {
         // Handle all atomics
-        result = createAtomicOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operands, node->getBasicType());
+        result = createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType());
     } else {
         // Pass through to generic operations.
         switch (glslangOperands.size()) {
         case 0:
-            result = createNoArgOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()));
+            result = createNoArgOperation(node->getOp(), precision, resultType());
             break;
         case 1:
             result = createUnaryOperation(
                 node->getOp(), precision,
                 TranslateNoContractionDecoration(node->getType().getQualifier()),
-                convertGlslangToSpvType(node->getType()), operands.front(),
+                resultType(), operands.front(),
                 glslangOperands[0]->getAsTyped()->getBasicType());
             break;
         default:
-            result = createMiscOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operands, node->getBasicType());
+            result = createMiscOperation(node->getOp(), precision, resultType(), operands, node->getBasicType());
             break;
         }
+        if (invertedType)
+            result = createInvertedSwizzle(precision, *glslangOperands[0]->getAsBinaryNode(), result);
     }
 
     if (noReturnValue)
@@ -1813,6 +1839,36 @@
     }
 }
 
+// If node is a swizzle operation, return the type that should be used if
+// the swizzle base is first consumed by another operation, before the swizzle
+// is applied.
+spv::Id TGlslangToSpvTraverser::getInvertedSwizzleType(const glslang::TIntermTyped& node)
+{
+    if (node.getAsOperator() && 
+        node.getAsOperator()->getOp() == glslang::EOpVectorSwizzle)
+        return convertGlslangToSpvType(node.getAsBinaryNode()->getLeft()->getType());
+    else
+        return spv::NoType;
+}
+
+// When inverting a swizzle with a parent op, this function
+// will apply the swizzle operation to a completed parent operation.
+spv::Id TGlslangToSpvTraverser::createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped& node, spv::Id parentResult)
+{
+    std::vector<unsigned> swizzle;
+    convertSwizzle(*node.getAsBinaryNode()->getRight()->getAsAggregate(), swizzle);
+    return builder.createRvalueSwizzle(precision, convertGlslangToSpvType(node.getType()), parentResult, swizzle);
+}
+
+
+// Convert a glslang AST swizzle node to a swizzle vector for building SPIR-V.
+void TGlslangToSpvTraverser::convertSwizzle(const glslang::TIntermAggregate& node, std::vector<unsigned>& swizzle)
+{
+    const glslang::TIntermSequence& swizzleSequence = node.getSequence();
+    for (int i = 0; i < (int)swizzleSequence.size(); ++i)
+        swizzle.push_back(swizzleSequence[i]->getAsConstantUnion()->getConstArray()[0].getIConst());
+}
+
 // Convert from a glslang type to an SPV type, by calling into a
 // recursive version of this function. This establishes the inherited
 // layout state rooted from the top-level type.
@@ -2505,6 +2561,7 @@
     if (! node->isImage() && ! node->isTexture()) {
         return spv::NoResult;
     }
+    auto resultType = [&node,this]{ return convertGlslangToSpvType(node->getType()); };
 
     // Process a GLSL texturing op (will be SPV image)
     const glslang::TSampler sampler = node->getAsAggregate() ? node->getAsAggregate()->getSequence()[0]->getAsTyped()->getType().getSampler()
@@ -2571,7 +2628,7 @@
                 operands.push_back(spv::ImageOperandsSampleMask);
                 operands.push_back(*(opIt++));
             }
-            return builder.createOp(spv::OpImageRead, convertGlslangToSpvType(node->getType()), operands);
+            return builder.createOp(spv::OpImageRead, resultType(), operands);
         }
 
         operands.push_back(*(opIt++));
@@ -2582,7 +2639,7 @@
             }
             if (builder.getImageTypeFormat(builder.getImageType(operands.front())) == spv::ImageFormatUnknown)
                 builder.addCapability(spv::CapabilityStorageImageReadWithoutFormat);
-            return builder.createOp(spv::OpImageRead, convertGlslangToSpvType(node->getType()), operands);
+            return builder.createOp(spv::OpImageRead, resultType(), operands);
         } else if (node->getOp() == glslang::EOpImageStore) {
             if (sampler.ms) {
                 operands.push_back(*(opIt + 1));
@@ -2606,7 +2663,7 @@
 
             // Create the return type that was a special structure
             spv::Id texelOut = *opIt;
-            spv::Id typeId0 = convertGlslangToSpvType(node->getType());
+            spv::Id typeId0 = resultType();
             spv::Id typeId1 = builder.getDerefTypeId(texelOut);
             spv::Id resultTypeId = builder.makeStructResultType(typeId0, typeId1);
 
@@ -2622,7 +2679,7 @@
             // as the first source operand, is required by SPIR-V atomic operations.
             operands.push_back(sampler.ms ? *(opIt++) : builder.makeUintConstant(0)); // For non-MS, the value should be 0
 
-            spv::Id resultTypeId = builder.makePointer(spv::StorageClassImage, convertGlslangToSpvType(node->getType()));
+            spv::Id resultTypeId = builder.makePointer(spv::StorageClassImage, resultType());
             spv::Id pointer = builder.createOp(spv::OpImageTexelPointer, resultTypeId, operands);
 
             std::vector<spv::Id> operands;
@@ -2630,7 +2687,7 @@
             for (; opIt != arguments.end(); ++opIt)
                 operands.push_back(*opIt);
 
-            return createAtomicOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operands, node->getBasicType());
+            return createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType());
         }
     }
 
@@ -2770,7 +2827,7 @@
         }
     }
 
-    return builder.createTextureCall(precision, convertGlslangToSpvType(node->getType()), sparse, cracked.fetch, cracked.proj, cracked.gather, noImplicitLod, params);
+    return builder.createTextureCall(precision, resultType(), sparse, cracked.fetch, cracked.proj, cracked.gather, noImplicitLod, params);
 }
 
 spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAggregate* node)
diff --git a/Test/baseResults/spv.swizzleInversion.frag.out b/Test/baseResults/spv.swizzleInversion.frag.out
new file mode 100755
index 0000000..6b92206
--- /dev/null
+++ b/Test/baseResults/spv.swizzleInversion.frag.out
@@ -0,0 +1,81 @@
+spv.swizzleInversion.frag
+Warning, version 450 is not yet complete; most version-specific features are present, but some are missing.
+
+
+Linked fragment stage:
+
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 46
+
+                              Capability Shader
+                              Capability InterpolationFunction
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main" 12 37
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 450
+                              Name 4  "main"
+                              Name 9  "v43"
+                              Name 12  "in4"
+                              Name 17  "v42"
+                              Name 23  "v44"
+                              Name 29  "v41"
+                              Name 35  "v33"
+                              Name 37  "in3"
+                              Name 40  "v32"
+                              Name 43  "v31"
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 3
+               8:             TypePointer Function 7(fvec3)
+              10:             TypeVector 6(float) 4
+              11:             TypePointer Input 10(fvec4)
+         12(in4):     11(ptr) Variable Input
+              15:             TypeVector 6(float) 2
+              16:             TypePointer Function 15(fvec2)
+              18:             TypeInt 32 1
+              19:     18(int) Constant 1
+              22:             TypePointer Function 10(fvec4)
+              24:    6(float) Constant 1073741824
+              25:   15(fvec2) ConstantComposite 24 24
+              28:             TypePointer Function 6(float)
+              30:             TypeInt 32 0
+              31:     30(int) Constant 1
+              32:             TypePointer Input 6(float)
+              36:             TypePointer Input 7(fvec3)
+         37(in3):     36(ptr) Variable Input
+         4(main):           2 Function None 3
+               5:             Label
+          9(v43):      8(ptr) Variable Function
+         17(v42):     16(ptr) Variable Function
+         23(v44):     22(ptr) Variable Function
+         29(v41):     28(ptr) Variable Function
+         35(v33):      8(ptr) Variable Function
+         40(v32):     16(ptr) Variable Function
+         43(v31):     28(ptr) Variable Function
+              13:   10(fvec4) ExtInst 1(GLSL.std.450) 76(InterpolateAtCentroid) 12(in4)
+              14:    7(fvec3) VectorShuffle 13 13 3 2 0
+                              Store 9(v43) 14
+              20:   10(fvec4) ExtInst 1(GLSL.std.450) 77(InterpolateAtSample) 12(in4) 19
+              21:   15(fvec2) VectorShuffle 20 20 2 0
+                              Store 17(v42) 21
+              26:   10(fvec4) ExtInst 1(GLSL.std.450) 78(InterpolateAtOffset) 12(in4) 25
+              27:   10(fvec4) VectorShuffle 26 26 2 1 0 3
+                              Store 23(v44) 27
+              33:     32(ptr) AccessChain 12(in4) 31
+              34:    6(float) ExtInst 1(GLSL.std.450) 78(InterpolateAtOffset) 33 25
+                              Store 29(v41) 34
+              38:    7(fvec3) ExtInst 1(GLSL.std.450) 76(InterpolateAtCentroid) 37(in3)
+              39:    7(fvec3) VectorShuffle 38 38 1 2 0
+                              Store 35(v33) 39
+              41:    7(fvec3) ExtInst 1(GLSL.std.450) 77(InterpolateAtSample) 37(in3) 19
+              42:   15(fvec2) VectorShuffle 41 41 2 0
+                              Store 40(v32) 42
+              44:     32(ptr) AccessChain 12(in4) 31
+              45:    6(float) ExtInst 1(GLSL.std.450) 78(InterpolateAtOffset) 44 25
+                              Store 43(v31) 45
+                              Return
+                              FunctionEnd
diff --git a/Test/spv.swizzleInversion.frag b/Test/spv.swizzleInversion.frag
new file mode 100644
index 0000000..9dca62f
--- /dev/null
+++ b/Test/spv.swizzleInversion.frag
@@ -0,0 +1,16 @@
+#version 450

+

+in vec4 in4;

+in vec3 in3;

+

+void main()

+{

+    vec3 v43 = interpolateAtCentroid(in4.wzx);

+    vec2 v42 = interpolateAtSample(in4.zx, 1);

+    vec4 v44 = interpolateAtOffset(in4.zyxw, vec2(2.0));

+    float v41 = interpolateAtOffset(in4.y, vec2(2.0));

+

+    vec3 v33 = interpolateAtCentroid(in3.yzx);

+    vec2 v32 = interpolateAtSample(in3.zx, 1);

+    float v31 = interpolateAtOffset(in4.y, vec2(2.0));

+}

diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h
index c328407..5ab3596 100644
--- a/glslang/Include/revision.h
+++ b/glslang/Include/revision.h
@@ -2,5 +2,5 @@
 // For the version, it uses the latest git tag followed by the number of commits.
 // For the date, it uses the current date (when then script is run).
 
-#define GLSLANG_REVISION "SPIRV99.1339"
-#define GLSLANG_DATE "25-Jul-2016"
+#define GLSLANG_REVISION "SPIRV99.1340"
+#define GLSLANG_DATE "26-Jul-2016"
diff --git a/gtests/Spv.FromFile.cpp b/gtests/Spv.FromFile.cpp
index dbe0507..a8f3dd8 100644
--- a/gtests/Spv.FromFile.cpp
+++ b/gtests/Spv.FromFile.cpp
@@ -184,6 +184,7 @@
         "spv.structure.frag",
         "spv.switch.frag",
         "spv.swizzle.frag",
+        "spv.swizzleInversion.frag",
         "spv.test.frag",
         "spv.test.vert",
         "spv.texture.frag",