Octree removal 5: replace object-cache interest management (VOCache partition cull) #479

Closed
opened 2026-10-06 09:30:24 +00:00 by sky_line · 2 comments
Owner

Part of #474. From the 2026-10-06 audit: the octrees are still built and maintained every frame, but almost nothing reads them. Rendering, culling, world picking, LOD, texture priority and lights all run on our own systems.

The core remaining dependency. LLVOCachePartition::cull (llvocache.cpp ~1011-1076) → region->addVisibleGroup → updateVisibleEntries (llviewerregion.cpp ~1409-1522) → createVisibleObjects decides which cached objects get instantiated. It runs every frame from driveVulkanWorldVOCacheCull (llappviewer.cpp ~6578-6645).

Replace with a flat per-region (or grid-binned) cache-entry container that keeps the same rules:

  • front frustum plus the pixel threshold (checkProjectionArea);
  • back sphere (sRearFarRadius);
  • calcSceneContribution priority;
  • the static-camera throttle;
  • the VRAM-hold logic.

Eviction already uses our own killCachedObjectsBeyond. LL's own comment (llvocache.cpp ~555) calls this system redundant with the object cache.

Verify with object-count and load-order parity in a busy region, and with the Zindra flight test (#469).

Part of #474. From the 2026-10-06 audit: the octrees are still built and maintained every frame, but almost nothing reads them. Rendering, culling, world picking, LOD, texture priority and lights all run on our own systems. **The core remaining dependency.** `LLVOCachePartition::cull` (llvocache.cpp ~1011-1076) → `region->addVisibleGroup` → `updateVisibleEntries` (llviewerregion.cpp ~1409-1522) → `createVisibleObjects` decides which cached objects get instantiated. It runs every frame from `driveVulkanWorldVOCacheCull` (llappviewer.cpp ~6578-6645). **Replace with** a flat per-region (or grid-binned) cache-entry container that keeps the same rules: - front frustum plus the pixel threshold (`checkProjectionArea`); - back sphere (`sRearFarRadius`); - `calcSceneContribution` priority; - the static-camera throttle; - the VRAM-hold logic. Eviction already uses our own `killCachedObjectsBeyond`. LL's own comment (llvocache.cpp ~555) calls this system redundant with the object cache. Verify with object-count and load-order parity in a busy region, and with the Zindra flight test (#469).
sky_line added this to the Slipstream project 2026-10-06 15:04:14 +00:00
Author
Owner

Design (agreed 2026-10-06)

Container: a CPU flat grid, not GPU

  • The consumer is the CPU: instantiating objects from cache data is CPU work. A GPU cull would need a per-frame readback plus mirroring tens of thousands of constantly changing cache entries, which is sync complexity for a cheap test.
  • Per region: a 2D grid of 16 m columns (16 x 16 over 256 m) holding root cache entries' bounding spheres in compact arrays, with a height range per cell for quick rejection.
  • Entries move between cells in O(1) on add, remove and update. No balancing, no per-frame rebound.

Cull

Front:

  • columns vs frustum (no far plane) intersected with the draw-distance sphere;
  • then per entry: frustum + sphere + projection area (checkProjectionArea, the same pixel thresholds).

Per-entry is more precise than today's per-group octree test.

Back: a sphere query within sRearFarRadius, time-sliced like selectBackObjects today.

Reused unchanged:

  • the static-camera throttle (mLODPeriod / idle hash) and cull history;
  • the VRAM hold (#405);
  • children following their parent;
  • calcSceneContribution, the waiting list, creation time-slicing (sNewObjectCreationThrottle);
  • killCachedObjectsBeyond eviction.

Look-ahead (separate toggle, off by default at first)

While moving fast (for example the Zindra flight, #469), bias the front cull and priority toward the direction of travel (velocity x a second or two). Judge it only by outcome metrics, on vs off, so it never contaminates the core change.

Validation

Light invariant checks (debug setting, sampled): no root entry that passes the rules is left unselected without a logged reason, and nothing selected fails every rule.

Outcome metrics (logged, the same for the old and new system, switchable by a setting in one build):

  • pop-in latency, from "on-screen and above threshold" to "instantiated";
  • missing-on-screen count;
  • cull CPU time;
  • objects instantiated.

Routes: a busy sim, teleports, region crossings, fast flight.

Detached culling camera (debug switch). The owner wants to see the culling directly:

  • a Develop menu toggle freezes the culling / streaming camera at its current pose: the VOCache selection, our GPU compute cull and LOD all keep using the frozen camera;
  • the view camera moves freely (normal camera controls / flycam);
  • an overlay draws the frozen frustum, the draw-distance and rear spheres, and wire boxes for cache entries by state: instantiated, waiting, not selected, VRAM-held;
  • so you can fly around and see exactly what the culling picked and loaded.

Rollout

  1. The grid replaces the octree cull behind a setting, with the old path kept for A/B in the same build.
  2. Validate with the metrics and the detached camera.
  3. Delete the VOCache octree path with #480.
## Design (agreed 2026-10-06) ### Container: a CPU flat grid, not GPU - The consumer is the CPU: instantiating objects from cache data is CPU work. A GPU cull would need a per-frame readback plus mirroring tens of thousands of constantly changing cache entries, which is sync complexity for a cheap test. - **Per region:** a 2D grid of 16 m columns (16 x 16 over 256 m) holding **root** cache entries' bounding spheres in compact arrays, with a height range per cell for quick rejection. - Entries move between cells in O(1) on add, remove and update. No balancing, no per-frame rebound. ### Cull **Front:** - columns vs frustum (no far plane) intersected with the draw-distance sphere; - then **per entry**: frustum + sphere + projection area (`checkProjectionArea`, the same pixel thresholds). Per-entry is more precise than today's per-group octree test. **Back:** a sphere query within `sRearFarRadius`, time-sliced like `selectBackObjects` today. **Reused unchanged:** - the static-camera throttle (`mLODPeriod` / idle hash) and cull history; - the VRAM hold (#405); - children following their parent; - `calcSceneContribution`, the waiting list, creation time-slicing (`sNewObjectCreationThrottle`); - `killCachedObjectsBeyond` eviction. ### Look-ahead (separate toggle, off by default at first) While moving fast (for example the Zindra flight, #469), bias the front cull and priority toward the direction of travel (velocity x a second or two). Judge it only by outcome metrics, on vs off, so it never contaminates the core change. ### Validation **Light invariant checks** (debug setting, sampled): no root entry that passes the rules is left unselected without a logged reason, and nothing selected fails every rule. **Outcome metrics** (logged, the same for the old and new system, switchable by a setting in one build): - pop-in latency, from "on-screen and above threshold" to "instantiated"; - missing-on-screen count; - cull CPU time; - objects instantiated. Routes: a busy sim, teleports, region crossings, fast flight. **Detached culling camera (debug switch).** The owner wants to see the culling directly: - a Develop menu toggle **freezes the culling / streaming camera** at its current pose: the VOCache selection, our GPU compute cull and LOD all keep using the frozen camera; - the **view camera moves freely** (normal camera controls / flycam); - an overlay draws the **frozen frustum**, the draw-distance and rear spheres, and **wire boxes for cache entries by state**: instantiated, waiting, not selected, VRAM-held; - so you can fly around and see exactly what the culling picked and loaded. ### Rollout 1. The grid replaces the octree cull behind a setting, with the old path kept for A/B in the same build. 2. Validate with the metrics and the detached camera. 3. Delete the VOCache octree path with #480.
Author
Owner

Shipped in 1.1.0 Beta 9 (v1.1.0-beta.9).

Shipped in 1.1.0 Beta 9 (v1.1.0-beta.9).
sky_line 2026-10-07 07:27:52 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sky_line/Slipstream#479
No description provided.