Skip to content

[SPIR-V] Add SPV_EXT_descriptor_heap + SPV_KHR_untyped_pointers codegen - #8517

Open
Jonathan Zakharov (jzakharovnv) wants to merge 9 commits into
microsoft:mainfrom
jzakharovnv:pr1-descriptor-heap-core
Open

[SPIR-V] Add SPV_EXT_descriptor_heap + SPV_KHR_untyped_pointers codegen#8517
Jonathan Zakharov (jzakharovnv) wants to merge 9 commits into
microsoft:mainfrom
jzakharovnv:pr1-descriptor-heap-core

Conversation

@jzakharovnv

@jzakharovnv Jonathan Zakharov (jzakharovnv) commented Jun 4, 2026

Copy link
Copy Markdown
Collaborator

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.

Diego Novillo (@dnovillo)

@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

✅ With the latest revision this PR passed the C/C++ code formatter.

@jzakharovnv

Copy link
Copy Markdown
Collaborator Author

@microsoft-github-policy-service agree company="NVIDIA"

@dnovillo Diego Novillo (dnovillo) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this! I just started looking at it and have a couple of questions. I'll add more as I read the PRs.

Comment thread tools/clang/lib/SPIRV/SpirvEmitter.cpp Outdated
SpirvEmitter::getDescriptorHeapRuntimeArrayType(const SpirvType *elemType,
bool onSamplerHeap) {
constexpr uint32_t kDefaultResourceHeapStride = 64;
constexpr uint32_t kDefaultSamplerHeapStride = 32;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I would float these defaults to SpirvEmitter.h and document where the seemingly magic values 32 and 64 come from.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the inclusion of OpConstantSizeOfEXT, per Tobski, these default stride constants have been removed.

Comment thread tools/clang/lib/SPIRV/SpirvEmitter.cpp Outdated
constexpr uint32_t kDefaultSamplerHeapStride = 32;
const uint32_t stride =
onSamplerHeap ? kDefaultSamplerHeapStride : kDefaultResourceHeapStride;
return spvContext.getRuntimeArrayType(elemType, stride);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@github-project-automation github-project-automation Bot moved this from New to In progress in HLSL Roadmap Jun 8, 2026
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, {});

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function can return failure (which is getting dropped here), and there is no test verifying its error handling.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for catching that, I'll add a test.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread tools/clang/lib/SPIRV/SpirvEmitter.cpp Outdated
tryToAssignToDescriptorHeapBuffer(expr))
return aliasResult.getValue();

auto *rhs = loadIfGLValue(expr->getRHS());

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LLVM's coding standards which DXC adopts (although not historically well enforced), have an "almost never auto" policy:

https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/CodingStandards.rst#use-auto-type-deduction-to-make-code-more-readable

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.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted, thanks for tip!

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The re-base removed the auto suggestion from Chris B (@llvm-beanz) Could you re-apply it?

Comment on lines +5110 to +5113
if (result && !result->isRValue()) {
result =
spvBuilder.createLoad(structType, result, buffer->getExprLoc(), range);
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (result && !result->isRValue()) {
result =
spvBuilder.createLoad(structType, result, buffer->getExprLoc(), range);
}
if (result && !result->isRValue())
result =
spvBuilder.createLoad(structType, result, buffer->getExprLoc(), range);

nit: https://llvm.org/docs/CodingStandards.html#don-t-use-braces-on-simple-single-statement-bodies-of-if-else-loop-statements

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix in next commit

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread tools/clang/lib/SPIRV/SpirvEmitter.cpp Outdated
}

// ConstantBuffer -> Uniform (UBO); all others -> StorageBuffer (SSBO)
// TODO: Remove this manual override once LowerTypeVisitor returns the

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be fixed before we merge this change? Seems like you're working around a clear bug here.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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!

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circling back! It has been a busy few weeks, but I am open to fixing this now if it means it could be reviewed before SIGGRAPH (July 19th). Would this be possible for you, or can we file an issue instead?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now we have these fixes in #8519 but not here. This will give you merge conflicts. Are you thinking of submitting each of these PRs separately? If so, this is probably the natural first one to submit. In which case, you'll probably need to move the code from #8519 here.


