HLSL: allow self-type cast (as no-op passthrough)

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
This commit is contained in:
LoopDawg 2018-05-17 13:03:12 -06:00
parent ebec909487
commit c59916710e
6 changed files with 205 additions and 48 deletions

View File

@ -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

View File

@ -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

View File

@ -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)

25
Test/hlsl.self_cast.frag Normal file
View File

@ -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;
}
}

View 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"},

View File

@ -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,