fix(rt): BuildTLAS on an empty scene builds an empty TLAS
The TLAS instance and metadata buffers were sized to the instance count, so building before anything was in the scene created zero-size buffers. That is invalid usage: NVIDIA fails the allocation with VK_ERROR_OUT_OF_DEVICE_MEMORY and BuildTLAS threw, leaving the TLAS with a buffer handle that has no memory behind it. Both buffers now get at least one slot, and the scratch buffer at least one byte, since an empty TLAS may report no scratch at all. An empty TLAS is valid to trace against; every ray misses. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
70d9c2c82a
commit
3fca002ef5
1 changed files with 10 additions and 3 deletions
|
|
@ -119,10 +119,15 @@ void RenderingElement3D::BuildTLAS(VkCommandBuffer cmd, std::uint32_t index, RTB
|
||||||
// (no-op when the chosen type is coherent — the previous behaviour),
|
// (no-op when the chosen type is coherent — the previous behaviour),
|
||||||
// and the queue submit carries the host-write -> shader-read ordering as
|
// and the queue submit carries the host-write -> shader-read ordering as
|
||||||
// it always has.
|
// it always has.
|
||||||
|
//
|
||||||
|
// At least one slot each: a TLAS built before anything is in the scene
|
||||||
|
// has zero instances, and a zero-size buffer is invalid (NVIDIA fails
|
||||||
|
// the allocation). The empty build reads no instance anyway.
|
||||||
if (tlas.instanceBuffer.buffer == VK_NULL_HANDLE
|
if (tlas.instanceBuffer.buffer == VK_NULL_HANDLE
|
||||||
|| primitiveCount > tlas.instanceBuffer.size / sizeof(VkAccelerationStructureInstanceKHR)) {
|
|| primitiveCount > tlas.instanceBuffer.size / sizeof(VkAccelerationStructureInstanceKHR)) {
|
||||||
tlas.instanceBuffer.Resize(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, primitiveCount, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
const std::uint32_t capacity = std::max(primitiveCount, 1u);
|
||||||
tlas.metadataBuffer.Resize(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, primitiveCount, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
tlas.instanceBuffer.Resize(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, capacity, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||||
|
tlas.metadataBuffer.Resize(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, capacity, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A topology change reshuffles which element occupies each slot (a count
|
// A topology change reshuffles which element occupies each slot (a count
|
||||||
|
|
@ -250,7 +255,9 @@ void RenderingElement3D::BuildTLAS(VkCommandBuffer cmd, std::uint32_t index, RTB
|
||||||
|
|
||||||
// Scratch buffer must hold at least max(buildScratchSize, updateScratchSize).
|
// Scratch buffer must hold at least max(buildScratchSize, updateScratchSize).
|
||||||
// Sizing for buildScratchSize covers both — refit is always smaller.
|
// Sizing for buildScratchSize covers both — refit is always smaller.
|
||||||
tlas.scratchBuffer.Resize(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, tlasBuildSizes.buildScratchSize);
|
// An empty TLAS may need no scratch at all, but the buffer can't be
|
||||||
|
// zero-size.
|
||||||
|
tlas.scratchBuffer.Resize(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, std::max<VkDeviceSize>(tlasBuildSizes.buildScratchSize, 1));
|
||||||
tlas.buffer.Resize(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, tlasBuildSizes.accelerationStructureSize);
|
tlas.buffer.Resize(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, tlasBuildSizes.accelerationStructureSize);
|
||||||
|
|
||||||
// Destroy the previous AS handle before creating a new one — the
|
// Destroy the previous AS handle before creating a new one — the
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue