Skip to content

RAD LOD Viewer#1254

Open
shadygm wants to merge 17 commits into
masterfrom
feat/rad-lod-viewer
Open

RAD LOD Viewer#1254
shadygm wants to merge 17 commits into
masterfrom
feat/rad-lod-viewer

Conversation

@shadygm
Copy link
Copy Markdown
Collaborator

@shadygm shadygm commented May 26, 2026

No description provided.

Copilot AI review requested due to automatic review settings May 26, 2026 21:00
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 adds end-to-end support for viewing RAD (“Random Access Dynamic”) splat files with optional hierarchical LOD selection, including loader integration, a Spark-style CPU LOD selector, Vulkan renderer/shader indirection, and UI controls for enabling/tuning/debugging LOD.

Changes:

  • Add a .rad loader and extend RAD decoding to populate a SplatLodTree (child_start/child_count + cached centers/sizes).
  • Add a SparkLodController and plumb selected LOD indices/levels into the Vulkan projection pipeline (new bindings + uniforms + debug coloring).
  • Add viewer settings + IPC/Python/RmlUI controls for toggling LOD and adjusting parameters.

Reviewed changes

Copilot reviewed 30 out of 30 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/visualizer/scene/scene_manager.cpp Detect RAD LOD availability on load and reset LOD enabled state.
src/visualizer/rendering/vksplat_viewport_renderer.cpp Stage/upload LOD buffers and pass them into VkSplat/VulkanGSRenderer; populate LOD uniforms.
src/visualizer/rendering/spark_lod_controller.hpp New Spark-style LOD controller interface + async plumbing.
src/visualizer/rendering/spark_lod_controller.cpp LOD traversal implementation and worker thread loop.
src/visualizer/rendering/rendering_types.hpp Add LOD-related render settings fields.
src/visualizer/rendering/rendering_manager.hpp Add LOD controller members and public LOD toggles.
src/visualizer/rendering/rendering_manager.cpp Implement LOD availability/enabled setters/getter.
src/visualizer/rendering/rendering_manager_vulkan.cpp Compute LOD selection per frame and attach indices/levels to render requests.
src/visualizer/ipc/view_context.hpp Expose LOD settings in IPC render settings proxy.
src/visualizer/ipc/render_settings_convert.hpp Convert LOD settings between proxy and internal settings.
src/visualizer/gui/rmlui/resources/rendering.rml Add LOD section UI controls + stats display.
src/visualizer/gui/resources/locales/en.json Add LOD labels and tooltips.
src/visualizer/CMakeLists.txt Build the new Spark LOD controller source.
src/rendering/rasterizer/vulkan/src/gs_renderer.h Add LOD uniforms + optional buffers to projection; update pipeline binding count.
src/rendering/rasterizer/vulkan/src/gs_renderer.cpp Bind LOD buffers into projection, switch dispatch sizing to uniforms.num_splats.
src/rendering/rasterizer/vulkan/src/gs_pipeline.cpp Ensure LOD buffers are included in buffer cleanup.
src/rendering/rasterizer/vulkan/src/buffer.h Add LOD buffers to Vulkan pipeline buffer bundle.
src/rendering/rasterizer/vulkan/shader/src/slang/vertex_shader.slang Implement LOD indirection + optional debug coloring; add new bindings.
src/rendering/rasterizer/vulkan/shader/src/slang/utils.slang Add lod_enabled/lod_count fields to the shared uniforms struct.
src/rendering/include/rendering/rendering.hpp Extend render request with optional LOD indices/levels pointers.
src/python/lfs/py_rendering.cpp Expose LOD settings to Python render settings UI.
src/python/lfs_plugins/rendering_panel.py Add LOD section bindings, tooltips, and stats refresh.
src/io/loaders/rad_loader.hpp New RAD loader declaration.
src/io/loaders/rad_loader.cpp New RAD loader implementation (validation + load + CUDA moves).
src/io/loader_service.cpp Register RAD loader and update supported-format messaging.
src/io/formats/rad.cpp Decode/convert RAD tensors correctly and attach LOD tree data to SplatData.
src/io/CMakeLists.txt Build the new RAD loader sources.
src/core/splat_data.cpp Move constructor/assignment now transfers lod_tree.
src/core/include/core/splat_data.hpp Define SplatLodTree and add it to SplatData.
src/core/argument_parser.cpp Extend CLI help and extension whitelist to include .rad.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +2634 to +2661
const std::size_t render_splat_count = request.lod_count > 0 ? request.lod_count : buffers_.num_splats;
populateVksplatCameraUniforms(uniforms,
request.frame_view,
request.scene,
active_sh_degree,
lfs::core::sh_float4_slots_for_rest(
static_cast<std::uint32_t>(splat_data.max_sh_coeffs_rest())),
buffers_.num_splats,
render_splat_count,
request.equirectangular,
request.gut);
uniforms.step = static_cast<std::uint32_t>(modelTransformCount(request.scene.model_transforms));
uniforms.lod_enabled = request.lod_count > 0 ? 1u : 0u;
uniforms.lod_count = static_cast<std::uint32_t>(request.lod_count);
}

// Stage LOD indices on host; actual GPU upload happens inside the
// active command batch right before projection dispatch.
if (request.lod_count > 0 && request.lod_indices != nullptr) {
auto& lod_buf = buffers_.lod_indices;
if (lod_buf.deviceSize() < request.lod_count) {
renderer_.resizeAndCopyDeviceBuffer(lod_buf, request.lod_count, false);
}
lod_buf.resize(request.lod_count);
std::memcpy(lod_buf.data(), request.lod_indices, request.lod_count * sizeof(uint32_t));
buffers_.has_lod_indices = true;
} else {
buffers_.has_lod_indices = false;
}
Comment on lines +167 to +171
s.lod_enabled = p.lod_enabled;
s.lod_debug_colors = p.lod_debug_colors;
s.lod_max_splats = static_cast<size_t>(p.lod_max_splats);
s.lod_pixel_scale_limit = p.lod_pixel_scale_limit;
s.lod_render_scale = p.lod_render_scale;
Comment on lines +957 to +958
_node, _name, count = self._active_splat_node()
return count
Comment on lines +48 to +55
uint8_t header[4];
file.read(reinterpret_cast<char*>(header), 4);

// RAD magic: "RAD0" in little-endian = 0x30444152
if (header[0] != 0x52 || header[1] != 0x41 || header[2] != 0x44 || header[3] != 0x30) {
return make_error(ErrorCode::INVALID_HEADER,
"Invalid RAD format (expected 'RAD0' magic)", path);
}
@shadygm shadygm marked this pull request as ready for review June 1, 2026 19:07
shadygm and others added 4 commits June 1, 2026 22:40
# Conflicts:
#	src/core/splat_data.cpp
#	src/io/loader_service.cpp
#	src/visualizer/rendering/rendering_manager.cpp
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.

3 participants