Large scene gpu backends#5
Merged
Merged
Conversation
Brings the vendored tinyusdz fork's large-scene RT work back upstream. It scales the VK_KHR_ray_query path from a single-BLAS scene to full-scale instanced assemblies (Moana island, ~42M instances) without faulting the driver, and hardens teardown against device loss. Verified: `make vk_test` passes on an RTX 5060 Ti (BVH8/BVH4 + ray_query + indexed ray_query, 0 mismatches). Included: - vkew: fix the VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_* sType values (they were off -- e.g. GEOMETRY_TRIANGLES_DATA was 1000150000 instead of the correct 1000150005; BUILD_GEOMETRY_INFO is 1000150000, CREATE_INFO 1000150017) and add the AS-build pipeline-stage/access sync flags. - Two-level GPU TLAS: per-prototype BLAS built once and shared across instances (lrt_vk_rtx_scene_build_instanced), instead of one soup BLAS per instance. - Device-local AS build input: stage vertex/index build inputs into device-local memory (NVIDIA requires it) via a one-shot copy. - Pooled per-prototype BLAS allocation (vk_subpool_*): a few 128 MiB blocks for input + AS storage + reused scratch, instead of ~6 vkAllocateMemory + 2 submits per prototype -- the naive path exhausts NVIDIA's allocator on ~100k prototypes. - 64-bit wide hit id: a 5-word/hit encoding (trace_ray_query_wide variant, -DLRT_WIDE_ID) storing instanceId + prim index separately, so scenes past the 32-bit prim_id*instances product still trace. compile_shaders.sh grows a separate source basename + extra-args so one .comp emits both variants. - Multi-TLAS slicing: split instances across K TLASes sharing one BLAS set and CPU-merge the nearest hit, past the single-TLAS instance limit. - Device-lost-safe teardown: a 5 s fence timeout flags device_lost on timeout / VK_ERROR_DEVICE_LOST; every destroy then skips driver calls and only frees host memory (NVIDIA segfaults inside the driver when destroying accels after a fault). - Hardening (pre-push audit): guard the trace descriptor-pool destroy with device_lost; free the suballocation pools on the build-failure path; only flag device_lost on a genuine GPU-build failure (a host-alloc failure keeps the engine usable). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Brings the vendored tinyusdz fork's CPU triangle/BVH-core improvements back upstream. All additive relative to upstream (no upstream function or API removed; recent upstream work -- lrt_tri_surface_project, NURBS trim loops -- is preserved). Verified against upstream's own tests: test_lightrt_c_surfaces and test_lightrt_c_quadtetra pass; test_lightrt_c_tri produces the identical 7 pre-existing failures (single-tri layout=10/11, BVH8_Q4) that upstream's own tri.c already fails -- i.e. the port is behavior-neutral. lightrt_c_vk_test also passes on an RTX 5060 Ti with this tri.c. Included: - Indexed triangle build (lrt_tri_scene_build_indexed): callers with shared/ welded vertices pass positions + uint32 indices instead of a 9*ntris soup. - Batched multi-scene build (lrt_tri_scene_build_batch / lrt_batch_build_one): build many small scenes in one parallel pass. - "Drop the soup" leaf-vertex recovery: lrt_tri_get_slot / lrt_tri_get_verts / lrt_tri_scene_has_verts / lrt_tri_slot_count let a caller recover hit-triangle vertices from the BVH leaves instead of retaining the full input soup (large resident-memory saving on 20M+ instance scenes). - Morton-LBVH curve build (parallel curve BVH). - MSVC / llvm-mingw portability: lrt_clzll / lrt_ctz wrap __builtin_clzll / __builtin_ctz so the SIMD leaf/lane code builds on MSVC 2022 and llvm-mingw. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New Windows-only GPU backend, mirror of the Vulkan "Path A" (CPU BVH build ->
GPU trace) on a D3D11 compute shader instead of Vulkan. Motivation: on AMD
GCN/Polaris the amdvlk Vulkan compute path mis-renders / hangs, while the D3D11
driver is solid; D3D11 is also ubiquitous on Windows and needs no SDK (d3d11 +
d3dcompiler + dxgi ship with the OS). Batches a whole ray array into ONE
dispatch, so a full-frame trace is a single GPU round-trip.
- lightrt_c_d3d11.{cpp,h}: lrt_d3d11_engine_create/destroy + lrt_d3d11_trace_scene,
same lrt_tri_scene / lrt_ray / lrt_hit surface as the Vulkan and CPU kernels.
The whole .cpp is #if defined(_WIN32) -- an empty translation unit elsewhere.
- d3d/shaders/trace_bvh.hlsl (+ gen_trace_bvh_hlsl.sh, trace_bvh_hlsl.h): the
trace shader is decompiled from the Vulkan trace_bvh SPIR-V with SPIRV-Cross,
so it walks the same serialized BVH4/BVH8 scene and returns identical hits.
- CMake: LIGHTRT_BUILD_D3D11 option (OFF by default), builds a lightrt_d3d11
static lib linking d3d11/d3dcompiler/dxgi; on non-Windows it warns and skips.
Verified on this Linux host only as far as the platform allows: the guarded TU
compiles to an empty object (0 exported symbols), and CMake configures cleanly
both by default and with -DLIGHTRT_BUILD_D3D11=ON (warn+skip). The actual D3D11
compile/link/run is UNVERIFIED here -- no Windows toolchain; it was validated in
the tinyusdz fork (tusdrender -d3d).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR expands LightRT’s GPU backends to handle much larger scenes by introducing (1) wide-ID ray-query tracing for instanced scenes that exceed 32-bit packed hit IDs, (2) chunked BLAS building and TLAS slicing to work around driver/build limits, and (3) a new Windows-only D3D11 compute tracing backend that reuses the Vulkan traversal shader via SPIRV-Cross decompilation.
Changes:
- Add ray-query shader support for “wide” hit IDs and plumb
tri_chunk/instance ID handling through the Vulkan RTX path. - Rework Vulkan RTX scene building to support chunked BLASes, true prototype+instance instancing (including multi-TLAS slicing), pooled BLAS allocations, and device-lost robustness.
- Add a Direct3D 11 compute backend + shader generation tooling, and integrate it behind a CMake option.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| vk/shaders/trace_ray_query.comp | Adds tri_chunk push constant and a wide-ID variant path for hits. |
| vk/shaders/trace_ray_query.spv.h | Regenerated SPIR-V header for the narrow ray-query shader. |
| vk/shaders/trace_ray_query_wide.spv.h | New generated SPIR-V header for the wide-ID ray-query shader. |
| scripts/compile_shaders.sh | Generalizes shader compilation and adds wide-ID header generation. |
| lightrt_vkew.h | Updates Vulkan enum/flag defines and adds AS build stage/access flags. |
| lightrt_c_vk.h | Adds new Vulkan RTX instancing APIs, wide-hit type, and device VRAM query API. |
| lightrt_c_vk.c | Implements wide pipeline + instanced/multi-TLAS RTX builds, BLAS pooling, chunked soup BLAS, and device-lost handling. |
| lightrt_c_tri.h | Adds indexed build API, batch build API, vertex recovery helpers, and TLAS sparse-BLAS clarification. |
| lightrt_c_tri.c | Implements indexed build gather path, batch scene build, prim->slot mapping, and portability fixes for threads/ctz/clz/aligned alloc. |
| lightrt_c_d3d11.h | New public API for a D3D11 compute tracing backend (Windows-only). |
| lightrt_c_d3d11.cpp | Implements D3D11 engine creation, shader compilation cache, and GPU trace/roundtrip. |
| d3d/shaders/trace_bvh.hlsl | New HLSL traversal shader decompiled from Vulkan SPIR-V. |
| d3d/shaders/trace_bvh_hlsl.h | Embedded raw-string version of the generated HLSL source. |
| d3d/shaders/gen_trace_bvh_hlsl.sh | Script to regenerate HLSL and embedded header from Vulkan SPIR-V via SPIRV-Cross. |
| CMakeLists.txt | Adds LIGHTRT_BUILD_D3D11 option and the lightrt_d3d11 static library target. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+8902
to
+8907
| if (!vertices || !indices || ntris == 0) { | ||
| tri_set_err(err, LRT_RESULT_INVALID_ARGUMENT); | ||
| return NULL; | ||
| } | ||
| (void)nverts; /* bounds are the caller's contract; gather trusts indices */ | ||
| return tri_scene_build_impl(vertices, ntris, opts, NULL, indices, err); |
Comment on lines
+1501
to
+1505
| vk_set_err(e, "GPU command timed out after 5 s (device lost or " | ||
| "misconfigured acceleration-structure build)"); | ||
| e->device_lost = 1; | ||
| vkDestroyFence(e->device, fence, NULL); | ||
| vkFreeCommandBuffers(e->device, e->cmd_pool, 1, &cb); |
Comment on lines
2551
to
2554
| if (!run_ok) { | ||
| if (err) *err = LRT_RESULT_OUT_OF_MEMORY; | ||
| return -1; | ||
| } |
Comment on lines
+194
to
+221
| lrt_vk_rtx_scene *lrt_vk_rtx_scene_build_instanced( | ||
| lrt_vk_engine *e, const lrt_vk_proto *protos, uint32_t nprotos, | ||
| const lrt_vk_instance *insts, uint32_t ninsts, uint32_t *out_tri_stride, | ||
| lrt_result *err); | ||
|
|
||
| /* Wide-id instanced build: same inputs as lrt_vk_rtx_scene_build_instanced, but | ||
| * the hit id is NOT packed into a single 32-bit prim_id. Instead the trace stores | ||
| * the TLAS instanceId and the prototype-local triangle index in SEPARATE 32-bit | ||
| * words (lrt_hit_wide below), so there is no ninsts*maxPrototypeTris product to | ||
| * overflow -- the only remaining ceiling is the device TLAS maxInstanceCount | ||
| * (commonly 2^24). Use this for instanced scenes the narrow builder rejects | ||
| * (Moana-island scale). A scene built this way MUST be traced with | ||
| * lrt_vk_rtx_scene_trace_wide (the narrow trace returns -1 on it). */ | ||
| lrt_vk_rtx_scene *lrt_vk_rtx_scene_build_instanced_wide( | ||
| lrt_vk_engine *e, const lrt_vk_proto *protos, uint32_t nprotos, | ||
| const lrt_vk_instance *insts, uint32_t ninsts, lrt_result *err); | ||
|
|
||
| /* Multi-TLAS wide instanced build: as lrt_vk_rtx_scene_build_instanced_wide, but | ||
| * splits the instances into ceil(ninsts / ~16M) TLAS slices, each its own TLAS | ||
| * over the SAME shared BLAS set, so a scene with MORE than the device TLAS | ||
| * maxInstanceCount (2^24) instances renders IN FULL (Moana island's ~42.8M | ||
| * instances -> 3 TLASes). Trace with lrt_vk_rtx_scene_trace_wide: it traces the | ||
| * slices sequentially and merges the nearest hit on the host, reporting GLOBAL | ||
| * instanceIds (0..ninsts-1). Costs K sequential dispatches per trace + K TLAS | ||
| * instance buffers of VRAM; the BLAS is stored once regardless of K. */ | ||
| lrt_vk_rtx_scene *lrt_vk_rtx_scene_build_instanced_multi( | ||
| lrt_vk_engine *e, const lrt_vk_proto *protos, uint32_t nprotos, | ||
| const lrt_vk_instance *insts, uint32_t ninsts, lrt_result *err); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.