fix(rt): rebuild TLASes in place, after earlier traces, and queue their handles like a Mesh's
BuildTLAS - A rebuild for a new instance count or build preference used to create a new acceleration structure and destroy the old one at once, though the command buffer being recorded could still use it (a scene and then a model built in one setup). The acceleration structure now spans its whole storage buffer, and a rebuild that fits builds into it again, so the handle and tlases[i].address stay the same and nothing is destroyed. A TLAS that outgrows its storage gets new storage and a new handle; the old handle goes to the deletion queue ahead of the storage it lives in. It is queued after the scratch is resized, and its address goes with it, so a Resize or create that throws leaves no address of a queued acceleration structure behind. - The barrier before the build also orders earlier traces and compute ray queries of the TLAS, which a refit or a rebuild in place would otherwise overwrite while they read it (BuildTlasWriteBarrier). Its source access mask holds no read bit: one does nothing, but makes synchronization validation 1.4.363 report the second of two builds in one command buffer as a write-after-write hazard. - TlasReadBarrier is now TlasBarrier, shared by both barriers. - Documented: call BuildTLAS once every earlier submission that used tlases[index] has completed, and when the address stays the same. TlasWithBuffer - Moves hand the acceleration structure over, and destroying or assigning over one queues it ahead of its storage. The implicit members dropped the handle over freed storage, or left two owners and a moved-from TLAS that refit through buffers it no longer had. Tests - TLASLifetime: destroying, moving, move-assigning and resetting a TlasWithBuffer. - TLASHighWaterMark skips without ray tracing. It asserts the acceleration structure is rebuilt in place on a shrink or a growth within capacity, that the old handle is queued before its storage on a growth past it, and that builds in one command buffer keep the handle while they fit, queue it once when one outgrows the storage, and free it only on its retire frame. - TLASBuildBarrier checks the barrier before the build too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
079b6b0e1f
commit
397ff2db51
6 changed files with 516 additions and 74 deletions
21
project.cpp
21
project.cpp
|
|
@ -437,16 +437,27 @@ extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> a
|
|||
// instance counts — and asserts that a shrink (and any growth within
|
||||
// the high-water capacity) reuses the existing allocation while a
|
||||
// growth past it reallocates, with the validation layer reporting no
|
||||
// errors when an oversized instance buffer is fed to the build. Needs a
|
||||
// Vulkan RT device at runtime, so it shares the native build settings.
|
||||
// errors when an oversized instance buffer is fed to the build. The
|
||||
// acceleration structure follows the same high-water mark: a rebuild
|
||||
// that fits its storage builds into the same handle. Needs a Vulkan
|
||||
// RT device at runtime, so it shares the native build settings.
|
||||
cfg.tests.push_back(LibraryTest("TLASHighWaterMark"));
|
||||
|
||||
// The barrier BuildTLAS records after the build carries the
|
||||
// The barriers BuildTLAS records around the build: the one before it
|
||||
// orders earlier builds, traces and compute ray queries before the
|
||||
// build overwrites the TLAS, and the one after it carries the
|
||||
// acceleration-structure memory dependency to the shaders that read
|
||||
// the TLAS, not just execution order. BuildTlasReadBarrier is pure
|
||||
// CPU logic, so no GPU device is needed at runtime.
|
||||
// the TLAS, not just execution order. BuildTlasWriteBarrier and
|
||||
// BuildTlasReadBarrier are pure CPU logic, so no GPU device is needed
|
||||
// at runtime.
|
||||
cfg.tests.push_back(LibraryTest("TLASBuildBarrier"));
|
||||
|
||||
// A TlasWithBuffer queues its acceleration structure for deferred
|
||||
// deletion, ahead of its storage, when it is destroyed or assigned
|
||||
// over, and moving one hands the acceleration structure over.
|
||||
// Headless; needs a Vulkan RT device at runtime, like MeshLifetime.
|
||||
cfg.tests.push_back(LibraryTest("TLASLifetime"));
|
||||
|
||||
// BuildTLAS on an empty scene (no elements registered yet) builds a
|
||||
// valid empty TLAS instead of creating zero-size buffers, and adding
|
||||
// and removing instances afterwards still rebuilds it. Needs a Vulkan
|
||||
|
|
|
|||
Loading…
Reference in a new issue