vk: land #792's four mesh fallback fixes (the fallback's compute pipelines crashed NVIDIA's Pascal driver) #1314
No reviewers
Labels
No labels
accessibility
autorelease: pending
autorelease: tagged
bug
dependencies
documentation
duplicate
enhancement
github_actions
good first issue
help wanted
invalid
question
testing wanted
wontfix
No milestone
No assignees
1 participant
Due date
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Hookshot!1314
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/mesh-fallback-spirv"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
This brings the four mesh fallback commits of the closed PR #792 (by hckrman101, found by AmiriisCustoms) onto main, as Crono141 suggested in #1001 after testing them on an RX 590 / RADV. They never came over with #779, and v2.0.11 still has the bug. This PR adds a test from a GTX 1070, the most common card in #1001's reports. Without these commits, the fallback can't run on it at all.
e6e816aAligned 4on the fallback's PhysicalStorageBuffer accesses2511050RX_VK_DUMP_MESH_SPV)6be15ceb9d6c6fThere was one conflict, in
6be15ce:dwisdw()on main (TLS_OBJECT). The resolution is the same change written fordw(), and the test's expected strings follow it. Every commit passestests/test_mesh_fallback.pyon its own.The bug on Pascal
PushU64(ctx, MESH_FALLBACK_PAYLOAD_PUSH_OFFSET)passes a byte offset (64) whereOpAccessChaintakes a member index. TheResolutionInfoblock has 5 or 6 members, so the access chain indexes past its end. NVIDIA's compiler segfaults on it. On Linux, guarded_compute catches the fault, but the replay then stops presenting for good: the picture freezes when the intro's forest scene starts, while the game's threads keep running. This matches the GTX 1060 / 1070 / 1070 Ti reports in #1001 of a black or frozen screen after the intro or at the Deku Tree.Tested on
GTX 1070 8 GB, NVIDIA 580.178.04 (the last driver branch for Pascal), Linux (Ubuntu), v2.0.9 game folder. I only swapped
bin/hookshot_vk.so: the tag v2.0.9 plus these four commits.emit_spirv_mesh.cppis the same in v2.0.9, v2.0.11 and main.Offline: every fallback stage, through the real driver
I wrote a small harness. It reads a stage's SPIR-V, builds a pipeline layout from its own descriptor decorations, enables every feature the GPU offers and calls
vkCreateComputePipelines, each compile in a child process. It ran over every task and mesh compute stage in the program cache (1,300 fallback programs, 2,468 compute modules):spirv-val --target-env vulkan1.3 --uniform-buffer-standard-layoutRX_VK_DUMP_MESH_SPV)vkCreateComputePipelineson the GTX 1070To check the cause on its own, I also edited the stock SPIR-V by hand, changing only the index 64 to the payload member. That made all 2,336 compile.
In game: same intro, headless, scripted A presses, 260 s
the driver faulted compiling a compute pipelinea5da9f84b72d1471), then no more presentsThe foliage, the trees and the Deku Tree are drawn (screenshots and both logs attached).
What this does not cover yet: the run ends at the Deku Tree's speech in the intro (260 s). I haven't played further or loaded a save, so the later GTX 1070 reports in #1001 are not checked: black after Link wakes up, and the hang while loading a save. Both runs log the same 16
view of texture ... (vk 139) as vk 95 ... not madelines (the BC4 view from #1101), so that view is not what froze the intro here.Which build ran: only the v2.0.9-based
hookshot_vk.sowas run in game. The branch in this PR (main + the four commits, with thedw()conflict resolution) was built and passes the tests, but has not been run in game.Overlap: #1023 (RDNA1) carries its own version of the payload member fix inside a larger change. This PR is the small, focused alternative, made of #792's commits as they were written.
Tests:
python -I -B tests/run_all.pypasses, exceptnx2/test_nup_read_name.py, which needszstandard. That module is missing on my machine, and the test fails the same way on main.hookshot_vk.sobuilds on Linux (RX_VK_ONLY=1 nx2/build.py --standalone).Additional Windows save-load test for #1314 on a GTX 1070 8 GB (NVIDIA 581.63, Windows 11 build 26200, i7-7700).
14e0865240f8a6d32677a655646dbeb92a5e6505built on Windows with LLVM-MinGW (RX_VK_ONLY=1,nx2/build.py --standalone);tests/test_mesh_fallback.pypassed. The PR head's renderer interface differs from v2.0.11, so for the game run I applied the PR's patch unchanged to the v2.0.11 tag, built that DLL, and ran it with the existing v2.0.11 executable and a copied save profile. The fallback test passed on that source as well.vkCreateComputePipelinesfor program6ea0c171f1a7b6d8(NVN task stage 6, Hookshot marker-77).--target-env vulkan1.3 --uniform-buffer-standard-layout. I saw no repeat of the pipeline fault or device loss in the observed log. With startup shader preparation skipped for this test, presentation slowed sharply around loading, then resumed at about 33 FPS in a subsequent five-second window.This confirms frame presentation recovered past the previous failure on Windows. It does not establish visual correctness or broader stability. Build and shader analysis were assisted by Codex.
Nice find, and the Pascal evidence (2,336 SIGSEGV -> 0 over the real driver, plus the hand-edited index-64 control) is convincing. I read all four commits against the emitter and they hold up.
PushU64(..., ctx.mesh_fallback_payload_member_index)is right. The member is set underwants_mesh_fallbackfor every fallback stage, and the byte offset stays only for the host-side memcpy in vk_draw.cpp.Stridedunrolled: same behaviour as the old loop (each index is still guarded by the< countIf), and it drops the mid-function OpVariable.std::max(threads, 1U)also coversmesh_threads == 0. The test'sAddLocalVariablecheck covers that.EmitIsbeRead: slot iswg * task_threads + i, so% task_threadsgivesias the native path does. The threads come from the task's workgroup size, not the mesh's, which is what you want, and it's guarded for 0.dispatch()callsbuild_descriptorsfor the compute program, so thedw().prog != &pcheck does catch a draw after a dispatch. Forcing a rebuild indraw()plus the bail-out infallback_recordis the right pairing.RX_VK_DUMP_MESH_SPVis env-gated and harmless. The shader cache stamp hasheseden/andvk_shader.cpp, so cached programs with the old SPIR-V are invalidated.Overlap: #1023 carries its own versions of the same fixes (
LoadWord/StoreWord,UModbymesh_fallback_task_threads, payload member, the OpVariable placement) inside a much larger rewrite ofemit_spirv_mesh.cpp; it's currently conflicting, so whichever lands second will need a rebase and a quick check that nothing is doubled up. #1317 only touchesvk_draw.cpp(remembering a failed compute pipeline) and is complementary. #1341's repair-at-module-creation layer is made redundant by this: the emitters are fixed at the source.Nits, none blocking:
run_all.pyand royalsaltmerchant's Windows build.mesh_fallback_task_threadsisn't in the program-cache record, but that's fine since the stamp change invalidates old records anyway.dw()resolution is a straightforward translation, so I'm comfortable.LGTM.
Thanks for merging this and #1317. Here is a longer play test on the card it was meant for, as a reference for other GTX 10xx owners.
Setup: v2.0.11 + this PR + #1317, GTX 1070 8 GB / NVIDIA 580.178.04, i7-7700HQ (4 cores), Linux, output 1920x1080 at 75% resolution. The last session was 40 minutes through Kokiri Forest up to the Deku Tree, after four shorter ones.
driver faulted, 0 failed fallback pipelines, no crash or freeze in any session. Stock v2.0.9–v2.0.11 froze at the intro on this card.Still wrong on this card, not from this PR:
RX_VK_MIRROR=0makes it much worse on NVIDIA, with white foliage silhouettes and large black triangles. Mirrors are needed here.For GTX 10xx owners: #1023 is the next piece needed for a correct picture on this card.