RAD LOD Viewer#1254
Open
shadygm wants to merge 17 commits into
Open
Conversation
Contributor
There was a problem hiding this comment.
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
.radloader and extend RAD decoding to populate aSplatLodTree(child_start/child_count + cached centers/sizes). - Add a
SparkLodControllerand 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); | ||
| } |
# Conflicts: # src/core/splat_data.cpp # src/io/loader_service.cpp # src/visualizer/rendering/rendering_manager.cpp
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.