Skip to content

[SPIR-V] Add descriptor heap RaytracingAccelerationStructure support - #8518

Open
Jonathan Zakharov (jzakharovnv) wants to merge 21 commits into
microsoft:mainfrom
jzakharovnv:pr2-raytracing-accel-struct
Open

[SPIR-V] Add descriptor heap RaytracingAccelerationStructure support#8518
Jonathan Zakharov (jzakharovnv) wants to merge 21 commits into
microsoft:mainfrom
jzakharovnv:pr2-raytracing-accel-struct

Conversation

@jzakharovnv

Copy link
Copy Markdown
Collaborator

Building off of #8517, this PR extends the SPV_EXT_descriptor_heap native heap lowering to cover RaytracingAccelerationStructure resources loaded from ResourceDescriptorHeap. It is part 2/4 in a series.

Acceleration structure descriptors are accessed via OpUntypedAccessChainKHR into a runtime array of OpTypeAccelerationStructureKHR, consistent with the image and sampler paths added in the previous commit.

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
Jonathan Zakharov (jzakharovnv) force-pushed the pr2-raytracing-accel-struct branch 3 times, most recently from d899b05 to b12b9ea Compare June 4, 2026 22:59
@jzakharovnv

Copy link
Copy Markdown
Collaborator Author

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

return true;
}

