GPU-ready texture cache: store block-compressed textures on disk (skip J2C decode + encode on reload) #274

Closed
opened 2026-10-03 23:47:08 +00:00 by sky_line · 2 comments
Owner

Cache GPU-ready block-compressed texture data on disk, so textures seen before skip the JPEG2000 decode and the GPU encode on later loads.

Why

Today every texture goes: download or LL disk cache (J2C) → CPU JPEG2000 decode (OpenJPEG; the most expensive CPU work in the viewer, which saturates the decode threads at login and teleports) → RGBA upload → GPU BC encode (#263 texture compression).

With a BC cache, a texture already seen loads from disk straight into the GPU: no J2C decode, no encode. Expected wins:

  • Much faster texture loading when returning to places you visit often.
  • Lower RAM peak at login and teleport (#262): decoded RGBA buffers in flight are a big part of that spike.
  • Less CPU during loading: decode threads freed for content you haven't seen.

Design sketch

  • Key: texture UUID + format (BC1/BC3/BC5/BC7 variant, sRGB/UNORM) + encoder version + resident mip level. SL assets are immutable, so entries never go stale except across encoder versions, which are ignored and age out.
  • Value: the BC blocks for the resident mip chain, plus the adaptive and constant-colour flags (see the adaptive decision cache from the texture-compression work).
  • Write path: after a GPU encode, an async readback of the BC blocks (a staging ring, not on the main thread), then an async disk write. Never stall a frame.
  • Read path: in the fetch/residency pipeline, check the BC cache before requesting a J2C decode. On a hit, upload the blocks directly into the BC image at that level. If the texture needs a higher detail level than cached, fall back to the normal J2C decode and cache the new level.
  • Storage:
    • Its own directory and index in the cache dir, with an LRU byte budget (setting, default about 2-4 GB).
    • Separate from LL's texture cache, which stays the source of truth.
    • Atomic writes, a corruption-tolerant index (bad entries are dropped).
    • Wiped by Clear Cache.
  • Format interaction: entries are only valid for the current compression level and format. Switching level means re-encoding as now (and caching the new format); old-format entries age out.
  • Memory rule: bounded index in RAM, bounded staging, no unbounded growth.

Costs and risks

  • Disk usage: BC7 is 8 bpp, often 3-5x larger on disk than J2C. Needs a clear budget setting and a size readout.
  • Partial-level semantics vs J2C's progressive discard levels: the cache stores fixed levels.
  • New plumbing: async readback, disk I/O thread, index.
  • Verify: that loading compressed blocks from disk is faster end-to-end than J2C decode + GPU encode on typical SSDs and HDDs.

Measure

Login and teleport time to "textures settled" and the peak RSS (#262), first visit vs return visit, with the cache on vs off, at a heavy region.

Cache **GPU-ready block-compressed texture data** on disk, so textures seen before skip the JPEG2000 decode and the GPU encode on later loads. ## Why Today every texture goes: download or LL disk cache (J2C) → **CPU JPEG2000 decode** (OpenJPEG; the most expensive CPU work in the viewer, which saturates the decode threads at login and teleports) → RGBA upload → GPU BC encode (#263 texture compression). With a BC cache, a texture already seen loads from disk straight into the GPU: no J2C decode, no encode. Expected wins: - **Much faster texture loading** when returning to places you visit often. - **Lower RAM peak at login and teleport (#262):** decoded RGBA buffers in flight are a big part of that spike. - **Less CPU during loading:** decode threads freed for content you haven't seen. ## Design sketch - **Key:** texture UUID + format (BC1/BC3/BC5/BC7 variant, sRGB/UNORM) + encoder version + resident mip level. SL assets are immutable, so entries never go stale except across encoder versions, which are ignored and age out. - **Value:** the BC blocks for the resident mip chain, plus the adaptive and constant-colour flags (see the adaptive decision cache from the texture-compression work). - **Write path:** after a GPU encode, an async readback of the BC blocks (a staging ring, not on the main thread), then an async disk write. Never stall a frame. - **Read path:** in the fetch/residency pipeline, check the BC cache before requesting a J2C decode. On a hit, upload the blocks directly into the BC image at that level. If the texture needs a *higher* detail level than cached, fall back to the normal J2C decode and cache the new level. - **Storage:** - Its own directory and index in the cache dir, with an LRU byte budget (setting, default about 2-4 GB). - Separate from LL's texture cache, which stays the source of truth. - Atomic writes, a corruption-tolerant index (bad entries are dropped). - Wiped by Clear Cache. - **Format interaction:** entries are only valid for the current compression level and format. Switching level means re-encoding as now (and caching the new format); old-format entries age out. - **Memory rule:** bounded index in RAM, bounded staging, no unbounded growth. ## Costs and risks - **Disk usage:** BC7 is 8 bpp, often 3-5x larger on disk than J2C. Needs a clear budget setting and a size readout. - **Partial-level semantics vs J2C's progressive discard levels:** the cache stores fixed levels. - **New plumbing:** async readback, disk I/O thread, index. - **Verify:** that loading compressed blocks from disk is faster end-to-end than J2C decode + GPU encode on typical SSDs and HDDs. ## Measure Login and teleport time to "textures settled" and the peak RSS (#262), first visit vs return visit, with the cache on vs off, at a heavy region.
Author
Owner

Part of #405 (RAM/VRAM management epic).

Part of #405 (RAM/VRAM management epic).
sky_line added this to the Slipstream project 2026-10-06 15:04:13 +00:00
Author
Owner

Ticket audit 2026-10-07: done and shipped in 1.0.0 Beta 10. On-disk GPU-ready (block-compressed) texture cache with LRU budget, validation, Clear Cache purge and preferences (e112c99873, f1b9153fdf, 2e46bbcecd, aa1f0e8780, 34ea8d1163, 2574b6b7f2). If you still see the problem on the current beta, please reopen or file a new report.

Ticket audit 2026-10-07: done and shipped in **1.0.0 Beta 10**. On-disk GPU-ready (block-compressed) texture cache with LRU budget, validation, Clear Cache purge and preferences (e112c99873, f1b9153fdf, 2e46bbcecd, aa1f0e8780, 34ea8d1163, 2574b6b7f2). If you still see the problem on the current beta, please reopen or file a new report.
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.

Reference
sky_line/Slipstream#274
No description provided.