From 1dc32b8bf8dd14e607d306c160b1bedf46067910 Mon Sep 17 00:00:00 2001 From: Jay Kwak <82421531+jkwak-work@users.noreply.github.com> Date: Fri, 11 Jul 2025 13:47:33 -0700 Subject: Add DebugGlobalVariable instructions to SPIR-V output (#7686) * Add DebugGlobalVariable instructions to SPIR-V output Implements generation of DebugGlobalVariable instructions for global variables like Texture2D and SamplerState in SPIR-V debug information output. Adds debug type support for texture and sampler types using DebugTypeComposite. * Handle two more types for DebugGlobalVariable kIROp_RaytracingAccelerationStructureType and kIROp_SamplerComparisonStateType had to be handled in `emitDebugTypeImpl()` * Fix format * Refactor debug type emission to reduce duplication Use IRSamplerStateTypeBase type check and fallback pattern instead of separate cases for each opcode type. * Fix compiler warning * Simplify `emitDebugTypeImpl()` more --- source/slang/slang-emit-spirv-ops-debug-info-ext.h | 36 +++++++++++++ source/slang/slang-emit-spirv.cpp | 59 +++++++++++++++++++++- tests/spirv/debug-local-variable-scope.slang | 21 -------- tests/spirv/debug-variable-scope.slang | 23 +++++++++ 4 files changed, 117 insertions(+), 22 deletions(-) delete mode 100644 tests/spirv/debug-local-variable-scope.slang create mode 100644 tests/spirv/debug-variable-scope.slang diff --git a/source/slang/slang-emit-spirv-ops-debug-info-ext.h b/source/slang/slang-emit-spirv-ops-debug-info-ext.h index 138204af7..ab2d7b730 100644 --- a/source/slang/slang-emit-spirv-ops-debug-info-ext.h +++ b/source/slang/slang-emit-spirv-ops-debug-info-ext.h @@ -554,6 +554,42 @@ SpvInst* emitOpDebugLocalVariable( flags); } +template +SpvInst* emitOpDebugGlobalVariable( + SpvInstParent* parent, + IRInst* inst, + const T& idResultType, + SpvInst* set, + IRInst* name, + SpvInst* type, + IRInst* source, + IRInst* line, + IRInst* col, + SpvInst* scope, + IRInst* linkageName, + SpvInst* variable, + IRInst* flags) +{ + static_assert(isSingular); + return emitInst( + parent, + inst, + SpvOpExtInst, + idResultType, + kResultID, + set, + SpvWord(18), // DebugGlobalVariable opcode in NonSemantic.Shader.DebugInfo.100 + name, + type, + source, + line, + col, + scope, + linkageName, + variable, + flags); +} + template SpvInst* emitOpDebugInlinedVariable( SpvInstParent* parent, diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index 28862f5b8..376a828cd 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -3215,6 +3215,7 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex if (layout) emitVarLayout(param, varInst, layout); emitDecorations(param, getID(varInst)); + maybeEmitDebugGlobalVariable(param, varInst); return varInst; } @@ -3237,6 +3238,7 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex if (layout) emitVarLayout(globalVar, varInst, layout); emitDecorations(globalVar, getID(varInst)); + maybeEmitDebugGlobalVariable(globalVar, varInst); return varInst; } @@ -3893,6 +3895,39 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex return nullptr; } + void maybeEmitDebugGlobalVariable(IRInst* globalInst, SpvInst* spvVar) + { + auto scope = findDebugScope(globalInst->getModule()->getModuleInst()); + if (!scope) + return; + + auto name = getName(globalInst); + IRBuilder builder(globalInst); + auto varType = tryGetPointedToType(&builder, globalInst->getDataType()); + auto debugType = emitDebugType(varType); + + // Use default debug source and line info similar to struct debug type emission + auto loc = globalInst->findDecoration(); + IRInst* source = loc ? loc->getSource() : m_defaultDebugSource; + IRInst* line = loc ? loc->getLine() : builder.getIntValue(builder.getUIntType(), 0); + IRInst* col = loc ? loc->getCol() : line; + + emitOpDebugGlobalVariable( + getSection(SpvLogicalSectionID::GlobalVariables), + nullptr, // Don't associate with IR inst to avoid duplicate registration + m_voidType, + getNonSemanticDebugInfoExtInst(), + name, + debugType, + source, + line, + col, + scope, + name, // linkageName same as name + spvVar, + builder.getIntValue(builder.getUIntType(), 0)); // flags + } + SpvInst* emitMakeUInt64(SpvInstParent* parent, IRInst* inst) { IRBuilder builder(inst); @@ -8524,7 +8559,29 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex debugBaseType, builder.getIntValue(builder.getUIntType(), kDebugTypeAtomicQualifier)); } - return ensureInst(m_voidType); + + // Fallback for texture types, raytracing types, and other composite types + // Declare variables for debug location like struct handling does + IRInst* source = m_defaultDebugSource; + IRInst* line = builder.getIntValue(builder.getUIntType(), 0); + IRInst* col = line; + + // Emit a composite debug type (struct-like for most types) + return emitOpDebugTypeComposite( + getSection(SpvLogicalSectionID::ConstantsAndTypes), + nullptr, + m_voidType, + getNonSemanticDebugInfoExtInst(), + name, + builder.getIntValue(builder.getUIntType(), 0), + source, + line, + col, + scope, + name, + builder.getIntValue(builder.getUIntType(), 0), // Size (unknown) + builder.getIntValue(builder.getUIntType(), kUnknownPhysicalLayout), + List()); // No members } SpvInst* emitDebugType(IRType* type) diff --git a/tests/spirv/debug-local-variable-scope.slang b/tests/spirv/debug-local-variable-scope.slang deleted file mode 100644 index 22f6aef2e..000000000 --- a/tests/spirv/debug-local-variable-scope.slang +++ /dev/null @@ -1,21 +0,0 @@ -//TEST:SIMPLE(filecheck=CHECK):-target spirv -entry main -stage fragment -g2 -emit-spirv-directly - -Texture2D testTex : register(t0); -SamplerState testSampler : register(s0); - -struct PSIn -{ - float4 pos : SV_Position; -}; - -float4 main(PSIn input) : SV_TARGET -{ - uint4 testPos = input.pos; - float bias = -1.0; - float2 tc = testPos.xy / 32.0; - float4 colVal = testTex.SampleBias(testSampler, tc, bias); - return float4(colVal.xyz, 1.0); -} - -// CHECK: %[[FUNC_ID:[0-9]+]] = OpExtInst %void {{.*}} DebugFunction %{{[0-9]+}} -// CHECK: DebugLocalVariable %{{[0-9]+}} %{{[0-9]+}} %{{[0-9]+}} %{{.*}} %{{.*}} %[[FUNC_ID]] diff --git a/tests/spirv/debug-variable-scope.slang b/tests/spirv/debug-variable-scope.slang new file mode 100644 index 000000000..946c1a08b --- /dev/null +++ b/tests/spirv/debug-variable-scope.slang @@ -0,0 +1,23 @@ +//TEST:SIMPLE(filecheck=CHECK):-target spirv-asm -entry main -stage fragment -g2 -emit-spirv-directly + +Texture2D testTex : register(t0); +SamplerState testSampler : register(s0); + +struct PSIn +{ + float4 pos : SV_Position; +}; + +float4 main(PSIn input) : SV_TARGET +{ + uint4 testPos = input.pos; + float bias = -1.0; + float2 tc = testPos.xy / 32.0; + float4 colVal = testTex.SampleBias(testSampler, tc, bias); + return float4(colVal.xyz, 1.0); +} + +// CHECK: %[[COMPILATION_UNIT_ID:[0-9]+]] = OpExtInst %void {{.*}} DebugCompilationUnit +// CHECK: %[[FUNC_ID:[0-9]+]] = OpExtInst %void {{.*}} DebugFunction %{{[0-9]+}} +// CHECK: DebugLocalVariable %{{[0-9]+}} %{{[0-9]+}} %{{[0-9]+}} %{{.*}} %{{.*}} %[[FUNC_ID]] +// CHECK: DebugGlobalVariable %{{[0-9]+}} %{{[0-9]+}} %{{[0-9]+}} %{{.*}} %{{.*}} %[[COMPILATION_UNIT_ID]] -- cgit v1.2.3