Skip to content

Drop idle textures after half a minute of time, not 1800 frames - #376

Merged
cybersecurity merged 3 commits into
OpenCommunityEdition:mainfrom
hkmodd:feature/texture-idle-time
Oct 19, 2026
Merged

cybersecurity merged 3 commits into
OpenCommunityEdition:mainfrom
hkmodd:feature/texture-idle-time

Conversation

@hkmodd

@hkmodd hkmodd commented Oct 16, 2026

Copy link
Copy Markdown

Summary

The texture cache checked every 600 frames for textures not drawn in the last 1800 frames and dropped them. At 60 frames a second that is a check every ten seconds and a drop after half a minute. At 360 frames a second it is a drop after five seconds:

  • looking away from part of a level for five seconds dropped its textures;
  • turning back converted and uploaded them again;
  • the faster the display, the more often this happened.

On b30 at 357 frames a second, 105 textures were dropped in 38 seconds of play.

With this change the cache counts time instead of frames:

  • it sweeps every 10 seconds, timed with SDL_GetTicks (the Android guest bridges it and the web has it);
  • each sweep drops the textures not drawn since the sweep three sweeps earlier, so a texture goes 30 to 40 seconds after it was last drawn, as it did at 60 frames a second;
  • the frame counter still orders the palette variants.

Testing

tools/harness/tests/test_texture_idle.py runs xgpu_texture_cache_begin_frame, taken from the sources, against a fake clock. In every case a texture drawn every frame is never dropped.

Case Frame rate Hidden texture last drawn Required drop
fast 360 fps at 1 s 30–40 s later
steady 60 fps at 1 s 30–40 s later, as before
late 360 fps at 25 s, after several sweeps 30–40 s later

On main, fast and late fail: the texture is dropped after 5.7 and 6.7 seconds. steady passes on main.

Four negative controls, each expected to fail one case:

Mutation Fails
A sweep every frame fast
The sweep's own frame taken as the earlier one fast
Sweeps not counted late
A 60 s idle time steady

xbox_textures.c compiles without warnings in the Windows release build.

Not checked:

  • Time saved in play. Not measured. Each upload took 1.6 ms or less on an RTX 4080; the saving is larger where conversion and uploads cost more.
  • Linux, Android and web builds. Not compiled: the fork's CI is unavailable, and this machine has no Linux sysroot or Emscripten. The change uses only SDL_GetTicks, which the Android guest bridges (guest_sdl.c) and the other builds get from SDL3.

🤖 Generated with Claude Code

The texture cache dropped a texture once it had gone 1800 frames without
being drawn, and checked every 600 frames: half a minute and ten seconds
at 60 frames a second. At 360 frames a second it is five seconds, so
looking away from part of a level for five seconds dropped its textures,
and turning back converted and uploaded them again; the faster the
display, the more often. On b30 at 357 frames a second, 105 textures were
dropped in 38 seconds of play.

The cache now sweeps every 10 seconds of time (SDL_GetTicks, which the
Android guest and the web have too) and drops the textures not drawn since
the sweep three sweeps before: 30 to 40 seconds after they were last
drawn, which is what it did at 60 frames a second. The frame counter still
orders the palette variants.

