Linux/RADV, RX 9070 XT: RX_VK_PARALLEL=2/4 brings 60 fps but textures go missing / "explode" (v2.0.11) #1576

Closed
opened 2026-11-10 09:21:49 +00:00 by dkNorth · 5 comments
dkNorth commented 2026-11-10 09:21:49 +00:00 (Migrated from github.com)

Hookshot version

v2.0.11 (Linux AppImage build)

What kind of problem

Graphics (missing, black or wrong-coloured things, lighting, flicker)

What happened

I A/B-tested the RADV performance switches from #1000 / #1402 in the same spot (Hyrule Field area), about a minute each. The parallel replay is the only switch that gets me to a steady 60 fps, but it breaks textures:

Variant Env Median fps (5 s samples) Picture
Baseline (defaults) 51.8 OK
A RX_VK_BATCH=0 RX_VK_IMPORT_CHUNK_MB=1 53.6 OK
B RX_VK_PARALLEL=4 60.0 some textures missing
C A + RX_VK_PARALLEL=2 59.9 textures "explode" (garbled, flying all over)
D A + RX_VK_PARALLEL=4 58.8 textures "explode"

So with RX_VK_BATCH=0 the corruption gets much worse than with batching on. No crash, no device lost, nothing marked as an error in the logs.

The parallel replay itself looks healthy in the log, e.g. (4 threads):

vk: parallel replay: big command buffers recorded on 4 threads in segments of ~160 draws and dispatches
vk: parallel replay, a command buffer: dry pass 0.26 ms, segments 3.82 ms (6.0 of them), lock taken 1306 times, waited for 0.55 ms (all threads)
nvn: 400000 recordings made, 58026 live copies (19.1 MB), 379 texture copies; 6 command buffers' segments (2.4 MB)

This is with #1069 and #1108 (the parallel replay fixes from v2.0.8) already in, so it looks like a texture race those didn't cover. #1000 lists RX_VK_PARALLEL=4 as a RADV low-fps workaround, so others may run into this too.

Without parallel the frame is CPU-bound here (GPU time 2-11 ms a frame, most present intervals 17.8-22 ms), so the parallel replay would be a big win on this card if the texture side can be made safe.

Where in the game

Hyrule Field (also seen right after loading the save)

How often

Every time with RX_VK_PARALLEL set; never without it.

Graphics card and driver version

AMD Radeon RX 9070 XT (RADV GFX1201), Mesa 26.2.6

CPU, RAM and operating system

Ryzen 7 9800X3D, 32 GB, Bazzite (Fedora 45 base, kernel 7.2.15), KDE Plasma Wayland (game window through XWayland: SDL_VIDEO_DRIVER=x11)

Changes from the defaults

Always set: RX_VK_OOT_VISUAL=1 RX_VK_PRESENT_QUEUE=1, plus the per-variant switches in the table.

The game code was built with RX_MARCH=znver5. Runs B-D above used my own rebuild of hookshot_vk.so (v2.0.11 source, -march=znver5 + clang PGO, no code changes), so I re-ran D with the official prebuilt hookshot_vk.so from the v2.0.11 AppImage: same corruption (video below), median 60.0 fps.

Other software hooked into the game

No, nothing hooked in

hookshot_log.txt

Logs available on request (the attachment upload failed on my side); the relevant lines are quoted above.

Screenshots or video

9 s recording of variant D with the official renderer, Hyrule Field: wide horizontal bands of the screen show the wrong texture (smeared water/ground stretched across), black stripes, while Link and parts of the scene in between are drawn right. (the upload failed on my side; I will add the clip in a comment)

