fix(vk): task + mesh draws through the compute fallback on Navi 21 too (#996) #1992

Merged
getzabelz merged 1 commit from fix/navi21-task-mesh-fallback into main 2026-11-11 01:44:29 +00:00
getzabelz commented 2026-11-10 22:57:33 +00:00 (Migrated from github.com)

Related to #996 (AMD on Windows: driver timeouts and device lost). A follow-up to #1747.

#1747 turned the compute fallback on by default for task + mesh draws on Navi 22 (RX 6700 XT, 0x73df), because AMD's Windows driver timed out on the native path there. Navi 21 (0x73bf: RX 6800, RX 6800 XT, RX 6900 XT) hangs the same way. This adds it to the same default, so those cards get the fallback without setting anything.

The change

gpu/vk/vk_main.cpp:

task_mesh_fallback = dev.props.vendorID == 0x1002 && (dev.props.deviceID == 0x73bf || dev.props.deviceID == 0x73df);
  • AMD and Windows only, as before. RADV on Linux is untouched.
  • RX_VK_TASK_MESH_FALLBACK still decides over it either way: =0 gives a Navi 21 the native path back.
  • The RX 6950 XT (0x73a5) is left out: I have not been able to test it.

Evidence

RX 6800 XT (1002:73BF), driver 0x800161 (32.0.21045.16010), Windows 11, 3440x1440, at the entrance to Hyrule Castle:

Build Path Result
Current main Native task + mesh Device lost (VK_ERROR_DEVICE_LOST, Windows LiveKernelEvent 141/117) within a couple of minutes of starting, a few seconds into play. The usual sign came first: a 5.3 s GPU wait (sync waits (5282 ms)) and a capture's write-back timing out.
Current main RX_VK_TASK_MESH_FALLBACK=1 25 minutes there, no device loss, no long GPU wait, and no fallback pipeline failing. The crates at the entrance draw correctly.
v2.0.13 Native Device lost twice in about 15 minutes in the same area (LiveKernelEvent 141/117, present failed (VkResult -4)).
v2.0.13 RX_VK_FORCE_MESH_FALLBACK=1 (the whole older fallback) 32 minutes, no device loss. The crates drew as flickering lights; that is fixed in main's fallback.

So on this card the native task + mesh path is what loses the device, and main's fallback both avoids it and draws correctly. Several reports in #996 are from RX 6800 / 6800 XT owners with the same symptoms (driver timeouts while playing, Hyrule Field, Kokiri).

To be transparent: the main builds tested also had #1823 applied (the driver-fault quarantine). That one is about the pause-menu freeze with no TDR; it does not touch the task + mesh path or the device loss here.

What it also brings on Navi 21

Turning task_mesh_fallback on is not only the draw path. Everything main gates on it applies too:

  • Fallback compute pipelines are built without the driver's optimizer (vk_draw.cpp, as on Navi 22).
  • #1747's retry without the optimizer, after a graphics pipeline fails with VK_ERROR_UNKNOWN, now applies on Navi 21 too. It was not needed in the 25 minutes tested: no "recovered with optimization disabled" in the log.
  • The program cache key includes the mode (vk_shader.cpp). The first start after this change prepares the shaders again on these cards: 1,299 fallback programs in about 4.5 minutes here. A new translator stamp does the same anyway.

Frame rate: a rough look at the logs, leaving out menu frames, gives 47.5 fps on average with the fallback (371 samples over 25 minutes) against 56.2 fps on the native path. The native figure comes from only 10 samples, in other moments of play, before it lost the device. That is too little to measure; the fallback may cost some frame rate, but a lost device costs the session.

Tests

  • New tests/test_task_mesh_fallback_devices.py checks:

    • that Navi 21 and Navi 22 are both in the default;
    • that it is AMD-only and inside #ifdef _WIN32;
    • that RX_VK_TASK_MESH_FALLBACK is read after the default, so it decides for any GPU.

    It fails on current main's code and passes with this change.

  • docs/development.md now lists RX_VK_TASK_MESH_FALLBACK, which was not documented.

  • Full run_all.py on Windows: 291 passed (current main: 290). The 6 failures fail the same way on a clean main on this PC (local environment); none is new.

Related to #996 (AMD on Windows: driver timeouts and device lost). A follow-up to #1747. #1747 turned the compute fallback on by default for task + mesh draws on **Navi 22** (RX 6700 XT, `0x73df`), because AMD's Windows driver timed out on the native path there. **Navi 21** (`0x73bf`: RX 6800, RX 6800 XT, RX 6900 XT) hangs the same way. This adds it to the same default, so those cards get the fallback without setting anything. ## The change `gpu/vk/vk_main.cpp`: ```cpp task_mesh_fallback = dev.props.vendorID == 0x1002 && (dev.props.deviceID == 0x73bf || dev.props.deviceID == 0x73df); ``` - **AMD and Windows only, as before.** RADV on Linux is untouched. - **`RX_VK_TASK_MESH_FALLBACK` still decides over it either way:** `=0` gives a Navi 21 the native path back. - **The RX 6950 XT (`0x73a5`) is left out:** I have not been able to test it. ## Evidence RX 6800 XT (`1002:73BF`), driver `0x800161` (32.0.21045.16010), Windows 11, 3440x1440, at the entrance to Hyrule Castle: | Build | Path | Result | |---|---|---| | Current `main` | Native task + mesh | **Device lost** (`VK_ERROR_DEVICE_LOST`, Windows `LiveKernelEvent` 141/117) within a couple of minutes of starting, a few seconds into play. The usual sign came first: a 5.3 s GPU wait (`sync waits (5282 ms)`) and a capture's write-back timing out. | | Current `main` | `RX_VK_TASK_MESH_FALLBACK=1` | **25 minutes there, no device loss**, no long GPU wait, and no fallback pipeline failing. The crates at the entrance draw correctly. | | v2.0.13 | Native | Device lost **twice in about 15 minutes** in the same area (`LiveKernelEvent` 141/117, `present failed (VkResult -4)`). | | v2.0.13 | `RX_VK_FORCE_MESH_FALLBACK=1` (the whole older fallback) | **32 minutes, no device loss**. The crates drew as flickering lights; that is fixed in `main`'s fallback. | So on this card the native task + mesh path is what loses the device, and `main`'s fallback both avoids it and draws correctly. Several reports in #996 are from RX 6800 / 6800 XT owners with the same symptoms (driver timeouts while playing, Hyrule Field, Kokiri). To be transparent: the `main` builds tested also had #1823 applied (the driver-fault quarantine). That one is about the pause-menu freeze with no TDR; it does not touch the task + mesh path or the device loss here. ## What it also brings on Navi 21 Turning `task_mesh_fallback` on is not only the draw path. Everything `main` gates on it applies too: - **Fallback compute pipelines are built without the driver's optimizer** (`vk_draw.cpp`, as on Navi 22). - **#1747's retry without the optimizer**, after a graphics pipeline fails with `VK_ERROR_UNKNOWN`, now applies on Navi 21 too. It was not needed in the 25 minutes tested: no "recovered with optimization disabled" in the log. - **The program cache key includes the mode** (`vk_shader.cpp`). The first start after this change prepares the shaders again on these cards: 1,299 fallback programs in about 4.5 minutes here. A new translator stamp does the same anyway. **Frame rate:** a rough look at the logs, leaving out menu frames, gives 47.5 fps on average with the fallback (371 samples over 25 minutes) against 56.2 fps on the native path. The native figure comes from only 10 samples, in other moments of play, before it lost the device. That is too little to measure; the fallback may cost some frame rate, but a lost device costs the session. ## Tests - New `tests/test_task_mesh_fallback_devices.py` checks: - that Navi 21 and Navi 22 are both in the default; - that it is AMD-only and inside `#ifdef _WIN32`; - that `RX_VK_TASK_MESH_FALLBACK` is read after the default, so it decides for any GPU. It fails on current `main`'s code and passes with this change. - `docs/development.md` now lists `RX_VK_TASK_MESH_FALLBACK`, which was not documented. - Full `run_all.py` on Windows: 291 passed (current `main`: 290). The 6 failures fail the same way on a clean `main` on this PC (local environment); none is new.
hckrman101 (Migrated from github.com) approved these changes 2026-11-11 01:40:53 +00:00
hckrman101 (Migrated from github.com) left a comment

Thanks, this is a small, well-scoped change, and the evidence is good: the A/B on the same card and spot (native loses the device within minutes, RX_VK_TASK_MESH_FALLBACK=1 plays 25 min), the v2.0.13 cross-check, and the honest fps note. It also matches what #996 keeps getting from Windows RX 6800 / 6800 XT / 6900 XT owners (Hyrule Field, camera turns, Zora's Domain).

Detection. PCI id under #ifdef _WIN32 with vendor 0x1002, so it only reaches AMD's Windows driver. RADV, the Deck (VanGogh), RDNA1 (no mesh shaders, already on the full fallback) and RDNA3/4 are untouched. One gap worth a look: 0x73bf is not every Navi 21. The XTXH 6900 XT boards (LC, Toxic and the like) report 0x73af. One shows up in #1000 on RADV (PCI 1002:73af), so Windows owners of that board will keep the native path. The 6950 XT is 0x73a5. Same chip, same driver. I understand leaving out what you couldn't test, but I'd add 0x73af at least, or say in the comment that those ids are left out on purpose. Not blocking.

Fit with main. The PR is 44 commits behind, but it merges cleanly. Main has since added the Mesh shaders row (#1971), with if (mesh_mode == 1) task_mesh_fallback = false; between the #endif and the env read. So Automatic picks up the new default, Native turns it off, Compute already runs everything on the fallback, and the env var still wins. Your test's checks (inside #ifdef _WIN32, env read after the default) still hold with that line there. The mesh-query gating (dev.mesh_queries) is independent of this. Small nit for the docs row: mention that Native in the Mesh shaders row also turns it off, since that's what players will reach for before an env var.

Side effects. As you list: the non-mesh VK_ERROR_UNKNOWN retry and the no-optimizer build of the fallback compute pipelines now apply on Navi 21. Mesh-only programs stay native and keep the PR 430 no-optimizer rule. The one-time re-preparation of shaders on first start (1,299 programs, about 4.5 min) is a real cost, but a one-off.

Relation to #1965 (build task/mesh programs with the optimizer on RADV): no shared code. #1965 only changes the amd check in build_graphics (vk_draw.cpp) and excludes VK_DRIVER_ID_MESA_RADV. This PR is Windows-only in vk_main.cpp, so neither changes what the other does on any GPU, and they can land in either order. After both, a Windows Navi 21 takes the compute fallback for task + mesh draws, and a Linux Navi 21 on RADV stays native with the optimizer on.

CI: the only failure is test_log_batch.py on windows-2022 (GetTickCount64() - t0 < 200), a timing check on a runner. It has nothing to do with this change. Ubuntu passes, and so does the Windows renderer build.

Looks good to me.

Thanks, this is a small, well-scoped change, and the evidence is good: the A/B on the same card and spot (native loses the device within minutes, `RX_VK_TASK_MESH_FALLBACK=1` plays 25 min), the v2.0.13 cross-check, and the honest fps note. It also matches what #996 keeps getting from Windows RX 6800 / 6800 XT / 6900 XT owners (Hyrule Field, camera turns, Zora's Domain). **Detection.** PCI id under `#ifdef _WIN32` with vendor 0x1002, so it only reaches AMD's Windows driver. RADV, the Deck (VanGogh), RDNA1 (no mesh shaders, already on the full fallback) and RDNA3/4 are untouched. One gap worth a look: `0x73bf` is not every Navi 21. The XTXH 6900 XT boards (LC, Toxic and the like) report `0x73af`. One shows up in #1000 on RADV (`PCI 1002:73af`), so Windows owners of that board will keep the native path. The 6950 XT is `0x73a5`. Same chip, same driver. I understand leaving out what you couldn't test, but I'd add `0x73af` at least, or say in the comment that those ids are left out on purpose. Not blocking. **Fit with main.** The PR is 44 commits behind, but it merges cleanly. Main has since added the Mesh shaders row (#1971), with `if (mesh_mode == 1) task_mesh_fallback = false;` between the `#endif` and the env read. So Automatic picks up the new default, Native turns it off, Compute already runs everything on the fallback, and the env var still wins. Your test's checks (inside `#ifdef _WIN32`, env read after the default) still hold with that line there. The mesh-query gating (`dev.mesh_queries`) is independent of this. Small nit for the docs row: mention that Native in the Mesh shaders row also turns it off, since that's what players will reach for before an env var. **Side effects.** As you list: the non-mesh `VK_ERROR_UNKNOWN` retry and the no-optimizer build of the fallback compute pipelines now apply on Navi 21. Mesh-only programs stay native and keep the PR 430 no-optimizer rule. The one-time re-preparation of shaders on first start (1,299 programs, about 4.5 min) is a real cost, but a one-off. **Relation to #1965** (build task/mesh programs with the optimizer on RADV): no shared code. #1965 only changes the `amd` check in `build_graphics` (vk_draw.cpp) and excludes `VK_DRIVER_ID_MESA_RADV`. This PR is Windows-only in vk_main.cpp, so neither changes what the other does on any GPU, and they can land in either order. After both, a Windows Navi 21 takes the compute fallback for task + mesh draws, and a Linux Navi 21 on RADV stays native with the optimizer on. **CI:** the only failure is `test_log_batch.py` on windows-2022 (`GetTickCount64() - t0 < 200`), a timing check on a runner. It has nothing to do with this change. Ubuntu passes, and so does the Windows renderer build. Looks good to me.
@ -436,2 +436,4 @@
// 25 minutes there with none. Navi 21 is 0x73bf (RX 6800, 6800 XT, 6900 XT); Navi 22 is 0x73df (RX 6700 XT)
task_mesh_fallback = dev.props.vendorID == 0x1002 && (dev.props.deviceID == 0x73bf || dev.props.deviceID == 0x73df);
#endif
if (const char* e = getenv("RX_VK_TASK_MESH_FALLBACK")) task_mesh_fallback = atoi(e) != 0;
hckrman101 (Migrated from github.com) commented 2026-11-11 01:40:53 +00:00

Navi 21 also ships as 0x73af (XTXH RX 6900 XT boards) and 0x73a5 (RX 6950 XT). Same chip and same driver, so they probably hang the same way. I'd consider adding 0x73af, or noting here that it's left out on purpose (the test's ids == set(DEVICES) would need the same change).

Navi 21 also ships as `0x73af` (XTXH RX 6900 XT boards) and `0x73a5` (RX 6950 XT). Same chip and same driver, so they probably hang the same way. I'd consider adding `0x73af`, or noting here that it's left out on purpose (the test's `ids == set(DEVICES)` would need the same change).
Commenting is not possible because the repository is archived.
No description provided.