From d50c3f34a2eda5bf5e278c78d32cc9923fd83b82 Mon Sep 17 00:00:00 2001 From: aidanfnv Date: Tue, 1 Jul 2025 00:41:52 -0700 Subject: Add arguments for controlling floating point denormal mode (#7461) * Implement -fp-denorm-mode slangc arg * Split fp-denorm-mode into 3 args for fp16/32/64 * Remove redundant option categories * Use emitInst for multiple of the same OpExecutionMode * Fix formatting * Remove -denorm any * Re-add option categories * emitinst for ftz * Use enums for type text * Remove extra categories again * Add tests for denorm mode * Move denorm mode to post linking * format code (#8) Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com> * regenerate command line reference (#9) Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com> * Clean up tests * Fix option text * format code (#10) Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com> * Add tests for "any" mode * Return "any" enum if option not set * Simplify emission logic * Add support for generic entrypoints * Move denorm modes to end of CompilerOptionName enum * format code (#11) Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com> * Move new enum members to before CountOf * Add not checks to tests, fix generic test, add functionality tests * Rename denorm to fpDenormal * Clean up functional test * Rename denorm test dir * Fix formatting, regenerate cmdline ref * Fold simple tests into functional tests, add more dxil checks * Remove no-op DX tests, make tests more consistent * Disable VK functionality tests that will fail on the CI configs * Fix formatting * Add comments to disabled tests explaining why --------- Co-authored-by: slangbot Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com> --- tests/fp-denormal-mode/denorm-mode-fp16.slang | 54 ++++++++++++++++++++ tests/fp-denormal-mode/denorm-mode-fp32.slang | 64 ++++++++++++++++++++++++ tests/fp-denormal-mode/denorm-mode-fp64.slang | 58 +++++++++++++++++++++ tests/fp-denormal-mode/denorm-mode-generic.slang | 26 ++++++++++ 4 files changed, 202 insertions(+) create mode 100644 tests/fp-denormal-mode/denorm-mode-fp16.slang create mode 100644 tests/fp-denormal-mode/denorm-mode-fp32.slang create mode 100644 tests/fp-denormal-mode/denorm-mode-fp64.slang create mode 100644 tests/fp-denormal-mode/denorm-mode-generic.slang (limited to 'tests') diff --git a/tests/fp-denormal-mode/denorm-mode-fp16.slang b/tests/fp-denormal-mode/denorm-mode-fp16.slang new file mode 100644 index 000000000..f770ccbbe --- /dev/null +++ b/tests/fp-denormal-mode/denorm-mode-fp16.slang @@ -0,0 +1,54 @@ +//TEST:SIMPLE(filecheck=CHECK_ANY):-target spirv-assembly -entry computeMain -stage compute +//TEST:SIMPLE(filecheck=CHECK_ANY):-target spirv-assembly -entry computeMain -stage compute -denorm-mode-fp16 any +//TEST:SIMPLE(filecheck=CHECK_PRESERVE):-target spirv-assembly -entry computeMain -stage compute -denorm-mode-fp16 preserve +//TEST:SIMPLE(filecheck=CHECK_FTZ):-target spirv-assembly -entry computeMain -stage compute -denorm-mode-fp16 ftz + +//TEST:SIMPLE(filecheck=CHECK_DXIL):-target dxil-assembly -entry computeMain -stage compute -profile cs_6_2 +//TEST:SIMPLE(filecheck=CHECK_DXIL):-target dxil-assembly -entry computeMain -stage compute -profile cs_6_2 -denorm-mode-fp16 any +//TEST:SIMPLE(filecheck=CHECK_DXIL):-target dxil-assembly -entry computeMain -stage compute -profile cs_6_2 -denorm-mode-fp16 preserve +//TEST:SIMPLE(filecheck=CHECK_DXIL):-target dxil-assembly -entry computeMain -stage compute -profile cs_6_2 -denorm-mode-fp16 ftz + +//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=PRESERVE):-vk -compute -Xslang -denorm-mode-fp16 -Xslang preserve +// Capability shaderDenormFlushToZeroFloat16 is VK_FALSE on the Vulkan device used for CI testing, resulting in +// runtime error VUID-RuntimeSpirv-shaderDenormFlushToZeroFloat16-06299 during CI testing +//DISABLE_TEST(compute):COMPARE_COMPUTE(filecheck-buffer=FTZ):-vk -compute -Xslang -denorm-mode-fp16 -Xslang ftz + +// CHECK_ANY-NOT: DenormPreserve +// CHECK_ANY-NOT: DenormFlushToZero + +// CHECK_PRESERVE: OpExecutionMode %computeMain DenormPreserve 16 +// CHECK_PRESERVE-NOT: OpExecutionMode %computeMain DenormPreserve 32 +// CHECK_PRESERVE-NOT: OpExecutionMode %computeMain DenormPreserve 64 +// CHECK_PRESERVE-NOT: DenormFlushToZero + +// CHECK_FTZ: OpExecutionMode %computeMain DenormFlushToZero 16 +// CHECK_FTZ-NOT: OpExecutionMode %computeMain DenormFlushToZero 32 +// CHECK_FTZ-NOT: OpExecutionMode %computeMain DenormFlushToZero 64 +// CHECK_FTZ-NOT: DenormPreserve + +// CHECK_DXIL-NOT: fp32-denorm-mode +// CHECK_DXIL-NOT: preserve +// CHECK_DXIL-NOT: ftz + +// In preserve mode, denormalized numbers should be preserved +// PRESERVE: 66 + +// In flush-to-zero mode, denormalized numbers should be flushed to zero +// FTZ: 0 + +// Smallest normal fp16 +//TEST_INPUT: set inputBuffer = ubuffer(data=[0x0400], stride=2) +RWStructuredBuffer inputBuffer; + +//TEST_INPUT:ubuffer(data=[0], stride=2):out,name=outputBuffer +RWStructuredBuffer outputBuffer; + +[shader("compute")] +[numthreads(1, 1, 1)] +void computeMain() +{ + half smallestNormal = inputBuffer[0]; + half denormal = smallestNormal / 10; + + outputBuffer[0] = denormal; +} diff --git a/tests/fp-denormal-mode/denorm-mode-fp32.slang b/tests/fp-denormal-mode/denorm-mode-fp32.slang new file mode 100644 index 000000000..530d99b6d --- /dev/null +++ b/tests/fp-denormal-mode/denorm-mode-fp32.slang @@ -0,0 +1,64 @@ +//TEST:SIMPLE(filecheck=CHECK_ANY):-target spirv-assembly -entry computeMain -stage compute +//TEST:SIMPLE(filecheck=CHECK_ANY):-target spirv-assembly -entry computeMain -stage compute -denorm-mode-fp16 any +//TEST:SIMPLE(filecheck=CHECK_PRESERVE_SPIRV):-target spirv-assembly -entry computeMain -stage compute -denorm-mode-fp32 preserve +//TEST:SIMPLE(filecheck=CHECK_FTZ_SPIRV):-target spirv-assembly -entry computeMain -stage compute -denorm-mode-fp32 ftz + +//TEST:SIMPLE(filecheck=CHECK_ANY):-target dxil-assembly -entry computeMain -stage compute -profile cs_6_2 +//TEST:SIMPLE(filecheck=CHECK_ANY):-target dxil-assembly -entry computeMain -stage compute -profile cs_6_2 -denorm-mode-fp32 any +//TEST:SIMPLE(filecheck=CHECK_PRESERVE_DXIL):-target dxil-assembly -entry computeMain -stage compute -profile cs_6_2 -denorm-mode-fp32 preserve +//TEST:SIMPLE(filecheck=CHECK_FTZ_DXIL):-target dxil-assembly -entry computeMain -stage compute -profile cs_6_2 -denorm-mode-fp32 ftz + +// Capability shaderDenormPreserveFloat32 is VK_FALSE on the Vulkan device used for CI testing, resulting in +// runtime error VUID-RuntimeSpirv-shaderDenormPreserveFloat32-06297 during CI testing +//DISABLE_TEST(compute):COMPARE_COMPUTE(filecheck-buffer=PRESERVE):-vk -compute -Xslang -denorm-mode-fp32 -Xslang preserve +// Capability shaderDenormFlushToZeroFloat32 is VK_FALSE on the Vulkan device used for CI testing, resulting in +// runtime error VUID-RuntimeSpirv-shaderDenormFlushToZeroFloat32-06300 during CI testing +//DISABLE_TEST(compute):COMPARE_COMPUTE(filecheck-buffer=FTZ):-vk -compute -Xslang -denorm-mode-fp32 -Xslang ftz + +//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=PRESERVE):-slang -compute -dx12 -use-dxil -profile cs_6_2 -shaderobj -Xslang -denorm-mode-fp32 -Xslang preserve +//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=FTZ):-slang -compute -dx12 -use-dxil -profile cs_6_2 -Xslang -denorm-mode-fp32 -Xslang ftz + +// CHECK_ANY-NOT: DenormPreserve +// CHECK_ANY-NOT: DenormFlushToZero + +// CHECK_PRESERVE_SPIRV: OpExecutionMode %computeMain DenormPreserve 32 +// CHECK_PRESERVE_SPIRV-NOT: OpExecutionMode %computeMain DenormPreserve 16 +// CHECK_PRESERVE_SPIRV-NOT: OpExecutionMode %computeMain DenormPreserve 64 +// CHECK_PRESERVE_SPIRV-NOT: DenormFlushToZero + +// CHECK_FTZ_SPIRV: OpExecutionMode %computeMain DenormFlushToZero 32 +// CHECK_FTZ_SPIRV-NOT: OpExecutionMode %computeMain DenormFlushToZero 16 +// CHECK_FTZ_SPIRV-NOT: OpExecutionMode %computeMain DenormFlushToZero 64 +// CHECK_FTZ_SPIRV-NOT: DenormPreserve + +// CHECK_ANY-NOT: preserve +// CHECK_ANY-NOT: ftz + +// CHECK_PRESERVE_DXIL: attributes #0 = { "fp32-denorm-mode"="preserve" } +// CHECK_PRESERVE_DXIL-NOT: ftz + +// CHECK_FTZ_DXIL: attributes #0 = { "fp32-denorm-mode"="ftz" } +// CHECK_FTZ_DXIL-NOT: preserve + +// In preserve mode, denormalized numbers should be preserved +// PRESERVE: CCCCD + +// In flush-to-zero mode, denormalized numbers should be flushed to zero +// FTZ: 0 + +// Smallest normal fp32 +//TEST_INPUT: set inputBuffer = ubuffer(data=[0x00800000], stride=4) +RWStructuredBuffer inputBuffer; + +//TEST_INPUT:ubuffer(data=[0], stride=4):out,name=outputBuffer +RWStructuredBuffer outputBuffer; + +[shader("compute")] +[numthreads(1, 1, 1)] +void computeMain() +{ + float smallestNormal = inputBuffer[0]; + float denormal = smallestNormal / 10; + + outputBuffer[0] = denormal; +} diff --git a/tests/fp-denormal-mode/denorm-mode-fp64.slang b/tests/fp-denormal-mode/denorm-mode-fp64.slang new file mode 100644 index 000000000..0f4ac6c3c --- /dev/null +++ b/tests/fp-denormal-mode/denorm-mode-fp64.slang @@ -0,0 +1,58 @@ +//TEST:SIMPLE(filecheck=CHECK_ANY):-target spirv-assembly -entry computeMain -stage compute +//TEST:SIMPLE(filecheck=CHECK_ANY):-target spirv-assembly -entry computeMain -stage compute -denorm-mode-fp64 any +//TEST:SIMPLE(filecheck=CHECK_PRESERVE):-target spirv-assembly -entry computeMain -stage compute -denorm-mode-fp64 preserve +//TEST:SIMPLE(filecheck=CHECK_FTZ):-target spirv-assembly -entry computeMain -stage compute -denorm-mode-fp64 ftz + +//TEST:SIMPLE(filecheck=CHECK_DXIL):-target dxil-assembly -entry computeMain -stage compute -profile cs_6_2 +//TEST:SIMPLE(filecheck=CHECK_DXIL):-target dxil-assembly -entry computeMain -stage compute -profile cs_6_2 -denorm-mode-fp64 any +//TEST:SIMPLE(filecheck=CHECK_DXIL):-target dxil-assembly -entry computeMain -stage compute -profile cs_6_2 -denorm-mode-fp64 preserve +//TEST:SIMPLE(filecheck=CHECK_DXIL):-target dxil-assembly -entry computeMain -stage compute -profile cs_6_2 -denorm-mode-fp64 ftz + +// Capability shaderDenormPreserveFloat64 is VK_FALSE on the Vulkan device used for CI testing, resulting in +// runtime error VUID-RuntimeSpirv-shaderDenormPreserveFloat64-06298 during CI testing +//DISABLE_TEST(compute):COMPARE_COMPUTE(filecheck-buffer=PRESERVE):-vk -compute -Xslang -denorm-mode-fp64 -Xslang preserve +// Capability shaderDenormFlushToZeroFloat64 is VK_FALSE on the Vulkan device used for CI testing, resulting in +// runtime error VUID-RuntimeSpirv-shaderDenormFlushToZeroFloat64-06301 during CI testing +//DISABLE_TEST(compute):COMPARE_COMPUTE(filecheck-buffer=FTZ):-vk -compute -Xslang -denorm-mode-fp64 -Xslang ftz + +// CHECK_ANY-NOT: DenormPreserve +// CHECK_ANY-NOT: DenormFlushToZero + +// CHECK_PRESERVE: OpExecutionMode %computeMain DenormPreserve 64 +// CHECK_PRESERVE-NOT: OpExecutionMode %computeMain DenormPreserve 16 +// CHECK_PRESERVE-NOT: OpExecutionMode %computeMain DenormPreserve 32 +// CHECK_PRESERVE-NOT: DenormFlushToZero + +// CHECK_FTZ: OpExecutionMode %computeMain DenormFlushToZero 64 +// CHECK_FTZ-NOT: OpExecutionMode %computeMain DenormFlushToZero 16 +// CHECK_FTZ-NOT: OpExecutionMode %computeMain DenormFlushToZero 32 +// CHECK_FTZ-NOT: DenormPreserve + +// CHECK_DXIL-NOT: fp32-denorm-mode +// CHECK_DXIL-NOT: preserve +// CHECK_DXIL-NOT: ftz + +// In preserve mode, denormalized numbers should be preserved +// PRESERVE: 9999999A +// PRESERVE: 19999 + +// In flush-to-zero mode, denormalized numbers should be flushed to zero +// FTZ: 0 +// FTZ: 0 + +// Smallest normal fp32 +//TEST_INPUT: set inputBuffer = ubuffer(data=[0x00100000 0x00000000], stride=8) +RWStructuredBuffer inputBuffer; + +//TEST_INPUT:ubuffer(data=[0], stride=8):out,name=outputBuffer +RWStructuredBuffer outputBuffer; + +[shader("compute")] +[numthreads(1, 1, 1)] +void computeMain() +{ + double smallNormal = asdouble(inputBuffer[1], inputBuffer[0]); + double denorm = smallNormal / 10; + + outputBuffer[0] = denorm; +} diff --git a/tests/fp-denormal-mode/denorm-mode-generic.slang b/tests/fp-denormal-mode/denorm-mode-generic.slang new file mode 100644 index 000000000..e53478d41 --- /dev/null +++ b/tests/fp-denormal-mode/denorm-mode-generic.slang @@ -0,0 +1,26 @@ +//TEST:SIMPLE(filecheck=CHECK_ANY):-target spirv-assembly -entry genericEntry -stage compute +//TEST:SIMPLE(filecheck=CHECK_ANY):-target spirv-assembly -entry genericEntry -stage compute +//TEST:SIMPLE(filecheck=CHECK_ANY):-target spirv-assembly -entry genericEntry -stage compute + +//TEST:SIMPLE(filecheck=CHECK_PRESERVE):-target spirv-assembly -entry genericEntry -stage compute -denorm-mode-fp32 preserve +//TEST:SIMPLE(filecheck=CHECK_PRESERVE):-target spirv-assembly -entry genericEntry -stage compute -denorm-mode-fp32 preserve +//TEST:SIMPLE(filecheck=CHECK_PRESERVE):-target spirv-assembly -entry genericEntry -stage compute -denorm-mode-fp32 preserve + +//TEST:SIMPLE(filecheck=CHECK_FTZ):-target spirv-assembly -entry genericEntry -stage compute -denorm-mode-fp32 ftz +//TEST:SIMPLE(filecheck=CHECK_FTZ):-target spirv-assembly -entry genericEntry -stage compute -denorm-mode-fp32 ftz +//TEST:SIMPLE(filecheck=CHECK_FTZ):-target spirv-assembly -entry genericEntry -stage compute -denorm-mode-fp32 ftz + +// CHECK_ANY-NOT: DenormPreserve +// CHECK_ANY-NOT: DenormFlushToZero + +// CHECK_PRESERVE: DenormPreserve 32 +// CHECK_FTZ: DenormFlushToZero 32 + +[shader("compute")] +[numthreads(1, 1, 1)] +__generic void genericEntry() +{ + T a = T(1); + T b = T(2); + T result = a + b; +} -- cgit v1.2.3