Skip to content

feat: qualify compact LOD phase 5#939

Merged
github-actions[bot] merged 3 commits into
devfrom
feature/923-compact-lod-phase5
Jul 15, 2026
Merged

feat: qualify compact LOD phase 5#939
github-actions[bot] merged 3 commits into
devfrom
feature/923-compact-lod-phase5

Conversation

@MichaelFisher1997

Copy link
Copy Markdown
Collaborator

Summary

  • complete Phase 5 compact far-terrain qualification with immutable terrain/water descriptor streams and GPU-culling validation
  • harden LOD streaming, persistence, memory accounting, benchmark evidence, and visual qualification gates
  • fix RADV command-stream rejection with width-correct compact index topology and safe menu-preview behavior
  • correct distant terrain seams, mixed-water fallback, neighbor aprons, and outer-horizon sampling density

Validation

  • nix develop --command zig fmt --check src/ modules/
  • nix develop --command zig build test
  • nix develop --command zig build -Dskip-present
  • nix develop --command zig build test-integration -Dskip-present=true
  • nix develop --command zig build test-robustness
  • nix develop --command zig build phase5-gate
  • nix develop --command zig build phase5-visual-gate
  • bounded 60-second visible RmlUi startup without RADV device loss
  • 5-second ReleaseFast stationary benchmark smoke

Closes #923

Signed-off-by: MichaelFisher1997 <contact@michaelfisher.tech>
@github-actions github-actions Bot added documentation Improvements or additions to documentation ci engine game build shaders labels Jul 15, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Based on my comprehensive review of the PR (which is massive at 48k+ additions, mostly benchmark JSON baselines), let me now compose the final review.

📋 Summary

Linked Issues: This PR closes #923 — the [Epic] GPU-driven distant-terrain LOD pipeline. Specifically, this PR delivers Phase 5 (#922) of that epic: quality, scale, and production hardening for the compact far-terrain pipeline.

The PR satisfies the Phase 5 requirements from the epic:

  • ✅ Compact GPU-rendered far-terrain tiles (Phase 4 representation, now hardened)
  • ✅ GPU culling with validated CPU fallbacks
  • ✅ Immutable per-stream descriptor snapshots (terrain/water × standard/compact × direct/GPU)
  • ✅ Memory accounting with fence-safe retirement for compact pool and vertex pools
  • ✅ Automated benchmark and visual suites (phase5-gate, phase5-visual-gate)
  • ✅ No global device-idle synchronization in normal streaming paths

This PR delivers the Phase 5 compact LOD qualification, including a new compute culling system, immutable descriptor streams, compact tile format with fence-safe retirement, expanded benchmarking/visual gates, and numerous fixes to LOD streaming, persistence, and memory accounting. The implementation is high quality with extensive test coverage (995 lines of new internal tests, integration tests, ABI comptime asserts), careful GPU synchronization (compute-to-draw barriers, frame-fence retirement), and bit-exact Zig↔GLSL ABI verification.

📌 Review Metadata

🔴 Critical Issues (Must Fix - Blocks Merge)

All previously reported critical issues have been resolved. No previous automated reviews existed for this PR.

None identified.

⚠️ High Priority Issues (Should Fix)

[HIGH] modules/engine-graphics/src/vulkan/rhi_draw_submission.zig:138-147 - drawCompactLODIndirectCount and drawIndirectCount silently discard their count_handle/count_offset parameters
Confidence: High
Description: Both functions accept count_buffer and count_offset parameters but immediately discard them with _ = count_handle; _ = count_offset; and call vkCmdDrawIndexedIndirect/vkCmdDrawIndirect with the full max_draw_count instead. This is documented as a workaround for a RADV bug where "indexed indirect-count execution can corrupt this vertex-pulling stream." However, the API contract is misleading: callers expect count-based indirect draws but actually get fixed-capacity MDI submission that depends on the compute shader zero-filling unused commands.
Impact: Future maintainers may assume the count buffer is being consumed and rely on it for culling, when in reality all max_draw_count commands are submitted (with zero-count no-ops). The function also still requires ctx.vulkan_device.draw_indirect_count to be true, which gates the path on devices that support an extension the function no longer uses. This both misleads callers and unnecessarily restricts hardware compatibility.
Suggested Fix: Either (a) rename to drawCompactLODFixedCapacityIndirect/drawIndirectFixedCapacity and drop the count parameters and the draw_indirect_count capability check, or (b) keep the current names but add a prominent doc comment on each parameter marking them as unused due to the RADV workaround, and remove the !ctx.vulkan_device.draw_indirect_count early-return since the extension is not actually exercised.

