recover_rings ran vkQueueWaitIdle while holding the global layer mutex,
stalling every other thread in any intercepted Vulkan call for the whole
GPU drain. Collect candidates under the lock, wait unlocked, then revalidate
before resetting the cursor.
The wait window allows destroy/recreate reusing the same buffer handle, a
concurrent recovery, or a disable (unmap, author change) to land mid-drain.
Each drain carries its ring's slot, buffer/memory identity, cursor, and reset
count plus a per-ring draining flag: a replacement (draining==false, own
slot/identity) is left alone instead of being reset or disabled, a concurrent
drain skips instead of double-resetting, and a ring disabled during the wait
is never reset. A failed wait stays a failure even if the cursor reads zero.
Squashed from the working branch. Adds the Basalt patches, constrained
constellation pose solver, Rift S optics, world anchor and boundary
persistence, SteamVR camera queue and room setup guard, and tests.