if (isRaytracingAccelerationStructure(decl->getType())) {

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.

Since acceleration structures are distinct from image and buffers, do they still fit in max(sizeof(image), sizeof(buffer))? If not, the stride will be too small and heap indexing will land in the wrong spot.

Maybe we need to incorporate acceleration structures when computing the default stride if RT is used?

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.

Good catch, it would be correct to include acceleration structures in the computation for the resource heap stride. Will address this in my next set of commits.

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.

@@ -0,0 +1,42 @@
// RUN: %dxc -T lib_6_6 -fspv-use-descriptor-heap -fspv-target-env=vulkan1.3 -fvk-resource-heap-stride 64 -fvk-sampler-heap-stride 32 -fspv-extension=SPV_KHR_ray_tracing -fspv-extension=SPV_EXT_descriptor_heap -fspv-extension=SPV_KHR_untyped_pointers -spirv %s | FileCheck %s

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 is using flags introduced in #8519. It will break if the PRs get merged in order. Perhaps move this test to #8519 and add only default stride tests 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.

Another result of some clumsy commits and now outdated commits! Should be able to remove the usage of these flags now that strides are computed automatically. Will address next set of commits.

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.

@github-project-automation github-project-automation Bot moved this from New to In progress in HLSL Roadmap Jul 17, 2026
@dnovillo Diego Novillo (dnovillo) added the spirv Work related to SPIR-V label Jul 17, 2026
@jzakharovnv
Jonathan Zakharov (jzakharovnv) force-pushed the pr2-raytracing-accel-struct branch 2 times, most recently from 23aff82 to 02f3581 Compare July 23, 2026 19:39

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

Only a question left on detecting RT usage of the heap.

if (shaderModelKindIsRayTracing(fi->shaderModelKind)) {
needsAccelStruct = true;
break;
}

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 would fail for compute/graphics shaders that need to use RayQuery and have AS on the heap. I think this should be a translation unit walk looking for a vardecls and setting the flag on the first match.

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.

This ended up being a much harder problem than I anticipated. I filed an issue with #8714 and have provided some work arounds in a revised Included AccelerationStructure in resource heap stride calculation. There also exists the work around of using the options provided in [SPIR-V] Add -fvk-resource-heap-stride / -fvk-sampler-heap-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.

This ended up being a much harder problem than I anticipated. I filed an issue with #8714 and have provided some work arounds in a revised Included AccelerationStructure in resource heap stride calculation. There also exists the work around of using the options provided in [SPIR-V] Add -fvk-resource-heap-stride / -fvk-sampler-heap-stride.

Sure. Thanks for documenting workarounds. I think this is now ready.

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.

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

Extends native SPIR-V descriptor-heap lowering to acceleration structures and broader resource operations.

Changes:

  • Adds descriptor-size-based heap strides, including acceleration structures.
  • Adds native buffer, image, sampler, atomic, and alias lowering.
  • Expands SPIR-V tests and documentation.

Reviewed changes

Copilot reviewed 51 out of 51 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
tools/clang/unittests/SPIRV/SpirvContextTest.cpp Extends runtime-array uniqueness tests.
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 gradient and bias sampling.
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.rwtexture-dims.hlsl Tests storage-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 nonuniform-index handling.
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.mixed-bound.hlsl Tests bound and heap resources together.
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 interoperability.
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.gather.hlsl Tests texture 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-access 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 shared heap strides.
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.array-stride.accelstruct.hlsl Tests acceleration-structure stride inclusion.
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.append-consume.error.hlsl Tests append/consume diagnostics.
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.acceleration-structure.stride.error.hlsl Tests missing acceleration stride diagnostics.
tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.acceleration-structure.hlsl Tests acceleration-structure heap loads.
tools/clang/test/CodeGenSPIRV/resource-heap-ext-texture.hlsl Removes the superseded aggregate test.
tools/clang/lib/SPIRV/SpirvType.cpp Includes stride IDs in type 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 lowering and acceleration support.
tools/clang/lib/SPIRV/SpirvContext.cpp Canonicalizes buffer and runtime-array types.
tools/clang/lib/SPIRV/SpirvBuilder.cpp Builds descriptor-size constants 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 Emits new instructions and decorations.
tools/clang/lib/SPIRV/DeclResultIdMapper.h Declares function-variable aliases.
tools/clang/lib/SPIRV/DeclResultIdMapper.cpp Registers function-variable aliases.
tools/clang/lib/SPIRV/CapabilityVisitor.cpp Enforces Vulkan 1.3 for native heaps.
tools/clang/lib/SPIRV/AstTypeProbe.cpp Recognizes acceleration-structure types.
tools/clang/include/clang/SPIRV/SpirvVisitor.h Adds visitor methods.
tools/clang/include/clang/SPIRV/SpirvType.h Stores runtime-array stride IDs.
tools/clang/include/clang/SPIRV/SpirvInstruction.h Defines new instruction classes.
tools/clang/include/clang/SPIRV/SpirvContext.h Extends type-context APIs.
tools/clang/include/clang/SPIRV/SpirvBuilder.h Exposes descriptor-stride builders.
tools/clang/include/clang/SPIRV/AstTypeProbe.h Declares acceleration-type probing.
docs/SPIR-V.rst Documents native descriptor heaps.
Comments suppressed due to low confidence (1)

tools/clang/lib/SPIRV/SpirvEmitter.cpp:7072

  • Only casts are stripped here, so a syntactically valid parenthesized heap base such as (ResourceDescriptorHeap)[i] is diagnosed as unsupported even though it still refers directly to the builtin variable. Use IgnoreParenCasts() consistently when resolving the base declaration.
      const auto *declRefExpr = dyn_cast<DeclRefExpr>(baseExpr->IgnoreCasts());
      const auto *decl =
          declRefExpr ? dyn_cast<VarDecl>(declRefExpr->getDecl()) : nullptr;
      if (!decl) {
        emitError("unsupported ResourceDescriptorHeap/SamplerDescriptorHeap "
                  "expression",
                  baseExpr->getExprLoc());
        return nullptr;

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

// (Dim2D, depth=0, not-arrayed, non-MS, sampled, Unknown format), so
// %[[TexDesc]] serves as both the placeholder for the size calculation and
// the real descriptor type for the Texture2D access below.
// CHECK-DAG: %[[TexDesc:[a-zA-Z0-9_]+]] = OpTypeImage %float 2D 0 0 0 1 Unknown

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.

Fixing test in next set of commits


// --- Types (user-declared + stride-computation placeholders) ---------------
// CHECK-DAG: %[[Accel:[a-zA-Z0-9_]+]] = OpTypeAccelerationStructureKHR
// CHECK-DAG: %[[Img:[a-zA-Z0-9_]+]] = OpTypeImage %float 2D 0 0 0 1 Unknown

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.

Fixing test in next set of commits

Comment on lines +864 to +868
if (!needsAccelStruct && !spirvOptions.allowedExtensions.empty())
needsAccelStruct =
featureManager.isExtensionEnabled(Extension::KHR_ray_tracing) ||
featureManager.isExtensionEnabled(Extension::NV_ray_tracing) ||
featureManager.isExtensionEnabled(Extension::KHR_ray_query);

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 docs/SPIR-V.rst Outdated
Comment on lines +2102 to +2105
The concrete descriptor type is selected at each heap access. For image,
sampler, and texel buffer resources, DXC forms a runtime array of that
descriptor type and decorates the array with a byte ``ArrayStride``, then uses
``OpUntypedAccessChainKHR`` followed by ``OpLoad``:

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.

Fixing documentation in next set of commits


// Three distinct descriptor heap sizes exist:
// the image/Texture2D type (%[[TexDesc]]), the Uniform buffer, and the sampler.
// Regression test: make sure of no per-element nor per acces behavior exists

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.

Fixing test in next set of commits

Comment on lines +5252 to +5259
auto &alias = descriptorHeapImageAliasVars[dstVar];
if (!alias.indexVar)
alias.indexVar = createDescriptorHeapIndexVar(dstVar);
alias.imageType = found->second.imageType;
alias.arrayType = found->second.arrayType;
alias.heap = found->second.heap;
storeDescriptorHeapIndex(alias.indexVar, found->second.index,
found->second.indexType, srcExpr);
Comment thread docs/SPIR-V.rst Outdated
Comment on lines +2144 to +2148
This path supports texture, RWTexture, sampler, Buffer/RWBuffer,
StructuredBuffer/RWStructuredBuffer without associated counter operations,
ByteAddressBuffer/RWByteAddressBuffer, ConstantBuffer, and TextureBuffer heap
loads, including direct field and array-element accesses for
``ConstantBuffer<T>`` and ``TextureBuffer<T>``. ``NonUniformResourceIndex`` is
Comment on lines +7048 to +7059
// The heap index expression must be immediately converted to a concrete
// resource type (an implicit cast inserted by the front-end). If the
// parent is missing or is not a cast (e.g. the result is discarded as
// a statement, or used in a context with no target resource type) we
// cannot determine the resource type.
const auto *parentExpr =
dyn_cast_or_null<CastExpr>(parentMap->getParent(expr));
if (!parentExpr) {
emitError("ResourceDescriptorHeap/SamplerDescriptorHeap indexing must "
"be used as a resource",
expr->getExprLoc());
return nullptr;
Comment on lines +7098 to +7103
emitError("acceleration structure loaded from ResourceDescriptorHeap "
"requires the resource heap stride to account for "
"acceleration structure descriptors; compile with "
"-fspv-extension=SPV_KHR_ray_tracing or "
"-fspv-extension=SPV_KHR_ray_query",
expr->getExprLoc());
Comment on lines +327 to +329

EXPECT_NE(spvContext.getRuntimeArrayType(int32, llvm::None),
spvContext.getRuntimeArrayType(int32, 32));

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 set of commits.

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

Copilot reviewed 52 out of 52 changed files in this pull request and generated 1 comment.

Suppressed comments (3)

tools/clang/lib/SPIRV/SpirvEmitter.cpp:5315

  • A heap-to-heap reassignment of RaytracingAccelerationStructure also reaches this branch because mixingDetected includes (isASType && wasHeap) regardless of srcIsHeap. That assignment does not mix bound and heap resources, so this diagnostic is misleading; report the unsupported AS reassignment separately.
    emitError("mixing bound and descriptor heap resources in the same variable "
              "is not supported with SPV_EXT_descriptor_heap",
              loc);

tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.array-stride.hlsl:62

  • Use the possessive “its” rather than “it's” (“it is”).
// The sampler array just uses the sampler size as it's stride.

docs/SPIR-V.rst:2089

  • This is a significant user-visible compiler feature, but docs/ReleaseNotes.md has no native descriptor-heap entry. Please add release-note coverage, or point to the shared release note planned for this four-PR series.
When ``-fspv-use-descriptor-heap`` is specified, DXC lowers
``ResourceDescriptorHeap`` and ``SamplerDescriptorHeap`` through
``SPV_EXT_descriptor_heap`` instead of the default emulated heap path. This
also requires ``SPV_KHR_untyped_pointers`` and ``-fspv-target-env=vulkan1.3``

Comment thread tools/clang/lib/SPIRV/SpirvEmitter.cpp Outdated
Comment on lines +2105 to +2107
(void)doExpr(init->IgnoreParenCasts());
tryToAssignDescriptorHeapBufferAlias(decl, init);
return true;

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.

Good catch, will fix

@dnovillo

Copy link
Copy Markdown
Collaborator

Added an analysis on this series: #8517 (comment)

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.
Jonathan Zakharov (jzakharovnv) added a commit to jzakharovnv/DirectXShaderCompiler that referenced this pull request Aug 16, 2026
Copilot AI review requested due to automatic review settings August 16, 2026 21:42

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

Copilot reviewed 59 out of 59 changed files in this pull request and generated 1 comment.

Suppressed comments (3)

tools/clang/unittests/SPIRV/SpirvContextTest.cpp:1

  • These integer-to-pointer casts are implementation-defined and can be problematic on platforms with non-integral pointer representations or with sanitizers enabled. Prefer using stable, non-dereferenced addresses as tokens (e.g., alignas(SpirvInstruction) static char token1, token2; and cast &tokenN), which preserves the intent (pointer identity) without relying on integer pointer values.
    tools/clang/include/clang/SPIRV/SpirvContext.h:1
  • getHashValue() hashes only getStride().hasValue() (not the stride value when present). With many runtime arrays that differ by literal stride, this will create avoidable hash collisions and slow lookups/uniquing. Include the stride value in the hash when getStride() has a value (and still include getArrayStrideId() when present) while keeping operator== as the source of truth.
//===-- SpirvContext.h - Context holding SPIR-V codegen data ----*- C++ -*-===//

tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.array-stride.hlsl:62

  • Fix grammar: use the possessive 'its' (not the contraction 'it's').
// The sampler array just uses the sampler size as it's stride.

Comment on lines 3561 to 3568
// do not need to mark the "param.var.*" variables as precise.
const bool isPrecise = false;
const bool isNoInterp = param->hasAttr<HLSLNoInterpolationAttr>() ||
(argInst && argInst->isNoninterpolated());

auto *tempVar = spvBuilder.addFnVar(varType, arg->getLocStart(), varName,
isPrecise, isNoInterp);

Copilot AI review requested due to automatic review settings August 16, 2026 21:44

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

Copilot reviewed 59 out of 59 changed files in this pull request and generated 1 comment.

Suppressed comments (2)

tools/clang/unittests/SPIRV/SpirvContextTest.cpp:1

  • Using integer-to-pointer reinterpret_cast for sentinel identities is implementation-defined and can be problematic under some sanitizers/toolchains. Prefer using addresses of real objects with stable storage (e.g., two distinct local dummy objects and reinterpret_cast<SpirvInstruction *>(&dummy)), which preserves the “pointer identity only” intent without relying on invalid pointer values.
    tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.array-stride.hlsl:62
  • Correct the grammar: use the possessive 'its' instead of 'it's'.
// The sampler array just uses the sampler size as it's stride.

Comment on lines +3552 to 3571
// instead of crashing. TODO: implement full buffer-alias function-call
// support (VariablePointersStorageBuffer + matching createFnParam type).
const auto *var = dyn_cast<VarDecl>(declRefExpr->getDecl());
if (var && descriptorHeapBufferAliasVars.count(var)) {
emitError("heap buffer alias cannot be passed to a user function; "
"access the buffer element directly at the call site",
arg->getLocStart());
// emitError does not halt codegen; returning nullptr here propagates
// to spvBuilder and causes an access violation before the diagnostic
// surfaces. Return a zero uint placeholder so downstream expression
// consumers remain valid. The emitted error ensures the shader is
// rejected even if codegen continues with the placeholder.
QualType retTy = callExpr->getCallReturnType(astContext);
if (retTy->isVoidType())
return nullptr;
return spvBuilder.getConstantInt(astContext.UnsignedIntTy,
llvm::APInt(32, 0), false);
}
argInfo = declIdMapper.getDeclEvalInfo(declRefExpr->getDecl(),
arg->getLocStart());
Extends the SPV_EXT_descriptor_heap native heap lowering to cover RaytracingAccelerationStructure resources loaded from ResourceDescriptorHeap.

Acceleration structure descriptors are accessed via OpUntypedAccessChainKHR into a runtime array of OpTypeAccelerationStructureKHR, consistent with the image and sampler paths added in the previous commit.
Copilot AI review requested due to automatic review settings August 17, 2026 05:45

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

Copilot reviewed 59 out of 59 changed files in this pull request and generated 2 comments.

Suppressed comments (3)

tools/clang/unittests/SPIRV/SpirvContextTest.cpp:1

  • Casting small integers like 1/2 to pointers is implementation-defined and can trip sanitizers even if never dereferenced. A safer way to get stable distinct pointer identities is to take the addresses of two dummy objects (e.g., int dummy1, dummy2; and reinterpret_cast<SpirvInstruction*>(&dummy1) / &dummy2) so the test remains robust across platforms and tooling.
    tools/clang/test/CodeGenSPIRV/sm6_6.descriptorheap.ext.targetenv.error.hlsl:1
  • This checked diagnostic string reads incomplete (it doesn’t say what target env is being used / why it’s “not permitted”). If the underlying diagnostic can include the selected target environment (e.g., Vulkan 1.2) and the required one (Vulkan 1.3), the test should be updated to match the more actionable message.
    tools/clang/lib/SPIRV/SpirvEmitter.cpp:3104
  • The early-return diagnostic for returning heap buffer aliases only triggers when the returned expression resolves to a VarDecl recorded in descriptorHeapBufferAliasVars. Returning a heap-sourced buffer-like value directly (e.g., return ResourceDescriptorHeap[i]; for StructuredBuffer/ByteAddressBuffer/ConstantBuffer/TextureBuffer) can still reach loadIfGLValue() and risks emitting the same invalid whole-resource load that this code is trying to prevent. Consider extending this rejection to cover direct heap subscripts of buffer-like resource types as well, not just alias variables.
    if (isHeapSourcedValue(srcExpr)) {
      if (isDescriptorHeap(srcExpr)) {
        // Direct heap subscript: register the heap variable so the declaration
        // mapper can resolve it for the return instruction.
        const Expr *base = nullptr;
        getDescriptorHeapOperands(srcExpr, &base, /* index= */ nullptr);
        const Expr *parentExpr = cast<CastExpr>(parentMap->getParent(srcExpr));
        QualType resourceType = parentExpr->getType();
        const auto *declRefExpr = dyn_cast<DeclRefExpr>(base->IgnoreCasts());
        declIdMapper.createResourceHeap(cast<VarDecl>(declRefExpr->getDecl()),
                                        resourceType);
      }
      // Buffer alias: emitting a load of the whole resource (runtime-array
      // struct) produces invalid SPIR-V.  emitError does not halt codegen,
      // so terminate the basic block with an undef return value before
      // returning to prevent loadIfGLValue from emitting an invalid load and
      // leaving the block without a terminator.
      // TODO: implement cross-function alias propagation for buffer aliases
      //       using VariablePointersStorageBuffer (tracked as follow-up).
      else if (const auto *var =
                   dyn_cast_or_null<VarDecl>(getReferencedDef(srcExpr))) {
        if (descriptorHeapBufferAliasVars.count(var)) {
          emitError("heap buffer alias cannot be returned from a function; "
                    "access the buffer element directly at the return site",
                    retVal->getLocStart());
          spvBuilder.createReturnValue(
              spvBuilder.getUndef(curFunction->getReturnType()),
              stmt->getReturnLoc());
          return;
        }
      }
    }

Comment on lines +3308 to +3313
// consume the assignment to prevent a null-deref. Image aliases do have a
// backing function variable, so they can fall through to the plain handle
// store.
if (descriptorHeapBufferAliasVars.count(dstVar) ||
declIdMapper.hasFnVarAlias(dstVar))
return static_cast<SpirvInstruction *>(nullptr);
Comment on lines +3327 to +3329
tryToAssignToDescriptorHeapAlias(expr))
return aliasResult.getValue();

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.

4 participants