fix(vk): mesh fallback flicker: wait for the last draw before clearing the shared buffers (#1383 review) #1509

Merged
rakefire-impala merged 1 commit from fix/mesh-fallback-flicker-barrier-before-reset into main 2026-11-10 14:47:17 +00:00
rakefire-impala commented 2026-11-10 05:43:36 +00:00 (Migrated from github.com)

Since #1383, a recording thread's mesh fallback programs share one record/payload buffer pair. Each fallback draw clears it at the start, but nothing ordered that clear after the previous fallback draw finished reading it. This adds the barrier. It's the write-after-read hazard raised in #1383's review, which the merged version doesn't include yet.

Part of splitting up #1023.

Problem

fallback_record does, in order:

  1. end_pass(cmd)
  2. vkCmdFillBuffer(records ...), and the payload fill
  3. full_barrier(cmd)
  4. the task and mesh dispatches, then the draw

The previous fallback draw's vertex stage reads those records. Without a barrier between that draw and step 2, the fill can overwrite records an earlier draw in flight is still reading. On a GPU without mesh shaders, that can show up as fallback-drawn geometry (foliage, grass) flickering or drawing the wrong primitives.

Change

A full_barrier(cmd) after end_pass, before the fills. Six lines, including the comment and a test check. full_barrier already skips itself when nothing was recorded since the last one, so back-to-back fallback draws pay one barrier, not two.

Tests

tests/test_mesh_fallback.py checks for a barrier between end_pass and the first records fill. The check fails on main without this change.

Risk

Only fallback draws (GPUs without VK_EXT_mesh_shader) take this path. The cost is one barrier per fallback draw, which already has several.

Tested on

GPU AMD Radeon RX 5500M (RDNA1, 4 GB VRAM, no VK_EXT_mesh_shader)
Result Game-free tests pass; part of the build being played now
Since #1383, a recording thread's mesh fallback programs share one record/payload buffer pair. Each fallback draw clears it at the start, but nothing ordered that clear after the **previous** fallback draw finished reading it. This adds the barrier. It's the write-after-read hazard raised in #1383's review, which the merged version doesn't include yet. Part of splitting up #1023. ## Problem `fallback_record` does, in order: 1. `end_pass(cmd)` 2. `vkCmdFillBuffer(records ...)`, and the payload fill 3. `full_barrier(cmd)` 4. the task and mesh dispatches, then the draw The previous fallback draw's **vertex stage reads those records**. Without a barrier between that draw and step 2, the fill can overwrite records an earlier draw in flight is still reading. On a GPU without mesh shaders, that can show up as fallback-drawn geometry (foliage, grass) flickering or drawing the wrong primitives. ## Change A `full_barrier(cmd)` after `end_pass`, before the fills. Six lines, including the comment and a test check. `full_barrier` already skips itself when nothing was recorded since the last one, so back-to-back fallback draws pay one barrier, not two. ## Tests `tests/test_mesh_fallback.py` checks for a barrier between `end_pass` and the first records fill. The check fails on main without this change. ## Risk Only fallback draws (GPUs without `VK_EXT_mesh_shader`) take this path. The cost is one barrier per fallback draw, which already has several. ## Tested on | | | |---|---| | GPU | AMD Radeon RX 5500M (RDNA1, 4 GB VRAM, no `VK_EXT_mesh_shader`) | | Result | Game-free tests pass; part of the build being played now |
Commenting is not possible because the repository is archived.
No description provided.