Skip to content

Commit 1e59ce9

Browse files
authored
[SPIR-V] Fix debug instruction with cbuffer + FXC (microsoft#6531)
When the requested constant buffer layout is DX, some type lowering can become complex (Nx1 matrices for ex). To simplify the lowering, the backend "clones" those variables: - on one end, we expose the correct layout - but then, we copy this to a local variable to have a different layout compatible with the operations we usually do on such types. This means the type can sometimes be an HybridStructType, which is not completely lowered, or a normal lowerer SPIR-V type. Both should be allowed, but some codepaths had to be updated to reflect this. --------- Signed-off-by: Nathan Gauër <[email protected]>
1 parent 690ec7c commit 1e59ce9

File tree

3 files changed

+55
-13
lines changed

3 files changed

+55
-13
lines changed

tools/clang/lib/SPIRV/DeclResultIdMapper.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1481,12 +1481,28 @@ SpirvVariable *DeclResultIdMapper::createCTBuffer(const HLSLBufferDecl *decl) {
14811481
decl->getAttr<VKBindingAttr>(), decl->getAttr<VKCounterBindingAttr>());
14821482
}
14831483

1484+
if (!spirvOptions.debugInfoRich) {
1485+
return bufferVar;
1486+
}
1487+
14841488
auto *dbgGlobalVar = createDebugGlobalVariable(
14851489
bufferVar, QualType(), decl->getLocation(), decl->getName());
1486-
if (dbgGlobalVar != nullptr) {
1487-
// C/TBuffer needs HLSLBufferDecl for debug type lowering.
1488-
spvContext.registerStructDeclForSpirvType(bufferVar->getResultType(), decl);
1489-
}
1490+
assert(dbgGlobalVar);
1491+
(void)dbgGlobalVar; // For NDEBUG builds.
1492+
1493+
auto *resultType = bufferVar->getResultType();
1494+
// Depending on the requested layout (DX or VK), constant buffers is either a
1495+
// struct containing every constant fields, or a pointer to the type. This is
1496+
// caused by the workaround we implemented to support FXC/DX layout. See #3672
1497+
// for more details.
1498+
assert(isa<SpirvPointerType>(resultType) ||
1499+
isa<HybridStructType>(resultType));
1500+
if (auto *ptr = dyn_cast<SpirvPointerType>(resultType))
1501+
resultType = ptr->getPointeeType();
1502+
// Debug type lowering requires the HLSLBufferDecl. Updating the type<>decl
1503+
// mapping.
1504+
spvContext.registerStructDeclForSpirvType(resultType, decl);
1505+
14901506
return bufferVar;
14911507
}
14921508

tools/clang/lib/SPIRV/LowerTypeVisitor.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -163,15 +163,16 @@ bool LowerTypeVisitor::visitInstruction(SpirvInstruction *instr) {
163163
debugInstruction->setDebugSpirvType(spirvType);
164164
} else if (const auto *debugSpirvType =
165165
debugInstruction->getDebugSpirvType()) {
166-
// When it does not have a QualType, SpirvEmitter or DeclResultIdMapper
167-
// generates a hybrid type. In that case, we keep the hybrid type for the
168-
// DebugGlobalVariable, not QualType. We have to lower the hybrid type and
169-
// update the SpirvType for the DebugGlobalVariable.
170-
assert(isa<SpirvDebugGlobalVariable>(debugInstruction) &&
171-
isa<HybridType>(debugSpirvType));
172-
const SpirvType *loweredSpirvType = lowerType(
173-
debugSpirvType, instr->getLayoutRule(), instr->getSourceLocation());
174-
debugInstruction->setDebugSpirvType(loweredSpirvType);
166+
// When it does not have a QualType, either the type is already lowered,
167+
// or it's an HybridStructType we should lower.
168+
assert(isa<SpirvDebugGlobalVariable>(debugInstruction));
169+
if (isa<HybridType>(debugSpirvType)) {
170+
const SpirvType *loweredSpirvType = lowerType(
171+
debugSpirvType, instr->getLayoutRule(), instr->getSourceLocation());
172+
debugInstruction->setDebugSpirvType(loweredSpirvType);
173+
} else {
174+
debugInstruction->setDebugSpirvType(debugSpirvType);
175+
}
175176
}
176177
}
177178

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %dxc -T vs_6_6 -spirv -fvk-use-dx-layout -fspv-target-env=vulkan1.3 -fspv-extension=SPV_KHR_non_semantic_info -fspv-debug=vulkan-with-source -fcgl %s | FileCheck %s
2+
3+
// CHECK: [[dbg_ty_name:%[0-9]+]] = OpString "type.cbuff"
4+
// CHECK: [[dbg_name:%[0-9]+]] = OpString "cbuff"
5+
6+
cbuffer cbuff
7+
{
8+
float4 a;
9+
};
10+
// CHECK: [[type_cbuff:%[0-9a-zA-Z_]+]] = OpTypeStruct %v4float
11+
// CHECK: [[ptr_cbuff:%[0-9a-zA-Z_]+]] = OpTypePointer Uniform [[type_cbuff]]
12+
// CHECK: [[cbuff:%[0-9a-zA-Z_]+]] = OpVariable [[ptr_cbuff]] Uniform
13+
14+
15+
// CHECK: [[dbg_member:%[0-9]+]] = OpExtInst %void {{%[0-9]+}} DebugTypeMember {{%[0-9]+}} {{%[0-9]+}} {{%[0-9]+}} %uint_8 %uint_12 %uint_0 %uint_128 %uint_3
16+
// CHECK: [[dbg_ty:%[0-9]+]] = OpExtInst %void {{%[0-9]+}} DebugTypeComposite [[dbg_ty_name]] %uint_1 {{%[0-9]+}} %uint_6 %uint_9 {{%[0-9]+}} [[dbg_ty_name]] %uint_128 %uint_3 [[dbg_member]]
17+
// CHECK: OpExtInst %void {{%[0-9]+}} DebugGlobalVariable [[dbg_name]] [[dbg_ty]] {{%[0-9]+}} %uint_6 %uint_9 {{%[0-9]+}} [[dbg_name]] %cbuff %uint_8
18+
19+
20+
float4 main() : SV_Position
21+
{
22+
// CHECK: [[ptr:%[0-9]+]] = OpAccessChain %_ptr_Uniform_v4float [[cbuff]] %int_0
23+
// CHECK: OpLoad %v4float [[ptr]]
24+
return a;
25+
}

0 commit comments

Comments
 (0)