Merge pull request #589 from steve-lunarg/vec1-promotion-fix

HLSL: allow promotion from 1-vector types to scalars, e.g, float<-float1
diff --git a/Test/baseResults/hlsl.promote.vec1.frag.out b/Test/baseResults/hlsl.promote.vec1.frag.out
new file mode 100644
index 0000000..3b68450
--- /dev/null
+++ b/Test/baseResults/hlsl.promote.vec1.frag.out
@@ -0,0 +1,118 @@
+hlsl.promote.vec1.frag
+Shader version: 450
+gl_FragCoord origin is upper left
+0:? Sequence
+0:3  Function Definition: main( (temp 4-component vector of float)
+0:3    Function Parameters: 
+0:?     Sequence
+0:7      move second child to first child (temp float)
+0:7        'f1a' (temp float)
+0:7        Construct float (temp float)
+0:7          'f1b' (temp 1-component vector of float)
+0:8      move second child to first child (temp 1-component vector of float)
+0:8        'f1b' (temp 1-component vector of float)
+0:8        Construct float (temp 1-component vector of float)
+0:8          'f1a' (temp float)
+0:11      step (global 3-component vector of float)
+0:11        Constant:
+0:11          0.000000
+0:11          0.000000
+0:11          0.000000
+0:11        'f3' (temp 3-component vector of float)
+0:13      sine (global float)
+0:13        Construct float (in float)
+0:13          'f1b' (temp 1-component vector of float)
+0:15      Sequence
+0:15        move second child to first child (temp 4-component vector of float)
+0:?           '@entryPointOutput' (layout(location=0 ) out 4-component vector of float)
+0:?           Constant:
+0:?             0.000000
+0:?             0.000000
+0:?             0.000000
+0:?             0.000000
+0:15        Branch: Return
+0:?   Linker Objects
+0:?     '@entryPointOutput' (layout(location=0 ) out 4-component vector of float)
+
+
+Linked fragment stage:
+
+
+Shader version: 450
+gl_FragCoord origin is upper left
+0:? Sequence
+0:3  Function Definition: main( (temp 4-component vector of float)
+0:3    Function Parameters: 
+0:?     Sequence
+0:7      move second child to first child (temp float)
+0:7        'f1a' (temp float)
+0:7        Construct float (temp float)
+0:7          'f1b' (temp 1-component vector of float)
+0:8      move second child to first child (temp 1-component vector of float)
+0:8        'f1b' (temp 1-component vector of float)
+0:8        Construct float (temp 1-component vector of float)
+0:8          'f1a' (temp float)
+0:11      step (global 3-component vector of float)
+0:11        Constant:
+0:11          0.000000
+0:11          0.000000
+0:11          0.000000
+0:11        'f3' (temp 3-component vector of float)
+0:13      sine (global float)
+0:13        Construct float (in float)
+0:13          'f1b' (temp 1-component vector of float)
+0:15      Sequence
+0:15        move second child to first child (temp 4-component vector of float)
+0:?           '@entryPointOutput' (layout(location=0 ) out 4-component vector of float)
+0:?           Constant:
+0:?             0.000000
+0:?             0.000000
+0:?             0.000000
+0:?             0.000000
+0:15        Branch: Return
+0:?   Linker Objects
+0:?     '@entryPointOutput' (layout(location=0 ) out 4-component vector of float)
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 26
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main" 23
+                              ExecutionMode 4 OriginUpperLeft
+                              Name 4  "main"
+                              Name 8  "f1a"
+                              Name 9  "f1b"
+                              Name 16  "f3"
+                              Name 23  "@entryPointOutput"
+                              Decorate 23(@entryPointOutput) Location 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypePointer Function 6(float)
+              12:             TypeVector 6(float) 3
+              13:    6(float) Constant 0
+              14:   12(fvec3) ConstantComposite 13 13 13
+              15:             TypePointer Function 12(fvec3)
+              21:             TypeVector 6(float) 4
+              22:             TypePointer Output 21(fvec4)
+23(@entryPointOutput):     22(ptr) Variable Output
+              24:   21(fvec4) ConstantComposite 13 13 13 13
+         4(main):           2 Function None 3
+               5:             Label
+          8(f1a):      7(ptr) Variable Function
+          9(f1b):      7(ptr) Variable Function
+          16(f3):     15(ptr) Variable Function
+              10:    6(float) Load 9(f1b)
+                              Store 8(f1a) 10
+              11:    6(float) Load 8(f1a)
+                              Store 9(f1b) 11
+              17:   12(fvec3) Load 16(f3)
+              18:   12(fvec3) ExtInst 1(GLSL.std.450) 48(Step) 14 17
+              19:    6(float) Load 9(f1b)
+              20:    6(float) ExtInst 1(GLSL.std.450) 13(Sin) 19
+                              Store 23(@entryPointOutput) 24
+                              Return
+                              FunctionEnd
diff --git a/Test/hlsl.promote.vec1.frag b/Test/hlsl.promote.vec1.frag
new file mode 100644
index 0000000..a674ccb
--- /dev/null
+++ b/Test/hlsl.promote.vec1.frag
@@ -0,0 +1,16 @@
+
+float4 main() : SV_Target
+{
+    float f1a;
+    float1 f1b;
+
+    f1a = f1b;  // convert float1 to float
+    f1b = f1a;  // convert float to float1
+
+    float3 f3;
+    step(0.0, f3);
+
+    sin(f1b); // test 1-vectors in intrinsics
+
+    return float4(0,0,0,0);
+}
diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h
index 6c8cb82..8745c7a 100644
--- a/glslang/Include/Types.h
+++ b/glslang/Include/Types.h
@@ -1271,6 +1271,7 @@
     virtual       TArraySizes& getArraySizes()       { assert(arraySizes != nullptr); return *arraySizes; }
 
     virtual bool isScalar() const { return ! isVector() && ! isMatrix() && ! isStruct() && ! isArray(); }
+    virtual bool isScalarOrVec1() const { return isScalar() || vector1; }
     virtual bool isVector() const { return vectorSize > 1 || vector1; }
     virtual bool isMatrix() const { return matrixCols ? true : false; }
     virtual bool isArray()  const { return arraySizes != nullptr; }
diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp
index ee102fa..9c2590f 100644
--- a/glslang/MachineIndependent/Intermediate.cpp
+++ b/glslang/MachineIndependent/Intermediate.cpp
@@ -814,8 +814,10 @@
     TOperator constructorOp = mapTypeToConstructorOp(type);
 
     // scalar -> smeared -> vector, or
+    // vec1 -> scalar, or
     // bigger vector -> smaller vector or scalar
     if ((type.isVector() && node->getType().isScalar()) ||
+        (node->getType().isVector() && node->getVectorSize() == 1 && type.isScalar()) ||
         (node->getVectorSize() > type.getVectorSize() && type.isVector()))
         return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc());
 
diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp
index 17e2133..edd7e4d 100644
--- a/gtests/Hlsl.FromFile.cpp
+++ b/gtests/Hlsl.FromFile.cpp
@@ -157,6 +157,7 @@
         {"hlsl.pp.line.frag", "main"},
         {"hlsl.precise.frag", "main"},
         {"hlsl.promote.binary.frag", "main"},
+        {"hlsl.promote.vec1.frag", "main"},
         {"hlsl.promotions.frag", "main"},
         {"hlsl.rw.atomics.frag", "main"},
         {"hlsl.rw.bracket.frag", "main"},
diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp
index abe027e..31fb0d4 100755
--- a/hlsl/hlslParseHelper.cpp
+++ b/hlsl/hlslParseHelper.cpp
@@ -4308,8 +4308,8 @@
             return false;
 
         // shapes have to be convertible
-        if ((from.isScalar() && to.isScalar()) ||
-            (from.isScalar() && to.isVector()) ||
+        if ((from.isScalarOrVec1() && to.isScalarOrVec1()) ||
+            (from.isScalarOrVec1() && to.isVector())    ||
             (from.isVector() && to.isVector() && from.getVectorSize() >= to.getVectorSize()))
             return true;