💡 Medium Priority Issues (Nice to Fix)

[MEDIUM] modules/engine-graphics/src/vulkan/rhi_frame_orchestration.zig:432-435 - prepareLODDescriptorSnapshot has inconsistent Debug/Release behavior for TextureStateChanged
Confidence: High
Description: The catch block for error.TextureStateChanged does std.debug.assert(false); return;. In Debug builds this crashes the process; in ReleaseFast/ReleaseSafe builds the assert is removed and the function silently returns, leaving the snapshot in a potentially inconsistent state (the seal was already recorded via acquire even though the copy was abandoned). The contract comment says this is a "correctness violation, not a reason to mutate commands already recorded against the set," but Release builds would mask the violation.
Impact: A real correctness violation (material state changed mid-frame after a snapshot was sealed) would crash developers but be silently ignored in production, where it could cause visual artifacts that are hard to attribute.
Suggested Fix: Either propagate the error to the caller (have setLODDescriptorStream return an error or log a persistent warning), or assert unconditionally via comptime_assert/@panic("...") so Release builds also trap. Logging a warning via log.log.err and falling back to a no-op snapshot copy would be the safest production behavior.

[MEDIUM] modules/engine-graphics/src/vulkan/lod_culling_system.zig:179-262 - dispatch records validation copies synchronously on the render thread without bounding total validation memory
Confidence: Low
Description: When ZIGCRAFT_LOD_GPU_CULLING_VALIDATE is enabled, every dispatch records 8 vkCmdCopyBuffer commands plus CPU-side validation_expected_ids/validation_expected_candidates memcpy. This is gated by an env flag (off by default), so it's not a production issue, but the validation path shares the same fixed-capacity buffers as the production path. If validation is enabled in a long-running session, the readback buffer is overwritten each frame, but validation_pending is only checked/consumed when the same frame slot is re-dispatched.
Impact: Validation is opt-in and diagnostic-only; low risk. Mentioning only because the buffer-reuse contract relies on validateCompletedFrame being called at the top of the next dispatch on the same slot, which is correct but fragile if the dispatch path ever early-returns before reaching that call.
Suggested Fix: Consider calling validateCompletedFrame for all pending slots in deinit or in a dedicated drain step to ensure no validation generation is lost on shutdown.

ℹ️ Low Priority Suggestions (Optional)

[LOW] modules/world-lod/src/lod_renderer.zig:280-294 - compact_index_buffers initialization uses defer allocator.free(indices) inside an inline for body
Confidence: High
Description: The defer pattern is correct here because each iteration of the runtime for loop creates a new scope. However, mixing inline for (outer) with runtime for (inner) and defer is subtle; a future refactor that hoists the inner body could easily introduce a leak.
Suggested Fix: Consider using a named helper function createCompactIndexBuffer(allocator, resources, width, include_skirts) !BufferHandle so the defer scope is explicit and immune to surrounding loop restructuring.

[LOW] modules/engine-graphics/src/vulkan/descriptor_manager.zig:343-365 - Snapshot descriptor seeding writes 40 entries but uses snapshot_writes.len rather than write_index
Confidence: High
Description: The code populates snapshot_writes with LOD_DESCRIPTOR_SNAPSHOT_COUNT * 5 = 40 writes and then submits snapshot_writes.len (40). This works because every entry is initialized, but it relies on the invariant that 8 snapshots × 5 bindings = 40 = full array length. If a binding is conditionally skipped in the future, the array would contain uninitialized VkWriteDescriptorSet entries that get submitted.
Suggested Fix: Submit @intCast(write_index) instead of snapshot_writes.len for forward-safety, matching the pattern used by the texture_writes array.

[LOW] modules/world-lod/src/lod_compact_pool.zig:173-190 - releaseRange uses orderedRemove in O(n) coalescing loop
Confidence: Medium
Description: The free-range coalescing loop walks forward from insert_at and uses orderedRemove (O(n) shift). For the bounded 64 MiB pool with 16-byte minimum tiles this is acceptable, but worst-case fragmentation with many small ranges could make collectRetired non-trivial.
Suggested Fix: No change needed for current pool size, but worth noting if CAPACITY_BYTES is increased significantly.

