Skip to content

Commit 129c9f8

Browse files
authored
[SPIR-V] Re-enable rich debug instructions for objects (microsoft#6696)
This commit bumps SPIR-V tools version, and re-add support for objects debug instructions when using Vulkan's debug instructions. Because OpenCL debug instructions are not a non-semantic set, the SPIR-V spec would need to be modified, as today it does not allows forward references. Fixes microsoft#6691 --------- Signed-off-by: Nathan Gauër <[email protected]>
1 parent 393b759 commit 129c9f8

File tree

7 files changed

+124
-15
lines changed

7 files changed

+124
-15
lines changed

tools/clang/lib/SPIRV/DebugTypeVisitor.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -162,13 +162,13 @@ void DebugTypeVisitor::lowerDebugTypeMembers(
162162
}
163163

164164
// Note:
165-
// The NonSemantic.Shader.DebugInfo.100 way to define member functions
166-
// breaks both the NonSemantic and SPIR-V specification. Until this is
167-
// resolved, we cannot emit debug instructions for member functions without
168-
// creating invalid forward references.
169-
//
165+
// Generating forward references is possible for non-semantic debug info,
166+
// but not when using OpenCL.DebugInfo.100.
167+
// Doing so would go against the SPIR-V spec.
170168
// See https://github.com/KhronosGroup/SPIRV-Registry/issues/203
171-
#if 0
169+
if (!spvOptions.debugInfoVulkan)
170+
return;
171+
172172
// Push member functions to DebugTypeComposite Members operand.
173173
for (auto *subDecl : decl->decls()) {
174174
if (const auto *methodDecl = dyn_cast<FunctionDecl>(subDecl)) {
@@ -181,7 +181,6 @@ void DebugTypeVisitor::lowerDebugTypeMembers(
181181
}
182182
}
183183
}
184-
#endif
185184
}
186185

