From e5921f1309230cb7dea5d9d53bd3bc38c07da037 Mon Sep 17 00:00:00 2001 From: steve-lunarg Date: Sat, 15 Oct 2016 10:29:58 -0600 Subject: [PATCH 1/2] HLSL: Fix unary and binary operator type conversion issues This fixes defects as follows: 1. handleLvalue could be called on a non-L-value, and it shouldn't be. 2. HLSL allows unary negation on non-bool values. TUnaryOperator::promote can now promote other types (e.g, int, float) to bool for this op. 3. HLSL allows binary logical operations (&&, ||) on arbitrary types, similar (2). 4. HLSL allows mod operation on arbitrary types, which will be promoted. E.g, int % float -> float % float. --- Test/baseResults/hlsl.logical.binary.frag.out | 220 +++++++++++++ Test/baseResults/hlsl.logical.unary.frag.out | 292 ++++++++++++++++++ Test/baseResults/hlsl.promote.binary.frag.out | 280 +++++++++++++++++ Test/hlsl.logical.binary.frag | 21 ++ Test/hlsl.logical.unary.frag | 29 ++ Test/hlsl.promote.binary.frag | 28 ++ glslang/Include/intermediate.h | 8 +- glslang/MachineIndependent/Intermediate.cpp | 66 +++- .../MachineIndependent/localintermediate.h | 5 +- gtests/Hlsl.FromFile.cpp | 5 +- hlsl/hlslGrammar.cpp | 5 +- hlsl/hlslParseables.cpp | 3 - 12 files changed, 946 insertions(+), 16 deletions(-) create mode 100644 Test/baseResults/hlsl.logical.binary.frag.out create mode 100644 Test/baseResults/hlsl.logical.unary.frag.out create mode 100644 Test/baseResults/hlsl.promote.binary.frag.out create mode 100644 Test/hlsl.logical.binary.frag create mode 100644 Test/hlsl.logical.unary.frag create mode 100644 Test/hlsl.promote.binary.frag diff --git a/Test/baseResults/hlsl.logical.binary.frag.out b/Test/baseResults/hlsl.logical.binary.frag.out new file mode 100644 index 00000000..9e6593ee --- /dev/null +++ b/Test/baseResults/hlsl.logical.binary.frag.out @@ -0,0 +1,220 @@ +hlsl.logical.binary.frag +Shader version: 450 +gl_FragCoord origin is upper left +0:? Sequence +0:12 Function Definition: main( (temp structure{temp 4-component vector of float Color}) +0:12 Function Parameters: +0:? Sequence +0:13 Test condition and select (temp void) +0:13 Condition +0:13 logical-and (temp bool) +0:13 Convert int to bool (temp bool) +0:13 ival: direct index for structure (layout(offset=0 ) uniform int) +0:13 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) +0:13 Constant: +0:13 0 (const uint) +0:13 Convert int to bool (temp bool) +0:13 Convert float to int (temp int) +0:13 fval: direct index for structure (layout(offset=32 ) uniform float) +0:13 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) +0:13 Constant: +0:13 2 (const uint) +0:13 true case is null +0:14 Test condition and select (temp void) +0:14 Condition +0:14 logical-or (temp bool) +0:14 Convert int to bool (temp bool) +0:14 ival: direct index for structure (layout(offset=0 ) uniform int) +0:14 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) +0:14 Constant: +0:14 0 (const uint) +0:14 Convert int to bool (temp bool) +0:14 Convert float to int (temp int) +0:14 fval: direct index for structure (layout(offset=32 ) uniform float) +0:14 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) +0:14 Constant: +0:14 2 (const uint) +0:14 true case is null +0:17 move second child to first child (temp 4-component vector of float) +0:17 Color: direct index for structure (temp 4-component vector of float) +0:17 'psout' (temp structure{temp 4-component vector of float Color}) +0:17 Constant: +0:17 0 (const int) +0:17 Constant: +0:17 1.000000 +0:17 1.000000 +0:17 1.000000 +0:17 1.000000 +0:18 Sequence +0:18 Sequence +0:18 move second child to first child (temp 4-component vector of float) +0:? 'Color' (layout(location=0 ) out 4-component vector of float) +0:18 Color: direct index for structure (temp 4-component vector of float) +0:18 'psout' (temp structure{temp 4-component vector of float Color}) +0:18 Constant: +0:18 0 (const int) +0:18 Branch: Return +0:? Linker Objects +0:? 'Color' (layout(location=0 ) out 4-component vector of float) +0:? 'anon@0' (uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) + + +Linked fragment stage: + + +Shader version: 450 +gl_FragCoord origin is upper left +0:? Sequence +0:12 Function Definition: main( (temp structure{temp 4-component vector of float Color}) +0:12 Function Parameters: +0:? Sequence +0:13 Test condition and select (temp void) +0:13 Condition +0:13 logical-and (temp bool) +0:13 Convert int to bool (temp bool) +0:13 ival: direct index for structure (layout(offset=0 ) uniform int) +0:13 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) +0:13 Constant: +0:13 0 (const uint) +0:13 Convert int to bool (temp bool) +0:13 Convert float to int (temp int) +0:13 fval: direct index for structure (layout(offset=32 ) uniform float) +0:13 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) +0:13 Constant: +0:13 2 (const uint) +0:13 true case is null +0:14 Test condition and select (temp void) +0:14 Condition +0:14 logical-or (temp bool) +0:14 Convert int to bool (temp bool) +0:14 ival: direct index for structure (layout(offset=0 ) uniform int) +0:14 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) +0:14 Constant: +0:14 0 (const uint) +0:14 Convert int to bool (temp bool) +0:14 Convert float to int (temp int) +0:14 fval: direct index for structure (layout(offset=32 ) uniform float) +0:14 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) +0:14 Constant: +0:14 2 (const uint) +0:14 true case is null +0:17 move second child to first child (temp 4-component vector of float) +0:17 Color: direct index for structure (temp 4-component vector of float) +0:17 'psout' (temp structure{temp 4-component vector of float Color}) +0:17 Constant: +0:17 0 (const int) +0:17 Constant: +0:17 1.000000 +0:17 1.000000 +0:17 1.000000 +0:17 1.000000 +0:18 Sequence +0:18 Sequence +0:18 move second child to first child (temp 4-component vector of float) +0:? 'Color' (layout(location=0 ) out 4-component vector of float) +0:18 Color: direct index for structure (temp 4-component vector of float) +0:18 'psout' (temp structure{temp 4-component vector of float Color}) +0:18 Constant: +0:18 0 (const int) +0:18 Branch: Return +0:? Linker Objects +0:? 'Color' (layout(location=0 ) out 4-component vector of float) +0:? 'anon@0' (uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 57 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 4 "main" 53 + ExecutionMode 4 OriginUpperLeft + Name 4 "main" + Name 11 "$Global" + MemberName 11($Global) 0 "ival" + MemberName 11($Global) 1 "ival4" + MemberName 11($Global) 2 "fval" + MemberName 11($Global) 3 "fval4" + Name 13 "" + Name 45 "PS_OUTPUT" + MemberName 45(PS_OUTPUT) 0 "Color" + Name 47 "psout" + Name 53 "Color" + MemberDecorate 11($Global) 0 Offset 0 + MemberDecorate 11($Global) 1 Offset 16 + MemberDecorate 11($Global) 2 Offset 32 + MemberDecorate 11($Global) 3 Offset 48 + Decorate 11($Global) Block + Decorate 13 DescriptorSet 0 + Decorate 53(Color) Location 0 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeBool + 7: TypeInt 32 1 + 8: TypeVector 7(int) 4 + 9: TypeFloat 32 + 10: TypeVector 9(float) 4 + 11($Global): TypeStruct 7(int) 8(ivec4) 9(float) 10(fvec4) + 12: TypePointer Uniform 11($Global) + 13: 12(ptr) Variable Uniform + 14: 7(int) Constant 0 + 15: TypePointer Uniform 7(int) + 18: TypeInt 32 0 + 19: 18(int) Constant 0 + 23: 7(int) Constant 2 + 24: TypePointer Uniform 9(float) + 45(PS_OUTPUT): TypeStruct 10(fvec4) + 46: TypePointer Function 45(PS_OUTPUT) + 48: 9(float) Constant 1065353216 + 49: 10(fvec4) ConstantComposite 48 48 48 48 + 50: TypePointer Function 10(fvec4) + 52: TypePointer Output 10(fvec4) + 53(Color): 52(ptr) Variable Output + 4(main): 2 Function None 3 + 5: Label + 47(psout): 46(ptr) Variable Function + 16: 15(ptr) AccessChain 13 14 + 17: 7(int) Load 16 + 20: 6(bool) INotEqual 17 19 + SelectionMerge 22 None + BranchConditional 20 21 22 + 21: Label + 25: 24(ptr) AccessChain 13 23 + 26: 9(float) Load 25 + 27: 7(int) ConvertFToS 26 + 28: 6(bool) INotEqual 27 19 + Branch 22 + 22: Label + 29: 6(bool) Phi 20 5 28 21 + SelectionMerge 31 None + BranchConditional 29 30 31 + 30: Label + Branch 31 + 31: Label + 32: 15(ptr) AccessChain 13 14 + 33: 7(int) Load 32 + 34: 6(bool) INotEqual 33 19 + 35: 6(bool) LogicalNot 34 + SelectionMerge 37 None + BranchConditional 35 36 37 + 36: Label + 38: 24(ptr) AccessChain 13 23 + 39: 9(float) Load 38 + 40: 7(int) ConvertFToS 39 + 41: 6(bool) INotEqual 40 19 + Branch 37 + 37: Label + 42: 6(bool) Phi 34 31 41 36 + SelectionMerge 44 None + BranchConditional 42 43 44 + 43: Label + Branch 44 + 44: Label + 51: 50(ptr) AccessChain 47(psout) 14 + Store 51 49 + 54: 50(ptr) AccessChain 47(psout) 14 + 55: 10(fvec4) Load 54 + Store 53(Color) 55 + Return + FunctionEnd diff --git a/Test/baseResults/hlsl.logical.unary.frag.out b/Test/baseResults/hlsl.logical.unary.frag.out new file mode 100644 index 00000000..e3def3c0 --- /dev/null +++ b/Test/baseResults/hlsl.logical.unary.frag.out @@ -0,0 +1,292 @@ +hlsl.logical.unary.frag +Shader version: 450 +gl_FragCoord origin is upper left +0:? Sequence +0:12 Function Definition: main( (temp structure{temp 4-component vector of float Color}) +0:12 Function Parameters: +0:? Sequence +0:13 Negate conditional (temp bool) +0:13 Convert int to bool (temp bool) +0:13 ival: direct index for structure (layout(offset=0 ) uniform int) +0:13 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) +0:13 Constant: +0:13 0 (const uint) +0:14 Negate conditional (temp 4-component vector of bool) +0:14 Convert int to bool (temp 4-component vector of bool) +0:14 ival4: direct index for structure (layout(offset=16 ) uniform 4-component vector of int) +0:14 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) +0:14 Constant: +0:14 1 (const uint) +0:16 Negate conditional (temp bool) +0:16 Convert float to bool (temp bool) +0:16 fval: direct index for structure (layout(offset=32 ) uniform float) +0:16 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) +0:16 Constant: +0:16 2 (const uint) +0:17 Negate conditional (temp 4-component vector of bool) +0:17 Convert float to bool (temp 4-component vector of bool) +0:17 fval4: direct index for structure (layout(offset=48 ) uniform 4-component vector of float) +0:17 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) +0:17 Constant: +0:17 3 (const uint) +0:19 Test condition and select (temp void) +0:19 Condition +0:19 ival: direct index for structure (layout(offset=0 ) uniform int) +0:19 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) +0:19 Constant: +0:19 0 (const uint) +0:19 true case is null +0:20 Test condition and select (temp void) +0:20 Condition +0:20 fval: direct index for structure (layout(offset=32 ) uniform float) +0:20 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) +0:20 Constant: +0:20 2 (const uint) +0:20 true case is null +0:21 Test condition and select (temp void) +0:21 Condition +0:21 Negate conditional (temp bool) +0:21 Convert int to bool (temp bool) +0:21 ival: direct index for structure (layout(offset=0 ) uniform int) +0:21 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) +0:21 Constant: +0:21 0 (const uint) +0:21 true case is null +0:22 Test condition and select (temp void) +0:22 Condition +0:22 Negate conditional (temp bool) +0:22 Convert float to bool (temp bool) +0:22 fval: direct index for structure (layout(offset=32 ) uniform float) +0:22 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) +0:22 Constant: +0:22 2 (const uint) +0:22 true case is null +0:25 move second child to first child (temp 4-component vector of float) +0:25 Color: direct index for structure (temp 4-component vector of float) +0:25 'psout' (temp structure{temp 4-component vector of float Color}) +0:25 Constant: +0:25 0 (const int) +0:25 Constant: +0:25 1.000000 +0:25 1.000000 +0:25 1.000000 +0:25 1.000000 +0:26 Sequence +0:26 Sequence +0:26 move second child to first child (temp 4-component vector of float) +0:? 'Color' (layout(location=0 ) out 4-component vector of float) +0:26 Color: direct index for structure (temp 4-component vector of float) +0:26 'psout' (temp structure{temp 4-component vector of float Color}) +0:26 Constant: +0:26 0 (const int) +0:26 Branch: Return +0:? Linker Objects +0:? 'Color' (layout(location=0 ) out 4-component vector of float) +0:? 'anon@0' (uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) + + +Linked fragment stage: + + +Shader version: 450 +gl_FragCoord origin is upper left +0:? Sequence +0:12 Function Definition: main( (temp structure{temp 4-component vector of float Color}) +0:12 Function Parameters: +0:? Sequence +0:13 Negate conditional (temp bool) +0:13 Convert int to bool (temp bool) +0:13 ival: direct index for structure (layout(offset=0 ) uniform int) +0:13 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) +0:13 Constant: +0:13 0 (const uint) +0:14 Negate conditional (temp 4-component vector of bool) +0:14 Convert int to bool (temp 4-component vector of bool) +0:14 ival4: direct index for structure (layout(offset=16 ) uniform 4-component vector of int) +0:14 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) +0:14 Constant: +0:14 1 (const uint) +0:16 Negate conditional (temp bool) +0:16 Convert float to bool (temp bool) +0:16 fval: direct index for structure (layout(offset=32 ) uniform float) +0:16 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) +0:16 Constant: +0:16 2 (const uint) +0:17 Negate conditional (temp 4-component vector of bool) +0:17 Convert float to bool (temp 4-component vector of bool) +0:17 fval4: direct index for structure (layout(offset=48 ) uniform 4-component vector of float) +0:17 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) +0:17 Constant: +0:17 3 (const uint) +0:19 Test condition and select (temp void) +0:19 Condition +0:19 ival: direct index for structure (layout(offset=0 ) uniform int) +0:19 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) +0:19 Constant: +0:19 0 (const uint) +0:19 true case is null +0:20 Test condition and select (temp void) +0:20 Condition +0:20 fval: direct index for structure (layout(offset=32 ) uniform float) +0:20 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) +0:20 Constant: +0:20 2 (const uint) +0:20 true case is null +0:21 Test condition and select (temp void) +0:21 Condition +0:21 Negate conditional (temp bool) +0:21 Convert int to bool (temp bool) +0:21 ival: direct index for structure (layout(offset=0 ) uniform int) +0:21 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) +0:21 Constant: +0:21 0 (const uint) +0:21 true case is null +0:22 Test condition and select (temp void) +0:22 Condition +0:22 Negate conditional (temp bool) +0:22 Convert float to bool (temp bool) +0:22 fval: direct index for structure (layout(offset=32 ) uniform float) +0:22 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) +0:22 Constant: +0:22 2 (const uint) +0:22 true case is null +0:25 move second child to first child (temp 4-component vector of float) +0:25 Color: direct index for structure (temp 4-component vector of float) +0:25 'psout' (temp structure{temp 4-component vector of float Color}) +0:25 Constant: +0:25 0 (const int) +0:25 Constant: +0:25 1.000000 +0:25 1.000000 +0:25 1.000000 +0:25 1.000000 +0:26 Sequence +0:26 Sequence +0:26 move second child to first child (temp 4-component vector of float) +0:? 'Color' (layout(location=0 ) out 4-component vector of float) +0:26 Color: direct index for structure (temp 4-component vector of float) +0:26 'psout' (temp structure{temp 4-component vector of float Color}) +0:26 Constant: +0:26 0 (const int) +0:26 Branch: Return +0:? Linker Objects +0:? 'Color' (layout(location=0 ) out 4-component vector of float) +0:? 'anon@0' (uniform block{layout(offset=0 ) uniform int ival, layout(offset=16 ) uniform 4-component vector of int ival4, layout(offset=32 ) uniform float fval, layout(offset=48 ) uniform 4-component vector of float fval4}) + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 77 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 4 "main" 73 + ExecutionMode 4 OriginUpperLeft + Name 4 "main" + Name 10 "$Global" + MemberName 10($Global) 0 "ival" + MemberName 10($Global) 1 "ival4" + MemberName 10($Global) 2 "fval" + MemberName 10($Global) 3 "fval4" + Name 12 "" + Name 65 "PS_OUTPUT" + MemberName 65(PS_OUTPUT) 0 "Color" + Name 67 "psout" + Name 73 "Color" + MemberDecorate 10($Global) 0 Offset 0 + MemberDecorate 10($Global) 1 Offset 16 + MemberDecorate 10($Global) 2 Offset 32 + MemberDecorate 10($Global) 3 Offset 48 + Decorate 10($Global) Block + Decorate 12 DescriptorSet 0 + Decorate 73(Color) Location 0 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeInt 32 1 + 7: TypeVector 6(int) 4 + 8: TypeFloat 32 + 9: TypeVector 8(float) 4 + 10($Global): TypeStruct 6(int) 7(ivec4) 8(float) 9(fvec4) + 11: TypePointer Uniform 10($Global) + 12: 11(ptr) Variable Uniform + 13: 6(int) Constant 0 + 14: TypePointer Uniform 6(int) + 17: TypeBool + 18: TypeInt 32 0 + 19: 18(int) Constant 0 + 22: 6(int) Constant 1 + 23: TypePointer Uniform 7(ivec4) + 26: TypeVector 17(bool) 4 + 27: TypeVector 18(int) 4 + 28: 27(ivec4) ConstantComposite 19 19 19 19 + 31: 6(int) Constant 2 + 32: TypePointer Uniform 8(float) + 35: 8(float) Constant 0 + 38: 6(int) Constant 3 + 39: TypePointer Uniform 9(fvec4) + 42: 9(fvec4) ConstantComposite 35 35 35 35 + 65(PS_OUTPUT): TypeStruct 9(fvec4) + 66: TypePointer Function 65(PS_OUTPUT) + 68: 8(float) Constant 1065353216 + 69: 9(fvec4) ConstantComposite 68 68 68 68 + 70: TypePointer Function 9(fvec4) + 72: TypePointer Output 9(fvec4) + 73(Color): 72(ptr) Variable Output + 4(main): 2 Function None 3 + 5: Label + 67(psout): 66(ptr) Variable Function + 15: 14(ptr) AccessChain 12 13 + 16: 6(int) Load 15 + 20: 17(bool) INotEqual 16 19 + 21: 17(bool) LogicalNot 20 + 24: 23(ptr) AccessChain 12 22 + 25: 7(ivec4) Load 24 + 29: 26(bvec4) INotEqual 25 28 + 30: 26(bvec4) LogicalNot 29 + 33: 32(ptr) AccessChain 12 31 + 34: 8(float) Load 33 + 36: 17(bool) FOrdNotEqual 34 35 + 37: 17(bool) LogicalNot 36 + 40: 39(ptr) AccessChain 12 38 + 41: 9(fvec4) Load 40 + 43: 26(bvec4) FOrdNotEqual 41 42 + 44: 26(bvec4) LogicalNot 43 + 45: 14(ptr) AccessChain 12 13 + 46: 6(int) Load 45 + SelectionMerge 48 None + BranchConditional 46 47 48 + 47: Label + Branch 48 + 48: Label + 49: 32(ptr) AccessChain 12 31 + 50: 8(float) Load 49 + SelectionMerge 52 None + BranchConditional 50 51 52 + 51: Label + Branch 52 + 52: Label + 53: 14(ptr) AccessChain 12 13 + 54: 6(int) Load 53 + 55: 17(bool) INotEqual 54 19 + 56: 17(bool) LogicalNot 55 + SelectionMerge 58 None + BranchConditional 56 57 58 + 57: Label + Branch 58 + 58: Label + 59: 32(ptr) AccessChain 12 31 + 60: 8(float) Load 59 + 61: 17(bool) FOrdNotEqual 60 35 + 62: 17(bool) LogicalNot 61 + SelectionMerge 64 None + BranchConditional 62 63 64 + 63: Label + Branch 64 + 64: Label + 71: 70(ptr) AccessChain 67(psout) 13 + Store 71 69 + 74: 70(ptr) AccessChain 67(psout) 13 + 75: 9(fvec4) Load 74 + Store 73(Color) 75 + Return + FunctionEnd diff --git a/Test/baseResults/hlsl.promote.binary.frag.out b/Test/baseResults/hlsl.promote.binary.frag.out new file mode 100644 index 00000000..a2e7176c --- /dev/null +++ b/Test/baseResults/hlsl.promote.binary.frag.out @@ -0,0 +1,280 @@ +hlsl.promote.binary.frag +Shader version: 450 +gl_FragCoord origin is upper left +0:? Sequence +0:14 Function Definition: main( (temp structure{temp 4-component vector of float Color}) +0:14 Function Parameters: +0:? Sequence +0:15 mod (temp float) +0:15 Convert int to float (temp float) +0:15 ival: direct index for structure (layout(offset=32 ) uniform int) +0:15 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform bool bval, layout(offset=16 ) uniform 4-component vector of bool bval4, layout(offset=32 ) uniform int ival, layout(offset=48 ) uniform 4-component vector of int ival4, layout(offset=64 ) uniform float fval, layout(offset=80 ) uniform 4-component vector of float fval4}) +0:15 Constant: +0:15 2 (const uint) +0:15 fval: direct index for structure (layout(offset=64 ) uniform float) +0:15 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform bool bval, layout(offset=16 ) uniform 4-component vector of bool bval4, layout(offset=32 ) uniform int ival, layout(offset=48 ) uniform 4-component vector of int ival4, layout(offset=64 ) uniform float fval, layout(offset=80 ) uniform 4-component vector of float fval4}) +0:15 Constant: +0:15 4 (const uint) +0:16 mod (temp 4-component vector of float) +0:16 Convert int to float (temp 4-component vector of float) +0:16 ival4: direct index for structure (layout(offset=48 ) uniform 4-component vector of int) +0:16 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform bool bval, layout(offset=16 ) uniform 4-component vector of bool bval4, layout(offset=32 ) uniform int ival, layout(offset=48 ) uniform 4-component vector of int ival4, layout(offset=64 ) uniform float fval, layout(offset=80 ) uniform 4-component vector of float fval4}) +0:16 Constant: +0:16 3 (const uint) +0:16 fval4: direct index for structure (layout(offset=80 ) uniform 4-component vector of float) +0:16 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform bool bval, layout(offset=16 ) uniform 4-component vector of bool bval4, layout(offset=32 ) uniform int ival, layout(offset=48 ) uniform 4-component vector of int ival4, layout(offset=64 ) uniform float fval, layout(offset=80 ) uniform 4-component vector of float fval4}) +0:16 Constant: +0:16 5 (const uint) +0:18 mod (temp float) +0:18 Convert bool to float (temp float) +0:18 bval: direct index for structure (layout(offset=0 ) uniform bool) +0:18 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform bool bval, layout(offset=16 ) uniform 4-component vector of bool bval4, layout(offset=32 ) uniform int ival, layout(offset=48 ) uniform 4-component vector of int ival4, layout(offset=64 ) uniform float fval, layout(offset=80 ) uniform 4-component vector of float fval4}) +0:18 Constant: +0:18 0 (const uint) +0:18 fval: direct index for structure (layout(offset=64 ) uniform float) +0:18 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform bool bval, layout(offset=16 ) uniform 4-component vector of bool bval4, layout(offset=32 ) uniform int ival, layout(offset=48 ) uniform 4-component vector of int ival4, layout(offset=64 ) uniform float fval, layout(offset=80 ) uniform 4-component vector of float fval4}) +0:18 Constant: +0:18 4 (const uint) +0:19 mod (temp 4-component vector of float) +0:19 Convert bool to float (temp 4-component vector of float) +0:19 bval4: direct index for structure (layout(offset=16 ) uniform 4-component vector of bool) +0:19 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform bool bval, layout(offset=16 ) uniform 4-component vector of bool bval4, layout(offset=32 ) uniform int ival, layout(offset=48 ) uniform 4-component vector of int ival4, layout(offset=64 ) uniform float fval, layout(offset=80 ) uniform 4-component vector of float fval4}) +0:19 Constant: +0:19 1 (const uint) +0:19 fval4: direct index for structure (layout(offset=80 ) uniform 4-component vector of float) +0:19 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform bool bval, layout(offset=16 ) uniform 4-component vector of bool bval4, layout(offset=32 ) uniform int ival, layout(offset=48 ) uniform 4-component vector of int ival4, layout(offset=64 ) uniform float fval, layout(offset=80 ) uniform 4-component vector of float fval4}) +0:19 Constant: +0:19 5 (const uint) +0:21 Sequence +0:21 move second child to first child (temp int) +0:21 'l_int' (temp int) +0:21 Constant: +0:21 1 (const int) +0:22 mod second child into first child (temp int) +0:22 'l_int' (temp int) +0:22 Convert float to int (temp int) +0:22 fval: direct index for structure (layout(offset=64 ) uniform float) +0:22 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform bool bval, layout(offset=16 ) uniform 4-component vector of bool bval4, layout(offset=32 ) uniform int ival, layout(offset=48 ) uniform 4-component vector of int ival4, layout(offset=64 ) uniform float fval, layout(offset=80 ) uniform 4-component vector of float fval4}) +0:22 Constant: +0:22 4 (const uint) +0:25 move second child to first child (temp 4-component vector of float) +0:25 Color: direct index for structure (temp 4-component vector of float) +0:25 'psout' (temp structure{temp 4-component vector of float Color}) +0:25 Constant: +0:25 0 (const int) +0:25 Constant: +0:25 0.000000 +0:25 0.000000 +0:25 0.000000 +0:25 0.000000 +0:26 Sequence +0:26 Sequence +0:26 move second child to first child (temp 4-component vector of float) +0:? 'Color' (layout(location=0 ) out 4-component vector of float) +0:26 Color: direct index for structure (temp 4-component vector of float) +0:26 'psout' (temp structure{temp 4-component vector of float Color}) +0:26 Constant: +0:26 0 (const int) +0:26 Branch: Return +0:? Linker Objects +0:? 'Color' (layout(location=0 ) out 4-component vector of float) +0:? 'anon@0' (uniform block{layout(offset=0 ) uniform bool bval, layout(offset=16 ) uniform 4-component vector of bool bval4, layout(offset=32 ) uniform int ival, layout(offset=48 ) uniform 4-component vector of int ival4, layout(offset=64 ) uniform float fval, layout(offset=80 ) uniform 4-component vector of float fval4}) + + +Linked fragment stage: + + +Shader version: 450 +gl_FragCoord origin is upper left +0:? Sequence +0:14 Function Definition: main( (temp structure{temp 4-component vector of float Color}) +0:14 Function Parameters: +0:? Sequence +0:15 mod (temp float) +0:15 Convert int to float (temp float) +0:15 ival: direct index for structure (layout(offset=32 ) uniform int) +0:15 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform bool bval, layout(offset=16 ) uniform 4-component vector of bool bval4, layout(offset=32 ) uniform int ival, layout(offset=48 ) uniform 4-component vector of int ival4, layout(offset=64 ) uniform float fval, layout(offset=80 ) uniform 4-component vector of float fval4}) +0:15 Constant: +0:15 2 (const uint) +0:15 fval: direct index for structure (layout(offset=64 ) uniform float) +0:15 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform bool bval, layout(offset=16 ) uniform 4-component vector of bool bval4, layout(offset=32 ) uniform int ival, layout(offset=48 ) uniform 4-component vector of int ival4, layout(offset=64 ) uniform float fval, layout(offset=80 ) uniform 4-component vector of float fval4}) +0:15 Constant: +0:15 4 (const uint) +0:16 mod (temp 4-component vector of float) +0:16 Convert int to float (temp 4-component vector of float) +0:16 ival4: direct index for structure (layout(offset=48 ) uniform 4-component vector of int) +0:16 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform bool bval, layout(offset=16 ) uniform 4-component vector of bool bval4, layout(offset=32 ) uniform int ival, layout(offset=48 ) uniform 4-component vector of int ival4, layout(offset=64 ) uniform float fval, layout(offset=80 ) uniform 4-component vector of float fval4}) +0:16 Constant: +0:16 3 (const uint) +0:16 fval4: direct index for structure (layout(offset=80 ) uniform 4-component vector of float) +0:16 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform bool bval, layout(offset=16 ) uniform 4-component vector of bool bval4, layout(offset=32 ) uniform int ival, layout(offset=48 ) uniform 4-component vector of int ival4, layout(offset=64 ) uniform float fval, layout(offset=80 ) uniform 4-component vector of float fval4}) +0:16 Constant: +0:16 5 (const uint) +0:18 mod (temp float) +0:18 Convert bool to float (temp float) +0:18 bval: direct index for structure (layout(offset=0 ) uniform bool) +0:18 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform bool bval, layout(offset=16 ) uniform 4-component vector of bool bval4, layout(offset=32 ) uniform int ival, layout(offset=48 ) uniform 4-component vector of int ival4, layout(offset=64 ) uniform float fval, layout(offset=80 ) uniform 4-component vector of float fval4}) +0:18 Constant: +0:18 0 (const uint) +0:18 fval: direct index for structure (layout(offset=64 ) uniform float) +0:18 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform bool bval, layout(offset=16 ) uniform 4-component vector of bool bval4, layout(offset=32 ) uniform int ival, layout(offset=48 ) uniform 4-component vector of int ival4, layout(offset=64 ) uniform float fval, layout(offset=80 ) uniform 4-component vector of float fval4}) +0:18 Constant: +0:18 4 (const uint) +0:19 mod (temp 4-component vector of float) +0:19 Convert bool to float (temp 4-component vector of float) +0:19 bval4: direct index for structure (layout(offset=16 ) uniform 4-component vector of bool) +0:19 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform bool bval, layout(offset=16 ) uniform 4-component vector of bool bval4, layout(offset=32 ) uniform int ival, layout(offset=48 ) uniform 4-component vector of int ival4, layout(offset=64 ) uniform float fval, layout(offset=80 ) uniform 4-component vector of float fval4}) +0:19 Constant: +0:19 1 (const uint) +0:19 fval4: direct index for structure (layout(offset=80 ) uniform 4-component vector of float) +0:19 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform bool bval, layout(offset=16 ) uniform 4-component vector of bool bval4, layout(offset=32 ) uniform int ival, layout(offset=48 ) uniform 4-component vector of int ival4, layout(offset=64 ) uniform float fval, layout(offset=80 ) uniform 4-component vector of float fval4}) +0:19 Constant: +0:19 5 (const uint) +0:21 Sequence +0:21 move second child to first child (temp int) +0:21 'l_int' (temp int) +0:21 Constant: +0:21 1 (const int) +0:22 mod second child into first child (temp int) +0:22 'l_int' (temp int) +0:22 Convert float to int (temp int) +0:22 fval: direct index for structure (layout(offset=64 ) uniform float) +0:22 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform bool bval, layout(offset=16 ) uniform 4-component vector of bool bval4, layout(offset=32 ) uniform int ival, layout(offset=48 ) uniform 4-component vector of int ival4, layout(offset=64 ) uniform float fval, layout(offset=80 ) uniform 4-component vector of float fval4}) +0:22 Constant: +0:22 4 (const uint) +0:25 move second child to first child (temp 4-component vector of float) +0:25 Color: direct index for structure (temp 4-component vector of float) +0:25 'psout' (temp structure{temp 4-component vector of float Color}) +0:25 Constant: +0:25 0 (const int) +0:25 Constant: +0:25 0.000000 +0:25 0.000000 +0:25 0.000000 +0:25 0.000000 +0:26 Sequence +0:26 Sequence +0:26 move second child to first child (temp 4-component vector of float) +0:? 'Color' (layout(location=0 ) out 4-component vector of float) +0:26 Color: direct index for structure (temp 4-component vector of float) +0:26 'psout' (temp structure{temp 4-component vector of float Color}) +0:26 Constant: +0:26 0 (const int) +0:26 Branch: Return +0:? Linker Objects +0:? 'Color' (layout(location=0 ) out 4-component vector of float) +0:? 'anon@0' (uniform block{layout(offset=0 ) uniform bool bval, layout(offset=16 ) uniform 4-component vector of bool bval4, layout(offset=32 ) uniform int ival, layout(offset=48 ) uniform 4-component vector of int ival4, layout(offset=64 ) uniform float fval, layout(offset=80 ) uniform 4-component vector of float fval4}) + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 78 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 4 "main" 74 + ExecutionMode 4 OriginUpperLeft + Name 4 "main" + Name 12 "$Global" + MemberName 12($Global) 0 "bval" + MemberName 12($Global) 1 "bval4" + MemberName 12($Global) 2 "ival" + MemberName 12($Global) 3 "ival4" + MemberName 12($Global) 4 "fval" + MemberName 12($Global) 5 "fval4" + Name 14 "" + Name 62 "l_int" + Name 68 "PS_OUTPUT" + MemberName 68(PS_OUTPUT) 0 "Color" + Name 70 "psout" + Name 74 "Color" + MemberDecorate 12($Global) 0 Offset 0 + MemberDecorate 12($Global) 1 Offset 16 + MemberDecorate 12($Global) 2 Offset 32 + MemberDecorate 12($Global) 3 Offset 48 + MemberDecorate 12($Global) 4 Offset 64 + MemberDecorate 12($Global) 5 Offset 80 + Decorate 12($Global) Block + Decorate 14 DescriptorSet 0 + Decorate 74(Color) Location 0 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeInt 32 0 + 7: TypeVector 6(int) 4 + 8: TypeInt 32 1 + 9: TypeVector 8(int) 4 + 10: TypeFloat 32 + 11: TypeVector 10(float) 4 + 12($Global): TypeStruct 6(int) 7(ivec4) 8(int) 9(ivec4) 10(float) 11(fvec4) + 13: TypePointer Uniform 12($Global) + 14: 13(ptr) Variable Uniform + 15: 8(int) Constant 2 + 16: TypePointer Uniform 8(int) + 20: 8(int) Constant 4 + 21: TypePointer Uniform 10(float) + 25: 8(int) Constant 3 + 26: TypePointer Uniform 9(ivec4) + 30: 8(int) Constant 5 + 31: TypePointer Uniform 11(fvec4) + 35: 8(int) Constant 0 + 36: TypePointer Uniform 6(int) + 39: TypeBool + 40: 6(int) Constant 0 + 42: 10(float) Constant 0 + 43: 10(float) Constant 1065353216 + 48: 8(int) Constant 1 + 49: TypePointer Uniform 7(ivec4) + 52: TypeVector 39(bool) 4 + 53: 7(ivec4) ConstantComposite 40 40 40 40 + 55: 11(fvec4) ConstantComposite 42 42 42 42 + 56: 11(fvec4) ConstantComposite 43 43 43 43 + 61: TypePointer Function 8(int) + 68(PS_OUTPUT): TypeStruct 11(fvec4) + 69: TypePointer Function 68(PS_OUTPUT) + 71: TypePointer Function 11(fvec4) + 73: TypePointer Output 11(fvec4) + 74(Color): 73(ptr) Variable Output + 4(main): 2 Function None 3 + 5: Label + 62(l_int): 61(ptr) Variable Function + 70(psout): 69(ptr) Variable Function + 17: 16(ptr) AccessChain 14 15 + 18: 8(int) Load 17 + 19: 10(float) ConvertSToF 18 + 22: 21(ptr) AccessChain 14 20 + 23: 10(float) Load 22 + 24: 10(float) FMod 19 23 + 27: 26(ptr) AccessChain 14 25 + 28: 9(ivec4) Load 27 + 29: 11(fvec4) ConvertSToF 28 + 32: 31(ptr) AccessChain 14 30 + 33: 11(fvec4) Load 32 + 34: 11(fvec4) FMod 29 33 + 37: 36(ptr) AccessChain 14 35 + 38: 6(int) Load 37 + 41: 39(bool) INotEqual 38 40 + 44: 10(float) Select 41 43 42 + 45: 21(ptr) AccessChain 14 20 + 46: 10(float) Load 45 + 47: 10(float) FMod 44 46 + 50: 49(ptr) AccessChain 14 48 + 51: 7(ivec4) Load 50 + 54: 52(bvec4) INotEqual 51 53 + 57: 11(fvec4) Select 54 56 55 + 58: 31(ptr) AccessChain 14 30 + 59: 11(fvec4) Load 58 + 60: 11(fvec4) FMod 57 59 + Store 62(l_int) 48 + 63: 21(ptr) AccessChain 14 20 + 64: 10(float) Load 63 + 65: 8(int) ConvertFToS 64 + 66: 8(int) Load 62(l_int) + 67: 8(int) SMod 66 65 + Store 62(l_int) 67 + 72: 71(ptr) AccessChain 70(psout) 35 + Store 72 55 + 75: 71(ptr) AccessChain 70(psout) 35 + 76: 11(fvec4) Load 75 + Store 74(Color) 76 + Return + FunctionEnd diff --git a/Test/hlsl.logical.binary.frag b/Test/hlsl.logical.binary.frag new file mode 100644 index 00000000..06bc9f2f --- /dev/null +++ b/Test/hlsl.logical.binary.frag @@ -0,0 +1,21 @@ +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +uniform int ival; +uniform int4 ival4; +uniform float fval; +uniform float4 fval4; + +PS_OUTPUT main() +{ + if (ival && fval); + if (ival || fval); + + PS_OUTPUT psout; + psout.Color = 1.0; + return psout; +} + + diff --git a/Test/hlsl.logical.unary.frag b/Test/hlsl.logical.unary.frag new file mode 100644 index 00000000..cbcb3bfc --- /dev/null +++ b/Test/hlsl.logical.unary.frag @@ -0,0 +1,29 @@ +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +uniform int ival; +uniform int4 ival4; +uniform float fval; +uniform float4 fval4; + +PS_OUTPUT main() +{ + !ival; // scalar int + !ival4; // vector int + + !fval; // scalar float + !fval4; // vector float + + if (ival); + if (fval); + if (!ival); + if (!fval); + + PS_OUTPUT psout; + psout.Color = 1.0; + return psout; +} + + diff --git a/Test/hlsl.promote.binary.frag b/Test/hlsl.promote.binary.frag new file mode 100644 index 00000000..0203bed9 --- /dev/null +++ b/Test/hlsl.promote.binary.frag @@ -0,0 +1,28 @@ +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +uniform bool bval; +uniform bool4 bval4; +uniform int ival; +uniform int4 ival4; +uniform float fval; +uniform float4 fval4; + +PS_OUTPUT main() +{ + ival % fval; + ival4 % fval4; + + bval % fval; + bval4 % fval4; + + int l_int = 1; + l_int %= fval; + + PS_OUTPUT psout; + psout.Color = 0; + return psout; +} + diff --git a/glslang/Include/intermediate.h b/glslang/Include/intermediate.h index 27c798d1..fc267543 100644 --- a/glslang/Include/intermediate.h +++ b/glslang/Include/intermediate.h @@ -52,6 +52,8 @@ namespace glslang { +class TIntermediate; + // // Operators used by the high-level (parse tree) representation. // @@ -845,7 +847,7 @@ public: virtual TIntermOperator* getAsOperator() { return this; } virtual const TIntermOperator* getAsOperator() const { return this; } TOperator getOp() const { return op; } - virtual bool promote() { return true; } + virtual bool promote(TIntermediate&) { return true; } bool modifiesState() const; bool isConstructor() const; bool isTexture() const { return op > EOpTextureGuardBegin && op < EOpTextureGuardEnd; } @@ -1024,7 +1026,7 @@ public: virtual TIntermTyped* getRight() const { return right; } virtual TIntermBinary* getAsBinaryNode() { return this; } virtual const TIntermBinary* getAsBinaryNode() const { return this; } - virtual bool promote(); + virtual bool promote(TIntermediate&); virtual void updatePrecision(); protected: TIntermTyped* left; @@ -1044,7 +1046,7 @@ public: virtual const TIntermTyped* getOperand() const { return operand; } virtual TIntermUnary* getAsUnaryNode() { return this; } virtual const TIntermUnary* getAsUnaryNode() const { return this; } - virtual bool promote(); + virtual bool promote(TIntermediate&); virtual void updatePrecision(); protected: TIntermTyped* operand; diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp index 8e80bbd2..1441c55b 100644 --- a/glslang/MachineIndependent/Intermediate.cpp +++ b/glslang/MachineIndependent/Intermediate.cpp @@ -137,7 +137,7 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn // one and promote it to the right type. // TIntermBinary* node = addBinaryNode(op, left, right, loc); - if (! node->promote()) + if (! node->promote(*this)) return 0; node->updatePrecision(); @@ -246,7 +246,7 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm // build the node TIntermBinary* node = addBinaryNode(op, left, right, loc); - if (! node->promote()) + if (! node->promote(*this)) return nullptr; node->updatePrecision(); @@ -282,6 +282,10 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSo switch (op) { case EOpLogicalNot: + if (source == EShSourceHlsl) { + break; // HLSL can promote logical not + } + if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) { return 0; } @@ -349,7 +353,7 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSo // TIntermUnary* node = addUnaryNode(op, child, loc); - if (! node->promote()) + if (! node->promote(*this)) return 0; node->updatePrecision(); @@ -555,6 +559,10 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt case EOpAndAssign: case EOpInclusiveOrAssign: case EOpExclusiveOrAssign: + case EOpLogicalNot: + case EOpLogicalAnd: + case EOpLogicalOr: + case EOpLogicalXor: case EOpFunctionCall: case EOpReturn: @@ -841,6 +849,10 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat case EOpModAssign: // ... case EOpReturn: // function returns can also perform arbitrary conversions case EOpFunctionCall: // conversion of a calling parameter + case EOpLogicalNot: + case EOpLogicalAnd: + case EOpLogicalOr: + case EOpLogicalXor: return true; default: break; @@ -873,6 +885,8 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat case EbtFloat16: #endif return true; + case EbtBool: + return (source == EShSourceHlsl); default: return false; } @@ -1716,13 +1730,20 @@ bool TIntermOperator::isConstructor() const // // Returns false in nothing makes sense. // -bool TIntermUnary::promote() +bool TIntermUnary::promote(TIntermediate& intermediate) { switch (op) { case EOpLogicalNot: - if (operand->getBasicType() != EbtBool) + // Convert operand to a boolean type + if (operand->getBasicType() != EbtBool) { + // Add constructor to boolean type. If that fails, we can't do it, so return false. + TIntermTyped* converted = intermediate.convertToBasicType(op, EbtBool, operand); + if (converted == nullptr) + return false; - return false; + // Use the result of converting the node to a bool. + operand = converted; + } break; case EOpBitwiseNot: if (operand->getBasicType() != EbtInt && @@ -1774,13 +1795,31 @@ void TIntermUnary::updatePrecision() } } +// If it is not already, convert this node to the given basic type. +TIntermTyped* TIntermediate::convertToBasicType(TOperator op, TBasicType basicType, TIntermTyped* node) const +{ + if (node == nullptr) + return nullptr; + + // It's already this basic type: nothing needs to be done, so use the node directly. + if (node->getBasicType() == basicType) + return node; + + const TType& type = node->getType(); + const TType newType(basicType, type.getQualifier().storage, + type.getVectorSize(), type.getMatrixCols(), type.getMatrixRows(), type.isVector()); + + // Add constructor to the right vectorness of the right type. If that fails, we can't do it, so return nullptr. + return addConversion(op, newType, node); +} + // // Establishes the type of the resultant operation, as well as // makes the operator the correct one for the operands. // // Returns false if operator can't work on operands. // -bool TIntermBinary::promote() +bool TIntermBinary::promote(TIntermediate& intermediate) { // Arrays and structures have to be exact matches. if ((left->isArray() || right->isArray() || left->getBasicType() == EbtStruct || right->getBasicType() == EbtStruct) @@ -1843,6 +1882,15 @@ bool TIntermBinary::promote() case EOpLogicalAnd: case EOpLogicalOr: case EOpLogicalXor: + if (intermediate.getSource() == EShSourceHlsl) { + TIntermTyped* convertedL = intermediate.convertToBasicType(op, EbtBool, left); + TIntermTyped* convertedR = intermediate.convertToBasicType(op, EbtBool, right); + if (convertedL == nullptr || convertedR == nullptr) + return false; + left = convertedL; + right = convertedR; + } + // logical ops operate only on scalar Booleans and will promote to scalar Boolean. if (left->getBasicType() != EbtBool || left->isVector() || left->isMatrix()) return false; @@ -1864,6 +1912,9 @@ bool TIntermBinary::promote() case EOpAndAssign: case EOpInclusiveOrAssign: case EOpExclusiveOrAssign: + if (intermediate.getSource() == EShSourceHlsl) + break; + // Check for integer-only operands. if ((left->getBasicType() != EbtInt && left->getBasicType() != EbtUint && left->getBasicType() != EbtInt64 && left->getBasicType() != EbtUint64) || @@ -2051,6 +2102,7 @@ bool TIntermBinary::promote() case EOpAndAssign: case EOpInclusiveOrAssign: case EOpExclusiveOrAssign: + if ((left->isMatrix() && right->isVector()) || (left->isVector() && right->isMatrix()) || left->getBasicType() != right->getBasicType()) diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index aae22ecc..c8742cb4 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -246,6 +246,9 @@ public: TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc) const; TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc, const TType&) const; + // Add conversion from node's type to given basic type. + TIntermTyped* convertToBasicType(TOperator op, TBasicType basicType, TIntermTyped* node) const; + // Constant folding (in Constant.cpp) TIntermTyped* fold(TIntermAggregate* aggrNode); TIntermTyped* foldConstructor(TIntermAggregate* aggrNode); @@ -390,7 +393,7 @@ protected: bool userOutputUsed() const; static int getBaseAlignmentScalar(const TType&, int& size); bool isSpecializationOperation(const TIntermOperator&) const; - + const EShLanguage language; // stage, known at construction time EShSource source; // source language, known a bit later std::string entryPointName; diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp index b50816a1..9c1a3eed 100644 --- a/gtests/Hlsl.FromFile.cpp +++ b/gtests/Hlsl.FromFile.cpp @@ -142,6 +142,8 @@ INSTANTIATE_TEST_CASE_P( {"hlsl.load.rwtexture.array.dx10.frag", "main"}, {"hlsl.load.offset.dx10.frag", "main"}, {"hlsl.load.offsetarray.dx10.frag", "main"}, + {"hlsl.logical.unary.frag", "main"}, + {"hlsl.logical.binary.frag", "main"}, {"hlsl.multiEntry.vert", "RealEntrypoint"}, {"hlsl.multiReturn.frag", "main"}, {"hlsl.matrixindex.frag", "main"}, @@ -149,6 +151,7 @@ INSTANTIATE_TEST_CASE_P( {"hlsl.overload.frag", "PixelShaderFunction"}, {"hlsl.pp.line.frag", "main"}, {"hlsl.precise.frag", "main"}, + {"hlsl.promote.binary.frag", "main"}, {"hlsl.promotions.frag", "main"}, {"hlsl.rw.bracket.frag", "main"}, {"hlsl.rw.scalar.bracket.frag", "main"}, @@ -179,7 +182,7 @@ INSTANTIATE_TEST_CASE_P( {"hlsl.samplelevel.basic.dx10.vert", "main"}, {"hlsl.samplelevel.offset.dx10.frag", "main"}, {"hlsl.samplelevel.offsetarray.dx10.frag", "main"}, - { "hlsl.sample.sub-vec4.dx10.frag", "main"}, + {"hlsl.sample.sub-vec4.dx10.frag", "main"}, {"hlsl.semicolons.frag", "main"}, {"hlsl.shapeConv.frag", "main"}, {"hlsl.shapeConvRet.frag", "main"}, diff --git a/hlsl/hlslGrammar.cpp b/hlsl/hlslGrammar.cpp index 7766f857..89465bff 100755 --- a/hlsl/hlslGrammar.cpp +++ b/hlsl/hlslGrammar.cpp @@ -1935,7 +1935,10 @@ bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node) return true; node = intermediate.addUnaryMath(unaryOp, node, loc); - node = parseContext.handleLvalue(loc, "unary operator", node); + + // These unary ops require lvalues + if (unaryOp == EOpPreIncrement || unaryOp == EOpPreDecrement) + node = parseContext.handleLvalue(loc, "unary operator", node); return node != nullptr; } diff --git a/hlsl/hlslParseables.cpp b/hlsl/hlslParseables.cpp index d33cfb89..7ab159dc 100755 --- a/hlsl/hlslParseables.cpp +++ b/hlsl/hlslParseables.cpp @@ -245,7 +245,6 @@ glslang::TString& AppendTypeName(glslang::TString& s, const char* argOrder, cons char order = *argOrder; if (UseHlslTypes) { - // TODO: handle sub-vec4 returns switch (type) { case '-': s += "void"; break; case 'F': s += "float"; break; @@ -832,8 +831,6 @@ void TBuiltInParseablesHlsl::initialize(int /*version*/, EProfile /*profile*/, c { "GatherCmpAlpha", /* O-4 */ "V4", nullptr, "%@,S,V,S,V,,,", "FIU,s,F,,I,,,", EShLangAll }, { "GatherCmpAlpha", /* O-4, status */"V4", nullptr, "%@,S,V,S,V,,,,S","FIU,s,F,,I,,,,U",EShLangAll }, - // TODO: Cmp forms - // Mark end of list, since we want to avoid a range-based for, as some compilers don't handle it yet. { nullptr, nullptr, nullptr, nullptr, nullptr, 0 }, }; From 6cb1637f37d3907dc9e7eacb71065e3bacabff55 Mon Sep 17 00:00:00 2001 From: steve-lunarg Date: Wed, 19 Oct 2016 12:57:22 -0600 Subject: [PATCH 2/2] Move promote methods to TIntermediate class A need arose to use capabilities from TIntermediate during node promotion. These methods have been moved from virtual methods on the TIntermUnary and TIntermBinary nodes to methods on TIntermediate, so it is easy for them construct new nodes and so on. This is done as a separate commit to verify that no test results are changed as a result. --- glslang/Include/intermediate.h | 4 +- glslang/MachineIndependent/Intermediate.cpp | 118 +++++++++++------- .../MachineIndependent/localintermediate.h | 3 + 3 files changed, 74 insertions(+), 51 deletions(-) diff --git a/glslang/Include/intermediate.h b/glslang/Include/intermediate.h index fc267543..f5a5a7b4 100644 --- a/glslang/Include/intermediate.h +++ b/glslang/Include/intermediate.h @@ -847,7 +847,7 @@ public: virtual TIntermOperator* getAsOperator() { return this; } virtual const TIntermOperator* getAsOperator() const { return this; } TOperator getOp() const { return op; } - virtual bool promote(TIntermediate&) { return true; } + void setOp(TOperator newOp) { op = newOp; } bool modifiesState() const; bool isConstructor() const; bool isTexture() const { return op > EOpTextureGuardBegin && op < EOpTextureGuardEnd; } @@ -1026,7 +1026,6 @@ public: virtual TIntermTyped* getRight() const { return right; } virtual TIntermBinary* getAsBinaryNode() { return this; } virtual const TIntermBinary* getAsBinaryNode() const { return this; } - virtual bool promote(TIntermediate&); virtual void updatePrecision(); protected: TIntermTyped* left; @@ -1046,7 +1045,6 @@ public: virtual const TIntermTyped* getOperand() const { return operand; } virtual TIntermUnary* getAsUnaryNode() { return this; } virtual const TIntermUnary* getAsUnaryNode() const { return this; } - virtual bool promote(TIntermediate&); virtual void updatePrecision(); protected: TIntermTyped* operand; diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp index 1441c55b..758ae4f2 100644 --- a/glslang/MachineIndependent/Intermediate.cpp +++ b/glslang/MachineIndependent/Intermediate.cpp @@ -137,8 +137,8 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn // one and promote it to the right type. // TIntermBinary* node = addBinaryNode(op, left, right, loc); - if (! node->promote(*this)) - return 0; + if (! promote(node)) + return nullptr; node->updatePrecision(); @@ -246,7 +246,7 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm // build the node TIntermBinary* node = addBinaryNode(op, left, right, loc); - if (! node->promote(*this)) + if (! promote(node)) return nullptr; node->updatePrecision(); @@ -353,8 +353,8 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSo // TIntermUnary* node = addUnaryNode(op, child, loc); - if (! node->promote(*this)) - return 0; + if (! promote(node)) + return nullptr; node->updatePrecision(); @@ -1725,24 +1725,45 @@ bool TIntermOperator::isConstructor() const } // -// Make sure the type of a unary operator is appropriate for its -// combination of operation and operand type. +// Make sure the type of an operator is appropriate for its +// combination of operation and operand type. This will invoke +// promoteUnary, promoteBinary, etc as needed. // -// Returns false in nothing makes sense. +// Returns false if nothing makes sense. // -bool TIntermUnary::promote(TIntermediate& intermediate) +bool TIntermediate::promote(TIntermOperator* node) { + if (node == nullptr) + return false; + + if (node->getAsUnaryNode()) + return promoteUnary(*node->getAsUnaryNode()); + + if (node->getAsBinaryNode()) + return promoteBinary(*node->getAsBinaryNode()); + + return false; +} + +// +// See TIntermediate::promote +// +bool TIntermediate::promoteUnary(TIntermUnary& node) +{ + const TOperator op = node.getOp(); + TIntermTyped* operand = node.getOperand(); + switch (op) { case EOpLogicalNot: // Convert operand to a boolean type if (operand->getBasicType() != EbtBool) { // Add constructor to boolean type. If that fails, we can't do it, so return false. - TIntermTyped* converted = intermediate.convertToBasicType(op, EbtBool, operand); + TIntermTyped* converted = convertToBasicType(op, EbtBool, operand); if (converted == nullptr) return false; // Use the result of converting the node to a bool. - operand = converted; + node.setOperand(operand = converted); // also updates stack variable } break; case EOpBitwiseNot: @@ -1777,8 +1798,8 @@ bool TIntermUnary::promote(TIntermediate& intermediate) return false; } - setType(operand->getType()); - getWritableType().getQualifier().makeTemporary(); + node.setType(operand->getType()); + node.getWritableType().getQualifier().makeTemporary(); return true; } @@ -1814,13 +1835,14 @@ TIntermTyped* TIntermediate::convertToBasicType(TOperator op, TBasicType basicTy } // -// Establishes the type of the resultant operation, as well as -// makes the operator the correct one for the operands. +// See TIntermediate::promote // -// Returns false if operator can't work on operands. -// -bool TIntermBinary::promote(TIntermediate& intermediate) +bool TIntermediate::promoteBinary(TIntermBinary& node) { + TOperator op = node.getOp(); + TIntermTyped* left = node.getLeft(); + TIntermTyped* right = node.getRight(); + // Arrays and structures have to be exact matches. if ((left->isArray() || right->isArray() || left->getBasicType() == EbtStruct || right->getBasicType() == EbtStruct) && left->getType() != right->getType()) @@ -1828,8 +1850,8 @@ bool TIntermBinary::promote(TIntermediate& intermediate) // Base assumption: just make the type the same as the left // operand. Only deviations from this will be coded. - setType(left->getType()); - type.getQualifier().clear(); + node.setType(left->getType()); + node.getWritableType().getQualifier().clear(); // Composite and opaque types don't having pending operator changes, e.g., // array, structure, and samplers. Just establish final type and correctness. @@ -1842,7 +1864,7 @@ bool TIntermBinary::promote(TIntermediate& intermediate) return false; } else { // Promote to conditional - setType(TType(EbtBool)); + node.setType(TType(EbtBool)); } return true; @@ -1870,32 +1892,32 @@ bool TIntermBinary::promote(TIntermediate& intermediate) // Relational comparisons need numeric types and will promote to scalar Boolean. if (left->getBasicType() == EbtBool) return false; - setType(TType(EbtBool)); + node.setType(TType(EbtBool)); break; case EOpEqual: case EOpNotEqual: // All the above comparisons result in a bool (but not the vector compares) - setType(TType(EbtBool)); + node.setType(TType(EbtBool)); break; case EOpLogicalAnd: case EOpLogicalOr: case EOpLogicalXor: - if (intermediate.getSource() == EShSourceHlsl) { - TIntermTyped* convertedL = intermediate.convertToBasicType(op, EbtBool, left); - TIntermTyped* convertedR = intermediate.convertToBasicType(op, EbtBool, right); + if (getSource() == EShSourceHlsl) { + TIntermTyped* convertedL = convertToBasicType(op, EbtBool, left); + TIntermTyped* convertedR = convertToBasicType(op, EbtBool, right); if (convertedL == nullptr || convertedR == nullptr) return false; - left = convertedL; - right = convertedR; + node.setLeft(left = convertedL); // also updates stack variable + node.setRight(right = convertedR); // also updates stack variable } // logical ops operate only on scalar Booleans and will promote to scalar Boolean. if (left->getBasicType() != EbtBool || left->isVector() || left->isMatrix()) return false; - setType(TType(EbtBool)); + node.setType(TType(EbtBool)); break; case EOpRightShift: @@ -1912,7 +1934,7 @@ bool TIntermBinary::promote(TIntermediate& intermediate) case EOpAndAssign: case EOpInclusiveOrAssign: case EOpExclusiveOrAssign: - if (intermediate.getSource() == EShSourceHlsl) + if (getSource() == EShSourceHlsl) break; // Check for integer-only operands. @@ -2011,33 +2033,33 @@ bool TIntermBinary::promote(TIntermediate& intermediate) if (left->isVector()) { if (left->getVectorSize() != right->getMatrixRows()) return false; - op = EOpVectorTimesMatrix; - setType(TType(basicType, EvqTemporary, right->getMatrixCols())); + node.setOp(op = EOpVectorTimesMatrix); + node.setType(TType(basicType, EvqTemporary, right->getMatrixCols())); } else { - op = EOpMatrixTimesScalar; - setType(TType(basicType, EvqTemporary, 0, right->getMatrixCols(), right->getMatrixRows())); + node.setOp(op = EOpMatrixTimesScalar); + node.setType(TType(basicType, EvqTemporary, 0, right->getMatrixCols(), right->getMatrixRows())); } } else if (left->isMatrix() && !right->isMatrix()) { if (right->isVector()) { if (left->getMatrixCols() != right->getVectorSize()) return false; - op = EOpMatrixTimesVector; - setType(TType(basicType, EvqTemporary, left->getMatrixRows())); + node.setOp(op = EOpMatrixTimesVector); + node.setType(TType(basicType, EvqTemporary, left->getMatrixRows())); } else { - op = EOpMatrixTimesScalar; + node.setOp(op = EOpMatrixTimesScalar); } } else if (left->isMatrix() && right->isMatrix()) { if (left->getMatrixCols() != right->getMatrixRows()) return false; - op = EOpMatrixTimesMatrix; - setType(TType(basicType, EvqTemporary, 0, right->getMatrixCols(), left->getMatrixRows())); + node.setOp(op = EOpMatrixTimesMatrix); + node.setType(TType(basicType, EvqTemporary, 0, right->getMatrixCols(), left->getMatrixRows())); } else if (! left->isMatrix() && ! right->isMatrix()) { if (left->isVector() && right->isVector()) { ; // leave as component product } else if (left->isVector() || right->isVector()) { - op = EOpVectorTimesScalar; + node.setOp(op = EOpVectorTimesScalar); if (right->isVector()) - setType(TType(basicType, EvqTemporary, right->getVectorSize())); + node.setType(TType(basicType, EvqTemporary, right->getVectorSize())); } } else { return false; @@ -2048,7 +2070,7 @@ bool TIntermBinary::promote(TIntermediate& intermediate) if (left->isVector()) { if (left->getVectorSize() != right->getMatrixRows() || left->getVectorSize() != right->getMatrixCols()) return false; - op = EOpVectorTimesMatrixAssign; + node.setOp(op = EOpVectorTimesMatrixAssign); } else { return false; } @@ -2056,19 +2078,19 @@ bool TIntermBinary::promote(TIntermediate& intermediate) if (right->isVector()) { return false; } else { - op = EOpMatrixTimesScalarAssign; + node.setOp(op = EOpMatrixTimesScalarAssign); } } else if (left->isMatrix() && right->isMatrix()) { if (left->getMatrixCols() != left->getMatrixRows() || left->getMatrixCols() != right->getMatrixCols() || left->getMatrixCols() != right->getMatrixRows()) return false; - op = EOpMatrixTimesMatrixAssign; + node.setOp(op = EOpMatrixTimesMatrixAssign); } else if (!left->isMatrix() && !right->isMatrix()) { if (left->isVector() && right->isVector()) { // leave as component product } else if (left->isVector() || right->isVector()) { if (! left->isVector()) return false; - op = EOpVectorTimesScalarAssign; + node.setOp(op = EOpVectorTimesScalarAssign); } } else { return false; @@ -2112,8 +2134,8 @@ bool TIntermBinary::promote(TIntermediate& intermediate) if (left->isVector() && right->isVector() && left->getVectorSize() != right->getVectorSize()) return false; if (right->isVector() || right->isMatrix()) { - type.shallowCopy(right->getType()); - type.getQualifier().makeTemporary(); + node.getWritableType().shallowCopy(right->getType()); + node.getWritableType().getQualifier().makeTemporary(); } break; @@ -2137,7 +2159,7 @@ bool TIntermBinary::promote(TIntermediate& intermediate) case EOpExclusiveOrAssign: case EOpLeftShiftAssign: case EOpRightShiftAssign: - if (getType() != left->getType()) + if (node.getType() != left->getType()) return false; break; default: diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index c8742cb4..1dd14403 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -393,6 +393,9 @@ protected: bool userOutputUsed() const; static int getBaseAlignmentScalar(const TType&, int& size); bool isSpecializationOperation(const TIntermOperator&) const; + bool promote(TIntermOperator*); + bool promoteUnary(TIntermUnary&); + bool promoteBinary(TIntermBinary&); const EShLanguage language; // stage, known at construction time EShSource source; // source language, known a bit later