AMD RX 9070 XT: OoT's networks fall back to software matrices (no 16x8x16 cooperative matrix), ~56 ms GPU per frame #52

Closed
opened 2026-11-07 06:48:19 +00:00 by LNagad · 4 comments
LNagad commented 2026-11-07 06:48:19 +00:00 (Migrated from github.com)

Hardware: Ryzen 7 7800X3D, Radeon RX 9070 XT 16 GB (AMD proprietary driver, Adrenalin 32.0.32015.12012, Vulkan 1.4), 16 GB RAM, Windows 11
Build: HookshotBuilder from the important release (bundled source matches fc80ed7 apart from host/hos_thread.c), game 0400486024DEC000 v131072, build e0f3ccfa

What happens

On RDNA 4 the cooperative-matrix probe rejects the device, so both networks run through the shuffle expansion:

vk: subgroups: default 64 lanes, 32-64, pinned to 32 on stages 0xf0
vk: matrix multiplies in software (the cooperative matrices lack 16x8x16 f16)
vk: AMD Radeon RX 9070 XT, Vulkan 1.4, driver 0x8001a0; mesh shaders yes, host memory import yes, pipeline libraries yes

That is most of the GPU frame on this card:

Scene Network GPU time / frame fps
Opening movie (5 draws, 14 dispatches) movie upscaler, real ~56 ms ~17.6, picture lags behind the audio
Kokiri Forest gameplay (~1,900 draws, ~120 dispatches) TAAU stood in (RX_VK_TAAU_KEYS=fd029a317a9a4b94) 3.3-4.3 ms 60

So with the TAAU stand-in gameplay is a locked 60 here, but the picture is the stretched pre-network image. The movie upscaler has no stand-in, and HOS_NO_MOVIES=1 is not an option for OoT: the title screen waits on Dm_Title_0005.webm and stays black without it.

Why the probe fails

RADV and AMD's driver expose VK_KHR_cooperative_matrix on RDNA 3/4 with 16x16x16 f16 shapes (WMMA, wave32), not 16x8x16, and the per-lane element layout differs from PTX mma.m16n8k16, so both conditions in vk_coopmat.cpp fail.

A possible path

HMMA.16816 could still use the 16x16x16 multiply if the fragments go through workgroup shared memory instead of being mapped lane to lane:

  1. each lane writes its A/B/C fragment registers to shared memory in the console's (PTX) layout, B and C padded to 16 columns with zeros;
  2. OpCooperativeMatrixLoadKHR the 16x16 A, B and C tiles row-major from shared memory;
  3. one OpCooperativeMatrixMulAddKHR (16x16x16);
  4. OpCooperativeMatrixStoreKHR the result to shared memory and each lane reads back its 16x8 D fragment in the console's layout.

It needs no knowledge of the device's lane layout, only 16x16x16 f16 support and a subgroup-sized scratch area per warp. It wastes half the multiply, but that is still a single hardware instruction against the current expansion. I can test builds on this card if that helps.

