[SPIR-V] Add SPV_EXT_descriptor_heap + SPV_KHR_untyped_pointers codegen - #8517
[SPIR-V] Add SPV_EXT_descriptor_heap + SPV_KHR_untyped_pointers codegen#8517Jonathan Zakharov (jzakharovnv) wants to merge 17 commits into
Conversation
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
f640327 to
cbcae38
Compare
|
@microsoft-github-policy-service agree company="NVIDIA" |
Diego Novillo (dnovillo)
left a comment
There was a problem hiding this comment.
Thanks for this! I just started looking at it and have a couple of questions. I'll add more as I read the PRs.
|
Jonathan Zakharov (@jzakharovnv) I think the OpConstantSizeOfEXT usage in this MR isn't quite right - it looks like you're just taking the stride of the descriptor type being loaded and using that? This works for the sampler heap where there's only one type (samplers), but not for the resource heap. The stride of all resource descriptors must be the same for all descriptors, and has to be based on the biggest of the buffer/image sizes. This is illustrated in the VK extension doc here: https://docs.vulkan.org/features/latest/features/proposals/VK_EXT_descriptor_heap.html#_shader_model_6_6_samplerheap_and_resourceheap I might be misunderstanding the code, but I don't see anything for finding the largest of the two sizes? They're both POT, so it is a simple "which is max" calculation, but I don't see it being done in this PR. |
|
Tobski You are right, this is my blunder. Will fix shortly. |
|
Tobski Shared max(image,buffer) stride for descriptor heap resource arrays ought to be closer to the original intent. Please take a look when you can. Thanks! |
Looks right to me now! Thanks! |
Diego Novillo (dnovillo)
left a comment
There was a problem hiding this comment.
A question on changes that have gone in #8519 that we may to reflect here. Not sure how you want to handle it.
bd79339 to
cbcae38
Compare
|
Diego Novillo (@dnovillo) In response to your last comment on this PR, yes I think it's more correct to have the TODO commit a part of this initial branch rather than one down the line. Cherrypicked and rebased to reflect this. |
Diego Novillo (dnovillo)
left a comment
There was a problem hiding this comment.
Just one minor change and it's good to from my side.
Diego Novillo (dnovillo)
left a comment
There was a problem hiding this comment.
LGTM. Just one final nit. Thanks for doing this!
d0835c8 to
88bd33c
Compare
|
There was a problem hiding this comment.
Pull request overview
Adds native SPIR-V descriptor-heap lowering using SPV_EXT_descriptor_heap and SPV_KHR_untyped_pointers.
Changes:
- Implements native image, sampler, and buffer descriptor access.
- Adds descriptor-size-based runtime-array strides and image atomic support.
- Expands tests and documents Vulkan 1.3 requirements and limitations.
Reviewed changes
Copilot reviewed 47 out of 47 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
tools/clang/unittests/SPIRV/SpirvContextTest.cpp |
Tests runtime-array type uniqueness. |
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.typed-formats.hlsl |
Tests typed image formats. |
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.texturecube.hlsl |
Tests cube textures and samplers. |
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.texture.hlsl |
Tests texel buffers. |
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.texture-sampler-assignment.hlsl |
Tests resource reassignment. |
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.texture-ms.hlsl |
Tests multisampled textures. |
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.texture-dims.hlsl |
Tests sampled texture dimensions. |
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.structured-buffer-atomic.hlsl |
Tests structured-buffer atomics. |
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.static-global.hlsl |
Tests static global resources. |
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.sampler-comparison.hlsl |
Tests comparison samplers. |
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.sample-grad-bias.hlsl |
Tests sampling operands. |
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.rwtexture-dims.hlsl |
Tests RW texture dimensions. |
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.rwtexture-atomics.hlsl |
Tests untyped image atomics. |
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.rwbyteaddressbuffer.hlsl |
Tests writable byte buffers. |
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.nonuniform.hlsl |
Tests divergent heap indexing. |
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.mixed-bound.hlsl |
Tests bound/native resource coexistence. |
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.mixed-alias.error.hlsl |
Tests mixed-alias diagnostics. |
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.load-offset.hlsl |
Tests texture load offsets. |
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.groupshared.hlsl |
Tests groupshared coexistence. |
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.gather.hlsl |
Tests gather operations. |
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.function-params.hlsl |
Tests resource function parameters. |
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.discarded.error.hlsl |
Tests discarded-index diagnostics. |
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.counter-ops.error.hlsl |
Tests unsupported counter diagnostics. |
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.constant-texture-buffer.hlsl |
Tests constant and texture buffers. |
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.constant-buffer-assignment.hlsl |
Tests constant-buffer reassignment. |
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.buffer.hlsl |
Tests native buffer lowering. |
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.array-stride.hlsl |
Tests descriptor-array strides. |
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.append-consume.error.hlsl |
Tests append/consume diagnostics. |
tools/clang/test/CodeGenSPIRV/resource-heap-ext-texture.hlsl |
Removes superseded coverage. |
tools/clang/lib/SPIRV/SpirvType.cpp |
Extends runtime-array equality. |
tools/clang/lib/SPIRV/SpirvInstruction.cpp |
Implements new SPIR-V instructions. |
tools/clang/lib/SPIRV/SpirvEmitter.h |
Declares heap lowering and alias state. |
tools/clang/lib/SPIRV/SpirvEmitter.cpp |
Implements native heap code generation. |
tools/clang/lib/SPIRV/SpirvContext.cpp |
Uniques buffer and stride-ID types. |
tools/clang/lib/SPIRV/SpirvBuilder.cpp |
Builds descriptor sizes and strides. |
tools/clang/lib/SPIRV/LowerTypeVisitor.cpp |
Lowers untyped image pointers. |
tools/clang/lib/SPIRV/EmitVisitor.h |
Declares new emission handlers. |
tools/clang/lib/SPIRV/EmitVisitor.cpp |
Serializes new instructions and decorations. |
tools/clang/lib/SPIRV/DeclResultIdMapper.h |
Declares function alias registration. |
tools/clang/lib/SPIRV/DeclResultIdMapper.cpp |
Implements alias registration. |
tools/clang/lib/SPIRV/CapabilityVisitor.cpp |
Requires Vulkan 1.3 and extensions. |
tools/clang/include/clang/SPIRV/SpirvVisitor.h |
Adds visitor hooks. |
tools/clang/include/clang/SPIRV/SpirvType.h |
Adds stride-ID runtime arrays. |
tools/clang/include/clang/SPIRV/SpirvInstruction.h |
Defines new instruction classes. |
tools/clang/include/clang/SPIRV/SpirvContext.h |
Adds type caches and APIs. |
tools/clang/include/clang/SPIRV/SpirvBuilder.h |
Exposes descriptor-stride builders. |
docs/SPIR-V.rst |
Documents native descriptor heaps. |
Fixes #8603: MergeBinaryOpSelect produced an OpSelect with a vector result type and a scalar condition, which is only legal in SPIR-V 1.4+ (KhronosGroup/SPIRV-Tools#6827). This exposes #8740 where the resource-heap-ext-texture.hlsl test fails validation - for now this is worked around by disabling the test, since #8517 looks like it is reworking it anyway. Assisted-by: copilot --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: b04b21af-2d8b-4af5-b9ad-1b84073588f5
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 54 out of 54 changed files in this pull request and generated 2 comments.
Suppressed comments (4)
tools/clang/unittests/SPIRV/SpirvContextTest.cpp:1
- Using integer-to-pointer
reinterpret_castin tests can be implementation-defined and may fail on platforms with non-flat pointer models (or under certain sanitizers). Since the test only needs stable distinct pointer identities, prefer deriving pointers from real storage (e.g., addresses of suitably aligned dummy storage) rather than forging small integer addresses.
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.image-alias-fn-param.hlsl:1 - LIT directives like
// XFAIL:are parsed, not treated as free-form comments. The secondXFAIL:line reads like explanatory text rather than a valid XFAIL condition and can be mis-parsed or silently ignored depending on the harness. Keep a single validXFAIL:directive (e.g.,*), and convert the explanation into a normal comment (e.g.,// Reason:) to avoid directive parsing issues.
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.array-stride.hlsl:62 - Grammatically, this should be possessive 'its' rather than the contraction 'it's'.
// Every resource runtime array shares the one resource stride.
// The sampler array just uses the sampler size as it's stride.
tools/clang/include/clang/SPIRV/SpirvInstruction.h:2286
- This new instruction stores SSA operands but does not define a
replaceOperand(...)override (unlike several other operand-bearing instructions in this PR). If the codebase relies onreplaceOperandduring cloning/legalization/remapping passes, adding an override here would prevent future maintenance issues and keep operand-remapping behavior consistent.
/// \brief OpSpecConstantOp instruction where the operation is ternary.
class SpirvSpecConstantTernaryOp : public SpirvInstruction {
public:
SpirvSpecConstantTernaryOp(spv::Op specConstantOp, QualType resultType,
SourceLocation loc, SpirvInstruction *operand1,
SpirvInstruction *operand2,
SpirvInstruction *operand3);
DEFINE_RELEASE_MEMORY_FOR_CLASS(SpirvSpecConstantTernaryOp)
// For LLVM-style RTTI
static bool classof(const SpirvInstruction *inst) {
return inst->getKind() == IK_SpecConstantTernaryOp;
}
bool invokeVisitor(Visitor *v) override;
spv::Op getSpecConstantopcode() const { return specOp; }
SpirvInstruction *getOperand1() const { return operand1; }
SpirvInstruction *getOperand2() const { return operand2; }
SpirvInstruction *getOperand3() const { return operand3; }
private:
spv::Op specOp;
SpirvInstruction *operand1;
SpirvInstruction *operand2;
SpirvInstruction *operand3;
};
|
All the blocker issues I had found earlier are now gone. This is ready to go. A couple of things to do beforehand:
Gregory Roth (@pow2clk) could you please give this another look? |
Building off of microsoft#8281, this commit adds a native lowering via SPV_EXT_descriptor_heap and SPV_KHR_untyped_pointers. ResourceDescriptorHeap and SamplerDescriptorHeap are lowered to untyped variables decorated with ResourceHeapEXT and SamplerHeapEXT. Each heap access emits OpUntypedAccessChainKHR into a runtime array of the appropriate descriptor type. Buffer-like resources (StructuredBuffer, ByteAddressBuffer, ConstantBuffer, TextureBuffer) use OpTypeBufferEXT and OpBufferPointerEXT; image and sampler resources use OpLoad. Interlocked operations on RWTexture use OpUntypedImageTexelPointerEXT. Requires -fspv-target-env=vulkan1.3. Assisted by AI.
CapabilityVisitor::visitInstructionAllTypes was dropping the bool return of requestTargetEnv, so a vk<1.3 target-env would emit the diagnostic but keep lowering. Added sm6_6.descriptorheap.ext.targetenv.error.hlsl to cover rejection of -fspv-use-descriptor-heap with -fspv-target-env=vulkan1.2.
fae23d7 to
1f5a41a
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 54 out of 54 changed files in this pull request and generated 3 comments.
Suppressed comments (2)
tools/clang/lib/SPIRV/SpirvEmitter.cpp:2983
- Direct heap-buffer returns bypass the new rejection: this branch handles
return ResourceDescriptorHeap[i], then skips the alias-onlyelse ifand falls through toloadIfGLValue, which loads the whole buffer interface object and produces the same invalid SPIR-V that the alias diagnostic is meant to prevent. This form is valid HLSL and already appears insm6_6.descriptorheap.return.counter.hlsl; reject buffer-likeresourceTypehere (or implement pointer propagation) before falling through.
if (isDescriptorHeap(srcExpr)) {
tools/clang/lib/SPIRV/SpirvEmitter.cpp:3456
- This guard only runs for a
DeclRefExpr, so a direct heap expression such asconsume((StructuredBuffer<uint>)ResourceDescriptorHeap[i])bypasses the diagnostic. The later generic argument path then callsloadIfGLValueon theOpBufferPointerEXTresult and attempts to copy the whole buffer interface object into a Function variable, yielding invalid SPIR-V. Apply the heap-buffer rejection to all heap-sourced arguments before narrowing toDeclRefExpr.
if (const auto *declRefExpr = dyn_cast<DeclRefExpr>(arg)) {
|
Diego Novillo (@dnovillo) Chris B (@llvm-beanz) Gregory Roth (@pow2clk) Hi folks. It's time we bring this endless review cycle to an end. To wrap up what I've done: I've gone and made sure to address every human review comment and also done my best to address every Copilot comment. I've just filed #8823 through #8831 so no review gets lost. Any further reviews on these PRs (#8517, #8518, #8519) I will gladly file an issue for, but must draw the somewhere, otherwise this will go on forever. Thanks! |
Building off of #8281, this PR adds a native lowering via SPV_EXT_descriptor_heap and SPV_KHR_untyped_pointers and is part 1/3 in a series.
ResourceDescriptorHeap and SamplerDescriptorHeap are lowered to untyped variables decorated with ResourceHeapEXT and SamplerHeapEXT. Each heap access emits OpUntypedAccessChainKHR into a runtime array of the appropriate descriptor type. Buffer-like resources (StructuredBuffer, ByteAddressBuffer, ConstantBuffer, TextureBuffer) use OpTypeBufferEXT and OpBufferPointerEXT; image and sampler resources use OpLoad. Interlocked operations on RWTexture use OpUntypedImageTexelPointerEXT.
Requires -fspv-target-env=vulkan1.3.
Assisted by an AI agent.
Diego Novillo (@dnovillo)