Apart of #8518
Description
Under -fspv-use-descriptor-heap, all resource-heap runtime arrays must share a single stride (ArrayStrideIdEXT), equal to the largest descriptor size that may appear in the heap. Normally it is just the max of image and buffer descriptor sizes but becomes a three-way max when acceleration structures are present.
The stride value is built once and cached on first use, so the decision must be committed before the codegen loop. Currently the compiler predicts whether acceleration structures will appear in the heap using two proxies: (1) any function in the work queue is a ray-tracing stage, or (2) the user listed SPV_KHR_ray_tracing, SPV_NV_ray_tracing, or SPV_KHR_ray_query via -fspv-extension. Neither proxy is equivalent to "codegen will actually place an acceleration structure in the heap," so they misfire in both directions:
- False rejection: A compute shader that loads a
RaytracingAccelerationStructure from ResourceDescriptorHeap via inline ray query is rejected it satisfies neither proxy, so the stride is built without the acceleration structure size. Rather than emit a silently incorrect stride, the compiler errors out.
- Over-wide stride: A shader that lists a ray extension (e.g.
SPV_KHR_ray_query) but never places an acceleration structure in the heap gets the three-way stride and a spurious OpTypeAccelerationStructureKHR in the module, taking a performance penalty.
Root cause: SpirvBuilder::getResourceHeapArrayStride() caches the stride on first use, so the decision must be made before the codegen loop in HandleTranslationUnit(), before reachability or actual heap accesses are known.
Steps to Reproduce
Defect 1: legal shader rejected:
// dxc -T cs_6_6 -E main -fspv-use-descriptor-heap -fspv-target-env=vulkan1.3 -spirv repro.hlsl
RWBuffer<float4> output : register(u0);
[numthreads(1, 1, 1)]
void main(uint3 tid : SV_DispatchThreadID) {
RaytracingAccelerationStructure scene = ResourceDescriptorHeap[1];
RayDesc ray;
ray.Origin = float3(0, 0, 0);
ray.Direction = float3(0, 0, 1);
ray.TMin = 0.0; ray.TMax = 1000.0;
RayQuery<RAY_FLAG_NONE> q;
q.TraceRayInline(scene, RAY_FLAG_NONE, 0xff, ray);
output[tid.x] = float4(q.Proceed() ? 1.0 : 0.0, 0, 0, 0);
}
Expected: compiles; stride widened to max(image, buffer, acceleration_structure).
Defect 2: over-wide stride:
// dxc -T cs_6_6 -E main -fspv-use-descriptor-heap -fspv-target-env=vulkan1.3
// -fspv-extension=SPV_EXT_descriptor_heap -fspv-extension=SPV_KHR_untyped_pointers
// -fspv-extension=SPV_KHR_ray_query -spirv repro2.hlsl
RWBuffer<float4> output : register(u0);
[numthreads(1, 1, 1)]
void main(uint3 tid : SV_DispatchThreadID) {
Texture2D<float4> tex = ResourceDescriptorHeap[0];
output[tid.x] = tex.Load(int3(tid.x, 0, 0));
}
Expected: two-way stride max(sizeof(image), sizeof(buffer)), no acceleration structure type in the module.
Actual Behavior
Defect 1:
error: 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
Defect 2: Compiles, but emits a three-way stride and every heap slot is padded to a descriptor size the shader never uses.
Workarounds:
- Pass
-fspv-extension=SPV_KHR_ray_query. -fspv-extension is an exclusive allow-list however, so every other needed extension must be listed too.
- Pass
-fvk-resource-heap-stride N. Requires knowing driver-specific descriptor sizes. Wrong value results on crashes.
Apart of #8518
Description
Under
-fspv-use-descriptor-heap, all resource-heap runtime arrays must share a single stride (ArrayStrideIdEXT), equal to the largest descriptor size that may appear in the heap. Normally it is just the max of image and buffer descriptor sizes but becomes a three-way max when acceleration structures are present.The stride value is built once and cached on first use, so the decision must be committed before the codegen loop. Currently the compiler predicts whether acceleration structures will appear in the heap using two proxies: (1) any function in the work queue is a ray-tracing stage, or (2) the user listed
SPV_KHR_ray_tracing,SPV_NV_ray_tracing, orSPV_KHR_ray_queryvia-fspv-extension. Neither proxy is equivalent to "codegen will actually place an acceleration structure in the heap," so they misfire in both directions:RaytracingAccelerationStructurefromResourceDescriptorHeapvia inline ray query is rejected it satisfies neither proxy, so the stride is built without the acceleration structure size. Rather than emit a silently incorrect stride, the compiler errors out.SPV_KHR_ray_query) but never places an acceleration structure in the heap gets the three-way stride and a spuriousOpTypeAccelerationStructureKHRin the module, taking a performance penalty.Root cause:
SpirvBuilder::getResourceHeapArrayStride()caches the stride on first use, so the decision must be made before the codegen loop inHandleTranslationUnit(), before reachability or actual heap accesses are known.Steps to Reproduce
Defect 1: legal shader rejected:
Expected: compiles; stride widened to
max(image, buffer, acceleration_structure).Defect 2: over-wide stride:
Expected: two-way stride
max(sizeof(image), sizeof(buffer)), no acceleration structure type in the module.Actual Behavior
Defect 1:
Defect 2: Compiles, but emits a three-way stride and every heap slot is padded to a descriptor size the shader never uses.
Workarounds:
-fspv-extension=SPV_KHR_ray_query.-fspv-extensionis an exclusive allow-list however, so every other needed extension must be listed too.-fvk-resource-heap-stride N. Requires knowing driver-specific descriptor sizes. Wrong value results on crashes.