fix(vulkan-rt): work around NVIDIA descriptor-heap AS-read device-loss (#15)
Reading an acceleration structure through VK_EXT_descriptor_heap aborts with VK_ERROR_DEVICE_LOST on NVIDIA 610.43.02 — a brand-new-extension driver fault isolated in #7 (engine setup is correct and validation-clean; images/buffers through the same heap work, and both traceRayEXT and inline rayQuery fault identically on the AS read). An acceleration structure can equally be reached by its device address via OpConvertUToAccelerationStructureKHR, which reads no descriptor and so never touches the faulting heap path. glslang has no GLSL spelling for that conversion, so VulkanShader rewrites the compiled SPIR-V at module-load time: every `OpLoad %accelStruct <heap-ptr>` becomes a load of the TLAS device address from a synthesized push-constant block followed by the convert. RTPass pushes the active frame's TLAS address into that push constant. User GLSL and example code are unchanged; acceleration structures still bind into the heap normally. The workaround is gated on Device::workaroundDescriptorHeapAS (true only on the NVIDIA proprietary driver) and confined to one fenced block in Crafter.Graphics-ShaderVulkan.cppm plus the RTPass push and the shaderInt64 feature toggle — delete those once a fixed NVIDIA driver ships and the heap AS read becomes the direct path again. Verified: VulkanTriangle ray-traces correctly on native NVIDIA (RTX 4090), validation-layer-clean, no device loss. The SPIR-V rewrite was independently validated with spirv-val on both the VulkanTriangle and Sponza raygen modules. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
b9f65f5273
commit
950059c86e
7 changed files with 270 additions and 30 deletions
|
|
@ -566,12 +566,22 @@ void Device::Initialize() {
|
|||
memoryDecompressionProperties.pNext = const_cast<void*>(rayTracingProperties.pNext);
|
||||
rayTracingProperties.pNext = &memoryDecompressionProperties;
|
||||
}
|
||||
// Chain driver properties onto the tail of the query so we can detect
|
||||
// the NVIDIA proprietary driver for the descriptor-heap AS-read
|
||||
// workaround (issue #15 / #7).
|
||||
descriptorHeapProperties.pNext = &driverProperties;
|
||||
VkPhysicalDeviceProperties2 properties2 {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
|
||||
.pNext = &rayTracingProperties
|
||||
};
|
||||
vkGetPhysicalDeviceProperties2(physDevice, &properties2);
|
||||
|
||||
// NVIDIA's brand-new VK_EXT_descriptor_heap acceleration-structure read
|
||||
// path faults (see #7); enable the SPIR-V rewrite workaround there. Other
|
||||
// drivers (and any future fixed NVIDIA driver, once this gate is removed)
|
||||
// take the normal heap-bound AS path unchanged.
|
||||
workaroundDescriptorHeapAS = (driverProperties.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY);
|
||||
|
||||
// Sanity-gate: GDeflate 1.0 must actually be in the supported method set.
|
||||
if (memoryDecompressionSupported &&
|
||||
(memoryDecompressionProperties.decompressionMethods & VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT) == 0) {
|
||||
|
|
@ -699,6 +709,11 @@ void Device::Initialize() {
|
|||
.shaderSampledImageArrayDynamicIndexing = VK_TRUE,
|
||||
.shaderStorageBufferArrayDynamicIndexing = VK_TRUE,
|
||||
.shaderStorageImageArrayDynamicIndexing = VK_TRUE,
|
||||
// shaderInt64: only needed for the NVIDIA descriptor-heap AS-read
|
||||
// workaround (issue #15 / #7), which loads the TLAS device address
|
||||
// as a 64-bit push constant. Gated so it isn't required on drivers
|
||||
// that don't take the workaround path. Remove with the workaround.
|
||||
.shaderInt64 = workaroundDescriptorHeapAS ? VK_TRUE : VK_FALSE,
|
||||
.shaderInt16 = VK_TRUE
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue