[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#8517jzakharovnv wants to merge 2 commits into
Conversation
You can test this locally with the following command:git-clang-format --diff 517dd5eb5d8cbb46c15fc1230acac1d2f4779092 8e419f728e179614398fbf2c82102823091c6b97 -- tools/clang/include/clang/SPIRV/SpirvBuilder.h tools/clang/include/clang/SPIRV/SpirvContext.h tools/clang/include/clang/SPIRV/SpirvInstruction.h tools/clang/include/clang/SPIRV/SpirvType.h tools/clang/include/clang/SPIRV/SpirvVisitor.h tools/clang/lib/SPIRV/CapabilityVisitor.cpp tools/clang/lib/SPIRV/DeclResultIdMapper.cpp tools/clang/lib/SPIRV/DeclResultIdMapper.h tools/clang/lib/SPIRV/EmitVisitor.cpp tools/clang/lib/SPIRV/EmitVisitor.h tools/clang/lib/SPIRV/LowerTypeVisitor.cpp tools/clang/lib/SPIRV/SpirvBuilder.cpp tools/clang/lib/SPIRV/SpirvContext.cpp tools/clang/lib/SPIRV/SpirvEmitter.cpp tools/clang/lib/SPIRV/SpirvEmitter.h tools/clang/lib/SPIRV/SpirvInstruction.cpp tools/clang/lib/SPIRV/SpirvType.cpp tools/clang/unittests/SPIRV/SpirvContextTest.cppView the diff from clang-format here.diff --git a/tools/clang/lib/SPIRV/SpirvBuilder.cpp b/tools/clang/lib/SPIRV/SpirvBuilder.cpp
index a146a5dd..9fce2c57 100644
--- a/tools/clang/lib/SPIRV/SpirvBuilder.cpp
+++ b/tools/clang/lib/SPIRV/SpirvBuilder.cpp
@@ -2012,7 +2012,8 @@ SpirvConstant *SpirvBuilder::getConstantNull(QualType type) {
return nullConst;
}
-SpirvConstant *SpirvBuilder::getConstantSizeOfEXT(const SpirvType *operandType) {
+SpirvConstant *
+SpirvBuilder::getConstantSizeOfEXT(const SpirvType *operandType) {
// Reuse the existing instruction for a given descriptor type; multiple heap
// accesses of the same element type share one OpConstantSizeOfEXT.
auto found = constantSizeOfEXTMap.find(operandType);
diff --git a/tools/clang/lib/SPIRV/SpirvInstruction.cpp b/tools/clang/lib/SPIRV/SpirvInstruction.cpp
index 0a9371ef..0f39e24d 100644
--- a/tools/clang/lib/SPIRV/SpirvInstruction.cpp
+++ b/tools/clang/lib/SPIRV/SpirvInstruction.cpp
@@ -724,8 +724,8 @@ SpirvConstantSizeOfEXT::SpirvConstantSizeOfEXT(QualType resultType,
bool SpirvConstantSizeOfEXT::operator==(
const SpirvConstantSizeOfEXT &that) const {
- return resultType == that.resultType &&
- astResultType == that.astResultType && operandType == that.operandType;
+ return resultType == that.resultType && astResultType == that.astResultType &&
+ operandType == that.operandType;
}
SpirvConstantNull::SpirvConstantNull(QualType type)
|
4b4b143 to
f640327
Compare
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: Claude.
f640327 to
cbcae38
Compare
|
@microsoft-github-policy-service agree company="NVIDIA" |
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.
| SpirvEmitter::getDescriptorHeapRuntimeArrayType(const SpirvType *elemType, | ||
| bool onSamplerHeap) { | ||
| constexpr uint32_t kDefaultResourceHeapStride = 64; | ||
| constexpr uint32_t kDefaultSamplerHeapStride = 32; |
There was a problem hiding this comment.
I think I would float these defaults to SpirvEmitter.h and document where the seemingly magic values 32 and 64 come from.
There was a problem hiding this comment.
Definitely agree that these need some better documentation. I placed them at this scope because they seem a little niche, and I want to try to avoid polluting very wide scopes, but I can move them up.
| constexpr uint32_t kDefaultSamplerHeapStride = 32; | ||
| const uint32_t stride = | ||
| onSamplerHeap ? kDefaultSamplerHeapStride : kDefaultResourceHeapStride; | ||
| return spvContext.getRuntimeArrayType(elemType, stride); |
There was a problem hiding this comment.
It doesn't seem that there are tests for OpDecorate ArrayStride N in this PR. I haven't checked the others. Could you add one (unless I missed it?)
There was a problem hiding this comment.
Yes, there is a healthy amount of testing in the last 2 PRs of this series, but I neglected to have for this one. I can fix that.
| addExtension(Extension::EXT_descriptor_heap, "DescriptorHeap", {}); | ||
| addExtension(Extension::KHR_untyped_pointers, "DescriptorHeap", {}); | ||
| const llvm::StringRef feature = "DescriptorHeap"; | ||
| featureManager.requestTargetEnv(SPV_ENV_VULKAN_1_3, feature, {}); |
There was a problem hiding this comment.
This function can return failure (which is getting dropped here), and there is no test verifying its error handling.
There was a problem hiding this comment.
Thanks for catching that, I'll add a test.
| tryToAssignToDescriptorHeapBuffer(expr)) | ||
| return aliasResult.getValue(); | ||
|
|
||
| auto *rhs = loadIfGLValue(expr->getRHS()); |
There was a problem hiding this comment.
LLVM's coding standards which DXC adopts (although not historically well enforced), have an "almost never auto" policy:
The heavy use of auto in this code makes it significantly harder to review this PR in a browser without an IDE telling me the types of things.
There was a problem hiding this comment.
Noted, thanks for tip!
| if (result && !result->isRValue()) { | ||
| result = | ||
| spvBuilder.createLoad(structType, result, buffer->getExprLoc(), range); | ||
| } |
There was a problem hiding this comment.
| if (result && !result->isRValue()) { | |
| result = | |
| spvBuilder.createLoad(structType, result, buffer->getExprLoc(), range); | |
| } | |
| if (result && !result->isRValue()) | |
| result = | |
| spvBuilder.createLoad(structType, result, buffer->getExprLoc(), range); |
There was a problem hiding this comment.
Will fix in next commit
| } | ||
|
|
||
| // ConstantBuffer -> Uniform (UBO); all others -> StorageBuffer (SSBO) | ||
| // TODO: Remove this manual override once LowerTypeVisitor returns the |
There was a problem hiding this comment.
Should this be fixed before we merge this change? Seems like you're working around a clear bug here.
There was a problem hiding this comment.
To get the storage class here rather than in LowerTypeVisitor is bit of a bandage but provides functionally correct output. I had left this TODO in with the aim of making this PR as small/unintrusive as possible and with room to improve with future commits. If you're okay with filing an issue, let me know, otherwise I can go about cleaning up this fix.
There was a problem hiding this comment.
I think I'm okay with using an issue to track that as a follow up. Normally it would be better to do that foundational work first to avoid committing code in an undesirable state unless there's a reason why it can't be done before this change merged.
There was a problem hiding this comment.
Understandable. I am open to clean the code up, it just may be a while before I am able to address everything (on the order of 2 weeks). Let me know if that is what you prefer!
|
|
||
| float4 main(uint idx : A) : SV_Target { | ||
| Texture2D<float4> tex = ResourceDescriptorHeap[NonUniformResourceIndex(idx)]; | ||
| SamplerState samp = SamplerDescriptorHeap[NonUniformResourceIndex(idx + 1)]; |
There was a problem hiding this comment.
This seems like something we should have the compiler issue a diagnostic on. Silently dropping something the user explicitly wrote seems unfortunate.
There was a problem hiding this comment.
I agree, this is a bit esoteric but correct according to @Tobski. How should we handle a diagnostic here, just a simple warning?
There was a problem hiding this comment.
Oh... Actually I think the correct solution for HLSL is that in the absence of NonUniformResourceIndex an access should be marked as Uniform, and NonUniformResourceIndex suppresses that.
It should have an effect, so no diagnostic should be required.
Building off of #8281, this PR adds a native lowering via SPV_EXT_descriptor_heap and SPV_KHR_untyped_pointers and is part 1/4 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.
@dnovillo