diff options
| author | Yong He <yonghe@outlook.com> | 2024-10-16 09:54:43 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-10-16 09:54:43 -0700 |
| commit | 2ee898109006986250d5356a59003eb741a89ca4 (patch) | |
| tree | d1c6f9c4cc7b17878c8bba53f6f89754e0a713e1 | |
| parent | 9e32b006318814e688501c4b547308d7fb472e78 (diff) | |
Fix spirv debug info for pointer types. (#5319)
* Fix spirv debug info for pointer types.
* fix comment.
| -rw-r--r-- | source/slang/slang-emit-spirv.cpp | 65 | ||||
| -rw-r--r-- | source/slang/slang-type-layout.h | 6 | ||||
| -rw-r--r-- | tests/spirv/debug-type-pointer-2.slang | 24 | ||||
| -rw-r--r-- | tests/spirv/debug-type-pointer.slang | 2 |
4 files changed, 60 insertions, 37 deletions
diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index ede573581..0f123b8fd 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -6233,6 +6233,7 @@ struct SPIRVEmitContext } Dictionary<IRType*, SpvInst*> m_mapTypeToDebugType; + HashSet<IRType*> m_emittingTypes; // Types that are being emitted. Dictionary<IRType*, SpvInst*> m_mapForwardRefsToDebugType; static constexpr const int kUnknownPhysicalLayout = 1 << 17; @@ -6289,9 +6290,9 @@ struct SPIRVEmitContext { auto fieldPtrBaseType = fieldPtrType->getValueType(); if (as<IRStructType>(fieldPtrBaseType) - && !m_mapTypeToDebugType.containsKey(fieldPtrBaseType)) + && m_emittingTypes.contains(fieldPtrBaseType)) { - forwardRef = emitDebugForwardRefs(type); + forwardRef = emitDebugForwardRefs(fieldPtrBaseType); SpvStorageClass storageClass = SpvStorageClassFunction; if (fieldPtrType->hasAddressSpace()) @@ -6327,18 +6328,21 @@ 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++; - } + SpvInst* forwardRef = nullptr; + // If `type` has been declared with a forward reference, fill in the forward reference. + if (m_mapForwardRefsToDebugType.tryGetValue(type, forwardRef)) + { + // "OpExtInstWithForwardRefsKHR" requires "forward declared ID" at the end. + auto tmp = m_memoryArena.allocateArray<SpvWord>(forwardRef->operandWordsCount + members.getCount()); + memcpy(tmp, forwardRef->operandWords, forwardRef->operandWordsCount * sizeof(SpvWord)); + for (Index i = 0; i < members.getCount(); i++) + tmp[forwardRef->operandWordsCount + i] = getID(members[i]); + forwardRef->operandWords = tmp; + forwardRef->operandWordsCount += (uint32_t)members.getCount(); } + return emitOpDebugTypeComposite( getSection(SpvLogicalSectionID::ConstantsAndTypes), nullptr, @@ -6453,35 +6457,19 @@ struct SPIRVEmitContext else if (auto ptrType = as<IRPtrTypeBase>(type)) { IRType* baseType = ptrType->getValueType(); - if (as<IRBasicType>(baseType)) - { - // If the base type of the pointer is basic types, - // emit the basic types and emit DebugTypePointer with it. - SpvInst* debugBaseType = emitDebugType(baseType); - SpvStorageClass storageClass = SpvStorageClassFunction; - if (ptrType->hasAddressSpace()) - storageClass = addressSpaceToStorageClass(ptrType->getAddressSpace()); - - return emitOpDebugTypePointer( - getSection(SpvLogicalSectionID::ConstantsAndTypes), - nullptr, - m_voidType, - getNonSemanticDebugInfoExtInst(), - debugBaseType, - builder.getIntValue(builder.getUIntType(), storageClass), - builder.getIntValue(builder.getUIntType(), kUnknownPhysicalLayout)); - } + // Emit DebugTypePointer for pointer types. + SpvInst* debugBaseType = emitDebugType(baseType); + SpvStorageClass storageClass = SpvStorageClassFunction; + if (ptrType->hasAddressSpace()) + storageClass = addressSpaceToStorageClass(ptrType->getAddressSpace()); - // If the base type of the pointer is more complex, - // emit the pointer as "uintptr" of DebugTypeBasic. - return emitOpDebugTypeBasic( + return emitOpDebugTypePointer( getSection(SpvLogicalSectionID::ConstantsAndTypes), nullptr, m_voidType, getNonSemanticDebugInfoExtInst(), - builder.getStringValue(String("uint64").getUnownedSlice()), - builder.getIntValue(builder.getUIntType(), 64), - builder.getIntValue(builder.getUIntType(), 0), + debugBaseType, + builder.getIntValue(builder.getUIntType(), storageClass), builder.getIntValue(builder.getUIntType(), kUnknownPhysicalLayout)); } return ensureInst(m_voidType); @@ -6491,7 +6479,12 @@ struct SPIRVEmitContext { if (auto debugType = m_mapTypeToDebugType.tryGetValue(type)) return *debugType; + bool isStruct = type->getOp() == kIROp_StructType; + if (isStruct) + m_emittingTypes.add(type); auto result = emitDebugTypeImpl(type); + if (isStruct) + m_emittingTypes.remove(type); m_mapTypeToDebugType[type] = result; return result; } diff --git a/source/slang/slang-type-layout.h b/source/slang/slang-type-layout.h index 701708363..4248df508 100644 --- a/source/slang/slang-type-layout.h +++ b/source/slang/slang-type-layout.h @@ -692,6 +692,12 @@ public: // Should this derive from SequenceTypeLayout? A pointer is kind of like an array without // bounds - in that it can be indexed. Of it it can be looked at as an indirection to a value. // Is the "Just Work"iness applicable? + // TODO(Yong): + // This reference can lead to memory leak when we have `struct S{ S* f; };` + // where `f` will have a var layout whose type layout is a pointer type layout + // whose valueTypeLayout is the layout for `S` itself, forming a cycle. + // We need to stop using reference pointers for layouts and instead allocate all + // type layout object from MemoryArena on the linkage. RefPtr<TypeLayout> valueTypeLayout; }; diff --git a/tests/spirv/debug-type-pointer-2.slang b/tests/spirv/debug-type-pointer-2.slang new file mode 100644 index 000000000..4112d4905 --- /dev/null +++ b/tests/spirv/debug-type-pointer-2.slang @@ -0,0 +1,24 @@ +//TEST:SIMPLE(filecheck=CHECK): -target spirv + +// Check that we do not emit forward reference for debug pointer types if there isn't a need to do so. + +// CHECK-NOT: OpExtension "SPV_KHR_relaxed_extended_instruction" +struct T +{ + uint inner; +} + +struct Problem +{ + int getVal() { return some_bda_ptr->inner;} + T *some_bda_ptr; +} + +uniform Problem probs; + +RWStructuredBuffer<float4> outputBuffer; +[shader("compute")] +float4 main() +{ + outputBuffer[0] = float(probs.getVal()); +}
\ No newline at end of file diff --git a/tests/spirv/debug-type-pointer.slang b/tests/spirv/debug-type-pointer.slang index fd3248c59..f6add1735 100644 --- a/tests/spirv/debug-type-pointer.slang +++ b/tests/spirv/debug-type-pointer.slang @@ -9,7 +9,7 @@ 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_LinkedNode:%[1-9][0-9]*]] = OpString "LinkedNode" +//SPV: [[STRING_LinkedNode:%[1-9][0-9]*]] = OpString "LinkedNode{{.*}}" //SPV: [[STRING_pNext:%[1-9][0-9]*]] = OpString "pNext" struct LinkedNode |
