HLSL: allow self-type cast (as no-op passthrough)
authorLoopDawg <sk_opengl@khasekhemwy.net>
Thu, 17 May 2018 19:03:12 +0000 (13:03 -0600)
committerLoopDawg <sk_opengl@khasekhemwy.net>
Thu, 17 May 2018 19:03:12 +0000 (13:03 -0600)
Previously, casting an object of a struct type to an identical type
would produce an error.  This PR allows this case.

As a side-effect of the change, several self-type casts in existing
tests go away.  For example:

    0:10          Construct float ( temp float)
    0:10            'f' ( in float)

becomes this (without the unneeded constructor op):

    0:10          'f' ( in float)

For vector or array types this can result in somewhat less overall code.

Fixes: #1218

Test/baseResults/hlsl.cast.frag.out
Test/baseResults/hlsl.self_cast.frag.out [new file with mode: 0644]
Test/baseResults/hlsl.shapeConv.frag.out
Test/hlsl.self_cast.frag [new file with mode: 0644]
gtests/Hlsl.FromFile.cpp
hlsl/hlslParseHelper.cpp

index 2fb3769..9eccd51 100755 (executable)
@@ -9,8 +9,7 @@ gl_FragCoord origin is upper left
 0:3      Branch: Return with expression
 0:3        add ( temp 4-component vector of float)
 0:3          add ( temp 4-component vector of float)
-0:3            Construct vec4 ( temp 4-component vector of float)
-0:3              'input' ( in 4-component vector of float)
+0:3            'input' ( in 4-component vector of float)
 0:3            Convert int to float ( temp 4-component vector of float)
 0:3              Convert float to int ( temp 4-component vector of int)
 0:3                'input' ( in 4-component vector of float)
@@ -47,8 +46,7 @@ gl_FragCoord origin is upper left
 0:3      Branch: Return with expression
 0:3        add ( temp 4-component vector of float)
 0:3          add ( temp 4-component vector of float)
-0:3            Construct vec4 ( temp 4-component vector of float)
-0:3              'input' ( in 4-component vector of float)
+0:3            'input' ( in 4-component vector of float)
 0:3            Convert int to float ( temp 4-component vector of float)
 0:3              Convert float to int ( temp 4-component vector of int)
 0:3                'input' ( in 4-component vector of float)
@@ -73,62 +71,57 @@ gl_FragCoord origin is upper left
 
 // Module Version 10000
 // Generated by (magic number): 80006
-// Id's are bound by 39
+// Id's are bound by 34
 
                               Capability Shader
                1:             ExtInstImport  "GLSL.std.450"
                               MemoryModel Logical GLSL450
-                              EntryPoint Fragment 4  "PixelShaderFunction" 32 35
+                              EntryPoint Fragment 4  "PixelShaderFunction" 27 30
                               ExecutionMode 4 OriginUpperLeft
                               Source HLSL 500
                               Name 4  "PixelShaderFunction"
                               Name 11  "@PixelShaderFunction(vf4;"
                               Name 10  "input"
-                              Name 30  "input"
-                              Name 32  "input"
-                              Name 35  "@entryPointOutput"
-                              Name 36  "param"
-                              Decorate 32(input) Location 0
-                              Decorate 35(@entryPointOutput) Location 0
+                              Name 25  "input"
+                              Name 27  "input"
+                              Name 30  "@entryPointOutput"
+                              Name 31  "param"
+                              Decorate 27(input) Location 0
+                              Decorate 30(@entryPointOutput) Location 0
                2:             TypeVoid
                3:             TypeFunction 2
                6:             TypeFloat 32
                7:             TypeVector 6(float) 4
                8:             TypePointer Function 7(fvec4)
                9:             TypeFunction 7(fvec4) 8(ptr)
