Skip to content

fix(vk): no mirror is made inside a parallel replay's segment - #1184

Merged
hckrman101 merged 1 commit into
NotRexed:mainfrom
t0masz407:fix/parallel-mirror-make
Nov 9, 2026
Merged

hckrman101 merged 1 commit into
NotRexed:mainfrom
t0masz407:fix/parallel-mirror-make

Conversation

@t0masz407

Copy link
Copy Markdown
Contributor

What this fixes

With RX_VK_PARALLEL, large structures go missing in play: houses, big rocks, bushes, the tree over the Kokiri shop. With small segments, geometry is torn into huge stretched triangles. Serial replay is complete. This is the RX_VK_PARALLEL part of #994.

gpu_buffer_bind makes a pool's VRAM mirror the first time the pool is bound (mirror_make):

  • It points the page table at the mirror at once.
  • It records the mirror's fill (the whole pool copied in) into the uploads of the current recording.

In a parallel replay that recording is the uploads of the segment whose worker bound the pool first. The workers record out of order, so this need not be the first segment in the queue that reads the pool. An earlier segment, submitted first, reads the mirror before it is filled.

This matches what was seen:

  • The more segment boundaries, the worse.
  • One segment is complete.
  • A structure that was missing comes back after a few minutes, once every pool in use is mirrored, and new pools after a scene change start it again.

Change

Inside a parallel segment (par_active), the first binding no longer makes the mirror. The pool is marked wanted, and the mirror is made at the next submission's start, as RX_VK_MIRROR_DEFER=1 already does for every pool. Serial replay is unchanged. The cost is that a pool first bound in a segment is read from guest memory for one more submission.

tests/test_parallel_mirror_make.py checks the first-binding condition: it fails on current main and passes with this change.

Tested

RX 7900 XTX, RADV (Mesa 26.2.6), Linux. Hookshot v2.0.7 plus #1069 and #1108 plus this change. Scripted runs: the same save in front of the Kokiri shop, 4 camera directions, 2 runs per setting.

setting before after
RX_VK_PARALLEL=0 complete (unchanged)
RX_VK_PARALLEL=4 shop tree and other structures missing complete, 8 of 8
RX_VK_PARALLEL=4, RX_VK_PARALLEL_SEG=40 torn geometry, huge triangles, 74-87 fps complete, 8 of 8, 120 fps (frame generation)
RX_VK_PARALLEL=4, RX_VK_PARALLEL_SEG=1000000 (one segment) complete

Ruled out before this was found: #1069 (RX_VK_RB_REFRESH_EACH=1), RX_VK_NO_DESC_REUSE, RX_VK_NO_GRID_PATCH. #1108 alone was not tested without this change.

Not covered

  • Hardware tested on a v2.0.7 base, not a current-main binary; the changed code is identical on main.
  • Only AMD/RADV on Linux.
  • mirror_sync inside a segment (a pool synced by a later segment first) was already handled by sync_seg and is unchanged.

🤖 Generated with Claude Code

…lier segment read it unfilled)

mirror_make fills a pool's new mirror in the uploads of the segment whose worker bound the pool first, and points the
page table at it at once. Workers record out of order: an earlier segment, submitted first, read the mirror before its
fill (missing houses, rocks and bushes, torn geometry; worse with more segments, gone once every pool was mirrored).
In a segment the mirror is now wanted and made at the next submission's start, as RX_VK_MIRROR_DEFER=1 does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013mj4MdWTJo5ht4ShZX8Vpp
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.

1 participant