summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2024-03-05 11:18:14 -0800
committerGitHub <noreply@github.com>2024-03-05 11:18:14 -0800
commit8d4b659b4d95fb72f4c483f6327acd60b44268bc (patch)
tree834583cc393987472036b9d3b3e740bc25f908f3
parentbb017e6aa8ddbfac6b9a78a66f4706964fbeaff4 (diff)
[SPIRV] Fix DebugLine generated from source with #line directive. (#3678)
-rw-r--r--source/slang/slang-emit-spirv-ops-debug-info-ext.h7
-rw-r--r--source/slang/slang-emit-spirv.cpp14
-rw-r--r--source/slang/slang-lower-to-ir.cpp50
3 files changed, 59 insertions, 12 deletions
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 cd4f274f8..a48a9eb04 100644
--- a/source/slang/slang-emit-spirv-ops-debug-info-ext.h
+++ b/source/slang/slang-emit-spirv-ops-debug-info-ext.h
@@ -10,10 +10,13 @@ SpvInst* emitOpDebugCompilationUnit(SpvInstParent* parent, IRInst* inst, const T
// https://github.com/KhronosGroup/SPIRV-Registry/blob/main/nonsemantic/NonSemantic.Shader.DebugInfo.100.asciidoc#DebugSource
template<typename T>
-SpvInst* emitOpDebugSource(SpvInstParent* parent, IRInst* inst, const T& idResultType, SpvInst* set, IRInst* file, SpvInst* text)
+SpvInst* emitOpDebugSource(SpvInstParent* parent, IRInst* inst, const T& idResultType, SpvInst* set, IRInst* file, SpvInst* text = nullptr)
{
static_assert(isSingular<T>);
- return emitInst(parent, inst, SpvOpExtInst, idResultType, kResultID, set, SpvWord(35), file, text);
+ if (text)
+ return emitInst(parent, inst, SpvOpExtInst, idResultType, kResultID, set, SpvWord(35), file, text);
+ else
+ return emitInst(parent, inst, SpvOpExtInst, idResultType, kResultID, set, SpvWord(35), file);
}
template<typename T>
diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp
index dd417e38f..e37d09af7 100644
--- a/source/slang/slang-emit-spirv.cpp
+++ b/source/slang/slang-emit-spirv.cpp
@@ -1599,10 +1599,20 @@ struct SPIRVEmitContext
case kIROp_DebugSource:
{
ensureExtensionDeclaration(UnownedStringSlice("SPV_KHR_non_semantic_info"));
- // SPIRV does not allow string lits longer than 65535, so we need to split the source string
- // in OpDebugSourceContinued instructions.
auto debugSource = as<IRDebugSource>(inst);
auto sourceStr = as<IRStringLit>(debugSource->getSource())->getStringSlice();
+ // If source content is empty, skip the content operand.
+ if (sourceStr.getLength() == 0)
+ {
+ return emitOpDebugSource(
+ getSection(SpvLogicalSectionID::ConstantsAndTypes),
+ inst,
+ inst->getFullType(),
+ getNonSemanticDebugInfoExtInst(),
+ debugSource->getFileName());
+ }
+ // SPIRV does not allow string lits longer than 65535, so we need to split the source string
+ // in OpDebugSourceContinued instructions.
auto sourceStrHead = sourceStr.getLength() > 65535 ? sourceStr.head(65535) : sourceStr;
auto spvStrHead = emitInst(
getSection(SpvLogicalSectionID::DebugStringsAndSource),
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp
index 638a9c577..753b21589 100644
--- a/source/slang/slang-lower-to-ir.cpp
+++ b/source/slang/slang-lower-to-ir.cpp
@@ -498,6 +498,7 @@ struct SharedIRGenContext
Dictionary<Stmt*, IRBlock*> continueLabels;
Dictionary<SourceFile*, IRInst*> mapSourceFileToDebugSourceInst;
+ Dictionary<String, IRInst*> mapSourcePathToDebugSourceInst;
void setGlobalValue(Decl* decl, LoweredValInfo value)
{
@@ -6366,26 +6367,59 @@ struct StmtLoweringVisitor : StmtVisitor<StmtLoweringVisitor>
}
};
+IRInst* getOrEmitDebugSource(IRGenContext* context, PathInfo path)
+{
+ if (auto result = context->shared->mapSourcePathToDebugSourceInst.tryGetValue(path.foundPath))
+ return *result;
+
+ ComPtr<ISlangBlob> outBlob;
+ if (path.hasFileFoundPath())
+ {
+ context->getLinkage()->getFileSystemExt()->loadFile(path.foundPath.getBuffer(), outBlob.writeRef());
+ }
+ UnownedStringSlice content;
+ if (outBlob)
+ content = UnownedStringSlice((char*)outBlob->getBufferPointer(), outBlob->getBufferSize());
+ IRBuilder builder(*context->irBuilder);
+ builder.setInsertInto(context->irBuilder->getModule());
+ auto debugSrcInst = builder.emitDebugSource(path.foundPath.getUnownedSlice(), content);
+ context->shared->mapSourcePathToDebugSourceInst[path.foundPath] = debugSrcInst;
+ return debugSrcInst;
+}
+
void maybeEmitDebugLine(IRGenContext* context, StmtLoweringVisitor& visitor, Stmt* stmt)
{
if (!context->includeDebugInfo)
return;
if (as<EmptyStmt>(stmt))
return;
+ auto sourceManager = context->getLinkage()->getSourceManager();
auto sourceView = context->getLinkage()->getSourceManager()->findSourceView(stmt->loc);
if (!sourceView)
return;
- auto source = sourceView->getSourceFile();
+
IRInst* debugSourceInst = nullptr;
- if (context->shared->mapSourceFileToDebugSourceInst.tryGetValue(source, debugSourceInst))
+ auto humaneLoc = context->getLinkage()->getSourceManager()->getHumaneLoc(stmt->loc, SourceLocType::Emit);
+
+ // Do a best-effort attempt to retrieve the nominal source file.
+ auto pathInfo = sourceView->getPathInfo(stmt->loc, SourceLocType::Emit);
+
+ // If the source file path correspond to an existing SourceFile in the source manager, use it.
+ auto source = sourceManager->findSourceFileByPathRecursively(pathInfo.foundPath);
+ if (!source)
+ source = sourceManager->findSourceFile(pathInfo.getMostUniqueIdentity());
+ if (source)
+ {
+ context->shared->mapSourceFileToDebugSourceInst.tryGetValue(source, debugSourceInst);
+ }
+ // If the source manager does not have an entry for the corresponding file name, make sure we still emit
+ // an source file entry in the spirv module.
+ if (!debugSourceInst)
{
- // When working with RenderDoc, we need to use actual source loc instead of the nominal one,
- // since RenderDoc has the builtin support to split a source file into multiple files based on
- // line directives in the file.
- auto humaneLoc = context->getLinkage()->getSourceManager()->getHumaneLoc(stmt->loc, SourceLocType::Actual);
- visitor.startBlockIfNeeded(stmt);
- context->irBuilder->emitDebugLine(debugSourceInst, humaneLoc.line, humaneLoc.line, humaneLoc.column, humaneLoc.column + 1);
+ debugSourceInst = getOrEmitDebugSource(context, pathInfo);
}
+ visitor.startBlockIfNeeded(stmt);
+ context->irBuilder->emitDebugLine(debugSourceInst, humaneLoc.line, humaneLoc.line, humaneLoc.column, humaneLoc.column + 1);
}
void maybeAddDebugLocationDecoration(IRGenContext* context, IRInst* inst)