diff options
| -rw-r--r-- | source/slang/slang-emit-spirv-ops-debug-info-ext.h | 7 | ||||
| -rw-r--r-- | source/slang/slang-emit-spirv.cpp | 106 | ||||
| -rw-r--r-- | tests/spirv/debug-type-pointer.slang | 11 |
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 |
