Skip to content

Commit a53e73e

Browse files
s-perronllvm-beanz
andauthored
[SPIRV][HLSL] Add DXC compatibility option for extension (#151554)
The default behaviour in DXC is to allow all extesions the compiler knows about. We did the same in clang: all extensions that clang knows about. However, this causes the shader to use different extensions because the two compilers have different sets of extensions. To avoid using a new extension when moving from DXC to Clang, we add the special DXC suboptions to `-fspv-extension`. If `-fspv-extension=DXC` is used, then the available extensions will be those available in DXC. --------- Co-authored-by: Chris B <[email protected]>
1 parent cfef05e commit a53e73e

File tree

4 files changed

+114
-12
lines changed

4 files changed

+114
-12
lines changed

clang/include/clang/Driver/Options.td

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9468,8 +9468,12 @@ def fspv_target_env_EQ : Joined<["-"], "fspv-target-env=">, Group<dxc_Group>,
94689468
def fspv_extension_EQ
94699469
: Joined<["-"], "fspv-extension=">,
94709470
Group<dxc_Group>,
9471-
HelpText<"Specify the available SPIR-V extensions. If this option is not "
9472-
"specified, then all extensions are available.">;
9471+
HelpText<
9472+
"Specify the available SPIR-V extensions. If this option is not "
9473+
"specified, then all extensions are available. If KHR is specified, "
9474+
"then all KHR extensions will be available. If DXC is specifided, "
9475+
"then all extensions implemented by the DirectX Shader compiler will "
9476+
"be available. This option is useful for moving from DXC to Clang.">;
94739477
def fvk_use_dx_layout
94749478
: DXCFlag<"fvk-use-dx-layout">,
94759479
HelpText<"Use DirectX memory layout for Vulkan resources.">;

clang/lib/Driver/ToolChains/HLSL.cpp

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -173,24 +173,72 @@ bool isLegalValidatorVersion(StringRef ValVersionStr, const Driver &D) {
173173
return true;
174174
}
175175

176-
std::string getSpirvExtArg(ArrayRef<std::string> SpvExtensionArgs) {
176+
void getSpirvExtOperand(StringRef SpvExtensionArg, raw_ostream &out) {
177+
// The extensions that are commented out are supported in DXC, but the SPIR-V
178+
// backend does not know about them yet.
179+
static const std::vector<StringRef> DxcSupportedExtensions = {
180+
"SPV_KHR_16bit_storage", "SPV_KHR_device_group",
181+
"SPV_KHR_fragment_shading_rate", "SPV_KHR_multiview",
182+
"SPV_KHR_post_depth_coverage", "SPV_KHR_non_semantic_info",
183+
"SPV_KHR_shader_draw_parameters", "SPV_KHR_ray_tracing",
184+
"SPV_KHR_shader_clock", "SPV_EXT_demote_to_helper_invocation",
185+
"SPV_EXT_descriptor_indexing", "SPV_EXT_fragment_fully_covered",
186+
"SPV_EXT_fragment_invocation_density",
187+
"SPV_EXT_fragment_shader_interlock", "SPV_EXT_mesh_shader",
188+
"SPV_EXT_shader_stencil_export", "SPV_EXT_shader_viewport_index_layer",
189+
// "SPV_AMD_shader_early_and_late_fragment_tests",
190+
"SPV_GOOGLE_hlsl_functionality1", "SPV_GOOGLE_user_type",
191+
"SPV_KHR_ray_query", "SPV_EXT_shader_image_int64",
192+
"SPV_KHR_fragment_shader_barycentric", "SPV_KHR_physical_storage_buffer",
193+
"SPV_KHR_vulkan_memory_model",
194+
// "SPV_KHR_compute_shader_derivatives",
195+
// "SPV_KHR_maximal_reconvergence",
196+
"SPV_KHR_float_controls", "SPV_NV_shader_subgroup_partitioned",
197+
// "SPV_KHR_quad_control"
198+
};
199+
200+
if (SpvExtensionArg.starts_with("SPV_")) {
201+
out << "+" << SpvExtensionArg;
202+
return;
203+
}
204+
205+
if (SpvExtensionArg.compare_insensitive("DXC") == 0) {
206+
bool first = true;
207+
std::string Operand;
208+
for (StringRef E : DxcSupportedExtensions) {
209+
if (!first)
210+
out << ",";
211+
else
212+
first = false;
213+
out << "+" << E;
214+
}
215+
return;
216+
}
217+
out << SpvExtensionArg;
218+
return;
219+
}
220+
221+
SmallString<1024> getSpirvExtArg(ArrayRef<std::string> SpvExtensionArgs) {
177222
if (SpvExtensionArgs.empty()) {
178-
return "-spirv-ext=all";
223+
return StringRef("-spirv-ext=all");
179224
}
180225

181-
std::string LlvmOption =
182-
(Twine("-spirv-ext=+") + SpvExtensionArgs.front()).str();
226+
llvm::SmallString<1024> LlvmOption;
227+
raw_svector_ostream out(LlvmOption);
228+
229+
out << "-spirv-ext=";
230+
getSpirvExtOperand(SpvExtensionArgs[0], out);
231+
183232
SpvExtensionArgs = SpvExtensionArgs.slice(1);
184-
for (auto Extension : SpvExtensionArgs) {
185-
if (Extension != "KHR")
186-
Extension = (Twine("+") + Extension).str();
187-
LlvmOption = (Twine(LlvmOption) + "," + Extension).str();
233+
for (StringRef Extension : SpvExtensionArgs) {
234+
out << ",";
235+
getSpirvExtOperand(Extension, out);
188236
}
189237
return LlvmOption;
190238
}
191239

192240
bool isValidSPIRVExtensionName(const std::string &str) {
193-
std::regex pattern("KHR|SPV_[a-zA-Z0-9_]+");
241+
std::regex pattern("dxc|DXC|khr|KHR|SPV_[a-zA-Z0-9_]+");
194242
return std::regex_match(str, pattern);
195243
}
196244

@@ -371,7 +419,7 @@ HLSLToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
371419
std::vector<std::string> SpvExtensionArgs =
372420
Args.getAllArgValues(options::OPT_fspv_extension_EQ);
373421
if (checkExtensionArgsAreValid(SpvExtensionArgs, getDriver())) {
374-
std::string LlvmOption = getSpirvExtArg(SpvExtensionArgs);
422+
SmallString<1024> LlvmOption = getSpirvExtArg(SpvExtensionArgs);
375423
DAL->AddSeparateArg(nullptr, Opts.getOption(options::OPT_mllvm),
376424
LlvmOption);
377425
}

clang/test/Driver/dxc_fspv_extension.hlsl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@
1414
// RUN: %clang_dxc -spirv -Tlib_6_7 -### %s -fspv-extension=SPV_TEST1 -fspv-extension=KHR -fspv-extension=SPV_TEST2 2>&1 | FileCheck %s -check-prefix=TEST3
1515
// TEST3: "-spirv-ext=+SPV_TEST1,KHR,+SPV_TEST2"
1616

17+
// Merge KHR with other extensions.
18+
// RUN: %clang_dxc -spirv -Tlib_6_7 -### %s -fspv-extension=KHR -fspv-extension=SPV_TEST2 2>&1 | FileCheck %s -check-prefix=TEST4
19+
// TEST4: "-spirv-ext=KHR,+SPV_TEST2"
20+
21+
// Convert DXC to a list of SPV extensions.
22+
// RUN: %clang_dxc -spirv -Tlib_6_7 -### %s -fspv-extension=DXC 2>&1 | FileCheck %s -check-prefix=TEST5
23+
// TEST5: "-spirv-ext={{(\+SPV_[a-zA-Z0-9_]+,?)+}}"
24+
1725
// Check for the error message if the extension name is not properly formed.
1826
// RUN: not %clang_dxc -spirv -Tlib_6_7 -### %s -fspv-extension=KHR_BAD -fspv-extension=TEST1 -fspv-extension=SPV_GOOD -fspv-extension=TEST2 2>&1 | FileCheck %s -check-prefix=FAIL
1927
// FAIL: invalid value 'KHR_BAD' in '-fspv-extension'

llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,24 @@ static const std::map<std::string, SPIRV::Extension::Extension, std::less<>>
3333
SPIRV::Extension::Extension::SPV_EXT_arithmetic_fence},
3434
{"SPV_EXT_demote_to_helper_invocation",
3535
SPIRV::Extension::Extension::SPV_EXT_demote_to_helper_invocation},
36+
{"SPV_EXT_descriptor_indexing",
37+
SPIRV::Extension::Extension::SPV_EXT_descriptor_indexing},
38+
{"SPV_EXT_fragment_fully_covered",
39+
SPIRV::Extension::Extension::SPV_EXT_fragment_fully_covered},
40+
{"SPV_EXT_fragment_invocation_density",
41+
SPIRV::Extension::Extension::SPV_EXT_fragment_invocation_density},
42+
{"SPV_EXT_fragment_shader_interlock",
43+
SPIRV::Extension::Extension::SPV_EXT_fragment_shader_interlock},
44+
{"SPV_EXT_mesh_shader",
45+
SPIRV::Extension::Extension::SPV_EXT_mesh_shader},
46+
{"SPV_EXT_shader_stencil_export",
47+
SPIRV::Extension::Extension::SPV_EXT_shader_stencil_export},
48+
{"SPV_EXT_shader_viewport_index_layer",
49+
SPIRV::Extension::Extension::SPV_EXT_shader_viewport_index_layer},
50+
{"SPV_GOOGLE_hlsl_functionality1",
51+
SPIRV::Extension::Extension::SPV_GOOGLE_hlsl_functionality1},
52+
{"SPV_GOOGLE_user_type",
53+
SPIRV::Extension::Extension::SPV_GOOGLE_user_type},
3654
{"SPV_INTEL_arbitrary_precision_integers",
3755
SPIRV::Extension::Extension::SPV_INTEL_arbitrary_precision_integers},
3856
{"SPV_INTEL_cache_controls",
@@ -58,6 +76,19 @@ static const std::map<std::string, SPIRV::Extension::Extension, std::less<>>
5876
SPIRV::Extension::Extension::SPV_INTEL_memory_access_aliasing},
5977
{"SPV_INTEL_joint_matrix",
6078
SPIRV::Extension::Extension::SPV_INTEL_joint_matrix},
79+
{"SPV_KHR_16bit_storage",
80+
SPIRV::Extension::Extension::SPV_KHR_16bit_storage},
81+
{"SPV_KHR_device_group",
82+
SPIRV::Extension::Extension::SPV_KHR_device_group},
83+
{"SPV_KHR_fragment_shading_rate",
84+
SPIRV::Extension::Extension::SPV_KHR_fragment_shading_rate},
85+
{"SPV_KHR_multiview", SPIRV::Extension::Extension::SPV_KHR_multiview},
86+
{"SPV_KHR_post_depth_coverage",
87+
SPIRV::Extension::Extension::SPV_KHR_post_depth_coverage},
88+
{"SPV_KHR_shader_draw_parameters",
89+
SPIRV::Extension::Extension::SPV_KHR_shader_draw_parameters},
90+
{"SPV_KHR_ray_tracing",
91+
SPIRV::Extension::Extension::SPV_KHR_ray_tracing},
6192
{"SPV_KHR_uniform_group_instructions",
6293
SPIRV::Extension::Extension::SPV_KHR_uniform_group_instructions},
6394
{"SPV_KHR_no_integer_wrap_decoration",
@@ -90,6 +121,17 @@ static const std::map<std::string, SPIRV::Extension::Extension, std::less<>>
90121
SPIRV::Extension::Extension::SPV_KHR_cooperative_matrix},
91122
{"SPV_KHR_non_semantic_info",
92123
SPIRV::Extension::Extension::SPV_KHR_non_semantic_info},
124+
{"SPV_KHR_ray_query", SPIRV::Extension::Extension::SPV_KHR_ray_query},
125+
{"SPV_EXT_shader_image_int64",
126+
SPIRV::Extension::Extension::SPV_EXT_shader_image_int64},
127+
{"SPV_KHR_fragment_shader_barycentric",
128+
SPIRV::Extension::Extension::SPV_KHR_fragment_shader_barycentric},
129+
{"SPV_KHR_physical_storage_buffer",
130+
SPIRV::Extension::Extension::SPV_KHR_physical_storage_buffer},
131+
{"SPV_KHR_vulkan_memory_model",
132+
SPIRV::Extension::Extension::SPV_KHR_vulkan_memory_model},
133+
{"SPV_NV_shader_subgroup_partitioned",
134+
SPIRV::Extension::Extension::SPV_NV_shader_subgroup_partitioned},
93135
{"SPV_INTEL_long_composites",
94136
SPIRV::Extension::Extension::SPV_INTEL_long_composites},
95137
{"SPV_INTEL_fp_max_error",

0 commit comments

Comments
 (0)