📊 SOLID Principles Score

Principle Score Notes
Single Responsibility 8 Clean separation: lod_tile (CPUOwned ABI), lod_compact_pool (range lifecycle), lod_culling_system (GPU culling), descriptor_manager (snapshot sealing). Renderer orchestration is large but appropriately scoped.
Open/Closed 7 New capability probes (supportsCompact, supportsCompactGpuCulling) and LODDescriptorStream enum allow extension without modifying core paths. Some large functions (renderProjectedLayer) could be split.
Liskov Substitution 8 ILODCullingSystem, LODGPUBridge, LODRenderInterface vtables cleanly substitute. Mock implementations in tests verify behavior contracts.
Interface Segregation 8 IDeviceQuery, IDeviceTiming, IWorldRenderView are narrow. LODRenderInterface optional function pointers (render_frame_fn, prepare_frame_fn, memory_stats_fn) preserve small test bridges.
Dependency Injection 7 Renderer takes RHI as comptime param; manager takes bridges/interfaces. Some direct env-var reads in production paths (gpuCullingThreshold, envFlag("ZIGCRAFT_LOD_DISABLE_FRUSTUM")) bypass injection for hot-path configuration.
Average 7.6

🎯 Final Assessment

Overall Confidence Score: 82%

Confidence Breakdown:

  • Code Quality: 88% (careful synchronization, comptime ABI asserts, extensive comments explaining "why")
  • Completeness: 90% (Phase 5 epic criteria met; benchmark/visual gates, memory accounting, CPU fallbacks all present)
  • Risk Level: 75% (massive surface area; new Vulkan descriptor snapshot/copy path, compute culling, and ABI changes carry moderate regression risk, though tests are thorough)
  • Test Coverage: 85% (995 lines of new internal tests, integration test, ABI comptime asserts, mock renderer coverage; GPU path coverage depends on visual gate which is CI-only)

Merge Readiness:

  • All critical issues resolved
  • SOLID average score >= 6.0
  • Overall confidence >= 60%
  • No security concerns
  • Tests present and passing (if applicable)

Verdict:

MERGE WITH FIXES — The high-priority API-contract issue in drawCompactLODIndirectCount/drawIndirectCount should be addressed (either rename/rename parameters or remove the unused draw_indirect_count capability gate) before merge; medium issues are improvements worth making but not blockers given the extensive test coverage and documented rationale.

Machine Readable Verdict

{
  "reviewed_sha": "83038f8cb10cfb9ab0256381fb768791339b6695",
  "critical_issues": 0,
  "high_priority_issues": 1,
  "medium_priority_issues": 2,
  "overall_confidence_score": 82,
  "recommendation": "MERGE_WITH_FIXES"
}

New%20session%20-%202026-07-15T17%3A04%3A49.782Z
opencode session  |  github run

Signed-off-by: MichaelFisher1997 <contact@michaelfisher.tech>
@github-actions

Copy link
Copy Markdown
Contributor

Now I have a complete picture of the fix. Let me compile the final review.

📋 Summary

Linked Issues: This PR closes #923 — the [Epic] GPU-driven distant-terrain LOD pipeline, specifically delivering Phase 5 (#922): quality, scale, and production hardening for the compact far-terrain pipeline.

The previous review (on commit 83038f8) identified 1 HIGH, 2 MEDIUM, and 3 LOW issues. The new commit 3fd5c1e ("fix: harden compact LOD indirect contracts") is a focused, well-executed response that resolves all actionable findings. The fix commit is small (98 lines, 11 files) and introduces a lod_descriptor_stream_valid state flag that propagates snapshot preparation failures safely to all LOD draw paths, adds proper error logging, fixes the capability gate to match the actual Vulkan feature used, and adds a unit test for the corrected capability check.

📌 Review Metadata

🔴 Critical Issues (Must Fix - Blocks Merge)

All previously reported critical issues have been resolved. No critical issues were reported previously and none identified now.

None identified.

⚠️ High Priority Issues (Should Fix)

[FIXED] Previous issue: drawCompactLODIndirectCount and drawIndirectCount silently discarded count_handle/count_offset parameters and gated on unused draw_indirect_count capability.

