KhronosGroup / KhronosGroup/glslang
enabling debug info results in a crash when compiling a raygen shader using SER
- Dominant language
- C++
- Stars
- 3.6k
- Forks
- 989
- Avg merge
- 1d 2h
- Merged PRs (30d)
- 31
Description
I recently added SER to a raygen shader using [GLSL_EXT_shader_invocation_reorder](https://github.com/KhronosGroup/GLSL/blob/main/extensions/ext/GLSL_EXT_shader_invocation_reorder.txt).
My code works fine when I have debug info disabled, but the moment I enable it the assert in `Instruction::addIdOperand` fails while parsing the first usage of my `hitObjectEXT hit_object`.
Here is the full callstack:
callstack
```
spv::Instruction::addIdOperand(unsigned int id) Line 111
spv::Builder::createDebugLocalVariable(unsigned int type, const char * const name, const unsigned __int64 argNumber) Line 1406
spv::Builder::createVariable(spv::Decoration precision, spv::StorageClass storageClass, unsigned int type, const char * name, unsigned int initializer, const bool compilerGenerated) Line 2872
'anonymous namespace'::::TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol * node, unsigned int forcedType) Line 5169
'anonymous namespace'::::TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol * symbol) Line 10778
'anonymous namespace'::::TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol * symbol) Line 2160
glslang::TIntermSymbol::traverse(glslang::TIntermTraverser * it) Line 66
'anonymous namespace'::TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TIntermAggregate * node) Line 3982
glslang::TIntermAggregate::traverse(glslang::TIntermTraverser * it) Line 159
glslang::TIntermAggregate::traverse(glslang::TIntermTraverser * it) Line 175
'anonymous namespace'::TGlslangToSpvTraverser::visitLoop(glslang::TVisit __formal, glslang::TIntermLoop * node) Line 4953
glslang::TIntermLoop::traverse(glslang::TIntermTraverser * it) Line 231
glslang::TIntermAggregate::traverse(glslang::TIntermTraverser * it) Line 175
glslang::TIntermAggregate::traverse(glslang::TIntermTraverser * it) Line 175
'anonymous namespace'::TGlslangToSpvTraverser::visitLoop(glslang::TVisit __formal, glslang::TIntermLoop * node) Line 4953
glslang::TIntermLoop::traverse(glslang::TIntermTraverser * it) Line 231
glslang::TIntermAggregate::traverse(glslang::TIntermTraverser * it) Line 175
glslang::TIntermAggregate::traverse(glslang::TIntermTraverser * it) Line 175
glslang::TIntermAggregate::traverse(glslang::TIntermTraverser * it) Line 175
'anonymous namespace'::TGlslangToSpvTraverser::visitFunctions(const glslang::TVector & glslFunctions) Line 6635
```
As a temporary fix I add the following to `SpvBuilder`. However, given how unfamiliar I am with the glslang codebase I decided against opening a PR.
patch
```
diff --git a/thirdparty/glslang/SPIRV/SpvBuilder.cpp b/thirdparty/glslang/SPIRV/SpvBuilder.cpp
index 0e4237fb8a..2feba23465 100644
--- a/thirdparty/glslang/SPIRV/SpvBuilder.cpp
+++ b/thirdparty/glslang/SPIRV/SpvBuilder.cpp
@@ -2865,16 +2865,20 @@ Id Builder::createVariable(Decoration precision, StorageClass storageClass, Id t
if (emitNonSemanticShaderDebugInfo && !compilerGenerated)
{
- // For debug info, we prefer respecting how the variable is declared in source code.
- // We may emulate some local variables as global variable with private storage in SPIR-V, but we still want to
- // treat them as local variables in debug info.
- if (storageClass == StorageClass::Function || (currentFunction && storageClass == StorageClass::Private)) {
- auto const debugLocalVariableId = createDebugLocalVariable(getDebugType(type), name);
- makeDebugDeclare(debugLocalVariableId, inst->getResultId());
- }
- else {
- createDebugGlobalVariable(getDebugType(type), name, inst->getResultId());
- }
+ // skip debug info for opaque types
+ Id debugType = getDebugType(type);
+ if (debugType) {
+ // For debug info, we prefer respecting how the variable is declared in source code.
+ // We may emulate some local variables as global variable with private storage in SPIR-V, but we still want to
+ // treat them as local variables in debug info.
+ if (storageClass == StorageClass::Function || (currentFunction && storageClass == StorageClass::Private)) {
+ auto const debugLocalVariableId = createDebugLocalVariable(getDebugType(type), name);
+ makeDebugDeclare(debugLocalVariableId, inst->getResultId());
+ } else {
+ createDebugGlobalVariable(getDebugType(type), name, inst->getResultId());
+ }
+ }
}
if (name)
```
Contributor guide
Research direction
Start in thirdparty/glslang/SPIRV/SpvBuilder.cpp, especially Builder::createVariable and createDebugLocalVariable, and reproduce the SER raygen shader compilation with debug info enabled and disabled. Done means the debug-enabled compilation no longer reaches the Instruction::addIdOperand assertion while handling hitObjectEXT.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers, computer-graphics
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 65/100