From a85c350df03c6cdf9b433f58fc0e66affda03e9e Mon Sep 17 00:00:00 2001 From: Darren Wihandi <65404740+fairywreath@users.noreply.github.com> Date: Sat, 18 Jan 2025 02:07:16 -0500 Subject: Implement Quad Control intrinsics (#5981) --- .../quad-control-comp-functionality.slang | 40 +++++++++ ...d-control-comp-functionality.slang.expected.txt | 16 ++++ .../quad-control-frag-many-entry-points.slang | 96 ++++++++++++++++++++++ .../quad-control/quad-control-frag.slang | 53 ++++++++++++ 4 files changed, 205 insertions(+) create mode 100644 tests/hlsl-intrinsic/quad-control/quad-control-comp-functionality.slang create mode 100644 tests/hlsl-intrinsic/quad-control/quad-control-comp-functionality.slang.expected.txt create mode 100644 tests/hlsl-intrinsic/quad-control/quad-control-frag-many-entry-points.slang create mode 100644 tests/hlsl-intrinsic/quad-control/quad-control-frag.slang (limited to 'tests') diff --git a/tests/hlsl-intrinsic/quad-control/quad-control-comp-functionality.slang b/tests/hlsl-intrinsic/quad-control/quad-control-comp-functionality.slang new file mode 100644 index 000000000..c8f82772d --- /dev/null +++ b/tests/hlsl-intrinsic/quad-control/quad-control-comp-functionality.slang @@ -0,0 +1,40 @@ +//TEST(compute):COMPARE_COMPUTE_EX:-vk -compute -shaderobj -emit-spirv-directly +//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -profile cs_6_7 -dx12 -use-dxil -shaderobj -render-feature hardware-device +//TEST(compute):COMPARE_COMPUTE_EX:-metal -compute -shaderobj + +//TEST_INPUT:ubuffer(data=[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0], stride=4):out,name outputBuffer +RWStructuredBuffer outputBuffer; + +[numthreads(16, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + uint index = dispatchThreadID.x; + + if (index < 4) + { + // Quad 1. + // Should return true, index 0's expr is true while all other indices' expr are false. + outputBuffer[index] = uint(QuadAny((index % 4) == 0)); + } + else if (index < 8) + { + // Quad 2. + // Should return false, all indices' expr are false. + bool falseCondition = (5 == 4); + outputBuffer[index] = uint(QuadAny(falseCondition)); + } + else if (index < 12) + { + // Quad 3. + // Should return false, index 0's expr is true while all other indices' expr are false. + outputBuffer[index] = uint(QuadAll((index % 4) == 0)); + } + else + { + // Quad 4. + // Should return true, all indices' expr are true. + bool trueCondition = (5 == 5); + outputBuffer[index] = uint(QuadAll(trueCondition)); + } +} + diff --git a/tests/hlsl-intrinsic/quad-control/quad-control-comp-functionality.slang.expected.txt b/tests/hlsl-intrinsic/quad-control/quad-control-comp-functionality.slang.expected.txt new file mode 100644 index 000000000..945f08f2c --- /dev/null +++ b/tests/hlsl-intrinsic/quad-control/quad-control-comp-functionality.slang.expected.txt @@ -0,0 +1,16 @@ +1 +1 +1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +1 +1 +1 +1 diff --git a/tests/hlsl-intrinsic/quad-control/quad-control-frag-many-entry-points.slang b/tests/hlsl-intrinsic/quad-control/quad-control-frag-many-entry-points.slang new file mode 100644 index 000000000..2312f0c95 --- /dev/null +++ b/tests/hlsl-intrinsic/quad-control/quad-control-frag-many-entry-points.slang @@ -0,0 +1,96 @@ +//TEST:SIMPLE(filecheck=CHECK_SPIRV): -target spirv -fvk-use-entrypoint-name +//TEST:SIMPLE(filecheck=CHECK_GLSL): -target glsl -fvk-use-entrypoint-name + +// +// Check that SPIRV quad control execution modes and GLSL layout/attribute decorations are only +// set on entry points that contain quad control functions and/or quad control decorations. +// + +Texture2D colorTexture1; +SamplerState samplerState; + +struct FragmentInput { + float2 uv : TEXCOORD0; +}; + +float4 getFragColor(float2 uv) { + float4 fragColor = float4(1.0, 1.0, 1.0, 1.0); + bool nonUniformCondition = uv.x > 0.5; + + if (QuadAny(nonUniformCondition)) { + float4 color = colorTexture1.Sample(samplerState, uv); + if (nonUniformCondition) { + fragColor = color; + } + } + + return fragColor; +} + +// CHECK_SPIRV: OpExecutionMode %fragmentMain1 MaximallyReconvergesKHR +// CHECK_SPIRV: OpExecutionMode %fragmentMain1 QuadDerivativesKHR +// CHECK_GLSL: layout(quad_derivatives) in +// CHECK_GLSL: [maximally_reconverges] +[shader("fragment")] +float4 fragmentMain1(FragmentInput input) : SV_Target +{ + bool nonUniformCondition = input.uv.x > 0.5; + + float4 fragColor = float4(1.0, 1.0, 1.0, 1.0); + + if (QuadAny(nonUniformCondition)) { + float4 color = colorTexture1.Sample(samplerState, input.uv); + if (nonUniformCondition) { + fragColor = color; + } + } + + return fragColor; +} + +// CHECK_SPIRV-NOT: OpExecutionMode %fragmentMain2 QuadDerivativesKHR +// CHECK_SPIRV: OpExecutionMode %fragmentMain2 MaximallyReconvergesKHR +// CHECK_GLSL-NOT: layout(quad_derivatives) in +// CHECK_GLSL: [maximally_reconverges] +[MaximallyReconverges] +[shader("fragment")] +float4 fragmentMain2(FragmentInput input) : SV_Target +{ + return float4(1.0, 1.0, 1.0, 1.0); +} + + +// CHECK_SPIRV-NOT: OpExecutionMode %fragmentMain3 MaximallyReconvergesKHR +// CHECK_SPIRV-NOT: OpExecutionMode %fragmentMain3 QuadDerivativesKHR +// CHECK_SPIRV: OpExecutionMode %fragmentMain3 RequireFullQuadsKHR +// CHECK_GLSL-NOT: layout(quad_derivatives) in +// CHECK_GLSL: layout(full_quads) in +// CHECK_GLSL-NOT: [maximally_reconverges] +[RequireFullQuads] +[shader("fragment")] +float4 fragmentMain3(FragmentInput input) : SV_Target +{ + return float4(1.0, 1.0, 1.0, 1.0); +} + +// CHECK_SPIRV: OpExecutionMode %fragmentMain4 MaximallyReconvergesKHR +// CHECK_SPIRV: OpExecutionMode %fragmentMain4 QuadDerivativesKHR +// CHECK_GLSL: layout(quad_derivatives) in +// CHECK_GLSL: [maximally_reconverges] +[shader("fragment")] +float4 fragmentMain4(FragmentInput input) : SV_Target +{ + return getFragColor(input.uv); +} + +// CHECK_SPIRV-NOT: OpExecutionMode %fragmentMain5 MaximallyReconvergesKHR +// CHECK_SPIRV-NOT: OpExecutionMode %fragmentMain5 QuadDerivativesKHR +// CHECK_SPIRV-NOT: OpExecutionMode %fragmentMain5 RequireFullQuadsKHR +// CHECK_GLSL-NOT: layout(quad_derivatives) in +// CHECK_GLSL-NOT: layout(full_quads) in +// CHECK_GLSL-NOT: [maximally_reconverges] +[shader("fragment")] +float4 fragmentMain5(FragmentInput input) : SV_Target +{ + return float4(1.0, 1.0, 1.0, 1.0); +} diff --git a/tests/hlsl-intrinsic/quad-control/quad-control-frag.slang b/tests/hlsl-intrinsic/quad-control/quad-control-frag.slang new file mode 100644 index 000000000..29a9546a0 --- /dev/null +++ b/tests/hlsl-intrinsic/quad-control/quad-control-frag.slang @@ -0,0 +1,53 @@ +//TEST:SIMPLE(filecheck=CHECK_SPIRV): -entry fragmentMain -stage fragment -target spirv +//TEST:SIMPLE(filecheck=CHECK_GLSL): -entry fragmentMain -stage fragment -target glsl +//TEST:SIMPLE(filecheck=CHECK_HLSL): -entry fragmentMain -stage fragment -target hlsl +//TEST:SIMPLE(filecheck=CHECK_METAL): -entry fragmentMain -stage fragment -target metal + +Texture2D colorTexture1; +Texture2D colorTexture2; +SamplerState samplerState; + +struct FragmentInput { + float2 uv : TEXCOORD0; +}; + +// CHECK_SPIRV: OpExecutionMode %fragmentMain MaximallyReconvergesKHR +// CHECK_SPIRV: OpExecutionMode %fragmentMain QuadDerivativesKHR +// CHECK_SPIRV: OpExecutionMode %fragmentMain RequireFullQuadsKHR +// CHECK_GLSL: layout(quad_derivatives) in +// CHECK_GLSL: layout(full_quads) in +// CHECK_GLSL: [maximally_reconverges] +[QuadDerivatives] +[RequireFullQuads] +float4 fragmentMain(FragmentInput input) : SV_Target +{ + bool nonUniformCondition1 = input.uv.x > 0.5; + bool nonUniformCondition2 = input.uv.y > 0.8; + + float4 fragColor = float4(1.0, 1.0, 1.0, 1.0); + + // CHECK_SPIRV: OpGroupNonUniformQuadAnyKHR + // CHECK_GLSL: subgroupQuadAny + // CHECK_HLSL: QuadAny + // CHECK_METAL: quad_any + if (QuadAny(nonUniformCondition1)) { + float4 color = colorTexture1.Sample(samplerState, input.uv); + if (nonUniformCondition1) { + fragColor = color; + } + } + + // CHECK_SPIRV: OpGroupNonUniformQuadAllKHR + // CHECK_GLSL: subgroupQuadAll + // CHECK_HLSL: QuadAll + // CHECK_METAL: quad_all + if (QuadAll(nonUniformCondition2)) { + float4 color = colorTexture2.Sample(samplerState, input.uv); + if (nonUniformCondition2) { + fragColor += color * 0.5; + } + } + + return fragColor; +} + -- cgit v1.2.3