### Hookshot version v2.0.11 (Linux AppImage build) ### What kind of problem Graphics (missing, black or wrong-coloured things, lighting, flicker) ### What happened I A/B-tested the RADV performance switches from #1000 / #1402 in the same spot (Hyrule Field area), about a minute each. The parallel replay is the only switch that gets me to a steady 60 fps, but it breaks textures: | Variant | Env | Median fps (5 s samples) | Picture | |---|---|---|---| | Baseline | (defaults) | 51.8 | OK | | A | `RX_VK_BATCH=0 RX_VK_IMPORT_CHUNK_MB=1` | 53.6 | OK | | B | `RX_VK_PARALLEL=4` | 60.0 | **some textures missing** | | C | A + `RX_VK_PARALLEL=2` | 59.9 | **textures "explode"** (garbled, flying all over) | | D | A + `RX_VK_PARALLEL=4` | 58.8 | **textures "explode"** | So with `RX_VK_BATCH=0` the corruption gets much worse than with batching on. No crash, no device lost, nothing marked as an error in the logs. The parallel replay itself looks healthy in the log, e.g. (4 threads): ``` vk: parallel replay: big command buffers recorded on 4 threads in segments of ~160 draws and dispatches vk: parallel replay, a command buffer: dry pass 0.26 ms, segments 3.82 ms (6.0 of them), lock taken 1306 times, waited for 0.55 ms (all threads) nvn: 400000 recordings made, 58026 live copies (19.1 MB), 379 texture copies; 6 command buffers' segments (2.4 MB) ``` This is with #1069 and #1108 (the parallel replay fixes from v2.0.8) already in, so it looks like a texture race those didn't cover. #1000 lists `RX_VK_PARALLEL=4` as a RADV low-fps workaround, so others may run into this too. Without parallel the frame is CPU-bound here (GPU time 2-11 ms a frame, most present intervals 17.8-22 ms), so the parallel replay would be a big win on this card if the texture side can be made safe. ### Where in the game Hyrule Field (also seen right after loading the save) ### How often Every time with `RX_VK_PARALLEL` set; never without it. ### Graphics card and driver version AMD Radeon RX 9070 XT (RADV GFX1201), Mesa 26.2.6 ### CPU, RAM and operating system Ryzen 7 9800X3D, 32 GB, Bazzite (Fedora 45 base, kernel 7.2.15), KDE Plasma Wayland (game window through XWayland: `SDL_VIDEO_DRIVER=x11`) ### Changes from the defaults Always set: `RX_VK_OOT_VISUAL=1 RX_VK_PRESENT_QUEUE=1`, plus the per-variant switches in the table. The game code was built with `RX_MARCH=znver5`. Runs B-D above used my own rebuild of `hookshot_vk.so` (v2.0.11 source, `-march=znver5` + clang PGO, no code changes), so I re-ran D with the **official prebuilt `hookshot_vk.so` from the v2.0.11 AppImage**: same corruption (video below), median 60.0 fps. ### Other software hooked into the game No, nothing hooked in ### hookshot_log.txt Logs available on request (the attachment upload failed on my side); the relevant lines are quoted above. ### Screenshots or video 9 s recording of variant D with the official renderer, Hyrule Field: wide horizontal bands of the screen show the wrong texture (smeared water/ground stretched across), black stripes, while Link and parts of the scene in between are drawn right. (the upload failed on my side; I will add the clip in a comment)
dkNorth commented 2026-11-10 09:22:44 +00:00 (Migrated from github.com)
https://github.com/user-attachments/assets/90bd3218-6a68-4103-aa16-93c94eff11ae
NotRexed commented 2026-11-10 10:08:12 +00:00 (Migrated from github.com)