float4 main(uint idx : A) : SV_Target {
Texture2D<float4> tex = ResourceDescriptorHeap[NonUniformResourceIndex(idx)];
SamplerState samp = SamplerDescriptorHeap[NonUniformResourceIndex(idx + 1)];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like something we should have the compiler issue a diagnostic on. Silently dropping something the user explicitly wrote seems unfortunate.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, this is a bit esoteric but correct according to Tobski. How should we handle a diagnostic here, just a simple warning?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@Tobski

Tobski commented Jul 7, 2026

Copy link
Copy Markdown

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.

@jzakharovnv

Copy link
Copy Markdown
Collaborator Author

Tobski You are right, this is my blunder. Will fix shortly.

@jzakharovnv

Copy link
Copy Markdown
Collaborator Author

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!

@Tobski

Tobski commented Jul 13, 2026

Copy link
Copy Markdown

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!

@dnovillo Diego Novillo (dnovillo) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A question on changes that have gone in #8519 that we may to reflect here. Not sure how you want to handle it.

Comment thread tools/clang/lib/SPIRV/SpirvEmitter.cpp Outdated
}

// ConstantBuffer -> Uniform (UBO); all others -> StorageBuffer (SSBO)
// TODO: Remove this manual override once LowerTypeVisitor returns the

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now we have these fixes in #8519 but not here. This will give you merge conflicts. Are you thinking of submitting each of these PRs separately? If so, this is probably the natural first one to submit. In which case, you'll probably need to move the code from #8519 here.

@dnovillo Diego Novillo (dnovillo) added the spirv Work related to SPIR-V label Jul 17, 2026
@jzakharovnv

Copy link
Copy Markdown
Collaborator Author

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.

@dnovillo Diego Novillo (dnovillo) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just one minor change and it's good to from my side.

Comment thread tools/clang/lib/SPIRV/SpirvEmitter.cpp Outdated
tryToAssignToDescriptorHeapBuffer(expr))
return aliasResult.getValue();

auto *rhs = loadIfGLValue(expr->getRHS());

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The re-base removed the auto suggestion from Chris B (@llvm-beanz) Could you re-apply it?

@dnovillo Diego Novillo (dnovillo) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Just one final nit. Thanks for doing this!