Checked with a harness test (tools/harness/tests/test_texture_idle.py)
that runs xgpu_texture_cache_begin_frame from the sources against a fake
clock: a texture last drawn 1 or 25 seconds in is dropped 30 to 40 seconds
later at 360 frames a second, and at 60 as before; on main the 360 cases
fail (dropped after 5.7 and 6.7 seconds) and the 60 one passes. Four
negative controls. Not measured: the time saved, which is small on an
RTX 4080 (each upload took 1.6 ms or less) and larger where conversion and
uploads cost more.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
damiantw added a commit to damiantw/halo-ce-web-multiplayer that referenced this pull request Oct 16, 2026
Drop idle textures after half a minute of time, not 1800 frames (upstream OpenCommunityEdition#376)
hkmodd and others added 2 commits October 16, 2026 23:58
The one conflict was in xgpu_texture_cache_begin_frame's declarations.
Main gained the high-res HUD's refresh of cached bitmaps (OpenCommunityEdition#378) and here
the sweep counts time (idle_since, now); both are kept, declarations
before statements.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nCommunityEdition#376)

xgpu_texture_cache_begin_frame now also reads the high-res HUD's
settings (OpenCommunityEdition#378), drops an entry's upscaled sheet (OpenCommunityEdition#380) and forgets the
recent lookups. The test's fake world gains those members and functions,
with settings that never change. Its 3 cases and 4 negative controls
pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hkmodd added a commit to hkmodd/OpenCE that referenced this pull request Oct 16, 2026
…nCommunityEdition#376)

xgpu_texture_cache_begin_frame now also reads the high-res HUD's
settings (OpenCommunityEdition#378), drops an entry's upscaled sheet (OpenCommunityEdition#380) and forgets the
recent lookups. The test's fake world gains those members and functions,
with settings that never change. Its 3 cases and 4 negative controls
pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hkmodd added a commit to hkmodd/OpenCE that referenced this pull request Oct 17, 2026
…nCommunityEdition#376)

xgpu_texture_cache_begin_frame now also reads the high-res HUD's
settings (OpenCommunityEdition#378), drops an entry's upscaled sheet (OpenCommunityEdition#380) and forgets the
recent lookups. The test's fake world gains those members and functions,
with settings that never change. Its 3 cases and 4 negative controls
pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hkmodd added a commit to hkmodd/OpenCE that referenced this pull request Oct 17, 2026
…nCommunityEdition#376)

xgpu_texture_cache_begin_frame now also reads the high-res HUD's
settings (OpenCommunityEdition#378), drops an entry's upscaled sheet (OpenCommunityEdition#380) and forgets the
recent lookups. The test's fake world gains those members and functions,
with settings that never change. Its 3 cases and 4 negative controls
pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hkmodd added a commit to hkmodd/OpenCE that referenced this pull request Oct 18, 2026
…nCommunityEdition#376)

xgpu_texture_cache_begin_frame now also reads the high-res HUD's
settings (OpenCommunityEdition#378), drops an entry's upscaled sheet (OpenCommunityEdition#380) and forgets the
recent lookups. The test's fake world gains those members and functions,
with settings that never change. Its 3 cases and 4 negative controls
pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@VerySmuggy VerySmuggy added bug Something isn't working priority: medium Normal priority labels Oct 19, 2026
hkmodd added a commit to hkmodd/OpenCE that referenced this pull request Oct 19, 2026
…nCommunityEdition#376)

xgpu_texture_cache_begin_frame now also reads the high-res HUD's
settings (OpenCommunityEdition#378), drops an entry's upscaled sheet (OpenCommunityEdition#380) and forgets the
recent lookups. The test's fake world gains those members and functions,
with settings that never change. Its 3 cases and 4 negative controls
pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hkmodd added a commit to hkmodd/OpenCE that referenced this pull request Oct 19, 2026
…nCommunityEdition#376)

xgpu_texture_cache_begin_frame now also reads the high-res HUD's
settings (OpenCommunityEdition#378), drops an entry's upscaled sheet (OpenCommunityEdition#380) and forgets the
recent lookups. The test's fake world gains those members and functions,
with settings that never change. Its 3 cases and 4 negative controls
pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hkmodd added a commit to hkmodd/OpenCE that referenced this pull request Oct 19, 2026
…nCommunityEdition#376)

xgpu_texture_cache_begin_frame now also reads the high-res HUD's
settings (OpenCommunityEdition#378), drops an entry's upscaled sheet (OpenCommunityEdition#380) and forgets the
recent lookups. The test's fake world gains those members and functions,
with settings that never change. Its 3 cases and 4 negative controls
pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cybersecurity
cybersecurity merged commit 5fd319d into OpenCommunityEdition:main Oct 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working priority: medium Normal priority

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants