From 4e6d3eaf5d114e141e940ebd8f1cd0f1ca571af3 Mon Sep 17 00:00:00 2001 From: LoopDawg Date: Wed, 16 May 2018 07:25:29 -0600 Subject: [PATCH] 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 --- Test/baseResults/hlsl.coverage.frag.out | 204 ++++++++++++++++++++++ Test/baseResults/hlsl.inoutquals.frag.out | 34 ++-- Test/hlsl.coverage.frag | 20 +++ gtests/Hlsl.FromFile.cpp | 1 + hlsl/hlslParseHelper.cpp | 17 ++ 5 files changed, 264 insertions(+), 12 deletions(-) create mode 100644 Test/baseResults/hlsl.coverage.frag.out create mode 100644 Test/hlsl.coverage.frag diff --git a/Test/baseResults/hlsl.coverage.frag.out b/Test/baseResults/hlsl.coverage.frag.out new file mode 100644 index 00000000..8fc6abf7 --- /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 0a8e5978..8eef84eb 100644 --- a/Test/baseResults/hlsl.inoutquals.frag.out +++ b/Test/baseResults/hlsl.inoutquals.frag.out @@ -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 diff --git a/Test/hlsl.coverage.frag b/Test/hlsl.coverage.frag new file mode 100644 index 00000000..c6cd0194 --- /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 7cf1cbf5..390e3d37 100644 --- a/gtests/Hlsl.FromFile.cpp +++ b/gtests/Hlsl.FromFile.cpp @@ -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"}, diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index e6d29eae..3ef9a5af 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -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);