From 316ce4d0cb8ed16c45c92bdcfb2aa1851fc70bde Mon Sep 17 00:00:00 2001 From: Chris Bieneman Date: Mon, 11 Aug 2025 19:25:39 -0500 Subject: [PATCH 01/11] [NFC] Simplify WaveActiveMax test This was a test I had written to cover some edge cases, and the test is a bit awkward and buggy. This corrects the test to hopefully be more consistent across vendors. --- test/WaveOps/WaveActiveMax.test | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/test/WaveOps/WaveActiveMax.test b/test/WaveOps/WaveActiveMax.test index ba50a77c2..d0b0d8265 100644 --- a/test/WaveOps/WaveActiveMax.test +++ b/test/WaveOps/WaveActiveMax.test @@ -4,12 +4,12 @@ RWStructuredBuffer Infs : register(u1); RWStructuredBuffer NegInfs : register(u2); RWStructuredBuffer Mix : register(u3); -[numthreads(32,1,1)] -void main(uint3 TID : SV_GroupThreadID) { - Nans[TID.x % 8] = WaveActiveMax(Nans[TID.x % 8]); - Infs[TID.x % 8] = WaveActiveMax(Infs[TID.x % 8]); - NegInfs[TID.x % 8] = WaveActiveMax(NegInfs[TID.x % 8]); - Mix[TID.x % 8] = WaveActiveMax(Mix[TID.x % 8]); +[numthreads(4,1,1)] +void main(uint3 GID : SV_GroupIndex) { + Nans[GID] = WaveActiveMax(Nans[GID]); + Infs[GID] = WaveActiveMax(Infs[GID]); + NegInfs[GID] = WaveActiveMax(NegInfs[GID]); + Mix[GID] = WaveActiveMax(Mix[GID]); } //--- pipeline.yaml @@ -66,8 +66,7 @@ DescriptorSets: #--- end # RUN: split-file %s %t -# RUN: %if !Vulkan %{ %dxc_target -T cs_6_0 -Fo %t.o %t/source.hlsl %} -# RUN: %if Vulkan %{ %dxc_target -T cs_6_0 -fspv-target-env=vulkan1.2 -Fo %t.o %t/source.hlsl %} +# RUN: %dxc_target -T cs_6_0 -Gis -Fo %t.o %t/source.hlsl # RUN: %offloader %t/pipeline.yaml %t.o | FileCheck %s # The behavior of this operation is consistent on Metal, so the test verifies that behavior. @@ -92,9 +91,7 @@ DescriptorSets: # CHECK: Name: Nans # CHECK-NEXT: Format: Float32 -# METAL-NEXT: Data: [ 0, 0, 0, 0 ] -# DX-NEXT: Data: -# VULKAN-NEXT: Data: +# CHECK-NEXT: Data: [ 0, 0, 0, 0 ] # CHECK: Name: Infs # CHECK-NEXT: Format: Float32 # CHECK-NEXT: Data: [ inf, inf, inf, inf ] From 951ec379c07d3d2a0febba7b2fc07136b45bf515 Mon Sep 17 00:00:00 2001 From: Chris Bieneman Date: Mon, 11 Aug 2025 19:36:56 -0500 Subject: [PATCH 02/11] Oops --- test/WaveOps/WaveActiveMax.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/WaveOps/WaveActiveMax.test b/test/WaveOps/WaveActiveMax.test index d0b0d8265..60b53a254 100644 --- a/test/WaveOps/WaveActiveMax.test +++ b/test/WaveOps/WaveActiveMax.test @@ -5,7 +5,7 @@ RWStructuredBuffer NegInfs : register(u2); RWStructuredBuffer Mix : register(u3); [numthreads(4,1,1)] -void main(uint3 GID : SV_GroupIndex) { +void main(uint GID : SV_GroupIndex) { Nans[GID] = WaveActiveMax(Nans[GID]); Infs[GID] = WaveActiveMax(Infs[GID]); NegInfs[GID] = WaveActiveMax(NegInfs[GID]); From 24c1f511f528e47a4cca67eda595b72a287bb83f Mon Sep 17 00:00:00 2001 From: Chris Bieneman Date: Mon, 11 Aug 2025 19:57:28 -0500 Subject: [PATCH 03/11] Add WARP handling --- test/WaveOps/WaveActiveMax.test | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/test/WaveOps/WaveActiveMax.test b/test/WaveOps/WaveActiveMax.test index 60b53a254..e6a607f21 100644 --- a/test/WaveOps/WaveActiveMax.test +++ b/test/WaveOps/WaveActiveMax.test @@ -67,9 +67,8 @@ DescriptorSets: # RUN: split-file %s %t # RUN: %dxc_target -T cs_6_0 -Gis -Fo %t.o %t/source.hlsl -# RUN: %offloader %t/pipeline.yaml %t.o | FileCheck %s - -# The behavior of this operation is consistent on Metal, so the test verifies that behavior. +# RUN: %if DirectX-WARP %{ %offloader %t/pipeline.yaml %t.o | FileCheck %s --check-prefixes=CHECK,WARP %} +# RUN: %if !DirectX-WARP %{ %offloader %t/pipeline.yaml %t.o | FileCheck %s --check-prefixes=CHECK,GPU %} # The SPIR-V Spec for OpGroupNonUniformFMax says: # > From the set of Value(s) provided by active invocations within a subgroup, @@ -87,17 +86,16 @@ DescriptorSets: # DirectX driver implementations seem to match SPIR-V, except WARP, which does # not treat -INF as an identity. -# XFAIL: DirectX-WARP - # CHECK: Name: Nans # CHECK-NEXT: Format: Float32 -# CHECK-NEXT: Data: [ 0, 0, 0, 0 ] +# CHECK-NEXT: Data: [ nan, nan, nan, nan ] # CHECK: Name: Infs # CHECK-NEXT: Format: Float32 # CHECK-NEXT: Data: [ inf, inf, inf, inf ] # CHECK: Name: NegInfs # CHECK-NEXT: Format: Float32 -# CHECK-NEXT: Data: [ 0, 0, 0, 0 ] +# GPU-NEXT: Data: [ 0, 0, 0, 0 ] +# WARP-NEXT: Data: [ -inf, -inf, -inf, -inf ] # CHECK: Name: Mix # CHECK-NEXT: Format: Float32 # CHECK-NEXT: Data: [ inf, inf, inf, inf ] From 85125a049b73eedc8087e04aa9a1762194fd94d9 Mon Sep 17 00:00:00 2001 From: Chris Bieneman Date: Mon, 11 Aug 2025 20:10:10 -0500 Subject: [PATCH 04/11] Tweaking handling of identity values --- test/WaveOps/WaveActiveMax.test | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/WaveOps/WaveActiveMax.test b/test/WaveOps/WaveActiveMax.test index e6a607f21..2832276ec 100644 --- a/test/WaveOps/WaveActiveMax.test +++ b/test/WaveOps/WaveActiveMax.test @@ -67,8 +67,8 @@ DescriptorSets: # RUN: split-file %s %t # RUN: %dxc_target -T cs_6_0 -Gis -Fo %t.o %t/source.hlsl -# RUN: %if DirectX-WARP %{ %offloader %t/pipeline.yaml %t.o | FileCheck %s --check-prefixes=CHECK,WARP %} -# RUN: %if !DirectX-WARP %{ %offloader %t/pipeline.yaml %t.o | FileCheck %s --check-prefixes=CHECK,GPU %} +# RUN: %if (DirectX-WARP || Metal) %{ %offloader %t/pipeline.yaml %t.o | FileCheck %s --check-prefixes=CHECK,NO_IDENT %} +# RUN: %if !DirectX-WARP %{ %offloader %t/pipeline.yaml %t.o | FileCheck %s --check-prefixes=CHECK,IDENT %} # The SPIR-V Spec for OpGroupNonUniformFMax says: # > From the set of Value(s) provided by active invocations within a subgroup, @@ -86,6 +86,8 @@ DescriptorSets: # DirectX driver implementations seem to match SPIR-V, except WARP, which does # not treat -INF as an identity. +# Metal also is consistent except that it does not treat -INF as an identity. + # CHECK: Name: Nans # CHECK-NEXT: Format: Float32 # CHECK-NEXT: Data: [ nan, nan, nan, nan ] @@ -94,8 +96,8 @@ DescriptorSets: # CHECK-NEXT: Data: [ inf, inf, inf, inf ] # CHECK: Name: NegInfs # CHECK-NEXT: Format: Float32 -# GPU-NEXT: Data: [ 0, 0, 0, 0 ] -# WARP-NEXT: Data: [ -inf, -inf, -inf, -inf ] +# IDENT-NEXT: Data: [ 0, 0, 0, 0 ] +# NO_IDENT-NEXT: Data: [ -inf, -inf, -inf, -inf ] # CHECK: Name: Mix # CHECK-NEXT: Format: Float32 # CHECK-NEXT: Data: [ inf, inf, inf, inf ] From 26735325ed0e7586d8dce0c03646542615a144f0 Mon Sep 17 00:00:00 2001 From: Chris Bieneman Date: Mon, 11 Aug 2025 20:24:59 -0500 Subject: [PATCH 05/11] Fix conditional --- test/WaveOps/WaveActiveMax.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/WaveOps/WaveActiveMax.test b/test/WaveOps/WaveActiveMax.test index 2832276ec..5396d1010 100644 --- a/test/WaveOps/WaveActiveMax.test +++ b/test/WaveOps/WaveActiveMax.test @@ -67,7 +67,7 @@ DescriptorSets: # RUN: split-file %s %t # RUN: %dxc_target -T cs_6_0 -Gis -Fo %t.o %t/source.hlsl -# RUN: %if (DirectX-WARP || Metal) %{ %offloader %t/pipeline.yaml %t.o | FileCheck %s --check-prefixes=CHECK,NO_IDENT %} +# RUN: %if DirectX-WARP || Metal %{ %offloader %t/pipeline.yaml %t.o | FileCheck %s --check-prefixes=CHECK,NO_IDENT %} # RUN: %if !DirectX-WARP %{ %offloader %t/pipeline.yaml %t.o | FileCheck %s --check-prefixes=CHECK,IDENT %} # The SPIR-V Spec for OpGroupNonUniformFMax says: From e85239bfc88afbb8e74ee63955cf89fca1076273 Mon Sep 17 00:00:00 2001 From: Chris Bieneman Date: Mon, 11 Aug 2025 20:39:18 -0500 Subject: [PATCH 06/11] Got it this time.. --- test/WaveOps/WaveActiveMax.test | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/WaveOps/WaveActiveMax.test b/test/WaveOps/WaveActiveMax.test index 5396d1010..0adc8349a 100644 --- a/test/WaveOps/WaveActiveMax.test +++ b/test/WaveOps/WaveActiveMax.test @@ -67,8 +67,8 @@ DescriptorSets: # RUN: split-file %s %t # RUN: %dxc_target -T cs_6_0 -Gis -Fo %t.o %t/source.hlsl -# RUN: %if DirectX-WARP || Metal %{ %offloader %t/pipeline.yaml %t.o | FileCheck %s --check-prefixes=CHECK,NO_IDENT %} -# RUN: %if !DirectX-WARP %{ %offloader %t/pipeline.yaml %t.o | FileCheck %s --check-prefixes=CHECK,IDENT %} +# RUN: %offloader %t/pipeline.yaml %t.o | \ +# RUN: FileCheck %s %if DirectX-WARP || Metal %{ --check-prefixes=CHECK,NO_IDENT %} %else %{ --check-prefixes=CHECK,IDENT %} # The SPIR-V Spec for OpGroupNonUniformFMax says: # > From the set of Value(s) provided by active invocations within a subgroup, From 4bb56e7d99bafb2485c9d0d4afde795c3cc0e8aa Mon Sep 17 00:00:00 2001 From: Chris Bieneman Date: Mon, 11 Aug 2025 21:03:12 -0500 Subject: [PATCH 07/11] Fixing nan check --- test/WaveOps/WaveActiveMax.test | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/test/WaveOps/WaveActiveMax.test b/test/WaveOps/WaveActiveMax.test index 0adc8349a..db1be62fc 100644 --- a/test/WaveOps/WaveActiveMax.test +++ b/test/WaveOps/WaveActiveMax.test @@ -67,8 +67,10 @@ DescriptorSets: # RUN: split-file %s %t # RUN: %dxc_target -T cs_6_0 -Gis -Fo %t.o %t/source.hlsl -# RUN: %offloader %t/pipeline.yaml %t.o | \ -# RUN: FileCheck %s %if DirectX-WARP || Metal %{ --check-prefixes=CHECK,NO_IDENT %} %else %{ --check-prefixes=CHECK,IDENT %} +# RUN: %offloader %t/pipeline.yaml %t.o | FileCheck %s \ +# RUN: %if DirectX-WARP %{ --check-prefixes=CHECK,NO_IDENT,NO_NAN %} \ +# RUN: %else %{ %if Metal %{ --check-prefixes=CHECK,NO_IDENT,NAN %} +# RUN: %else %{ --check-prefixes=CHECK,IDENT,NO_NAN %} %} # The SPIR-V Spec for OpGroupNonUniformFMax says: # > From the set of Value(s) provided by active invocations within a subgroup, @@ -86,11 +88,14 @@ DescriptorSets: # DirectX driver implementations seem to match SPIR-V, except WARP, which does # not treat -INF as an identity. -# Metal also is consistent except that it does not treat -INF as an identity. +# Metal also is consistent except that it preserves NaN and does not treat -INF +# as an identity. + # CHECK: Name: Nans # CHECK-NEXT: Format: Float32 -# CHECK-NEXT: Data: [ nan, nan, nan, nan ] +# NAN-NEXT: Data: [ nan, nan, nan, nan ] +# NO_NAN-NEXT: Data: # CHECK: Name: Infs # CHECK-NEXT: Format: Float32 # CHECK-NEXT: Data: [ inf, inf, inf, inf ] From 9b2e07103facd0e048e4c9569522a7f2d7658264 Mon Sep 17 00:00:00 2001 From: Chris Bieneman Date: Mon, 11 Aug 2025 21:17:58 -0500 Subject: [PATCH 08/11] Ugh... --- test/WaveOps/WaveActiveMax.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/WaveOps/WaveActiveMax.test b/test/WaveOps/WaveActiveMax.test index db1be62fc..c5a1bb1a4 100644 --- a/test/WaveOps/WaveActiveMax.test +++ b/test/WaveOps/WaveActiveMax.test @@ -69,7 +69,7 @@ DescriptorSets: # RUN: %dxc_target -T cs_6_0 -Gis -Fo %t.o %t/source.hlsl # RUN: %offloader %t/pipeline.yaml %t.o | FileCheck %s \ # RUN: %if DirectX-WARP %{ --check-prefixes=CHECK,NO_IDENT,NO_NAN %} \ -# RUN: %else %{ %if Metal %{ --check-prefixes=CHECK,NO_IDENT,NAN %} +# RUN: %else %{ %if Metal %{ --check-prefixes=CHECK,NO_IDENT,NAN %} \ # RUN: %else %{ --check-prefixes=CHECK,IDENT,NO_NAN %} %} # The SPIR-V Spec for OpGroupNonUniformFMax says: From 93c3a036f4254a2b0df36c551f600c0ee70df882 Mon Sep 17 00:00:00 2001 From: Chris Bieneman Date: Tue, 12 Aug 2025 19:38:11 -0500 Subject: [PATCH 09/11] This should get it going --- test/WaveOps/WaveActiveMax.test | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/test/WaveOps/WaveActiveMax.test b/test/WaveOps/WaveActiveMax.test index c5a1bb1a4..0a819a566 100644 --- a/test/WaveOps/WaveActiveMax.test +++ b/test/WaveOps/WaveActiveMax.test @@ -68,9 +68,8 @@ DescriptorSets: # RUN: split-file %s %t # RUN: %dxc_target -T cs_6_0 -Gis -Fo %t.o %t/source.hlsl # RUN: %offloader %t/pipeline.yaml %t.o | FileCheck %s \ -# RUN: %if DirectX-WARP %{ --check-prefixes=CHECK,NO_IDENT,NO_NAN %} \ -# RUN: %else %{ %if Metal %{ --check-prefixes=CHECK,NO_IDENT,NAN %} \ -# RUN: %else %{ --check-prefixes=CHECK,IDENT,NO_NAN %} %} +# RUN: %if Metal %{ --check-prefixes=CHECK,NAN %} \ +# RUN: %else %{ --check-prefixes=CHECK,NO_NAN %} # The SPIR-V Spec for OpGroupNonUniformFMax says: # > From the set of Value(s) provided by active invocations within a subgroup, @@ -80,16 +79,9 @@ DescriptorSets: # This makes Vulkan undefined for cases where all values are nan. -# Also SPIR-V states: -# > The identity I for Operation is -INF. +# DirectX driver implementations seem to match SPIR-V. -# This makes it defined that any lane value of -INF is ignored. - -# DirectX driver implementations seem to match SPIR-V, except WARP, which does -# not treat -INF as an identity. - -# Metal also is consistent except that it preserves NaN and does not treat -INF -# as an identity. +# Metal also is consistent except that it preserves NaN. # CHECK: Name: Nans @@ -101,8 +93,7 @@ DescriptorSets: # CHECK-NEXT: Data: [ inf, inf, inf, inf ] # CHECK: Name: NegInfs # CHECK-NEXT: Format: Float32 -# IDENT-NEXT: Data: [ 0, 0, 0, 0 ] -# NO_IDENT-NEXT: Data: [ -inf, -inf, -inf, -inf ] +# CHECK-NEXT: Data: [ -inf, -inf, -inf, -inf ] # CHECK: Name: Mix # CHECK-NEXT: Format: Float32 # CHECK-NEXT: Data: [ inf, inf, inf, inf ] From 882e76467a01e1f294b1eea418e7de59136e1e62 Mon Sep 17 00:00:00 2001 From: Chris Bieneman Date: Tue, 12 Aug 2025 19:39:58 -0500 Subject: [PATCH 10/11] Rename test --- .../WaveOps/EdgeConditions}/WaveActiveMax.test | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/{WaveOps => Feature/WaveOps/EdgeConditions}/WaveActiveMax.test (100%) diff --git a/test/WaveOps/WaveActiveMax.test b/test/Feature/WaveOps/EdgeConditions/WaveActiveMax.test similarity index 100% rename from test/WaveOps/WaveActiveMax.test rename to test/Feature/WaveOps/EdgeConditions/WaveActiveMax.test From 780add487130d70f33ae0d1da53c79655a22f940 Mon Sep 17 00:00:00 2001 From: Chris Bieneman Date: Wed, 22 Oct 2025 12:20:40 -0500 Subject: [PATCH 11/11] Add option to disable edge condition test(s) by default --- test/CMakeLists.txt | 4 +++- test/Feature/WaveOps/EdgeConditions/lit.cfg.py | 2 ++ test/lit.cfg.py | 3 +++ test/lit.site.cfg.py.in | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 test/Feature/WaveOps/EdgeConditions/lit.cfg.py diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6467681ab..5303768c5 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -56,6 +56,7 @@ endfunction() option(OFFLOADTEST_ENABLE_DEBUG "Enable available runtime debug layers (defaults On)." ON) option(OFFLOADTEST_ENABLE_VALIDATION "Enable available runtime validation layers (defaults Off)." OFF) +option(OFFLOADTEST_ENABLE_EDGE_CONDITIONS "Enable edge condition tests which are flaky (defaults Off)." OFF) list(APPEND OFFLOADTEST_DEPS api-query @@ -105,7 +106,8 @@ endif() llvm_canonicalize_cmake_booleans(OFFLOADTEST_TEST_CLANG OFFLOADTEST_ENABLE_DEBUG - OFFLOADTEST_ENABLE_VALIDATION) + OFFLOADTEST_ENABLE_VALIDATION + OFFLOADTEST_ENABLE_EDGE_CONDITIONS) foreach(platform ${platforms_to_test}) set(TEST_${platform} False) diff --git a/test/Feature/WaveOps/EdgeConditions/lit.cfg.py b/test/Feature/WaveOps/EdgeConditions/lit.cfg.py new file mode 100644 index 000000000..f0627a76e --- /dev/null +++ b/test/Feature/WaveOps/EdgeConditions/lit.cfg.py @@ -0,0 +1,2 @@ +if "EdgeConditions" in config.available_features: + config.unsupported = True diff --git a/test/lit.cfg.py b/test/lit.cfg.py index 958536fec..c5c2c11fc 100644 --- a/test/lit.cfg.py +++ b/test/lit.cfg.py @@ -173,6 +173,9 @@ def setDeviceFeatures(config, device, compiler): ) HLSLCompiler = "DXC" +if config.offloadtest_enable_edge_cond_tests: + config.available_features.add("EdgeConditions") + config.available_features.add(HLSLCompiler) tools.append(ToolSubst("obj2yaml", FindTool("obj2yaml"))) diff --git a/test/lit.site.cfg.py.in b/test/lit.site.cfg.py.in index 2bafae667..7af097054 100644 --- a/test/lit.site.cfg.py.in +++ b/test/lit.site.cfg.py.in @@ -21,6 +21,7 @@ config.offloadtest_enable_metal = @TEST_mtl@ config.offloadtest_os = "@CMAKE_SYSTEM_NAME@" config.offloadtest_enable_debug = @OFFLOADTEST_ENABLE_DEBUG@ config.offloadtest_enable_validation = @OFFLOADTEST_ENABLE_VALIDATION@ +config.offloadtest_enable_edge_cond_tests = @OFFLOADTEST_ENABLE_EDGE_CONDITIONS@ import lit.llvm lit.llvm.initialize(lit_config, config)