HLSL: require coverage mask to be arrayed output.

SPIR-V requires the coverage mask to be an array of integers, but HLSL
allows scalar integers.  This adds the requisite type conversion and
wrapped entry point handling.

Fixes: #1202
This commit is contained in:
LoopDawg 2018-05-16 07:25:29 -06:00
parent cfb05ec702
commit 4e6d3eaf5d
5 changed files with 264 additions and 12 deletions

View File

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

View File

@ -93,13 +93,16 @@ using depth_any
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 @@ using depth_any
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 @@ using depth_any
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 @@ using depth_any
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 @@ using depth_any
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

20
Test/hlsl.coverage.frag Normal file
View File

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

View File

@ -148,6 +148,7 @@ INSTANTIATE_TEST_CASE_P(
{"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"},

View File

@ -1481,6 +1481,14 @@ void HlslParseContext::fixBuiltInIoType(TType& type)
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 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
} 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);