diff options
| author | Yong He <yonghe@outlook.com> | 2024-03-05 11:18:14 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-05 11:18:14 -0800 |
| commit | 8d4b659b4d95fb72f4c483f6327acd60b44268bc (patch) | |
| tree | 834583cc393987472036b9d3b3e740bc25f908f3 | |
| parent | bb017e6aa8ddbfac6b9a78a66f4706964fbeaff4 (diff) | |
[SPIRV] Fix DebugLine generated from source with #line directive. (#3678)
| -rw-r--r-- | source/slang/slang-emit-spirv-ops-debug-info-ext.h | 7 | ||||
| -rw-r--r-- | source/slang/slang-emit-spirv.cpp | 14 | ||||
| -rw-r--r-- | source/slang/slang-lower-to-ir.cpp | 50 |
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) |
