Skip to content

vulkan: CPU caches written back / invalidated around the GPU's use of a non-coherent heap import (Mali) - #546

Merged
peiikai merged 2 commits into
peiikai:beta_6from
wolfchimneyrock:mali-cache-coherence
Nov 1, 2026
Merged

peiikai merged 2 commits into
peiikai:beta_6from
wolfchimneyrock:mali-cache-coherence

Conversation

@wolfchimneyrock

Copy link
Copy Markdown

From #526: the grass / shadow flashing on Mali. The guest heap's import isn't cache-coherent there, so the CPU's caches are written back / invalidated around the GPU's use of it.

Why: on a Mali-G610 with Arm's driver (libmali g29p1), a host-pointer import can only be memory type 1, HOST_VISIBLE | HOST_CACHED without HOST_COHERENT (vkGetMemoryHostPointerPropertiesEXT → memoryTypeBits 0x2; type 0, the coherent one, is the transient ring's).

What, only where the heap's memory type lacks HOST_COHERENT (decided at each heap import, logged as [vk] guest heap import: memory type N, coherent / not coherent: ...):

  • Before the GPU reads the heap, the range is written back with DC CVAC (allowed at EL0 on Linux):
    • snapshot copies (with the GPU's kept bytes in) and the per-object block copies;
    • the storage ranges a draw / dispatch binds, copy or original;
    • vertex / index data read in place (guest_direct);
    • the GPU's copies out of the heap (gmem_copy: the vertex cache, gfast).
  • The ranges a storing shader binds are written back and invalidated (DC CIVAC) when it is recorded, so no dirty CPU line lands on its results later. They are invalidated again once its submission is done: at the game's fence wait, including the overlap's early return, and at each render pass start.
  • plat_cache_op (platform.h) does nothing outside aarch64 Linux.
  • LARECOMP_VK_CACHE_CLEAN=0 / 1: off / on whatever the memory type.

Coherent imports (desktop GPUs) are unchanged: on a Radeon 780M (RADV) the log says memory type 5, coherent, and the walking route ran at 60 fps with 0 % missed-vblank windows.

Tested on a ROCK 5B (RK3588, Mali-G610, libmali g29p1), beta_6 + this. Scripted walking route through Mabe Village onto the Field, judged on the monitor:

grass / shadow flashing chain chomp 720p native, Field
before yes, both kinds head flickers / vanishes, missing triangles
this PR gone (6 walks, immediate and mailbox) good 30.7 fps, 4 % of 2 s windows with a frame ≥ 45 ms

The write-backs cost nothing measurable: 30 fps with 0-4 % hitching windows across runs, the same as without. They cover about 1.6-4.8 GB of ranges per 5 s, almost all of it lines that are already clean.

Not fixed: the title screen and save picker still flicker now and then. Cleaning the whole heap once a frame (a 57 ms diagnostic) removed it in one run, so it is probably another heap path, still open.

Note: on current beta_6, Mali needs LARECOMP_VK_STACK_ARRAYS=1 (see the #462 comment on #526). Without it the 3D scene never finishes building its shaders. These tests used it.

🤖 Generated with Claude Code

… a non-coherent heap import (Mali)

On a Mali-G610 with Arm's driver a host-pointer import can only be memory type 1 (HOST_VISIBLE | HOST_CACHED,
not HOST_COHERENT): what the CPU just wrote may still sit in its caches when the GPU reads the heap, and the CPU
may keep stale lines of what the GPU wrote. The overlap's snapshot copies are written right before the draws that
read them, so the GPU saw a slot's previous contents: grass and shadows flashing, objects vanishing for a frame
(peiikai#526). Where the heap's memory type lacks HOST_COHERENT: every range the GPU reads from the heap is written back
first (DC CVAC: snapshot copies, bound storage ranges, vertex / index data read in place, the GPU's copies out of
the heap); the ranges a storing shader binds are written back and invalidated (DC CIVAC) when it is recorded and
once its submission is done (the game's fence wait, render pass starts). Coherent imports: unchanged.
LARECOMP_VK_CACHE_CLEAN=0/1 overrides.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@peiikai

peiikai commented Nov 1, 2026

Copy link
Copy Markdown
Owner

Thanks, this reads well, and gating it on the import's memory type is the right call.

One build problem before CI: in runtime/platform.h the new plat_cache_op is inside the #ifdef __linux__ block, but exec.c calls it on every platform. Windows (and any other non-Linux Vulkan build) will fail with an undefined plat_cache_op. Moving it below the #endif fixes it, since its own #if defined(__aarch64__) && defined(__linux__) already makes it a no-op elsewhere. Adding a no-op copy to the #else branch would work too.

…forms build

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@wolfchimneyrock

Copy link
Copy Markdown
Author

Thanks, good catch. Fixed in a8948f5: plat_cache_op now sits below the #endif, so every platform gets it. Its own #if defined(__aarch64__) && defined(__linux__) keeps it a no-op off aarch64 Linux. I checked that the header compiles with __linux__ undefined; I don't have a Windows toolchain here, so CI will be the real test.

@peiikai

peiikai commented Nov 1, 2026

Copy link
Copy Markdown
Owner

Thanks, that looks right. CI is held for approval on fork PRs; we'll get it running.

@wolfchimneyrock

Copy link
Copy Markdown
Author

If this looks good to you it will probably be the last mali tweaking pr from me for a while since it gets to a smooth constant 30fps at both 1080p w/ 75% FSR1 and 720p native output on the rk3588, with no flickering or other artifacts during the gameplay that i tested.

@peiikai
peiikai merged commit bfd3898 into peiikai:beta_6 Nov 1, 2026
5 checks passed
@peiikai

peiikai commented Nov 1, 2026

Copy link
Copy Markdown
Owner

Merged into beta_6 in bfd3898. Thanks a lot for this and for all the Mali work. A steady 30 fps with no flicker on the RK3588 is a big step. The title screen flicker is noted as still open.

peiikai added a commit that referenced this pull request Nov 1, 2026
README: credit #546 to wolfchimneyrock
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants