Merge pull request #1381 from LoopDawg/coverage_array
HLSL: require coverage mask to be arrayed output.
diff --git a/Test/baseResults/hlsl.coverage.frag.out b/Test/baseResults/hlsl.coverage.frag.out
new file mode 100644
index 0000000..8fc6abf
--- /dev/null
+++ b/Test/baseResults/hlsl.coverage.frag.out
@@ -0,0 +1,204 @@
+hlsl.coverage.frag
+Shader version: 500
+gl_FragCoord origin is upper left
+0:? Sequence
+0:15 Function Definition: @main(struct-PS_INPUT1; ( temp structure{ temp 4-component vector of float vColor, temp uint nCoverageMask})
+0:15 Function Parameters:
+0:15 'i' ( in structure{})
+0:? Sequence
+0:17 move second child to first child ( temp 4-component vector of float)
+0:17 vColor: direct index for structure ( temp 4-component vector of float)
+0:17 'o' ( temp structure{ temp 4-component vector of float vColor, temp uint nCoverageMask})
+0:17 Constant:
+0:17 0 (const int)
+0:? Constant:
+0:? 1.000000
+0:? 0.000000
+0:? 0.000000
+0:? 1.000000
+0:18 move second child to first child ( temp uint)
+0:18 nCoverageMask: direct index for structure ( temp uint)
+0:18 'o' ( temp structure{ temp 4-component vector of float vColor, temp uint nCoverageMask})
+0:18 Constant:
+0:18 1 (const int)
+0:18 Constant:
+0:18 0 (const uint)
+0:19 Branch: Return with expression
+0:19 'o' ( temp structure{ temp 4-component vector of float vColor, temp uint nCoverageMask})
+0:15 Function Definition: main( ( temp void)
+0:15 Function Parameters:
+0:? Sequence
+0:15 Sequence
+0:15 move second child to first child ( temp structure{})
+0:? 'i' ( temp structure{})
+0:? 'i' ( in structure{})
+0:15 Sequence
+0:15 move second child to first child ( temp structure{ temp 4-component vector of float vColor, temp uint nCoverageMask})
+0:15 'flattenTemp' ( temp structure{ temp 4-component vector of float vColor, temp uint nCoverageMask})
+0:15 Function Call: @main(struct-PS_INPUT1; ( temp structure{ temp 4-component vector of float vColor, temp uint nCoverageMask})
+0:? 'i' ( temp structure{})
+0:15 move second child to first child ( temp 4-component vector of float)
+0:? '@entryPointOutput.vColor' (layout( location=0) out 4-component vector of float)
+0:15 vColor: direct index for structure ( temp 4-component vector of float)
+0:15 'flattenTemp' ( temp structure{ temp 4-component vector of float vColor, temp uint nCoverageMask})
+0:15 Constant:
+0:15 0 (const int)
+0:15 move second child to first child ( temp uint)
+0:15 direct index ( out uint SampleMaskIn)
+0:? '@entryPointOutput.nCoverageMask' ( out 1-element array of uint SampleMaskIn)
+0:15 Constant:
+0:15 0 (const int)
+0:15 nCoverageMask: direct index for structure ( temp uint)
+0:15 'flattenTemp' ( temp structure{ temp 4-component vector of float vColor, temp uint nCoverageMask})
+0:15 Constant:
+0:15 1 (const int)
+0:? Linker Objects
+0:? '@entryPointOutput.nCoverageMask' ( out 1-element array of uint SampleMaskIn)
+0:? '@entryPointOutput.vColor' (layout( location=0) out 4-component vector of float)
+
+
+Linked fragment stage:
+
+
+Shader version: 500
+gl_FragCoord origin is upper left
+0:? Sequence
+0:15 Function Definition: @main(struct-PS_INPUT1; ( temp structure{ temp 4-component vector of float vColor, temp uint nCoverageMask})
+0:15 Function Parameters:
+0:15 'i' ( in structure{})
+0:? Sequence
+0:17 move second child to first child ( temp 4-component vector of float)
+0:17 vColor: direct index for structure ( temp 4-component vector of float)
+0:17 'o' ( temp structure{ temp 4-component vector of float vColor, temp uint nCoverageMask})
+0:17 Constant:
+0:17 0 (const int)
+0:? Constant:
+0:? 1.000000
+0:? 0.000000
+0:? 0.000000
+0:? 1.000000
+0:18 move second child to first child ( temp uint)
+0:18 nCoverageMask: direct index for structure ( temp uint)
+0:18 'o' ( temp structure{ temp 4-component vector of float vColor, temp uint nCoverageMask})
+0:18 Constant:
+0:18 1 (const int)
+0:18 Constant:
+0:18 0 (const uint)
+0:19 Branch: Return with expression
+0:19 'o' ( temp structure{ temp 4-component vector of float vColor, temp uint nCoverageMask})
+0:15 Function Definition: main( ( temp void)
+0:15 Function Parameters:
+0:? Sequence
+0:15 Sequence
+0:15 move second child to first child ( temp structure{})
+0:? 'i' ( temp structure{})
+0:? 'i' ( in structure{})
+0:15 Sequence
+0:15 move second child to first child ( temp structure{ temp 4-component vector of float vColor, temp uint nCoverageMask})
+0:15 'flattenTemp' ( temp structure{ temp 4-component vector of float vColor, temp uint nCoverageMask})
+0:15 Function Call: @main(struct-PS_INPUT1; ( temp structure{ temp 4-component vector of float vColor, temp uint nCoverageMask})
+0:? 'i' ( temp structure{})
+0:15 move second child to first child ( temp 4-component vector of float)
+0:? '@entryPointOutput.vColor' (layout( location=0) out 4-component vector of float)
+0:15 vColor: direct index for structure ( temp 4-component vector of float)
+0:15 'flattenTemp' ( temp structure{ temp 4-component vector of float vColor, temp uint nCoverageMask})
+0:15 Constant:
+0:15 0 (const int)
+0:15 move second child to first child ( temp uint)
+0:15 direct index ( out uint SampleMaskIn)
+0:? '@entryPointOutput.nCoverageMask' ( out 1-element array of uint SampleMaskIn)
+0:15 Constant:
+0:15 0 (const int)
+0:15 nCoverageMask: direct index for structure ( temp uint)
+0:15 'flattenTemp' ( temp structure{ temp 4-component vector of float vColor, temp uint nCoverageMask})
+0:15 Constant:
+0:15 1 (const int)
+0:? Linker Objects
+0:? '@entryPointOutput.nCoverageMask' ( out 1-element array of uint SampleMaskIn)
+0:? '@entryPointOutput.vColor' (layout( location=0) out 4-component vector of float)
+
+// Module Version 10000
+// Generated by (magic number): 80006
+// Id's are bound by 52
+
+ Capability Shader
+ 1: ExtInstImport "GLSL.std.450"
+ MemoryModel Logical GLSL450
+ EntryPoint Fragment 4 "main" 41 47
+ ExecutionMode 4 OriginUpperLeft
+ Source HLSL 500
+ Name 4 "main"
+ Name 6 "PS_INPUT"
+ Name 11 "PS_OUTPUT"
+ MemberName 11(PS_OUTPUT) 0 "vColor"
+ MemberName 11(PS_OUTPUT) 1 "nCoverageMask"
+ Name 14 "@main(struct-PS_INPUT1;"
+ Name 13 "i"
+ Name 17 "o"
+ Name 32 "i"
+ Name 34 "i"
+ Name 36 "flattenTemp"
+ Name 37 "param"
+ Name 41 "@entryPointOutput.vColor"
+ Name 47 "@entryPointOutput.nCoverageMask"
+ Decorate 41(@entryPointOutput.vColor) Location 0
+ Decorate 47(@entryPointOutput.nCoverageMask) BuiltIn SampleMask
+ 2: TypeVoid
+ 3: TypeFunction 2
+ 6(PS_INPUT): TypeStruct
+ 7: TypePointer Function 6(PS_INPUT)
+ 8: TypeFloat 32
+ 9: TypeVector 8(float) 4
+ 10: TypeInt 32 0
+ 11(PS_OUTPUT): TypeStruct 9(fvec4) 10(int)
+ 12: TypeFunction 11(PS_OUTPUT) 7(ptr)
+ 16: TypePointer Function 11(PS_OUTPUT)
+ 18: TypeInt 32 1
+ 19: 18(int) Constant 0
+ 20: 8(float) Constant 1065353216
+ 21: 8(float) Constant 0
+ 22: 9(fvec4) ConstantComposite 20 21 21 20
+ 23: TypePointer Function 9(fvec4)
+ 25: 18(int) Constant 1
+ 26: 10(int) Constant 0
+ 27: TypePointer Function 10(int)
+ 33: TypePointer Input 6(PS_INPUT)
+ 34(i): 33(ptr) Variable Input
+ 40: TypePointer Output 9(fvec4)
+41(@entryPointOutput.vColor): 40(ptr) Variable Output
+ 44: 10(int) Constant 1
+ 45: TypeArray 10(int) 44
+ 46: TypePointer Output 45
+47(@entryPointOutput.nCoverageMask): 46(ptr) Variable Output
+ 50: TypePointer Output 10(int)
+ 4(main): 2 Function None 3
+ 5: Label
+ 32(i): 7(ptr) Variable Function
+ 36(flattenTemp): 16(ptr) Variable Function
+ 37(param): 7(ptr) Variable Function
+ 35: 6(PS_INPUT) Load 34(i)
+ Store 32(i) 35
+ 38: 6(PS_INPUT) Load 32(i)
+ Store 37(param) 38
+ 39:11(PS_OUTPUT) FunctionCall 14(@main(struct-PS_INPUT1;) 37(param)
+ Store 36(flattenTemp) 39
+ 42: 23(ptr) AccessChain 36(flattenTemp) 19
+ 43: 9(fvec4) Load 42
+ Store 41(@entryPointOutput.vColor) 43
+ 48: 27(ptr) AccessChain 36(flattenTemp) 25
+ 49: 10(int) Load 48
+ 51: 50(ptr) AccessChain 47(@entryPointOutput.nCoverageMask) 19
+ Store 51 49
+ Return
+ FunctionEnd
+14(@main(struct-PS_INPUT1;):11(PS_OUTPUT) Function None 12
+ 13(i): 7(ptr) FunctionParameter
+ 15: Label
+ 17(o): 16(ptr) Variable Function
+ 24: 23(ptr) AccessChain 17(o) 19
+ Store 24 22
+ 28: 27(ptr) AccessChain 17(o) 25
+ Store 28 26
+ 29:11(PS_OUTPUT) Load 17(o)
+ ReturnValue 29
+ FunctionEnd
diff --git a/Test/baseResults/hlsl.inoutquals.frag.out b/Test/baseResults/hlsl.inoutquals.frag.out
index 0a8e597..8eef84e 100644
--- a/Test/baseResults/hlsl.inoutquals.frag.out
+++ b/Test/baseResults/hlsl.inoutquals.frag.out
@@ -93,13 +93,16 @@
0:16 Constant:
0:16 1 (const int)
0:16 move second child to first child ( temp int)
-0:? 'sampleMask' ( out int SampleMaskIn)
+0:16 direct index ( out int SampleMaskIn)
+0:? 'sampleMask' ( out 1-element array of int SampleMaskIn)
+0:16 Constant:
+0:16 0 (const int)
0:? 'sampleMask' ( temp int)
0:? Linker Objects
0:? '@entryPointOutput.Depth' ( out float FragDepth)
0:? '@entryPointOutput.Color' (layout( location=0) out 4-component vector of float)
0:? 'inpos' ( noperspective in 4-component vector of float FragCoord)
-0:? 'sampleMask' ( out int SampleMaskIn)
+0:? 'sampleMask' ( out 1-element array of int SampleMaskIn)
Linked fragment stage:
@@ -199,22 +202,25 @@
0:16 Constant:
0:16 1 (const int)
0:16 move second child to first child ( temp int)
-0:? 'sampleMask' ( out int SampleMaskIn)
+0:16 direct index ( out int SampleMaskIn)
+0:? 'sampleMask' ( out 1-element array of int SampleMaskIn)
+0:16 Constant:
+0:16 0 (const int)
0:? 'sampleMask' ( temp int)
0:? Linker Objects
0:? '@entryPointOutput.Depth' ( out float FragDepth)
0:? '@entryPointOutput.Color' (layout( location=0) out 4-component vector of float)
0:? 'inpos' ( noperspective in 4-component vector of float FragCoord)
-0:? 'sampleMask' ( out int SampleMaskIn)
+0:? 'sampleMask' ( out 1-element array of int SampleMaskIn)
// Module Version 10000
// Generated by (magic number): 80006
-// Id's are bound by 88
+// Id's are bound by 92
Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
- EntryPoint Fragment 4 "main" 68 78 82 86
+ EntryPoint Fragment 4 "main" 68 78 82 88
ExecutionMode 4 OriginUpperLeft
ExecutionMode 4 DepthReplacing
Source HLSL 500
@@ -246,12 +252,12 @@
Name 74 "param"
Name 78 "@entryPointOutput.Color"
Name 82 "@entryPointOutput.Depth"
- Name 86 "sampleMask"
+ Name 88 "sampleMask"
Decorate 68(inpos) NoPerspective
Decorate 68(inpos) BuiltIn FragCoord
Decorate 78(@entryPointOutput.Color) Location 0
Decorate 82(@entryPointOutput.Depth) BuiltIn FragDepth
- Decorate 86(sampleMask) BuiltIn SampleMask
+ Decorate 88(sampleMask) BuiltIn SampleMask
2: TypeVoid
3: TypeFunction 2
6: TypeFloat 32
@@ -278,8 +284,11 @@
78(@entryPointOutput.Color): 77(ptr) Variable Output
81: TypePointer Output 6(float)
82(@entryPointOutput.Depth): 81(ptr) Variable Output
- 85: TypePointer Output 17(int)
- 86(sampleMask): 85(ptr) Variable Output
+ 85: 42(int) Constant 1
+ 86: TypeArray 17(int) 85
+ 87: TypePointer Output 86
+ 88(sampleMask): 87(ptr) Variable Output
+ 90: TypePointer Output 17(int)
4(main): 2 Function None 3
5: Label
66(inpos): 16(ptr) Variable Function
@@ -301,8 +310,9 @@
83: 7(ptr) AccessChain 70(flattenTemp) 59
84: 6(float) Load 83
Store 82(@entryPointOutput.Depth) 84
- 87: 17(int) Load 71(sampleMask)
- Store 86(sampleMask) 87
+ 89: 17(int) Load 71(sampleMask)
+ 91: 90(ptr) AccessChain 88(sampleMask) 53
+ Store 91 89
Return
FunctionEnd
13(MyFunc(f1;f1;f1;f1;): 2 Function None 8
diff --git a/Test/hlsl.coverage.frag b/Test/hlsl.coverage.frag
new file mode 100644
index 0000000..c6cd019
--- /dev/null
+++ b/Test/hlsl.coverage.frag
@@ -0,0 +1,20 @@
+
+// Verify that coverage mask is an array, as required by SPIR-V.
+
+struct PS_INPUT
+{
+};
+
+struct PS_OUTPUT
+{
+ float4 vColor : SV_Target0;
+ uint nCoverageMask : SV_Coverage;
+};
+
+PS_OUTPUT main( PS_INPUT i )
+{
+ PS_OUTPUT o;
+ o.vColor = float4(1.0, 0.0, 0.0, 1.0);
+ o.nCoverageMask = 0;
+ return o;
+}
diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp
index 7cf1cbf..390e3d3 100644
--- a/gtests/Hlsl.FromFile.cpp
+++ b/gtests/Hlsl.FromFile.cpp
@@ -148,6 +148,7 @@
{"hlsl.constructArray.vert", "main"},
{"hlsl.constructexpr.frag", "main"},
{"hlsl.constructimat.frag", "main"},
+ {"hlsl.coverage.frag", "main"},
{"hlsl.depthGreater.frag", "PixelShaderFunction"},
{"hlsl.depthLess.frag", "PixelShaderFunction"},
{"hlsl.discard.frag", "PixelShaderFunction"},
diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp
index e6d29ea..3ef9a5a 100755
--- a/hlsl/hlslParseHelper.cpp
+++ b/hlsl/hlslParseHelper.cpp
@@ -1481,6 +1481,14 @@
case EbvTessLevelOuter: requiredArraySize = 4; break;
case EbvTessLevelInner: requiredArraySize = 2; break;
+ case EbvSampleMask:
+ {
+ // Promote scalar to array of size 1. Leave existing arrays alone.
+ if (!type.isArray())
+ requiredArraySize = 1;
+ break;
+ }
+
case EbvWorkGroupId: requiredVectorSize = 3; break;
case EbvGlobalInvocationId: requiredVectorSize = 3; break;
case EbvLocalInvocationId: requiredVectorSize = 3; break;
@@ -2700,6 +2708,15 @@
} else if (assignsClipPos(left)) {
// Position can require special handling: see comment above assignPosition
return assignPosition(loc, op, left, right);
+ } else if (left->getQualifier().builtIn == EbvSampleMask) {
+ // Certain builtins are required to be arrayed outputs in SPIR-V, but may internally be scalars
+ // in the shader. Copy the scalar RHS into the LHS array element zero, if that happens.
+ if (left->isArray() && !right->isArray()) {
+ const TType derefType(left->getType(), 0);
+ left = intermediate.addIndex(EOpIndexDirect, left, intermediate.addConstantUnion(0, loc), loc);
+ left->setType(derefType);
+ // Fall through to add assign.
+ }
}
return intermediate.addAssign(op, left, right, loc);