Related but not AMD-specific, so not repeated here: missing foliage (#35, #46) and the overexposure (#36, #30) look the same on this card as in those reports.

**Hardware:** Ryzen 7 7800X3D, Radeon RX 9070 XT 16 GB (AMD proprietary driver, Adrenalin 32.0.32015.12012, Vulkan 1.4), 16 GB RAM, Windows 11 **Build:** HookshotBuilder from the `important` release (bundled source matches `fc80ed7` apart from `host/hos_thread.c`), game `0400486024DEC000` v131072, build `e0f3ccfa` ### What happens On RDNA 4 the cooperative-matrix probe rejects the device, so both networks run through the shuffle expansion: ``` vk: subgroups: default 64 lanes, 32-64, pinned to 32 on stages 0xf0 vk: matrix multiplies in software (the cooperative matrices lack 16x8x16 f16) vk: AMD Radeon RX 9070 XT, Vulkan 1.4, driver 0x8001a0; mesh shaders yes, host memory import yes, pipeline libraries yes ``` That is most of the GPU frame on this card: | Scene | Network | GPU time / frame | fps | |---|---|---|---| | Opening movie (5 draws, 14 dispatches) | movie upscaler, real | ~56 ms | ~17.6, picture lags behind the audio | | Kokiri Forest gameplay (~1,900 draws, ~120 dispatches) | TAAU stood in (`RX_VK_TAAU_KEYS=fd029a317a9a4b94`) | 3.3-4.3 ms | 60 | So with the TAAU stand-in gameplay is a locked 60 here, but the picture is the stretched pre-network image. The movie upscaler has no stand-in, and `HOS_NO_MOVIES=1` is not an option for OoT: the title screen waits on `Dm_Title_0005.webm` and stays black without it. ### Why the probe fails RADV and AMD's driver expose `VK_KHR_cooperative_matrix` on RDNA 3/4 with 16x16x16 f16 shapes (WMMA, wave32), not 16x8x16, and the per-lane element layout differs from PTX `mma.m16n8k16`, so both conditions in `vk_coopmat.cpp` fail. ### A possible path HMMA.16816 could still use the 16x16x16 multiply if the fragments go through workgroup shared memory instead of being mapped lane to lane: 1. each lane writes its A/B/C fragment registers to shared memory in the console's (PTX) layout, B and C padded to 16 columns with zeros; 2. `OpCooperativeMatrixLoadKHR` the 16x16 A, B and C tiles row-major from shared memory; 3. one `OpCooperativeMatrixMulAddKHR` (16x16x16); 4. `OpCooperativeMatrixStoreKHR` the result to shared memory and each lane reads back its 16x8 D fragment in the console's layout. It needs no knowledge of the device's lane layout, only 16x16x16 f16 support and a subgroup-sized scratch area per warp. It wastes half the multiply, but that is still a single hardware instruction against the current expansion. I can test builds on this card if that helps. Related but not AMD-specific, so not repeated here: missing foliage (#35, #46) and the overexposure (#36, #30) look the same on this card as in those reports.
LNagad commented 2026-11-07 07:52:39 +00:00 (Migrated from github.com)

Thanks for the quick fix! Tested black-screen-fix (b306c4d) on the real card (RX 9070 XT, AMD proprietary driver, Windows 11), rebuilt over the same folder and .nup.

Movies after the first one, and the title screen, are black (audio plays)

With the default settings the first movie of the opening plays fine, now at full speed. From the next one on, where the Great Deku Tree speaks and sends Navi to find Link, the picture goes fully black (only the FPS counter, 60 fps, audio keeps playing), and the title screen background is black too. The networks are left out as intended:

vk: program e409733c45530d75 not translated: a network left out on this card
vk: program 8306877b7dc8784b not translated: a network left out on this card
... (11 networks in total: e409733c, 8306877b, de3c10db, a41c78fa, e959b9b1, 5a4d7378, 8b73eaee, 14140d4c, 4c2c129f, 3f6f2b1d, 9dc98871)
vk: program 3f6f2b1d671badcd does not translate: its dispatch replaced by a linear upscale of 0x10686b4000 1920x1080 (vk 37) into 0x10000348400 2560x1440 (vk 37)

With RX_VK_NETWORK_KEEP=all (same build, nothing else changed) the movie and the title screen render correctly again, at ~17 fps as before. So the black comes from leaving the networks out: the source the upscale stub blits from apparently holds nothing on this path.

For reference, with all networks kept the chain logs as:

vk: network e409733c45530d75: dispatch 900x1x1, 1 textures 0 images: 1920x1080x1/37
vk: network 8306877b7dc8784b: dispatch 720x1x1, 0 textures 0 images:
vk: network de3c10dba4ff39d3: dispatch 97x1x1, 0 textures 0 images:
vk: network a41c78faa56ccf7d: dispatch 120x1x1, 0 textures 0 images:
vk: network e959b9b1451491c0: dispatch 70x1x1, 0 textures 0 images:
vk: network 5a4d7378db437fed: dispatch 60x1x1, 0 textures 0 images:
vk: network 8b73eaee02efc5e4: dispatch 85x1x1, 0 textures 0 images:
vk: network 14140d4c1dbe754f: dispatch 8100x1x1, 0 textures 0 images:
vk: network 4c2c129fe950b041: dispatch 5400x1x1, 1 textures 1 images: 1920x1080x1/37 1920x1080x1/64
vk: network 3f6f2b1d671badcd: dispatch 80x180x1, 2 textures 1 images: 1920x1080x1/64 2560x1440x1/37

Since the first movie works and the later ones do not, my guess is that after the first movie the 1920x1080 RGBA8 frame texture ends up flagged as GPU-written, so texture_touch stops re-uploading the frames the decoder writes from the CPU (the RX_VK_CPU_OVER_GPU case), and the stub keeps blitting a stale or empty image. With every network kept, e409733c samples the frame each time and it stays in sync. Syncing the frame before the blit, or upscaling straight from the decoded frame, would probably be enough.

Title menu text still missing (#40, #44)

On the title screen (with RX_VK_NETWORK_KEEP=all, so the background is visible) the strip under the logo shows its ornaments but none of the option text.

Other notes

  • In the in-engine wake-up / nightmare scene before the Deku Tree the audio runs ahead of the picture. I think this is the frame-locked animation falling behind whenever a frame takes longer than 16.7 ms (first-time pipeline builds), not a separate bug, but mentioning it in case.
  • Foliage and the overexposure look the same as in #35 / #36.

Happy to test the next build.

Thanks for the quick fix! Tested `black-screen-fix` (`b306c4d`) on the real card (RX 9070 XT, AMD proprietary driver, Windows 11), rebuilt over the same folder and .nup. ### Movies after the first one, and the title screen, are black (audio plays) With the default settings the **first** movie of the opening plays fine, now at full speed. From the next one on, where the Great Deku Tree speaks and sends Navi to find Link, the picture goes fully black (only the FPS counter, 60 fps, audio keeps playing), and the title screen background is black too. The networks are left out as intended: ``` vk: program e409733c45530d75 not translated: a network left out on this card vk: program 8306877b7dc8784b not translated: a network left out on this card ... (11 networks in total: e409733c, 8306877b, de3c10db, a41c78fa, e959b9b1, 5a4d7378, 8b73eaee, 14140d4c, 4c2c129f, 3f6f2b1d, 9dc98871) vk: program 3f6f2b1d671badcd does not translate: its dispatch replaced by a linear upscale of 0x10686b4000 1920x1080 (vk 37) into 0x10000348400 2560x1440 (vk 37) ``` With `RX_VK_NETWORK_KEEP=all` (same build, nothing else changed) the movie and the title screen render correctly again, at ~17 fps as before. So the black comes from leaving the networks out: the source the upscale stub blits from apparently holds nothing on this path. For reference, with all networks kept the chain logs as: ``` vk: network e409733c45530d75: dispatch 900x1x1, 1 textures 0 images: 1920x1080x1/37 vk: network 8306877b7dc8784b: dispatch 720x1x1, 0 textures 0 images: vk: network de3c10dba4ff39d3: dispatch 97x1x1, 0 textures 0 images: vk: network a41c78faa56ccf7d: dispatch 120x1x1, 0 textures 0 images: vk: network e959b9b1451491c0: dispatch 70x1x1, 0 textures 0 images: vk: network 5a4d7378db437fed: dispatch 60x1x1, 0 textures 0 images: vk: network 8b73eaee02efc5e4: dispatch 85x1x1, 0 textures 0 images: vk: network 14140d4c1dbe754f: dispatch 8100x1x1, 0 textures 0 images: vk: network 4c2c129fe950b041: dispatch 5400x1x1, 1 textures 1 images: 1920x1080x1/37 1920x1080x1/64 vk: network 3f6f2b1d671badcd: dispatch 80x180x1, 2 textures 1 images: 1920x1080x1/64 2560x1440x1/37 ``` Since the first movie works and the later ones do not, my guess is that after the first movie the 1920x1080 RGBA8 frame texture ends up flagged as GPU-written, so `texture_touch` stops re-uploading the frames the decoder writes from the CPU (the `RX_VK_CPU_OVER_GPU` case), and the stub keeps blitting a stale or empty image. With every network kept, `e409733c` samples the frame each time and it stays in sync. Syncing the frame before the blit, or upscaling straight from the decoded frame, would probably be enough. ### Title menu text still missing (#40, #44) On the title screen (with `RX_VK_NETWORK_KEEP=all`, so the background is visible) the strip under the logo shows its ornaments but none of the option text. ### Other notes - In the in-engine wake-up / nightmare scene before the Deku Tree the audio runs ahead of the picture. I think this is the frame-locked animation falling behind whenever a frame takes longer than 16.7 ms (first-time pipeline builds), not a separate bug, but mentioning it in case. - Foliage and the overexposure look the same as in #35 / #36. Happy to test the next build.
LNagad commented 2026-11-07 07:55:24 +00:00 (Migrated from github.com)

Screenshots for the comment above (RX 9070 XT, b306c4d):

1. Opening movie with the default settings: black, only the FPS counter (audio plays).

Image

2. Title screen with RX_VK_NETWORK_KEEP=all: the background renders again (17 fps), but the menu strip under the logo has no option text (#40, #44).

Image

3. Kokiri Forest in Hookshot: bare trees and grass (#35, #46) and the overexposure (#36).

Image

4. Same area in Lichii on this card, for reference.

Image
Screenshots for the comment above (RX 9070 XT, `b306c4d`): **1. Opening movie with the default settings:** black, only the FPS counter (audio plays). <img width="1280" height="720" alt="Image" src="https://github.com/user-attachments/assets/967c384d-4ff7-4fa2-a605-d84807ff0d2a" /> **2. Title screen with `RX_VK_NETWORK_KEEP=all`:** the background renders again (17 fps), but the menu strip under the logo has no option text (#40, #44). <img width="1280" height="720" alt="Image" src="https://github.com/user-attachments/assets/5b84106e-1a17-4a6b-bcda-75ec14f8436c" /> **3. Kokiri Forest in Hookshot:** bare trees and grass (#35, #46) and the overexposure (#36). <img width="1280" height="720" alt="Image" src="https://github.com/user-attachments/assets/f3eae251-c76b-43b6-8266-1953f503ceac" /> **4. Same area in Lichii on this card, for reference.** <img width="960" height="540" alt="Image" src="https://github.com/user-attachments/assets/217e735f-e508-4e1a-a02b-6dd1ad1ce87d" />
t0masz407 commented 2026-11-08 16:43:56 +00:00 (Migrated from github.com)

Same on RDNA 3 under RADV (RX 7900 XTX, Mesa 26.2.6): vk: matrix multiplies in software (the cooperative matrices lack 16x8x16 f16) and the gameplay network not translated: a network left out on this card, so the picture is the
1080p pre-network image stretched to the output, without the network's anti-aliasing. RADV exposes VK_KHR_cooperative_matrix on this
card too (RDNA 3 has the 16x16x16 f16 WMMA shape you describe), so the shared-memory route proposed above should cover
it as well. Happy to test builds on it.

🤖 Written with Claude Code

Same on RDNA 3 under RADV (RX 7900 XTX, Mesa 26.2.6): `vk: matrix multiplies in software (the cooperative matrices lack 16x8x16 f16)` and the gameplay network `not translated: a network left out on this card`, so the picture is the 1080p pre-network image stretched to the output, without the network's anti-aliasing. RADV exposes `VK_KHR_cooperative_matrix` on this card too (RDNA 3 has the 16x16x16 f16 WMMA shape you describe), so the shared-memory route proposed above should cover it as well. Happy to test builds on it. 🤖 Written with [Claude Code](https://claude.com/claude-code)
NotRexed commented 2026-11-09 05:43:32 +00:00 (Migrated from github.com)

Tracked in #1006, follow there. That issue collects every report of AMD-specific rendering problems, and this one is linked from it with its GPU, version and log details. If it still happens on v2.0.6 (https://github.com/NotRexed/Hookshot/releases/tag/v2.0.6; Update next to Play in the launcher), please add a comment there with your hookshot_log.txt.

Tracked in #1006, follow there. That issue collects every report of AMD-specific rendering problems, and this one is linked from it with its GPU, version and log details. If it still happens on v2.0.6 (https://github.com/NotRexed/Hookshot/releases/tag/v2.0.6; Update next to Play in the launcher), please add a comment there with your `hookshot_log.txt`.
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#52
No description provided.