Repository navigation
fix(vk): keep programs the driver faulted on out of the driver (#996) - #1823
Conversation
|
One adjacent fault-containment question from a source audit: the Windows and POSIX guards return the caught-fault result but leave Would clearing the output specifically on the caught-fault branches fit this work? Normal Vulkan error returns should retain their ordinary output/cleanup contract. A focused regression could have the authored driver stub write a sentinel and then raise the exception/signal, checking that the caller never destroys or publishes it. This is a source-derived question, not a reproduced real-driver crash or a claim that the current quarantine change causes one. Sharing here because the guards are already in your scope; I have not started a competing implementation. |
222066f to
eb72412
Compare
|
@hckrman101 Rebased on current
@Arkex-ai Good catch, and it fits here. All four guards (Windows SEH and Linux signal, graphics and compute) now set Played again (RX 6800 XT, driver 0x800161, this change on a v2.0.13 build). I removed
Then, in Hyrule Market, I opened and closed the pause menu and the map with no freeze and no further driver fault. Side note: #1766's description mentions a start that hung on an RTX 4070 Ti after a precompile worker's build faulted inside the driver. That looks like the same mechanism as here, so the quarantine may help on NVIDIA too. Full |
eb72412 to
dd68029
Compare
…aults file cannot be written From the review of NotRexed#1823: the gate serialized every build of a program on every driver, so NVIDIA, Intel and the Linux drivers lost the parallel builds of a program's state variants (the precompile and the worker), and a non-cold build on the presentation thread could wait for a precompile thread on the same program. The hang behind a faulted build was seen on AMD's Windows driver, so: - the gate is on for AMD (vendor 0x1002) by default; other drivers build side by side as before, and only the quarantine applies to them; - RX_VK_DRIVER_FAULTS=2 turns the gate on for every driver (NotRexed#1766 saw a start hang after a driver fault on an RTX 4070 Ti); - RX_VK_DRIVER_FAULTS=0 still turns everything off. The gate is not limited to "after a program faulted": the second build that hung was already inside the driver when the first one faulted. hookshot_driver_faults.txt beside a read-only executable (Program Files) is now said once in the log; the quarantine then lasts for the run. tests/test_driver_faults.py: a non-serial quarantine lets builds of one program into the driver side by side, never waits nor answers busy, and still keeps a faulted program out. It also checks the AMD default and the log line. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@hckrman101 Thanks, good point. I went with your first suggestion. New commit on top: dd68029 (rebased on current
Played on a build of current
Also from earlier play: a new program ( |
…xed#996) On AMD's Windows driver (amdvlk64.dll 0x800161) a fault caught inside vkCreateGraphicsPipelines leaves that program's compile unfinished in the driver. Every later build of the same program, with any state, then waits inside the driver forever on a condition variable that is never signalled. A full dump of the freeze on closing the pause menu (RX 6800 XT, v2.0.13, Hyrule Market) showed: - the presentation thread waited for program 6eaa646d07ea4e43; - the worker building it and a precompile thread were both inside the driver on that program; - another precompile thread was inside the driver on 5fa56485a6b07619. Both are among the programs logged "not made (-13)" (the caught fault) at every start. Those two precompile threads were the "N of N+2 done, nothing finished for 30 s" of every AMD log. There was no TDR. gpu/vk/driver_faults.h keeps such a program out of the driver: - for the rest of the run; - on later runs with the same vendor and driver version, through hookshot_driver_faults.txt beside the executable. A driver update tries them again. build_graphics also lets one build of a program into the driver at a time. A second build waits outside the driver and is refused if the first one faulted, instead of being caught inside the driver behind it. A cold probe is not made to wait: it is answered as a compile that is required. The graphics guards now answer a fault with -77, as the compute guards do, so a driver's own VK_ERROR_UNKNOWN is not taken for a fault. RX_VK_DRIVER_FAULTS=0 turns all of this off. On the RX 6800 XT, building the game: - before: 3 faults, 2 precompile threads stuck for good, 32.5 s; - first run with the fix: 3 faults, the second builds of those programs refused outside the driver, the precompile complete in 4.2 s; - next run: no fault at all, 3 programs skipped, 2.3 s. With NotRexed#1747 (AMD retry without the optimizer after VK_ERROR_UNKNOWN): that retry followed the guard's VK_ERROR_UNKNOWN, which a fault also was until now. It still runs after a fault (kDriverFault), inside the gate, and the program is quarantined only if the retry faults too. tests/test_driver_faults.py runs the real header with threads and checks build_graphics' gate. tests/test_linux_driver_fault_guard.py expects -77 for a graphics fault now. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…aults file cannot be written From the review of NotRexed#1823: the gate serialized every build of a program on every driver, so NVIDIA, Intel and the Linux drivers lost the parallel builds of a program's state variants (the precompile and the worker), and a non-cold build on the presentation thread could wait for a precompile thread on the same program. The hang behind a faulted build was seen on AMD's Windows driver, so: - the gate is on for AMD (vendor 0x1002) by default; other drivers build side by side as before, and only the quarantine applies to them; - RX_VK_DRIVER_FAULTS=2 turns the gate on for every driver (NotRexed#1766 saw a start hang after a driver fault on an RTX 4070 Ti); - RX_VK_DRIVER_FAULTS=0 still turns everything off. The gate is not limited to "after a program faulted": the second build that hung was already inside the driver when the first one faulted. hookshot_driver_faults.txt beside a read-only executable (Program Files) is now said once in the log; the quarantine then lasts for the run. tests/test_driver_faults.py: a non-serial quarantine lets builds of one program into the driver side by side, never waits nor answers busy, and still keeps a faulted program out. It also checks the AMD default and the log line. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dd68029 to
3dc9b5d
Compare
|
@hckrman101 Thanks for the approval. Rebased on current On the RADV note: I'll leave the gate on |
|
CI note: after the rebase, |
Conflicts resolved: - MKWVK_API_VERSION 18: upstream's version 17 is prompts_live (NotRexed#2366); the data folder's MkwVkHost.data_dir follows it as version 18. - host/hos_update.c: "Skip this version" stays in the data folder; upstream's call order (NotRexed#2283, the check after the saves' place is known) is kept, with hos_data_init having chosen that place first. tests/test_linux_update_skip.py builds the start with hos_data.c instead of the removed saves_dir. - host/prompts.c: upstream's live prompts and mod size tables (NotRexed#2366, NotRexed#2270), with the generated files (and the new rsizetable.mod.zs) in cache/prompts; made_dir makes cache/ too. - builder/linux/play-diagnostics.sh: upstream's socket stderr (NotRexed#2279), with hookshot_startup.log in logs/. - The program cache moved to vk_progcache.cpp (NotRexed#2323): its path is cache/. - hookshot_driver_faults.txt (NotRexed#1823) goes to cache/ and is moved there. - env_on/env_value_off (NotRexed#2042), env_override (vk_menu.cpp), the prepare watchdog (vk_main.cpp), audio and docs merged with the data folder paths. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fixes #1740
Fixes #1734
Related to #996: the freeze on closing the pause menu or map, with the music still playing.
The freeze
On AMD Windows (driver 0x800161), the game freezes when closing the pause menu or the map in Kokiri Forest and Hyrule Market, with the music still playing. There is no TDR and no device lost.
I took a full process dump of the freeze with Task Manager (RX 6800 XT, v2.0.13, closing the pause menu in Hyrule Market). I then read the thread stacks with the symbols in
hookshot.exe/hookshot_vk.dll:sead::MainThreadevent_wait(waiting for the frame)Presentation Threadmkwvk::draw→targets→jobs_wait, for program 6eaa646d07ea4e43's pipelinemkw_vk workergraphics_pipelinejob →build_graphics→guarded_graphics→amdvlk64.dll,SleepConditionVariableCS, program 6eaa646d07ea4e43precompile_run→build_graphics→amdvlk64.dll,SleepConditionVariableCS, program 6eaa646d07ea4e43I found the program keys by following the
Program&on each stack.Both programs are among the ones every AMD log reports at start as
graphics pipeline for 5fa56485a6b07619 / 6eaa646d07ea4e43 / 4e5ce183a33b0855 not made (-13). That-13is the__exceptinguarded_graphics, which catches an access violation inside AMD's compiler. Those two stuck precompile threads are also theprecompile: N of N+2 done, nothing finished for 30 sof every AMD start.What happens: the caught fault leaves that program's compile unfinished inside the driver. Every later
vkCreateGraphicsPipelinesof the same program, with any state, waits inside the driver for a condition variable that is never signalled. The game runs until it needs a new pipeline of one of those programs (closing the pause menu, some areas), and then the frame never finishes.The fix
gpu/vk/driver_faults.h(new, Vulkan-free) andbuild_graphics:FAIL_ON_PIPELINE_COMPILE_REQUIRED) is never made to wait: a build of its program under way answers it as a compile that is required. This gate is on for AMD (vendor0x1002) by default, where the hang was seen. Other drivers build a program's state variants side by side, as before, and only the quarantine applies to them.hookshot_driver_faults.txtbeside the executable, as<vendor> <driver version> <key>lines. On later runs with the same vendor and driver those programs are never asked of the driver, the precompile included. A driver update tries them again. If the file cannot be written (a read-only folder), the log says so once and the quarantine lasts for that run.-77, as the compute guards already did. A driver's ownVK_ERROR_UNKNOWNis no longer taken for a fault. The Windows guards keep Log a driver fault caught by the Windows pipeline guards #1766's log line with the exception code.*pl = VK_NULL_HANDLE. Whatever the driver wrote before it faulted is never published or destroyed; for example,fallback_compute_pipelines()destroys every non-null output on an error.RX_VK_DRIVER_FAULTS=0turns all of this off;=2turns the gate on for every driver.With #1747: its AMD retry without the optimizer followed
VK_ERROR_UNKNOWN, which until now also meant a fault. It still runs after a fault, now inside the gate. The program is quarantined only if the retry faults too.With #1772: the gate wraps
graphics_with. That can reach the driver up to three times through the play caches, all inside the gate.create_cachedreturns the guard's result unchanged, so a fault still reaches the quarantine.Results (RX 6800 XT, driver 0x800161, Windows 11)
The builder's precompile runs on the player's GPU, so the build log shows the effect directly:
6625 of 6627 done, nothing finished for 30 sIn game, before the fix, it froze on closing the pause menu in Hyrule Market, and in another session also on a menu. After the fix, in two sessions with the pause menu and the map opened and closed many times (over 200 menu-frame samples in the logs, Hyrule Market included), it never froze and there were no driver faults after start. A later session with the output clearing ran as a first run (
hookshot_driver_faults.txtremoved). The driver faulted three times (exception 0xc0000005), and the precompile still completed in 2.6 s with no thread left in the driver. Pausing in Hyrule Market did not freeze either. This was tested on a v2.0.13 build with the same change backported; this branch is rebased on currentmainand merges cleanly.Tests
tests/test_driver_faults.pycompiles the realdriver_faults.hand runs it with threads:kBusy;vk_draw.cppthat everyguarded_graphicscall ofbuild_graphics(including Work around AMD Vulkan task shader timeouts and restore cloth rendering #1747's retry) sits between the gate'sbeginandend, and that the guards stay self-contained fortest_precompile_compute_guard.pyandtest_linux_driver_fault_guard.py.tests/test_linux_driver_fault_guard.pynow expects-77for a graphics fault.tests/test_linux_driver_fault_guard.pyandtests/test_precompile_compute_guard.py: their fake drivers write a sentinel handle before they fault. The existing checks then assert that it is neither published nor destroyed. These run on Linux and on an MSVC-target build (CI).test_driver_faults.pyalso covers the non-serial mode (builds side by side, never waiting nor busy, a fault still quarantined), and checks that every fault branch clears the output, and that every driver call ofbuild_graphics(graphics_withincluded) is inside the gate.run_all.pyon Windows, rebased on currentmain: 291 passed. The 6 failures fail the same way on a cleanmainhere (local environment).Not covered
-77,failedonce); only their guards' output clearing is new.