if (result && !result->isRValue()) {
result =
spvBuilder.createLoad(structType, result, buffer->getExprLoc(), range);
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you re-apply the suggestion from Chris B (@llvm-beanz)? It got dropped.

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.
@damyanp

Copy link
Copy Markdown
Member

[Auto-generated note from Damyan Pepper (@damyanp)]

This looks like a user-visible bug fix/feature change. Please add (or point to) the corresponding entry in docs/ReleaseNotes.md.

If release-note coverage is planned in a related PR (including one that hasn’t been submitted yet), please mention that plan/link so we can avoid duplicate notes.

Copilot AI review requested due to automatic review settings August 4, 2026 00:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +5208 to +5214
const bool srcIsHeap = isDescriptorHeap(srcExpr->IgnoreParenCasts());
const bool wasHeap = descriptorHeapImageAliasVars.count(dstVar) ||
descriptorHeapBufferAliasVars.count(dstVar);
const bool wasBound = stateIt != descriptorHeapVarState.end() &&
stateIt->second == DescriptorHeapVarState::Bound;
const bool mixingDetected =
(srcIsHeap && wasBound) || (!srcIsHeap && wasHeap);
Comment on lines +1230 to +1233
} else if (const auto *varDecl = dyn_cast<VarDecl>(decl)) {
if (auto *alias =
emitDescriptorHeapBufferPointer(varDecl, expr->getLocStart()))
result = alias;
Comment on lines 7116 to +7120
const SpirvType *handleType =
lowerTypeVisitor.lowerType(resourceType, SpirvLayoutRule::Void,
llvm::None, baseExpr->getExprLoc());
const auto *arrayType =
spvContext.getRuntimeArrayType(handleType, llvm::None);
auto *untypedAccessChainPtr = spvBuilder.createUntypedAccessChainKHR(
untypedType, arrayType, var, index, baseExpr->getExprLoc());
const SpirvType *arrayType =
getDescriptorHeapRuntimeArrayType(handleType);
Comment thread docs/SPIR-V.rst
Comment on lines +2166 to +2169
A local resource variable initialized from a heap access is resolved entirely at
compile time: the variable is recorded as an alias for the heap index, and every
later use is re-lowered as a fresh access chain rather than as a load of a stored
descriptor handle. This is sound only when the variable holds a heap descriptor
// CHECK-DAG: %[[SampSize:[a-zA-Z0-9_]+]] = OpConstantSizeOfEXT %uint %[[SamplerDesc]]

// Every resource runtime array shares the one resource stride.
// The sampler array just uses the sampler size as it's stride.
Damyan Pepper (damyanp) added a commit that referenced this pull request Aug 6, 2026
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
@dnovillo

Copy link
Copy Markdown
Collaborator

Jonathan Zakharov (@jzakharovnv) Damyan Pepper (@damyanp) Gregory Roth (@pow2clk), I have gone over all the open review threads for all the PRs in this series #8517, #8518 and #8519. I would like to get them to the point where we can submit them so that other developers can start testing this implementation. I went over the reviews and tried to separate blocking issues from issues we could postpone in a follow-up PR or even open an issue to fix later.

I would like to get consensus on what we need done to get some forward progress. Given that this feature is protected by a flag, I don't think is should be too destabilizing to add it even when there are still things to fix. I don't want to have a broken initial version, but I also don't want to spend a long time getting it to be perfect before it goes in. We need the feature exposed to developers so they can start testing it.

I'll add all my notes here and will put cross-references in the other PRs so I don't lose track. These are the things I think should be fixed now before it goes in. These were signaled by Copilot on 4/Aug:

Two blocking issues for #8517

  1. The srcIsHeap misclassification. This one is a false error on valid HLSL, and would affect resource kinds that use aliases. May be do the check based on heap provenance rather than on the source being a subscript expression?
  2. The unregistered-decl path, which you already said you would fix. We don't need full support now. A clean diagnostic and a not %dxc test is enough, with an issue for the real fix.

One blocking issue for #8518

  1. The unregistered-decl path. This one could be converted into a diagnostic with a not %dxc test for now. The same defect shows up on [SPIR-V] Add SPV_EXT_descriptor_heap + SPV_KHR_untyped_pointers codegen #8517, so wherever you fix it is fine by me. An issue to follow-up would be enough for now.

Two blocking issues for #8519

  1. The acceleration-structure diagnostic firing under -fvk-resource-heap-stride. We are now rejecting valid use of this feature. Should be a straightforward fix adding && !spirvOptions.resourceHeapStride.has_value(), plus a RUN line.
  2. The release note. CONTRIBUTING.md. does call for one on new compiler options, so I would just add it.

Everything else I am happy to defer, and I do not think it should hold back the series:

  1. Chris B (@llvm-beanz)'s requestTargetEnv point and brace suggestion. You fixed both in 6bc5a9e and a later rebase dropped them, along with sm6_6.descriptorheap.ext.targetenv.error.hlsl. Could you fold them back in next time you touch the branch, and check whether the rebases lost anything else?
  2. The NonUniformResourceIndex question. This needs more discussion. The current behaviour matches what Tobski described and is documented. One thing we could have an issue for: the index OpCopyObject still carries NonUniformEXT, so modules pick up ShaderNonUniformEXT and SPV_EXT_descriptor_indexing that they do not need.
  3. Acceleration structures missing from the stride. [SPIR-V] Add descriptor heap RaytracingAccelerationStructure support #8518 fixes this, so it is only a problem if [SPIR-V] Add SPV_EXT_descriptor_heap + SPV_KHR_untyped_pointers codegen #8517 is submitted on its own.
  4. The SPIR-V.rst wording and the it's typo. Cosmetic, follow-up whenever.
  5. The acceleration structure reassignment rejection. The invalid SPIR-V is fixed, so we just have a misleading message. A follow-up PR can fix this.
  6. The parenthesized subscript rejection. This one predates these PRs, so it is not a regression here.
  7. The run-together error messages. Only reachable on an already-invalid command line, and both messages are still readable.
  8. The missing one-flag RUN lines. The fallback seems right. This seems more of a completeness thing than a risk.
  9. The untested requires -spirv branch. It is a copy of two existing branches in that file, neither of which is tested either.
  10. Two more that Copilot raised and you have already tracked as issues: the out/inout writeback and uninitialized-declaration cases in #8732, and the stride being derived from compiler flags rather than the heap layout in #8714. Thanks for filing those.

Damyan Pepper (damyanp) added a commit to damyanp/DirectXShaderCompiler that referenced this pull request Aug 7, 2026
Five issues triaged in isolated parallel sessions against a Debug build
of ab54009, collated by a separate session briefed only by on-disk
artifacts.

| # | verdict | history |
| --- | --- | --- |
| 2530 | repros | always (20/20 releases) |
| 3055 | repros | v1.4.1907 output byte-identical to main |
| 3259 | repros | always from v1.5.2010 |
| 8725 | repros | always from v1.8.2505 (5 of 20 can express lib_6_9) |
| 8732 | inconclusive | unmeasurable -- filed against unmerged PR microsoft#8517 |

microsoft#8732 is the useful outlier: every symbol it blames has zero occurrences
on main, so it is not does-not-repro -- the symptom was never in the
compiler being measured. It needs a human decision, not a fix.

The headline tooling fix is the invalid-probe classifier, which batch 004
predicted would be least trustworthy where the reported symptom is itself
a diagnostic. It was, in both directions: a release emitting a correct,
complete diagnostic -- what a fix looks like on such an issue -- scored
invalid-probe and could hide the fixing release; and a probe whose
predicate had *matched* was still discarded because the symptom text is
itself a marker, erasing ground truth and then misattributing it to the
profile. microsoft#3055 escaped only because dxc says "no matching member function
for call to" where the marker is "no matching function for call to".

The fix is deliberately narrow: a demotion is suppressed only when the
issue's own match.json positively quotes the marker text. Making the
classifier broadly more permissive would reintroduce the fake-regression
bug it exists to prevent, which has already produced wrong verdicts
twice. Verified against every archived predicate -- no legitimate
demotion is lost, and a reindex moved exactly the two probes that
demonstrated the defect out of 346.

Also fixed: reindex now re-scores variant captures, which previously were
never checked against the current classifier -- its first run found three
stale headers in microsoft#2202 that had been wrong since batch 004; invalid-probe
verdicts now record why on disk; `is not supported` is anchored to a
target/profile clause; ce_args() valueless-flag handling; a warning when
--args diverges from cmd.txt; a labels --refresh REST fallback. ~30 new
tests.

Ground truth was rebuilt for this batch (upstream/main merged, SPIRV-Tools
submodule to 1c336172, cached version headers cleared) because microsoft#8732 sits
in the blast radius of ec2ba18. That proved load-bearing rather than
precautionary: the reporter's own workaround compiles on v1.9.2607 but
fails on main under a newly enforced UniformConstant ArrayStride rule.
The stale build would have reported the feature's state incorrectly.

Batch 005's verdicts are therefore measured against a different compiler
than batches 001-004; triaged_with_commit records this per issue.

Report-only: no issue was edited, commented on or closed, and no DXC
source is touched.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6bd9cb60-aeb2-4d6c-9462-7a5e79fe1cda
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

spirv Work related to SPIR-V

Projects

Status: In progress

Development

Successfully merging this pull request may close these issues.

6 participants