Fixed in v2.0.12 (https://github.com/NotRexed/Hookshot/releases/tag/v2.0.12): a parallel replay segment no longer reads a pool's VRAM copy before it is filled (#1184). Update with the Hookshot Builder (or the game's update offer) and rebuild. If it still happens on v2.0.12, reopen this with your hookshot_log.txt.

Fixed in **v2.0.12** (https://github.com/NotRexed/Hookshot/releases/tag/v2.0.12): a parallel replay segment no longer reads a pool's VRAM copy before it is filled (#1184). Update with the Hookshot Builder (or the game's update offer) and rebuild. If it still happens on v2.0.12, reopen this with your `hookshot_log.txt`.
quazardous commented 2026-11-10 10:50:58 +00:00 (Migrated from github.com)

The same matrix on another RADV card (Radeon 780M, GFX1103): the parallel replay cuts GPU time 5x and shows no texture corruption. Not a contradiction of your report -- a second data point that narrows where the race lives.

Machine: ROG Ally X, Radeon 780M (vk: device 0: AMD Ryzen Z1 Extreme (RADV PHOENIX), Vulkan 1.4, driver 0x6802006) -- the same driver 0x6802006 as your log, so the same Mesa 26.2.6 build; Bazzite (Fedora 45 base, kernel 7.2.15); native bin/hookshot, v2.0.11 (source 10f983ad), the prebuilt renderer from the AppImage, no rebuild.

Method, so this is repeatable: the game drives itself. Scripted input on the game's own frame clock, offscreen rendering, and captures taken inside the renderer:

HOS_HEADLESS=1 HOS_AUDIO=0 HOS_DYNRES=0 HOS_REALTIME_STEP=0 RX_VK_FRAMEGEN=0 \
HOS_INPUT_EXCLUSIVE=1 HOS_INPUT_FRAME_CLOCK=1 \
HOS_INPUT_SCRIPT="60:A,64:A,68:A,100:LUP/5000,108:LLEFT/2000,..." \
RX_VK_OOT_VISUAL=1 RX_VK_PRESENT_QUEUE=1 \
RX_VK_SHOTS=<dir> RX_VK_SHOT_EVERY=60 <variant> ./bin/hookshot

RX_VK_OOT_VISUAL=1 RX_VK_PRESENT_QUEUE=1 in every run, as in yours. The save loads into Kokiri Forest and Link walks a fixed route for about three minutes.

Performance, measured over the identical window of presents (4560-6180) in all four runs, so the same frames in the same place -- the medians of the log's own N presents, X fps and GPU time X ms:

Variant Env fps (median) GPU time (median)
Baseline (defaults) 29.2 29.1 ms
B RX_VK_PARALLEL=4 32.0 5.5 ms
C RX_VK_BATCH=0 RX_VK_IMPORT_CHUNK_MB=1 RX_VK_PARALLEL=2 31.4 5.4 ms
D RX_VK_BATCH=0 RX_VK_IMPORT_CHUNK_MB=1 RX_VK_PARALLEL=4 31.7 5.3 ms

GPU time falls by 5.4x while fps rises only 9%: on this APU the frame is CPU-bound once the parallel replay is on, which is the same shape you describe, from a much slower starting point (29 ms of GPU time here against your 2-11 ms).

Picture: no corruption in any variant. Every capture of every run was swept, not sampled -- about 200 captures per run as contact sheets. Nothing like your bands: no wrong texture stretched across the frame, no black stripes, no missing textures. Three frames an automated pass flagged in variant C turned out to be the game's own area-transition panels (a coloured panel sweeping across while both scenes are drawn correctly) and its bloom; the baseline run shows exactly the same panels at the same kind of moment, so they are not the parallel replay.

What this does not cover, and where I would not generalise:

  • Kokiri Forest, not Hyrule Field. Textures stayed under budget the whole time (textures 2434 MB (budget 2560 MB), 184 eviction events). If the race needs eviction pressure, this route does not create it. A longer run that goes over budget is running now and I will add the result.
  • Three minutes a variant.
  • GFX1103 (Phoenix, RDNA3) against your GFX1201 (RDNA4).

That last line is worth something on its own: #1279 (hollow menu text, native Linux + RADV) is also GFX1201-only -- it does not reproduce here either, same driver build, ultrawide included. Two unrelated-looking RADV reports that both stop at RDNA4 point at the driver's RDNA4 path rather than at RADV or at the Linux build.

One thing worth knowing for anyone trying to compare runs: with the frame clock and per-frame stepping, the runs still do not line up frame for frame -- loading takes a different number of frames in each variant, and no constant offset realigns them (I searched +/-600 presents; the best RMSE stayed far from zero). So a pixel diff between two runs measures drift, not corruption; judging the picture has to be per-run.

Happy to run any other variant on this card -- a run is one command.


Tooling and method. Nothing custom does the measuring: the determinism is the game's own -- HOS_HEADLESS, HOS_INPUT_SCRIPT with HOS_INPUT_FRAME_CLOCK, HOS_REALTIME_STEP=0, and RX_VK_SHOTS so the captures come from inside the renderer rather than off a compositor or a VNC stream, which would smooth away exactly the one-frame artefacts in question. The fps and GPU-time figures are the medians of the game's own N presents, X fps and GPU time X ms lines, read over the identical window of presents in all four runs -- comparing the tails of the logs instead had given a flattering and wrong +35%, because the runs had reached different places. Around the runs I use wbox to hold the session offscreen and replay it, with the Hookshot-side configuration in hookshot-wbox -- configuration and scripts only: no game file, capture, reference image or build output goes in either repository, per CONTRIBUTING.md.

**The same matrix on another RADV card (Radeon 780M, GFX1103): the parallel replay cuts GPU time 5x and shows no texture corruption.** Not a contradiction of your report -- a second data point that narrows where the race lives. Machine: ROG Ally X, Radeon 780M (`vk: device 0: AMD Ryzen Z1 Extreme (RADV PHOENIX), Vulkan 1.4, driver 0x6802006`) -- the same `driver 0x6802006` as your log, so the same Mesa 26.2.6 build; Bazzite (Fedora 45 base, kernel 7.2.15); native `bin/hookshot`, v2.0.11 (`source 10f983ad`), the prebuilt renderer from the AppImage, no rebuild. Method, so this is repeatable: the game drives itself. Scripted input on the game's own frame clock, offscreen rendering, and captures taken inside the renderer: ```sh HOS_HEADLESS=1 HOS_AUDIO=0 HOS_DYNRES=0 HOS_REALTIME_STEP=0 RX_VK_FRAMEGEN=0 \ HOS_INPUT_EXCLUSIVE=1 HOS_INPUT_FRAME_CLOCK=1 \ HOS_INPUT_SCRIPT="60:A,64:A,68:A,100:LUP/5000,108:LLEFT/2000,..." \ RX_VK_OOT_VISUAL=1 RX_VK_PRESENT_QUEUE=1 \ RX_VK_SHOTS=<dir> RX_VK_SHOT_EVERY=60 <variant> ./bin/hookshot ``` `RX_VK_OOT_VISUAL=1 RX_VK_PRESENT_QUEUE=1` in every run, as in yours. The save loads into Kokiri Forest and Link walks a fixed route for about three minutes. **Performance, measured over the identical window of presents (4560-6180) in all four runs**, so the same frames in the same place -- the medians of the log's own `N presents, X fps` and `GPU time X ms`: | Variant | Env | fps (median) | GPU time (median) | |---|---|---|---| | Baseline | (defaults) | 29.2 | 29.1 ms | | B | `RX_VK_PARALLEL=4` | 32.0 | 5.5 ms | | C | `RX_VK_BATCH=0 RX_VK_IMPORT_CHUNK_MB=1 RX_VK_PARALLEL=2` | 31.4 | 5.4 ms | | D | `RX_VK_BATCH=0 RX_VK_IMPORT_CHUNK_MB=1 RX_VK_PARALLEL=4` | 31.7 | 5.3 ms | GPU time falls by 5.4x while fps rises only 9%: on this APU the frame is CPU-bound once the parallel replay is on, which is the same shape you describe, from a much slower starting point (29 ms of GPU time here against your 2-11 ms). **Picture: no corruption in any variant.** Every capture of every run was swept, not sampled -- about 200 captures per run as contact sheets. Nothing like your bands: no wrong texture stretched across the frame, no black stripes, no missing textures. Three frames an automated pass flagged in variant C turned out to be the game's own area-transition panels (a coloured panel sweeping across while both scenes are drawn correctly) and its bloom; the **baseline run shows exactly the same panels at the same kind of moment**, so they are not the parallel replay. What this does not cover, and where I would not generalise: - **Kokiri Forest, not Hyrule Field.** Textures stayed under budget the whole time (`textures 2434 MB (budget 2560 MB)`, 184 eviction events). If the race needs eviction pressure, this route does not create it. A longer run that goes over budget is running now and I will add the result. - Three minutes a variant. - GFX1103 (Phoenix, RDNA3) against your GFX1201 (RDNA4). That last line is worth something on its own: #1279 (hollow menu text, native Linux + RADV) is also GFX1201-only -- it does not reproduce here either, same driver build, ultrawide included. Two unrelated-looking RADV reports that both stop at RDNA4 point at the driver's RDNA4 path rather than at RADV or at the Linux build. One thing worth knowing for anyone trying to compare runs: with the frame clock and per-frame stepping, the runs still do **not** line up frame for frame -- loading takes a different number of frames in each variant, and no constant offset realigns them (I searched +/-600 presents; the best RMSE stayed far from zero). So a pixel diff between two runs measures drift, not corruption; judging the picture has to be per-run. Happy to run any other variant on this card -- a run is one command. --- **Tooling and method.** Nothing custom does the measuring: the determinism is the game's own -- `HOS_HEADLESS`, `HOS_INPUT_SCRIPT` with `HOS_INPUT_FRAME_CLOCK`, `HOS_REALTIME_STEP=0`, and `RX_VK_SHOTS` so the captures come from inside the renderer rather than off a compositor or a VNC stream, which would smooth away exactly the one-frame artefacts in question. The fps and GPU-time figures are the medians of the game's own `N presents, X fps` and `GPU time X ms` lines, read over the identical window of presents in all four runs -- comparing the tails of the logs instead had given a flattering and wrong +35%, because the runs had reached different places. Around the runs I use [wbox](https://github.com/quazardous/wbox-mcp) to hold the session offscreen and replay it, with the Hookshot-side configuration in [hookshot-wbox](https://github.com/quazardous/hookshot-wbox) -- configuration and scripts only: no game file, capture, reference image or build output goes in either repository, per CONTRIBUTING.md.
dkNorth commented 2026-11-10 12:11:12 +00:00 (Migrated from github.com)

Thanks, confirmed fixed on v2.0.12: with RX_VK_PARALLEL=4 (plus RX_VK_BATCH=0 RX_VK_IMPORT_CHUNK_MB=1) the textures stay intact now. Same RX 9070 XT / RADV (Mesa 26.2.6) setup, full detail, no frame generation: median 59.4 fps, 90% of 5 s samples above 51 fps, in scenes up to ~3200 draws a frame (v2.0.11 without parallel: ~52-54).

One thing left with the parallel replay: occasional one-frame black flashes in indoor areas. Nothing about it in hookshot_log.txt. I haven't A/B-tested the same rooms with the parallel replay off yet, but it may be the out-of-order segment case mentioned in vk_replay.cpp ("one-frame black scenes"). Happy to test a build or switch if you want to narrow it down.

Thanks, confirmed fixed on v2.0.12: with `RX_VK_PARALLEL=4` (plus `RX_VK_BATCH=0 RX_VK_IMPORT_CHUNK_MB=1`) the textures stay intact now. Same RX 9070 XT / RADV (Mesa 26.2.6) setup, full detail, no frame generation: median 59.4 fps, 90% of 5 s samples above 51 fps, in scenes up to ~3200 draws a frame (v2.0.11 without parallel: ~52-54). One thing left with the parallel replay: occasional one-frame **black flashes in indoor areas**. Nothing about it in `hookshot_log.txt`. I haven't A/B-tested the same rooms with the parallel replay off yet, but it may be the out-of-order segment case mentioned in `vk_replay.cpp` ("one-frame black scenes"). Happy to test a build or switch if you want to narrow it down.
quazardous commented 2026-11-10 16:53:37 +00:00 (Migrated from github.com)

Correction to my comment above, which I posted without seeing that v2.0.12 had closed this 40 minutes earlier.

Disregard the RDNA4 inference. I wrote that this and #1279 both stopping at GFX1201 pointed at the driver's RDNA4 path. #1184 shows it was a real race in the parallel replay, and #1279 turned out to be Linux font selection with no GPU in it at all. A race that does not fire on another card is not evidence that the bug belongs to the card: it is one timing, observed once. I should have said that my runs failed to reproduce it, and stopped there.

What still stands, because it is measurement and not inference: on a Radeon 780M, loading the same save and comparing the identical window of presents, the parallel replay took GPU time from 29.1 ms to 5.3-5.5 ms a frame while fps rose only 29.2 -> 32.0, and no variant corrupted the picture anywhere in the capture sweep. Textures stayed under budget throughout (textures 2434 MB (budget 2560 MB)).

I am on v2.0.13 now. If the fix changes that balance on this APU I will post the new figures rather than an opinion.

Correction to my comment above, which I posted without seeing that v2.0.12 had closed this 40 minutes earlier. **Disregard the RDNA4 inference.** I wrote that this and #1279 both stopping at GFX1201 pointed at the driver's RDNA4 path. #1184 shows it was a real race in the parallel replay, and #1279 turned out to be Linux font selection with no GPU in it at all. A race that does not fire on another card is not evidence that the bug belongs to the card: it is one timing, observed once. I should have said that my runs failed to reproduce it, and stopped there. What still stands, because it is measurement and not inference: on a Radeon 780M, loading the same save and comparing the identical window of presents, the parallel replay took GPU time from 29.1 ms to 5.3-5.5 ms a frame while fps rose only 29.2 -> 32.0, and no variant corrupted the picture anywhere in the capture sweep. Textures stayed under budget throughout (`textures 2434 MB (budget 2560 MB)`). I am on v2.0.13 now. If the fix changes that balance on this APU I will post the new figures rather than an opinion.
Commenting is not possible because the repository is archived.
No milestone
No assignees
1 participant
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
MagicBeanDev/Hookshot#1576
No description provided.