187186
SpirvDebugTypeTemplate *DebugTypeVisitor::lowerDebugTypeTemplate(

tools/clang/lib/SPIRV/SpirvEmitter.cpp

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -744,11 +744,12 @@ void SpirvEmitter::HandleTranslationUnit(ASTContext &context) {
744744
if (context.getDiagnostics().hasErrorOccurred())
745745
return;
746746

747-
if (spirvOptions.debugInfoRich) {
748-
emitWarning("Member functions will not be linked to their class in the "
749-
"debug information. "
750-
"See https://github.com/KhronosGroup/SPIRV-Registry/issues/203",
751-
{});
747+
if (spirvOptions.debugInfoRich && !spirvOptions.debugInfoVulkan) {
748+
emitWarning(
749+
"Member functions will not be linked to their class in the "
750+
"debug information. Prefer using -fspv-debug=vulkan-with-source. "
751+
"See https://github.com/KhronosGroup/SPIRV-Registry/issues/203",
752+
{});
752753
}
753754

754755
TranslationUnitDecl *tu = context.getTranslationUnitDecl();
@@ -930,6 +931,23 @@ void SpirvEmitter::HandleTranslationUnit(ASTContext &context) {
930931
}
931932
}
932933

934+
// Fixup debug instruction opcodes: change the opcode to
935+
// OpExtInstWithForwardRefsKHR is the instruction at least one forward
936+
// reference.
937+
if (spirvOptions.debugInfoRich) {
938+
std::string messages;
939+
if (!spirvToolsFixupOpExtInst(&m, &messages)) {
940+
emitFatalError("failed to fix OpExtInst opcodes: %0", {}) << messages;
941+
emitNote("please file a bug report on "
942+
"https://github.com/Microsoft/DirectXShaderCompiler/issues "
943+
"with source code if possible",
944+
{});
945+
return;
946+
} else if (!messages.empty()) {
947+
emitWarning("SPIR-V fix-opextinst-opcodes: %0", {}) << messages;
948+
}
949+
}
950+
933951
// Trim unused capabilities.
934952
// When optimizations are enabled, some optimization passes like DCE could
935953
// make some capabilities useless. To avoid logic duplication between this
@@ -14472,6 +14490,30 @@ SpirvEmitter::createFunctionScopeTempFromParameter(const ParmVarDecl *param) {
1447214490
return tempVar;
1447314491
}
1447414492

14493+
bool SpirvEmitter::spirvToolsFixupOpExtInst(std::vector<uint32_t> *mod,
14494+
std::string *messages) {
14495+
spvtools::Optimizer optimizer(featureManager.getTargetEnv());
14496+
optimizer.SetMessageConsumer(
14497+
[messages](spv_message_level_t /*level*/, const char * /*source*/,
14498+
const spv_position_t & /*position*/,
14499+
const char *message) { *messages += message; });
14500+
14501+
string::RawOstreamBuf printAllBuf(llvm::errs());
14502+
std::ostream printAllOS(&printAllBuf);
14503+
if (spirvOptions.printAll)
14504+
optimizer.SetPrintAll(&printAllOS);
14505+
14506+
spvtools::OptimizerOptions options;
14507+
options.set_run_validator(false);
14508+
options.set_preserve_bindings(spirvOptions.preserveBindings);
14509+
options.set_max_id_bound(spirvOptions.maxId);
14510+
14511+
optimizer.RegisterPass(
14512+
spvtools::CreateOpExtInstWithForwardReferenceFixupPass());
14513+
14514+
return optimizer.Run(mod->data(), mod->size(), mod, options);
14515+
}
14516+
1447514517
bool SpirvEmitter::spirvToolsTrimCapabilities(std::vector<uint32_t> *mod,
1447614518
std::string *messages) {
1447714519
spvtools::Optimizer optimizer(featureManager.getTargetEnv());

tools/clang/lib/SPIRV/SpirvEmitter.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,6 +1180,12 @@ class SpirvEmitter : public ASTConsumer {
11801180
/// Returns true on success and false otherwise.
11811181
bool spirvToolsOptimize(std::vector<uint32_t> *mod, std::string *messages);
11821182

1183+
// \brief Calls SPIRV-Tools optimizer fix-opextinst-opcodes pass. This pass
1184+
// fixes OpExtInst/OpExtInstWithForwardRefsKHR opcodes to use the correct one
1185+
// depending of the presence of forward references.
1186+
bool spirvToolsFixupOpExtInst(std::vector<uint32_t> *mod,
1187+
std::string *messages);
1188+
11831189
// \brief Calls SPIRV-Tools optimizer's, but only with the capability trimming
11841190
// pass. Removes unused capabilities from the given SPIR-V module |mod|, and
11851191
// returns info/warning/error messages via |messages|. This pass doesn't trim

tools/clang/test/CodeGenSPIRV/rich.debug.type.composite.warning.hlsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ float4 main(float4 color : COLOR) : SV_TARGET {
88
return color;
99
}
1010

11-
// CHECK: warning: Member functions will not be linked to their class in the debug information. See https://github.com/KhronosGroup/SPIRV-Registry/issues/203
11+
// CHECK: warning: Member functions will not be linked to their class in the debug information. Prefer using -fspv-debug=vulkan-with-source. See https://github.com/KhronosGroup/SPIRV-Registry/issues/203
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// RUN: %dxc -T ps_6_0 -E main -fspv-debug=vulkan-with-source -O0 %s -spirv | FileCheck %s
2+
3+
// CHECK-DAG: OpExtension "SPV_KHR_non_semantic_info"
4+
// CHECK-DAG: OpExtension "SPV_KHR_relaxed_extended_instruction"
5+
// CHECK: [[set:%[0-9]+]] = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
6+
7+
8+
// CHECK-DAG: [[strInt:%[0-9]+]] = OpString "int"
9+
// CHECK-DAG: [[strFloat:%[0-9]+]] = OpString "float"
10+
// CHECK-DAG: [[strBool:%[0-9]+]] = OpString "bool"
11+
// CHECK-DAG: [[strA:%[0-9]+]] = OpString "a"
12+
// CHECK-DAG: [[strB:%[0-9]+]] = OpString "b"
13+
// CHECK-DAG: [[strC:%[0-9]+]] = OpString "c"
14+
// CHECK-DAG: [[strFunc0:%[0-9]+]] = OpString "foo.func0"
15+
// CHECK-DAG: [[strFoo:%[0-9]+]] = OpString "foo"
16+
// CHECK-DAG: [[strFunc1:%[0-9]+]] = OpString "foo.func1"
17+
18+
// CHECK: [[int:%[0-9]+]] = OpExtInst %void [[set]] DebugTypeBasic [[strInt]] %uint_32 %uint_4 %uint_0
19+
// CHECK: [[unit:%[0-9]+]] = OpExtInst %void [[set]] DebugCompilationUnit %uint_1 %uint_4 {{%[0-9]+}} %uint_5
20+
21+
struct foo {
22+
23+
// CHECK: [[a:%[0-9]+]] = OpExtInst %void [[set]] DebugTypeMember [[strA]] [[int]] {{%[0-9]+}} %uint_24 %uint_7 %uint_0 %uint_32 %uint_3
24+
int a;
25+
26+
// CHECK: [[float:%[0-9]+]] = OpExtInst %void [[set]] DebugTypeBasic [[strFloat]] %uint_32 %uint_3 %uint_0
27+
// CHECK: [[v4f:%[0-9]+]] = OpExtInst %void [[set]] DebugTypeVector [[float]] %uint_4
28+
// CHECK: [[b:%[0-9]+]] = OpExtInst %void [[set]] DebugTypeMember [[strB]] [[v4f]] {{%[0-9]+}} %uint_29 %uint_10 %uint_32 %uint_128 %uint_3
29+
float4 b;
30+
31+
// CHECK: [[bool:%[0-9]+]] = OpExtInst %void [[set]] DebugTypeBasic [[strBool]] %uint_32 %uint_2 %uint_0
32+
// CHECK: [[c:%[0-9]+]] = OpExtInst %void [[set]] DebugTypeMember [[strC]] [[bool]] {{%[0-9]+}} %uint_33 %uint_8 %uint_160 %uint_32 %uint_3
33+
bool c;
34+
35+
// CHECK: [[func0t:%[0-9]+]] = OpExtInstWithForwardRefsKHR %void [[set]] DebugTypeFunction %uint_3 %void [[foo:%[0-9]+]] {{%[0-9]+}}
36+
// CHECK: [[func0:%[0-9]+]] = OpExtInstWithForwardRefsKHR %void [[set]] DebugFunction [[strFunc0]] [[func0t]] {{%[0-9]+}} %uint_39 %uint_3 [[foo]] {{%[0-9]+}} %uint_3 %uint_39
37+
// CHECK: [[foo]] = OpExtInstWithForwardRefsKHR %void [[set]] DebugTypeComposite [[strFoo]] %uint_1 {{%[0-9]+}} %uint_21 %uint_8 [[unit]] [[strFoo]] %uint_192 %uint_3 [[a]] [[b]] [[c]] [[func0]] [[func1:%[0-9]+]]
38+
39+
void func0(float arg) {
40+
b.x = arg;
41+
}
42+
43+
44+
// CHECK: [[func1t:%[0-9]+]] = OpExtInst %void [[set]] DebugTypeFunction %uint_3 [[int]] [[foo:%[0-9]+]] [[int]] [[float]] [[bool]]
45+
// CHECK: [[func1]] = OpExtInst %void [[set]] DebugFunction [[strFunc1]] [[func1t]] {{%[0-9]+}} %uint_46 %uint_3 [[foo]] {{%[0-9]+}} %uint_3 %uint_46
46+
int func1(int arg0, float arg1, bool arg2) {
47+
a = arg0;
48+
b.y = arg1;
49+
if (arg2) return arg0;
50+
return b.z;
51+
}
52+
53+
};
54+
55+
56+
float4 main(float4 color : COLOR) : SV_TARGET {
57+
foo a;
58+
a.func0(1);
59+
a.func1(1, 1, 1);
60+
61+
return color;
62+
}

0 commit comments

Comments
 (0)