summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/slang/slang-emit-spirv-ops-debug-info-ext.h7
-rw-r--r--source/slang/slang-emit-spirv.cpp106
-rw-r--r--tests/spirv/debug-type-pointer.slang11
3 files changed, 116 insertions, 8 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 0969b65a4..602adfee7 100644
--- a/source/slang/slang-emit-spirv-ops-debug-info-ext.h
+++ b/source/slang/slang-emit-spirv-ops-debug-info-ext.h
@@ -146,4 +146,11 @@ SpvInst* emitOpDebugExpression(SpvInstParent* parent, IRInst* inst, const T& idR
return emitInst(parent, inst, SpvOpExtInst, idResultType, kResultID, set, SpvWord(31), operations);
}
+template<typename T>
+SpvInst* emitOpDebugForwardRefsComposite(SpvInstParent* parent, IRInst* inst, const T& idResultType, SpvInst* set, IRInst* name, IRInst* tag, IRInst* source, IRInst* line, IRInst* col, SpvInst* scope, IRInst* linkageName, IRInst* size, IRInst* flags)
+{
+ static_assert(isSingular<T>);
+ return emitInst(parent, inst, SpvOpExtInstWithForwardRefsKHR, idResultType, kResultID, set, SpvWord(10), name, tag, source, line, col, scope, linkageName, size, flags);
+}
+
#endif // SLANG_IN_SPIRV_EMIT_CONTEXT
diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp
index 6b84668e3..28d66497d 100644
--- a/source/slang/slang-emit-spirv.cpp
+++ b/source/slang/slang-emit-spirv.cpp
@@ -5816,11 +5816,11 @@ struct SPIRVEmitContext
}
Dictionary<IRType*, SpvInst*> m_mapTypeToDebugType;
+ Dictionary<IRType*, SpvInst*> m_mapForwardRefsToDebugType;
+ static constexpr const int kUnknownPhysicalLayout = 1 << 17;
SpvInst* emitDebugTypeImpl(IRType* type)
{
- static const int kUnknownPhysicalLayout = 1 << 17;
-
auto scope = findDebugScope(type);
if (!scope)
return ensureInst(m_voidType);
@@ -5851,7 +5851,7 @@ struct SPIRVEmitContext
{
static uint32_t uid = 0;
uid++;
- name = builder.getStringValue((String("unamed_type_") + String(uid)).getUnownedSlice());
+ name = builder.getStringValue((String("unnamed_type_") + String(uid)).getUnownedSlice());
}
IRSizeAndAlignment structSizeAlignment;
getNaturalSizeAndAlignment(m_targetProgram->getOptionSet(), type, &structSizeAlignment);
@@ -5862,14 +5862,47 @@ struct SPIRVEmitContext
IRIntegerValue offset = 0;
IRSizeAndAlignment sizeAlignment;
getNaturalOffset(m_targetProgram->getOptionSet(), field, &offset);
- getNaturalSizeAndAlignment(m_targetProgram->getOptionSet(), field->getFieldType(), &sizeAlignment);
+
+ auto fieldType = field->getFieldType();
+ getNaturalSizeAndAlignment(m_targetProgram->getOptionSet(), fieldType, &sizeAlignment);
+
+ SpvInst* forwardRef = nullptr;
+ SpvInst* spvFieldType = nullptr;
+ if (auto fieldPtrType = as<IRPtrTypeBase>(fieldType))
+ {
+ auto fieldPtrBaseType = fieldPtrType->getValueType();
+ if (as<IRStructType>(fieldPtrBaseType)
+ && !m_mapTypeToDebugType.containsKey(fieldPtrBaseType))
+ {
+ forwardRef = emitDebugForwardRefs(type);
+
+ SpvStorageClass storageClass = SpvStorageClassFunction;
+ if (fieldPtrType->hasAddressSpace())
+ storageClass = (SpvStorageClass)fieldPtrType->getAddressSpace();
+
+ spvFieldType = emitOpDebugTypePointer(
+ getSection(SpvLogicalSectionID::ConstantsAndTypes),
+ nullptr,
+ m_voidType,
+ getNonSemanticDebugInfoExtInst(),
+ forwardRef,
+ builder.getIntValue(builder.getUIntType(), storageClass),
+ builder.getIntValue(builder.getUIntType(), kUnknownPhysicalLayout));
+ }
+ }
+
+ if (spvFieldType == nullptr)
+ {
+ spvFieldType = emitDebugType(fieldType);
+ }
+
auto memberType = emitOpDebugTypeMember(
getSection(SpvLogicalSectionID::ConstantsAndTypes),
nullptr,
m_voidType,
getNonSemanticDebugInfoExtInst(),
getName(field->getKey()),
- emitDebugType(field->getFieldType()),
+ spvFieldType,
source,
line,
col,
@@ -5877,6 +5910,17 @@ struct SPIRVEmitContext
builder.getIntValue(builder.getUIntType(), sizeAlignment.size * 8),
builder.getIntValue(builder.getUIntType(), 0));
members.add(memberType);
+
+ if (forwardRef)
+ {
+ // "OpExtInstWithForwardRefsKHR" requires "forward declared ID" at the end.
+ // TODO: May want to free/release the memory properly
+ auto tmp = m_memoryArena.allocateArray<SpvWord>(forwardRef->operandWordsCount + 1u);
+ ::memcpy(tmp, forwardRef->operandWords, forwardRef->operandWordsCount * sizeof(SpvWord));
+ tmp[forwardRef->operandWordsCount] = getID(memberType);
+ forwardRef->operandWords = tmp;
+ forwardRef->operandWordsCount++;
+ }
}
return emitOpDebugTypeComposite(
getSection(SpvLogicalSectionID::ConstantsAndTypes),
@@ -6035,6 +6079,58 @@ struct SPIRVEmitContext
return result;
}
+ SpvInst* emitDebugForwardRefsImpl(IRType* type)
+ {
+ auto scope = findDebugScope(type);
+ if (!scope)
+ return ensureInst(m_voidType);
+
+ auto name = getName(type);
+ IRBuilder builder(type);
+
+ if (auto structType = as<IRStructType>(type))
+ {
+ auto loc = structType->findDecoration<IRDebugLocationDecoration>();
+ IRInst* source = loc ? loc->getSource() : m_defaultDebugSource;
+ IRInst* line = loc ? loc->getLine() : builder.getIntValue(builder.getUIntType(), 0);
+ IRInst* col = loc ? loc->getCol() : line;
+ if (!name)
+ {
+ static uint32_t uid = 0;
+ uid++;
+ name = builder.getStringValue((String("unnamed_forward_type_") + String(uid)).getUnownedSlice());
+ }
+ IRSizeAndAlignment structSizeAlignment;
+ getNaturalSizeAndAlignment(m_targetProgram->getOptionSet(), type, &structSizeAlignment);
+
+ ensureExtensionDeclaration(UnownedStringSlice("SPV_KHR_relaxed_extended_instruction"));
+ return emitOpDebugForwardRefsComposite(
+ getSection(SpvLogicalSectionID::ConstantsAndTypes),
+ nullptr,
+ m_voidType,
+ getNonSemanticDebugInfoExtInst(),
+ name,
+ builder.getIntValue(builder.getUIntType(), 1), // struct
+ source,
+ line,
+ col,
+ scope,
+ name,
+ builder.getIntValue(builder.getUIntType(), structSizeAlignment.size * 8),
+ builder.getIntValue(builder.getUIntType(), kUnknownPhysicalLayout));
+ }
+ SLANG_UNIMPLEMENTED_X("Not implemented forward pointer debug type");
+ }
+
+ SpvInst* emitDebugForwardRefs(IRType* type)
+ {
+ if (auto debugType = m_mapForwardRefsToDebugType.tryGetValue(type))
+ return *debugType;
+ auto result = emitDebugForwardRefsImpl(type);
+ m_mapForwardRefsToDebugType[type] = result;
+ return result;
+ }
+
SpvInst* emitDebugFunction(SpvInst* firstBlock, SpvInst* spvFunc, IRFunc* function)
{
auto scope = findDebugScope(function);
diff --git a/tests/spirv/debug-type-pointer.slang b/tests/spirv/debug-type-pointer.slang
index ff6d5e6b8..fd3248c59 100644
--- a/tests/spirv/debug-type-pointer.slang
+++ b/tests/spirv/debug-type-pointer.slang
@@ -6,9 +6,10 @@
//TEST_INPUT:ubuffer(data=[0], stride=4):out,name=outputBuffer
RWStructuredBuffer<float> outputBuffer;
+//SPV:OpExtension "SPV_KHR_relaxed_extended_instruction"
//SPV: [[STRING_float:%[1-9][0-9]*]] = OpString "float"
//SPV: [[STRING_pValue:%[1-9][0-9]*]] = OpString "pValue"
-//SPV: [[STRING_uint64:%[1-9][0-9]*]] = OpString "uint64"
+//SPV: [[STRING_LinkedNode:%[1-9][0-9]*]] = OpString "LinkedNode"
//SPV: [[STRING_pNext:%[1-9][0-9]*]] = OpString "pNext"
struct LinkedNode
@@ -20,11 +21,15 @@ struct LinkedNode
//SPV: DebugTypeMember [[STRING_pValue]] [[TYPE_float_ptr]]
float *pValue;
- //SPV: [[TYPE_uint64:%[1-9][0-9]*]] = OpExtInst %void %{{[0-9]*}} DebugTypeBasic [[STRING_uint64]]
- //SPV: DebugTypeMember [[STRING_pNext]] [[TYPE_uint64]]
+ // "MEMBER_pNext" hasn't been declared yet, but OpExtInstWithForwardRefs requires at least one of these "forward declared ID".
+ //SPV: [[FORWARD_LinkedNode:%[1-9][0-9]*]] = OpExtInstWithForwardRefsKHR %void %{{[0-9]*}} DebugTypeComposite [[STRING_LinkedNode]] {{.*}} [[MEMBER_pNext:%[1-9][0-9]*]]
+ //SPV: [[TYPE_pLinkedNode:%[1-9][0-9]*]] = OpExtInst %void %{{[0-9]*}} DebugTypePointer [[FORWARD_LinkedNode]]
+ //SPV: [[MEMBER_pNext]] = {{.*}} DebugTypeMember [[STRING_pNext]] [[TYPE_pLinkedNode]]
LinkedNode *pNext;
};
+//SPV: OpExtInst %void %{{[0-9]*}} DebugTypeComposite [[STRING_LinkedNode]] {{.*}} [[MEMBER_pNext]]
+
float test(LinkedNode *pNode)
{
//SPV: DebugValue %pNodeNext