test(rt): pick hit-shader descriptors from the heap by a runtime index

On NVIDIA 610.43.02, selecting a descriptor-heap descriptor with a
runtime index in a hit shader lost the device, for storage buffers and
sampled images alike, which is why the examples use spec constants
there. HeapDynamicIndexHit renders two instances whose closest-hit picks
a buffer and a texture by a runtime index: one instance uses the same
set across every wave, the other a different set in every other pixel
column, so neighbouring lanes select different descriptors. It passes
on 615.78.08 and on llvmpipe.

On NVIDIA drivers older than 615.78.08 it skips rather than abort the
suite. With validation on it also renders in a child process with
validation off, since GPU-assisted validation hides the fault.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jorijn van der Graaf 2026-10-19 03:03:16 +02:00
commit 37fe0dc49f
Signed by: jorijnvdgraaf
GPG key ID: 2937E59CDCC1BCFB
5 changed files with 523 additions and 0 deletions

View file

@ -0,0 +1,35 @@
//SPDX-License-Identifier: LGPL-3.0-only
//SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
#version 460
#extension GL_EXT_ray_tracing : enable
#extension GL_EXT_shader_explicit_arithmetic_types_int16 : enable
#extension GL_EXT_descriptor_heap : enable
#extension GL_EXT_nonuniform_qualifier : enable
// Picks a storage buffer and a sampled image out of the descriptor heap by a
// runtime index. Instance 0 uses descriptor set 0 everywhere, so the index is
// the same across each wave. Instance 1 alternates between sets 1 and 0 from
// one pixel column to the next, so neighbouring lanes of every wave over it
// pick different descriptors. On NVIDIA 610.43.02 a runtime index here lost the
// device, for both descriptor kinds, which is why the engine's examples select
// hit-shader descriptors through spec constants.
layout(constant_id = 0) const uint16_t bufferStart = 0us;
layout(constant_id = 1) const uint textureBase = 0u;
layout(constant_id = 2) const uint colourBase = 0u;
layout(descriptor_heap, std430) readonly buffer Colour { vec4 value; } colours[];
layout(descriptor_heap) uniform texture2D textures[];
layout(descriptor_heap) uniform sampler samplers[];
layout(location = 0) rayPayloadInEXT vec3 hitValue;
void main() {
uint set = gl_InstanceCustomIndexEXT == 0u ? 0u : 1u - (gl_LaunchIDEXT.x & 1u);
vec4 colour = colours[nonuniformEXT(uint(bufferStart) + colourBase + set)].value;
vec4 texel = textureLod(sampler2D(textures[nonuniformEXT(textureBase + set)], samplers[0]),
vec2(0.5), 0.0);
// Red from the buffer, green from the texture, so each descriptor kind
// is checked separately.
hitValue = vec3(colour.r, texel.g, 0.0);
}