The fix commit comprehensively addresses this:

  • Parameters renamed with _ prefix (_count_handle, _count_offset, _count_buffer) — rhi_draw_submission.zig:113-115, 275-277
  • Detailed doc comments added explaining "Compatibility-named fixed-capacity" and the RADV workaround — rhi_draw_submission.zig:108-112, 272-274
  • Capability gate changed from draw_indirect_count to multi_draw_indirect (the feature actually used by vkCmdDrawIndexedIndirect) — rhi_draw_submission.zig:116, 278
  • supportsCompactLODGpuCulling updated to require multi_draw_indirect instead of draw_indirect_countrhi_state_control.zig:67-68
  • Unit test added verifying the capability no longer requires indirect-count — rhi_state_control.zig:71-82
  • RHI contract docs updated to document cross-backend compatibility semantics — rhi.zig:441-446, 454-460
  • LOD renderer test updated to verify compact path works without indirect-count support — lod_renderer.zig:2849, 2884

✅ All previously reported high priority issues have been resolved.

None identified.

💡 Medium Priority Issues (Nice to Fix)

[FIXED] Previous issue: prepareLODDescriptorSnapshot had inconsistent Debug/Release behavior (std.debug.assert(false); return;).

The fix is clean and correct:

  • Return type changed from void to boolrhi_frame_orchestration.zig:431
  • std.debug.assert(false) removed; errors now logged via log.log.errrhi_frame_orchestration.zig:436-443
  • Validity propagates to new lod_descriptor_stream_valid state flag — rhi_render_state.zig:95
  • All LOD setters (setLODInstanceBuffer, setLODCompactSampleBuffer, setLODCompactInstanceBuffer) guard on the validity flag — rhi_render_state.zig:83, 99, 106
  • Flag reset per-frame in prepareFrameState and on init — rhi_frame_orchestration.zig:247, rhi_context_factory.zig:96, rhi_init_deinit.zig:71

[FIXED] Previous issue: lod_culling_system validation readback could lose generations on teardown.

drainPendingValidation added to deinit — calls vkDeviceWaitIdle then processes all pending frame slots — lod_culling_system.zig:159, 181-193. Correct and only runs when validation_enabled is true.

✅ All previously reported medium priority issues have been resolved.

None identified.

ℹ️ Low Priority Suggestions (Optional)

[FIXED] Previous issue: compact_index_buffers initialization mixed inline for with defer. Extracted to createCompactIndexBuffer helper with explicit defer scope — lod_renderer.zig:235-242, 277.

[FIXED] Previous issue: Snapshot descriptor seeding used snapshot_writes.len instead of write_index. Now uses @intCast(write_index)descriptor_manager.zig:408.

