Skip to content

Large scene gpu backends#5

Merged
syoyo merged 3 commits into
mainfrom
large-scene-gpu-backends
Jul 1, 2026
Merged

Large scene gpu backends#5
syoyo merged 3 commits into
mainfrom
large-scene-gpu-backends

Conversation

@syoyo

@syoyo syoyo commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

No description provided.

syoyo and others added 3 commits July 2, 2026 03:28
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>
Copilot AI review requested due to automatic review settings July 1, 2026 20:18
@syoyo syoyo merged commit 17a956c into main Jul 1, 2026
1 check passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 thread lightrt_c_tri.c
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 thread lightrt_c_vk.c
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 thread lightrt_c_vk.c
Comment on lines 2551 to 2554
if (!run_ok) {
if (err) *err = LRT_RESULT_OUT_OF_MEMORY;
return -1;
}
Comment thread lightrt_c_vk.h
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);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants