Skip to content

Commit 8de82c9

Browse files
authored
[SPIR-V] Add support for Denorm Mode (#6435)
The -denorm option allows the shader to select the desired behavior with respect to denormal values. Note that this can't take advantage of the SPIRV-Tools capability trimming pass for the same reasons as described in: #6248 (comment) Fixes #6434
1 parent 40e27eb commit 8de82c9

File tree

8 files changed

+67
-0
lines changed

8 files changed

+67
-0
lines changed

include/dxc/Support/SPIRVOptions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ struct SpirvCodeGenOptions {
9292
std::vector<std::string> bindRegister;
9393
std::vector<std::string> bindGlobals;
9494
std::string entrypointName;
95+
std::string floatDenormalMode; // OPT_denorm
9596

9697
bool signaturePacking; ///< Whether signature packing is enabled or not
9798

lib/DxcSupport/HLSLOptions.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,6 +1201,8 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
12011201
hasUnsupportedSpirvOption(Args, errors))
12021202
return 1;
12031203

1204+
opts.SpirvOptions.floatDenormalMode = Args.getLastArgValue(OPT_denorm);
1205+
12041206
#else
12051207
if (Args.hasFlag(OPT_spirv, OPT_INVALID, false) ||
12061208
Args.hasFlag(OPT_fvk_invert_y, OPT_INVALID, false) ||

tools/clang/include/clang/SPIRV/FeatureManager.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ enum class Extension {
6060
NV_compute_shader_derivatives,
6161
KHR_fragment_shader_barycentric,
6262
KHR_maximal_reconvergence,
63+
KHR_float_controls,
6364
Unknown,
6465
};
6566

tools/clang/lib/SPIRV/CapabilityVisitor.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,18 @@ bool CapabilityVisitor::visit(SpirvExecutionMode *execMode) {
722722
addExtension(Extension::KHR_maximal_reconvergence, "",
723723
execModeSourceLocation);
724724
break;
725+
case spv::ExecutionMode::DenormPreserve:
726+
case spv::ExecutionMode::DenormFlushToZero:
727+
// KHR_float_controls was promoted to core in Vulkan 1.2.
728+
if (!featureManager.isTargetEnvVulkan1p2OrAbove()) {
729+
addExtension(Extension::KHR_float_controls, "SPV_KHR_float_controls",
730+
execModeSourceLocation);
731+
}
732+
addCapability(executionMode == spv::ExecutionMode::DenormPreserve
733+
? spv::Capability::DenormPreserve
734+
: spv::Capability::DenormFlushToZero,
735+
execModeSourceLocation);
736+
break;
725737
default:
726738
break;
727739
}

tools/clang/lib/SPIRV/FeatureManager.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ Extension FeatureManager::getExtensionSymbol(llvm::StringRef name) {
196196
Extension::KHR_fragment_shader_barycentric)
197197
.Case("SPV_KHR_maximal_reconvergence",
198198
Extension::KHR_maximal_reconvergence)
199+
.Case("SPV_KHR_float_controls", Extension::KHR_float_controls)
199200
.Default(Extension::Unknown);
200201
}
201202

@@ -261,6 +262,8 @@ const char *FeatureManager::getExtensionName(Extension symbol) {
261262
return "SPV_KHR_fragment_shader_barycentric";
262263
case Extension::KHR_maximal_reconvergence:
263264
return "SPV_KHR_maximal_reconvergence";
265+
case Extension::KHR_float_controls:
266+
return "SPV_KHR_float_controls";
264267
default:
265268
break;
266269
}

tools/clang/lib/SPIRV/SpirvEmitter.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,23 @@ void SpirvEmitter::HandleTranslationUnit(ASTContext &context) {
843843
SourceLocation());
844844
}
845845

846+
llvm::StringRef denormMode = spirvOptions.floatDenormalMode;
847+
if (!denormMode.empty()) {
848+
if (denormMode.equals_lower("preserve")) {
849+
spvBuilder.addExecutionMode(entryFunction,
850+
spv::ExecutionMode::DenormPreserve, {32}, {});
851+
} else if (denormMode.equals_lower("ftz")) {
852+
spvBuilder.addExecutionMode(
853+
entryFunction, spv::ExecutionMode::DenormFlushToZero, {32}, {});
854+
} else if (denormMode.equals_lower("any")) {
855+
// Do nothing. Since any behavior is allowed, we could optionally choose
856+
// to translate to DenormPreserve or DenormFlushToZero if one was known to
857+
// be more performant on most platforms.
858+
} else {
859+
assert(false && "unsupported denorm value");
860+
}
861+
}
862+
846863
// Output the constructed module.
847864
std::vector<uint32_t> m = spvBuilder.takeModule();
848865
if (context.getDiagnostics().hasErrorOccurred())
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// RUN: not %dxc -E main -T ps_6_2 -denorm bad -spirv %s 2>&1 | FileCheck %s
2+
3+
// CHECK: dxc failed : Unsupported value 'bad' for denorm option.
4+
5+
float4 main(float4 col : COL) : SV_Target {
6+
return col;
7+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// RUN: %dxc -E main -T ps_6_2 -denorm preserve -spirv %s | FileCheck --check-prefixes=CHECK-PRE %s
2+
// RUN: %dxc -E main -T ps_6_2 -denorm preserve -spirv -fspv-target-env=vulkan1.2 %s | FileCheck --check-prefixes=CHECK-PRE-VK12 %s
3+
// RUN: %dxc -E main -T ps_6_2 -denorm ftz -spirv %s | FileCheck --check-prefixes=CHECK-FTZ %s
4+
// RUN: %dxc -E main -T ps_6_2 -denorm any -spirv %s | FileCheck --check-prefixes=CHECK-DEFAULT %s
5+
// RUN: %dxc -E main -T ps_6_2 -spirv %s | FileCheck --check-prefixes=CHECK-DEFAULT %s
6+
7+
// CHECK-PRE: OpCapability DenormPreserve
8+
// CHECK-PRE: OpExtension "SPV_KHR_float_controls"
9+
// CHECK-PRE: OpExecutionMode %main DenormPreserve 32
10+
11+
// CHECK-PRE-VK12: OpCapability DenormPreserve
12+
// CHECK-PRE-VK12-NOT: OpExtension "SPV_KHR_float_controls"
13+
// CHECK-PRE-VK12: OpExecutionMode %main DenormPreserve 32
14+
15+
// CHECK-FTZ: OpCapability DenormFlushToZero
16+
// CHECK-FTZ: OpExtension "SPV_KHR_float_controls"
17+
// CHECK-FTZ: OpExecutionMode %main DenormFlushToZero 32
18+
19+
// CHECK-DEFAULT-NOT: OpCapability DenormPreserve
20+
// CHECK-DEFAULT-NOT: OpExtension "SPV_KHR_float_controls"
21+
// CHECK-DEFAULT-NOT: OpExecutionMode %main Denorm
22+
float4 main(float4 col : COL) : SV_Target {
23+
return col;
24+
}

0 commit comments

Comments
 (0)