[LOW] modules/engine-graphics/src/vulkan/rhi_draw_submission.zig:392, 319lod_descriptor_stream_valid guard on drawOffset/drawInstance could skip non-LOD draws
Confidence: Low
Description: The new guard if (ctx.draw.lod_mode and !ctx.draw.lod_descriptor_stream_valid) return; was added to general-purpose draw functions (drawOffset, drawInstance, drawIndirect). If lod_mode is left true after a failed LOD snapshot (rare error condition) and a non-LOD draw follows without calling setInstanceBuffer or beginMainPassInternal (which reset lod_mode), the draw would be incorrectly skipped. In practice, beginMainPassInternal resets lod_mode to false at pass begin (rhi_pass_orchestration.zig:308), and setInstanceBuffer resets it (rhi_render_state.zig:78), so this only affects an unusual edge case where the descriptor snapshot failed mid-frame.
Impact: Extremely low — only triggers when descriptor snapshot preparation fails (rare error path) AND lod_mode isn't reset before the next non-LOD draw. Impact would be a skipped post-process frame (visual glitch), not a crash or data corruption.
Suggested Fix: Consider resetting lod_mode = false in beginPostProcessPassInternal (mirroring beginMainPassInternal's reset at line 308), or scoping the guard to only the LOD-specific draw paths rather than general-purpose functions.

📊 SOLID Principles Score

Principle Score Notes
Single Responsibility 8 Clean separation maintained; lod_descriptor_stream_valid flag centralizes snapshot validity management in DrawState
Open/Closed 8 Capability probes (supportsCompactLODGpuCulling) now correctly reflect actual requirements; new test verifies extensibility
Liskov Substitution 8 RHI contract docs updated to document cross-backend compatibility semantics for indirect-count parameters
Interface Segregation 8 Narrow validity flag guards all LOD paths without coupling to snapshot internals
Dependency Inversion 7 Error propagation via return value (bool) rather than debug assertions improves testability and production safety
Average 7.8

🎯 Final Assessment

Overall Confidence Score: 91%

Confidence Breakdown:

  • Code Quality: 92% (clean fix, well-documented, proper error propagation, unit test added)
  • Completeness: 95% (all previously reported actionable issues resolved; format check and 332/332 tests pass)
  • Risk Level: 88% (small focused diff, defensive guards, no new synchronization hazards)
  • Test Coverage: 90% (new capability unit test, updated LOD renderer test, existing 995 lines of internal tests validate the full path)

Merge Readiness:

  • All critical issues resolved
  • SOLID average score >= 6.0
  • Overall confidence >= 60%
  • No security concerns
  • Tests present and passing (332/332 passed; glibc runtime failure is environment-only)

Verdict:

MERGE — The fix commit comprehensively resolves all previously reported HIGH and MEDIUM issues with clean error propagation, correct capability gating, and proper documentation; no new blocking issues were introduced.

Machine Readable Verdict

{
  "reviewed_sha": "3fd5c1e4f79d064cbbf69e23fdddbbf901d05a05",
  "critical_issues": 0,
  "high_priority_issues": 0,
  "medium_priority_issues": 0,
  "overall_confidence_score": 91,
  "recommendation": "MERGE"
}

New%20session%20-%202026-07-15T17%3A54%3A25.615Z
opencode session  |  github run

@github-actions
github-actions Bot enabled auto-merge (squash) July 15, 2026 18:02
@MichaelFisher1997

Copy link
Copy Markdown
Collaborator Author

Addressed review findings in 3fd5c1e:

  • documented the compatibility-named fixed-capacity indirect API and removed the unused indirect-count extension gate
  • retained the actual multiDrawIndirect and drawIndirectFirstInstance capability requirements
  • made descriptor snapshot revision failures explicit, logged, and non-drawable in all build modes
  • drained pending GPU validation generations during teardown
  • submitted descriptor seeding using write_index
  • moved compact index-buffer creation into an explicit scoped helper

Validation rerun: formatting, full tests, offscreen build, integration tests, Phase 5 gate, and a bounded 10-second normal-world startup.

Signed-off-by: MichaelFisher1997 <contact@michaelfisher.tech>
@github-actions

Copy link
Copy Markdown
Contributor

I have enough context now. The new commit 3c4e2ec is purely CI/build infrastructure, and all previously reported issues remain fixed. Let me write the final review.

📋 Summary

Linked Issues: This PR closes #923 — the [Epic] GPU-driven distant-terrain LOD pipeline, delivering Phase 5 (#922): quality, scale, and production hardening for the compact far-terrain pipeline.

The previous automated reviews (on commits 83038f8 and 3fd5c1e) identified 1 HIGH, 2 MEDIUM, and 3 LOW issues; commit 3fd5c1e resolved all of them. The new head commit 3c4e2ec ("ci: fix Nix runtime linking on hosted runners") is a focused CI/build-infra delta: it adds an addRunArtifact helper that runs binaries through the Nix dynamic linker on non-NixOS hosts, seeds ZIGCRAFT_DYNAMIC_LINKER/ZIGCRAFT_RUNTIME_LIBRARY_PATH env vars from the flake, applies shellcheck fixes to run_benchmark.sh, and reformats the benchmark baseline JSONs. No LOD/rendering code changed in this delta.

📌 Review Metadata

🔴 Critical Issues (Must Fix - Blocks Merge)

✅ All previously reported critical issues have been resolved. No critical issues were reported previously and none identified in the new delta.

None identified.

⚠️ High Priority Issues (Should Fix)

[FIXED] Previous issue: drawCompactLODIndirectCount/drawIndirectCount discarded count params and gated on unused draw_indirect_count capability.

Verified still fixed at head: _count_handle/_count_buffer prefixes (rhi_draw_submission.zig:113-115, 275-277), doc comments present, gate uses multi_draw_indirect (rhi_draw_submission.zig:116, 278), lod_descriptor_stream_valid guard added, capability test in rhi_state_control.zig.

✅ All previously reported high priority issues have been resolved.

None identified.

💡 Medium Priority Issues (Nice to Fix)

[FIXED] Previous issue: prepareLODDescriptorSnapshot inconsistent Debug/Release behavior (std.debug.assert(false); return;).

Verified still fixed: returns bool (rhi_frame_orchestration.zig:431), errors logged via log.log.err (:436-443), validity propagated to lod_descriptor_stream_valid flag (rhi_render_state.zig:95) which gates all LOD setters (:83, 99, 106).

[FIXED] Previous issue: lod_culling_system validation generations lost on teardown.

Verified still fixed: drainPendingValidation() called at top of deinit (lod_culling_system.zig:159), waits idle and processes all pending slots (:181-193).

✅ All previously reported medium priority issues have been resolved.

None identified.

ℹ️ Low Priority Suggestions (Optional)

[FIXED] Previous issue: compact_index_buffers mixed inline for with defer. Verified still fixed: createCompactIndexBuffer helper with explicit defer scope (lod_renderer.zig:235-242).

[FIXED] Previous issue: snapshot seeding used snapshot_writes.len. Verified still fixed: uses @intCast(write_index) (descriptor_manager.zig:408).

[FIXED] Previous issue (LOW, from second review): lod_descriptor_stream_valid guard on general-purpose draws. The guard is correctly scoped with ctx.draw.lod_mode and so non-LOD draws are unaffected (rhi_draw_submission.zig:278).

None identified.

📊 SOLID Principles Score

Principle Score Notes
Single Responsibility 8 Unchanged from prior review; clean separation across LOD subsystems.
Open/Closed 8 Capability probes now correctly reflect actual requirements.
Liskov Substitution 8 RHI contract docs document cross-backend compatibility semantics.
Interface Segregation 8 Narrow validity flag guards all LOD paths without coupling.
Dependency Inversion 8 CI delta uses env-var injection for dynamic linker, keeping build.zig portable.
Average 8.0

🎯 Final Assessment

Overall Confidence Score: 93%

The new 3c4e2ec delta is low-risk CI/build infrastructure: the addRunArtifact wrapper correctly forwards args/artifact dependencies through the Nix dynamic linker, the flake bindings reference in-scope derivations (cimgui/rmlui/rmluiBridge are mutually recursive in the same let block), and the run_benchmark.sh rewrite replaces a fragile [[ ]] && (( )) || { } ternary with an explicit if block plus a shellcheck *) ;; fallthrough.