-              20:             TypeInt 32 1
-              21:             TypeVector 20(int) 4
-              25:    6(float) Constant 1067014160
-              26:    7(fvec4) ConstantComposite 25 25 25 25
-              31:             TypePointer Input 7(fvec4)
-       32(input):     31(ptr) Variable Input
-              34:             TypePointer Output 7(fvec4)
-35(@entryPointOutput):     34(ptr) Variable Output
+              15:             TypeInt 32 1
+              16:             TypeVector 15(int) 4
+              20:    6(float) Constant 1067014160
+              21:    7(fvec4) ConstantComposite 20 20 20 20
+              26:             TypePointer Input 7(fvec4)
+       27(input):     26(ptr) Variable Input
+              29:             TypePointer Output 7(fvec4)
+30(@entryPointOutput):     29(ptr) Variable Output
 4(PixelShaderFunction):           2 Function None 3
                5:             Label
-       30(input):      8(ptr) Variable Function
-       36(param):      8(ptr) Variable Function
-              33:    7(fvec4) Load 32(input)
-                              Store 30(input) 33
-              37:    7(fvec4) Load 30(input)
-                              Store 36(param) 37
-              38:    7(fvec4) FunctionCall 11(@PixelShaderFunction(vf4;) 36(param)
-                              Store 35(@entryPointOutput) 38
+       25(input):      8(ptr) Variable Function
+       31(param):      8(ptr) Variable Function
+              28:    7(fvec4) Load 27(input)
+                              Store 25(input) 28
+              32:    7(fvec4) Load 25(input)
+                              Store 31(param) 32
+              33:    7(fvec4) FunctionCall 11(@PixelShaderFunction(vf4;) 31(param)
+                              Store 30(@entryPointOutput) 33
                               Return
                               FunctionEnd
 11(@PixelShaderFunction(vf4;):    7(fvec4) Function None 9
        10(input):      8(ptr) FunctionParameter
               12:             Label
               13:    7(fvec4) Load 10(input)
-              14:    6(float) CompositeExtract 13 0
-              15:    6(float) CompositeExtract 13 1
-              16:    6(float) CompositeExtract 13 2
-              17:    6(float) CompositeExtract 13 3
-              18:    7(fvec4) CompositeConstruct 14 15 16 17
-              19:    7(fvec4) Load 10(input)
-              22:   21(ivec4) ConvertFToS 19
-              23:    7(fvec4) ConvertSToF 22
-              24:    7(fvec4) FAdd 18 23
-              27:    7(fvec4) FAdd 24 26
-                              ReturnValue 27
+              14:    7(fvec4) Load 10(input)
+              17:   16(ivec4) ConvertFToS 14
+              18:    7(fvec4) ConvertSToF 17
+              19:    7(fvec4) FAdd 13 18
+              22:    7(fvec4) FAdd 19 21
+                              ReturnValue 22
                               FunctionEnd
diff --git a/Test/baseResults/hlsl.self_cast.frag.out b/Test/baseResults/hlsl.self_cast.frag.out
new file mode 100644 (file)
index 0000000..b2decf3
--- /dev/null
@@ -0,0 +1,130 @@
+hlsl.self_cast.frag
+Shader version: 500
+gl_FragCoord origin is upper left
+0:? Sequence
+0:5  Function Definition: @main( ( temp void)
+0:5    Function Parameters: 
+0:?     Sequence
+0:?       Sequence
+0:8        Sequence
+0:8          move second child to first child ( temp structure{})
+0:8            'b' ( temp structure{})
+0:8            'a' ( temp structure{})
+0:?       Sequence
+0:13        Sequence
+0:13          move second child to first child ( temp structure{ temp float f})
+0:13            'b' ( temp structure{ temp float f})
+0:13            'a' ( temp structure{ temp float f})
+0:?       Sequence
+0:18        Sequence
+0:18          move second child to first child ( temp 2-element array of structure{})
+0:18            'b' ( temp 2-element array of structure{})
+0:18            'a' ( temp 2-element array of structure{})
+0:?       Sequence
+0:23        Sequence
+0:23          move second child to first child ( temp 2-element array of structure{ temp float f})
+0:23            'b' ( temp 2-element array of structure{ temp float f})
+0:23            'a' ( temp 2-element array of structure{ temp float f})
+0:5  Function Definition: main( ( temp void)
+0:5    Function Parameters: 
+0:?     Sequence
+0:5      Function Call: @main( ( temp void)
+0:?   Linker Objects
+
+
+Linked fragment stage:
+
+
+Shader version: 500
+gl_FragCoord origin is upper left
+0:? Sequence
+0:5  Function Definition: @main( ( temp void)
+0:5    Function Parameters: 
+0:?     Sequence
+0:?       Sequence
+0:8        Sequence
+0:8          move second child to first child ( temp structure{})
+0:8            'b' ( temp structure{})
+0:8            'a' ( temp structure{})
+0:?       Sequence
+0:13        Sequence
+0:13          move second child to first child ( temp structure{ temp float f})
+0:13            'b' ( temp structure{ temp float f})
+0:13            'a' ( temp structure{ temp float f})
+0:?       Sequence
+0:18        Sequence
+0:18          move second child to first child ( temp 2-element array of structure{})
+0:18            'b' ( temp 2-element array of structure{})
+0:18            'a' ( temp 2-element array of structure{})
+0:?       Sequence
+0:23        Sequence
+0:23          move second child to first child ( temp 2-element array of structure{ temp float f})
+0:23            'b' ( temp 2-element array of structure{ temp float f})
+0:23            'a' ( temp 2-element array of structure{ temp float f})
+0:5  Function Definition: main( ( temp void)
+0:5    Function Parameters: 
+0:?     Sequence
+0:5      Function Call: @main( ( temp void)
+0:?   Linker Objects
+
+// Module Version 10000
+// Generated by (magic number): 80006
+// Id's are bound by 32
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main"
+                              ExecutionMode 4 OriginUpperLeft
+                              Source HLSL 500
+                              Name 4  "main"
+                              Name 6  "@main("
+                              Name 8  "Test0"
+                              Name 10  "b"
+                              Name 11  "a"
+                              Name 14  "Test1"
+                              MemberName 14(Test1) 0  "f"
+                              Name 16  "b"
+                              Name 17  "a"
+                              Name 23  "b"
+                              Name 24  "a"
+                              Name 28  "b"
+                              Name 29  "a"
+               2:             TypeVoid
+               3:             TypeFunction 2
+        8(Test0):             TypeStruct
+               9:             TypePointer Function 8(Test0)
+              13:             TypeFloat 32
+       14(Test1):             TypeStruct 13(float)
+              15:             TypePointer Function 14(Test1)
+              19:             TypeInt 32 0
+              20:     19(int) Constant 2
+              21:             TypeArray 8(Test0) 20
+              22:             TypePointer Function 21
+              26:             TypeArray 14(Test1) 20
+              27:             TypePointer Function 26
+         4(main):           2 Function None 3
+               5:             Label
+              31:           2 FunctionCall 6(@main()
+                              Return
+                              FunctionEnd
+       6(@main():           2 Function None 3
+               7:             Label
+           10(b):      9(ptr) Variable Function
+           11(a):      9(ptr) Variable Function
+           16(b):     15(ptr) Variable Function
+           17(a):     15(ptr) Variable Function
+           23(b):     22(ptr) Variable Function
+           24(a):     22(ptr) Variable Function
+           28(b):     27(ptr) Variable Function
+           29(a):     27(ptr) Variable Function
+              12:    8(Test0) Load 11(a)
+                              Store 10(b) 12
+              18:   14(Test1) Load 17(a)
+                              Store 16(b) 18
+              25:          21 Load 24(a)
+                              Store 23(b) 25
+              30:          26 Load 29(a)
+                              Store 28(b) 30
+                              Return
+                              FunctionEnd
index 0a2a5b2..15ebe4d 100755 (executable)
@@ -40,8 +40,7 @@ gl_FragCoord origin is upper left
 0:10      move second child to first child ( temp 3-component vector of float)
 0:10        'u' ( temp 3-component vector of float)
 0:10        Construct vec3 ( temp 3-component vector of float)
-0:10          Construct float ( temp float)
-0:10            'f' ( in float)
+0:10          'f' ( in float)
 0:11      Sequence
 0:11        move second child to first child ( temp 2-component vector of float)
 0:11          'w' ( temp 2-component vector of float)
@@ -203,8 +202,7 @@ gl_FragCoord origin is upper left
 0:10      move second child to first child ( temp 3-component vector of float)
 0:10        'u' ( temp 3-component vector of float)
 0:10        Construct vec3 ( temp 3-component vector of float)
-0:10          Construct float ( temp float)
-0:10            'f' ( in float)
+0:10          'f' ( in float)
 0:11      Sequence
 0:11        move second child to first child ( temp 2-component vector of float)
 0:11          'w' ( temp 2-component vector of float)
diff --git a/Test/hlsl.self_cast.frag b/Test/hlsl.self_cast.frag
new file mode 100644 (file)
index 0000000..8ef4027
--- /dev/null
@@ -0,0 +1,25 @@
+struct Test0 {};
+struct Test1 { float f; };
+
+void main()
+{
+    {
+        Test0 a;
+        Test0 b = (Test0)a;
+    }
+
+    {
+        Test1 a;
+        Test1 b = (Test1)a;
+    }
+
+    {
+        Test0 a[2];
+        Test0 b[2] = (Test0[2])a;
+    }
+
+    {
+        Test1 a[2];
+        Test1 b[2] = (Test1[2])a;
+    }
+}
index 390e3d3..861c098 100644 (file)
@@ -315,6 +315,7 @@ INSTANTIATE_TEST_CASE_P(
         {"hlsl.semicolons.frag", "main"},
         {"hlsl.shapeConv.frag", "main"},
         {"hlsl.shapeConvRet.frag", "main"},
+        {"hlsl.self_cast.frag", "main"},
         {"hlsl.snorm.uav.comp", "main"},
         {"hlsl.staticMemberFunction.frag", "main"},
         {"hlsl.store.rwbyteaddressbuffer.type.comp", "main"},
index 3ef9a5a..d80f356 100755 (executable)
@@ -6401,12 +6401,18 @@ bool HlslParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node
         return true;
     }
 
-    if (op == EOpConstructStruct && ! type.isArray() && isScalarConstructor(node))
-        return false;
+    if (op == EOpConstructStruct && ! type.isArray()) {
+        if (isScalarConstructor(node))
+            return false;
 
-    if (op == EOpConstructStruct && ! type.isArray() && (int)type.getStruct()->size() != function.getParamCount()) {
-        error(loc, "Number of constructor parameters does not match the number of structure fields", "constructor", "");
-        return true;
+        // Self-type construction: e.g, we can construct a struct from a single identically typed object.
+        if (function.getParamCount() == 1 && type == *function[0].type)
+            return false;
+
+        if ((int)type.getStruct()->size() != function.getParamCount()) {
+            error(loc, "Number of constructor parameters does not match the number of structure fields", "constructor", "");
+            return true;
+        }
     }
 
     if ((op != EOpConstructStruct && size != 1 && size < type.computeNumComponents()) ||
@@ -8132,6 +8138,10 @@ TIntermTyped* HlslParseContext::handleConstructor(const TSourceLoc& loc, TInterm
     if (node == nullptr)
         return nullptr;
 
+    // Construct identical type
+    if (type == node->getType())
+        return node;
+
     // Handle the idiom "(struct type)<scalar value>"
     if (type.isStruct() && isScalarConstructor(node)) {
         // 'node' will almost always get used multiple times, so should not be used directly,