Skip to content

Commit

Permalink
Add option to set the max id (microsoft#6654)
Browse files Browse the repository at this point in the history
Vulkan implementation can have different limits on the maximum value
used as an id in a SPIR-V binary. SPIRV-Tools generall assumes this
limit is 0x3FFFFF because all implementations must support at least that
value for an id.  Since many implementations can support larger values,
the tools allows an option that will set a different limit. This commit
add an option to DXC to do the same.

Fixes microsoft#6636
  • Loading branch information
s-perron authored Jun 10, 2024
1 parent 1d19665 commit 4b7993c
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 0 deletions.
2 changes: 2 additions & 0 deletions include/dxc/Support/HLSLOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,8 @@ def fspv_preserve_interface : Flag<["-"], "fspv-preserve-interface">, Group<spir
HelpText<"Preserves all interface variables in the entry point, even when those variables are unused">;
def fvk_allow_rwstructuredbuffer_arrays: Flag<["-"], "fvk-allow-rwstructuredbuffer-arrays">, Group<spirv_Group>, Flags<[CoreOption, DriverOption, HelpHidden]>,
HelpText<"Allow arrays of RWStructuredBuffers, AppendStructuredBuffers, and ConsumeStructuredBuffers. This is in development, and the option will be removed when the feature is complete.">;
def fspv_max_id : MultiArg<["-"], "fspv-max-id", 1>, MetaVarName<"<shift> <space>">, Group<spirv_Group>, Flags<[CoreOption, DriverOption]>,
HelpText<"Set the maximum value for an id in the SPIR-V binary. Default is 0x3FFFFF, which is the largest value all drivers must support.">;
// SPIRV Change Ends

//////////////////////////////////////////////////////////////////////////////
Expand Down
1 change: 1 addition & 0 deletions include/dxc/Support/SPIRVOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ struct SpirvCodeGenOptions {
SpirvLayoutRule ampPayloadLayoutRule;
llvm::StringRef stageIoOrder;
llvm::StringRef targetEnv;
uint32_t maxId;
llvm::SmallVector<int32_t, 4> bShift;
llvm::SmallVector<int32_t, 4> sShift;
llvm::SmallVector<int32_t, 4> tShift;
Expand Down
9 changes: 9 additions & 0 deletions lib/DxcSupport/HLSLOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1179,6 +1179,15 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
opts.SpirvOptions.targetEnv =
Args.getLastArgValue(OPT_fspv_target_env_EQ, "vulkan1.0");

llvm::APInt maxId;

// 0X3FFFFF is the default value for -fspv-max-id because it is the largest
// value that is guaranteed to be allowed in all Vulkan implementations.
if (Args.getLastArgValue(OPT_fspv_max_id, "3FFFFF").getAsInteger(16, maxId)) {
errors << "-fspv-max-id must be an integer in hexadecimal format";
}
opts.SpirvOptions.maxId = maxId.getLimitedValue(0xFFFFFFFF);

// Handle -Oconfig=<comma-separated-list> option.
uint32_t numOconfigs = 0;
for (const Arg *A : Args.filtered(OPT_Oconfig)) {
Expand Down
6 changes: 6 additions & 0 deletions tools/clang/lib/SPIRV/SpirvEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14415,6 +14415,8 @@ bool SpirvEmitter::spirvToolsValidate(std::vector<uint32_t> *mod,
} else {
options.SetRelaxBlockLayout(true);
}
options.SetUniversalLimit(spv_validator_limit_max_id_bound,
spirvOptions.maxId);

return tools.Validate(mod->data(), mod->size(), options);
}
Expand Down Expand Up @@ -14487,6 +14489,7 @@ bool SpirvEmitter::spirvToolsTrimCapabilities(std::vector<uint32_t> *mod,
spvtools::OptimizerOptions options;
options.set_run_validator(false);
options.set_preserve_bindings(spirvOptions.preserveBindings);
options.set_max_id_bound(spirvOptions.maxId);

optimizer.RegisterPass(spvtools::CreateTrimCapabilitiesPass());

Expand All @@ -14509,6 +14512,7 @@ bool SpirvEmitter::spirvToolsOptimize(std::vector<uint32_t> *mod,
spvtools::OptimizerOptions options;
options.set_run_validator(false);
options.set_preserve_bindings(spirvOptions.preserveBindings);
options.set_max_id_bound(spirvOptions.maxId);

if (spirvOptions.optConfig.empty()) {
// Add performance passes.
Expand Down Expand Up @@ -14550,6 +14554,8 @@ bool SpirvEmitter::spirvToolsLegalize(std::vector<uint32_t> *mod,
spvtools::OptimizerOptions options;
options.set_run_validator(false);
options.set_preserve_bindings(spirvOptions.preserveBindings);
options.set_max_id_bound(spirvOptions.maxId);

// Add interface variable SROA if the signature packing is enabled.
if (spirvOptions.signaturePacking) {
optimizer.RegisterPass(
Expand Down
23 changes: 23 additions & 0 deletions tools/clang/test/CodeGenSPIRV/max_id.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// RUN: not %dxc -T cs_6_0 -E main %s -spirv -fspv-max-id 30 2>&1 | FileCheck %s --check-prefix=CHECK-30
// RUN: %dxc -T cs_6_0 -E main %s -spirv -fspv-max-id 400 2>&1 | FileCheck %s --check-prefix=CHECK-400

// With a lower limit, there will be an ID overflow in the optimizer. Note that
// the error message can vary depending on where the optimizer fails. This test
// is low enough to fail as early as possible leading to a consistent error
// message.
// CHECK-30: fatal error: failed to optimize SPIR-V: ID overflow. Try running compact-ids.

// With a larger limit, the test case can compile successfully.
// CHECK-400: Bound: 204


RWStructuredBuffer<int> data;

[numthreads(1,1,1)]
void main(uint3 id : SV_DispatchThreadID)
{
[[unroll]]
for( int i = 0; i < 64; i++ ) {
data[i] = i;
}
}

0 comments on commit 4b7993c

Please sign in to comment.