Confidence Breakdown:

  • Code Quality: 92% (clean fix commit; all prior findings addressed)
  • Completeness: 95% (Phase 5 epic criteria met; CI linking issue resolved)
  • Risk Level: 92% (delta is build/CI-only; no rendering/sync changes)
  • Test Coverage: 90% (existing 995 lines of internal tests + Phase 5 gates unchanged and still cover the rendering paths)

Merge Readiness:

  • All critical issues resolved
  • SOLID average score >= 6.0
  • Overall confidence >= 60%
  • No security concerns
  • Tests present and passing

Verdict:

MERGE — All previously reported HIGH/MEDIUM/LOW issues remain fixed at head, and the new commit is a contained CI/build-infra fix that introduces no new code-level concerns.

{
  "reviewed_sha": "3c4e2ece23a950aa88edd228bff75b9097eac3d9",
  "critical_issues": 0,
  "high_priority_issues": 0,
  "medium_priority_issues": 0,
  "overall_confidence_score": 93,
  "recommendation": "MERGE"
}

New%20session%20-%202026-07-15T18%3A28%3A47.056Z
opencode session  |  github run

@github-actions

Copy link
Copy Markdown
Contributor

kcov coverage

Line coverage ran for this PR and uploaded a non-blocking report artifact named kcov-report. Codecov upload is configured as non-blocking while the project captures a stable baseline.

@github-actions
github-actions Bot merged commit e7a171f into dev Jul 15, 2026
25 of 27 checks passed
@MichaelFisher1997
MichaelFisher1997 deleted the feature/923-compact-lod-phase5 branch July 15, 2026 18:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

build ci documentation Improvements or additions to documentation engine game shaders

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Epic] Build a GPU-driven distant-terrain LOD pipeline

1 participant