Repository navigation
fix(vk): dark lighting and glowing bloom on AMD: 64-lane graphics warps and Lichii #273's fragment shuffle fallback - #1507
Conversation
|
Data point for the testers asked for here, from an RX 7800 XT (RDNA3), Windows 11, driver 0x8001a0, v2.0.12: The log line is I have not tested this PR on this card. If it helps I can build it on top of v2.0.12 and report the first-start preparation time (the PR says graphics programs are translated again on AMD), whether the picture changes anywhere, and the log lines, using |
|
Thanks, that's exactly the data this needs. On your card this PR does turn the 64-lane path on. The condition is The two parts are independent. The most useful runs, set in
For each run: the first-start preparation time, and whether lighting, bloom or anything else looks different. On the RX 5500M it showed most in Kokiri Forest and in Link's house (a basket drew white). Both switches are in the program cache's stamp, so each run re-translates once. |
dae962a to
64081e3
Compare
|
First result for run 3 (both parts, the PR's default) on an RX 7800 XT (RDNA3), Windows 11, driver 0x8001a0, Build: v2.0.12 plus this PR (merged with no conflicts), plus PR #1130 at 6f76660 and two local memory edits for AMD (image pool preallocation, larger capture buffer classes), so it is not a clean main + PR build. First start: What I saw (normal play, about 12 minutes): lighting and bloom looked normal in Kokiri Forest, in Link's house and in front of Ganon's Castle as adult Link. No white-glowing objects, no too-dark areas, no errors, no device lost. I did not see those problems on this card before the PR either, so "normal" shows no regression, not that the PR fixes anything here. Frame times (not conclusive): mean 57.7 game fps (median 60, 5% worst 46), GPU 4.9 ms a frame on average, p95 9.5 ms. 28 submits of 40 ms or more (15 of 100 ms or more, longest 1.4 s) against 12 in a 9.6-minute session on the same GPU without this PR; the dominant part of the long ones is Not done yet: runs 1 (0/0, main's behaviour) and 2 (0/1), on the same route, to separate the two parts and the frame times. I will post them here. |
…n to 32 lanes RDNA2 and RDNA3 pin their fragment, task and mesh stages to 32 lanes (requiredSubgroupSizeStages 0xf0, an RX 7800 XT in NotRexed#1507's review), and pin_subgroup does: those stages run as NVN's 32-lane warps, so they keep main's short path. Only the stages that run at 64 lanes take the long one: the vertex stage there, every graphics stage on RDNA1 (0x20, compute only), where the SPIR-V is unchanged from this PR's first commit. The fragment shuffle fallback (Lichii NotRexed#273) stays for every stage: it is AMD's compiler, not the lanes. RX_VK_WARP64 still sets every graphics stage. The pinned stages are in the program cache's stamp. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Following your point, I've pushed a narrower version ( The test plan stays the same. In run 3 (both parts on), only your vertex programs are re-translated with the long path, so the first-start time should come out close to run 2's. |
|
Run 1 ( Picture: normal in all three places in both runs. Nothing white, nothing too dark, no errors, no device lost. First start: Frame times over the same first 26,400 presents (about 7.3 minutes), one run each, run 3 done first:
I would not read this as a cost of the PR: one run each, the order was fixed, and the PR changes the translated shaders, so run 3 also compiled many pipelines for the first time in play (21 against 5 slow driver compiles), which can explain part of the hitches. I cannot separate that from a real cost with these two runs. The longest hitch is the other way round (3.2 s in run 1). Thanks for narrowing it per stage. For a fair comparison I will repeat run 3 on |
…les and depth-compare textures Fixes the dark lighting and the white-glowing objects (a basket in Link's house) on an AMD RX 5500M. - Warp size: AMD GPUs let only compute pin its subgroups to NVN's 32 lanes (requiredSubgroupSizeStages 0x20 on the RX 5500M); a fragment or vertex stage runs at 64. The translator was told 32 lanes everywhere (warp_size_potentially_larger_than_guest false), so the ballots and shuffles of the game's fragment shaders ran across both halves of a 64-lane wave. make_profile now sets it, and max_subgroup_size to the device's most, when graphics stages cannot be pinned and the default is wider than 32: Eden's long path keeps each 32-lane guest warp to its half, and is right at 32 lanes too. NVIDIA (32 lanes) is unchanged. - Compute and the mesh fallback's compute stages keep the short path (profile_pinned): they are pinned to 32. Giving every compute program the long path made its SPIR-V new and longer, missing the driver's cache, and AMD compiled shaders for hours at start. - Lichii NotRexed#273: on AMD's proprietary driver, fragment-stage subgroup shuffles take the broadcast fallback (has_broken_spirv_fragment_shuffle); and a depth-compare texture is never an integer image, whatever its descriptor says (the lighting's shadow samples). - The device's driver ID and subgroup sizes are read at start; the program cache's stamp includes the profile's warp choices, so a cache translated for another GPU's warps is not used. tests/test_amd_fragment_warp.py checks the profile, the pinned profile's uses, the stamp, the shuffle fallback and the depth-compare rule. (Rebased on main: the depth-compare change itself came with NotRexed#834; only the test checks it here.) (cherry picked from commit b17e373)
… diagnostics - SHFL.BFLY in fragment stages takes Lichii NotRexed#273's broadcast fallback on AMD's proprietary driver, as the other shuffles do. The quad swap stays native: its programs have neither the lane-id input nor the Ballot capability the fallback needs (rerouting it crashed shader prep). - RX_VK_WARP64=0|1 and RX_VK_FRAG_SHUFFLE_FALLBACK=0|1 override the warp profile for diagnosis (both are in the program cache's stamp).
…n to 32 lanes RDNA2 and RDNA3 pin their fragment, task and mesh stages to 32 lanes (requiredSubgroupSizeStages 0xf0, an RX 7800 XT in NotRexed#1507's review), and pin_subgroup does: those stages run as NVN's 32-lane warps, so they keep main's short path. Only the stages that run at 64 lanes take the long one: the vertex stage there, every graphics stage on RDNA1 (0x20, compute only), where the SPIR-V is unchanged from this PR's first commit. The fragment shuffle fallback (Lichii NotRexed#273) stays for every stage: it is AMD's compiler, not the lanes. RX_VK_WARP64 still sets every graphics stage. The pinned stages are in the program cache's stamp.
6943ac0 to
c433687
Compare
|
Thanks for runs 1 and 3. #1507 has merged since, including the per-stage change ( Your run 3 had more long submits than run 1 (15 against 7 of 100 ms or more) and more slow driver compiles (21 against 5). But it was on the wider version, which put the long warp path on every fragment shader with warp operations. On your card the merged version gives it only to the vertex stage, and only 59 of the 17,233 distinct vertex shaders in my program cache use warp operations. The other part that could still cost RDNA3 something is the fragment shuffle fallback. On AMD's Windows driver it turns each fragment-shader shuffle into 32 broadcasts, and pinning the fragment stage to 32 lanes doesn't turn it off. Your run 1 had it off and the picture was normal, and the white basket it fixes has only been seen on an RDNA1 card so far. So it may only be needed where the fragment stage runs at 64 lanes. Could you test that on current main? No PR build is needed. Use the same route both times, each after a warm-up pass. The switch is in the program cache's stamp, so changing it re-translates once.
For each run, the most useful numbers are the frame times (game fps mean and 5% worst, submits of 100 ms or more) and the count of |
Fixes dark lighting and white-glowing objects (a basket in Link's house, bloom) on AMD's Windows driver. Two causes: 64-lane graphics waves that the translator treated as 32-lane, and AMD's broken fragment-stage subgroup shuffles (Lichii #273).
Part of splitting up #1023. Needs testers with RDNA2 or newer: I only have RDNA1.
Problem
requiredSubgroupSizeStages= 0x20 on the RX 5500M). Fragment and vertex stages run at 64. The translator assumed 32 lanes everywhere (warp_size_potentially_larger_than_guestfalse), so the ballots and shuffles in the game's fragment shaders ran across both halves of a 64-lane wave, giving dark lighting and glowing bloom.Change
make_profilesetswarp_size_potentially_larger_than_guest, andmax_subgroup_sizeto the device's largest, only when a graphics stage can't be pinned and the default is wider than 32. Eden's long path then keeps each 32-lane guest warp to its half. NVIDIA (32 lanes) is unchanged.profile_graphics): a graphics stage the GPU does pin to 32 lanes (pin_subgroup) keeps main's short path, so only stages that really run at 64 lanes change:0x20, compute only): vertex and fragment take the long path.0xf0, reported from an RX 7800 XT in this thread): only the vertex stage. Fragment, task and mesh keep main's translation.profile_pinned), including the mesh fallback's compute stages, because they are pinned to 32. Giving every compute program the long path changed its SPIR-V, missed the driver's cache, and AMD recompiled shaders for hours at start.has_broken_spirv_fragment_shuffle), and so doesSHFL.BFLY. The quad swap stays native: its programs have neither the lane-id input nor the Ballot capability the fallback needs, and rerouting it crashed shader preparation.RX_VK_WARP64=0|1andRX_VK_FRAG_SHUFFLE_FALLBACK=0|1override both, whatever the GPU, to help bisect reports.The depth-compare part of #273 is already on main (#834); only the test checks it here.
Risk
On RDNA1, this changes the vertex and fragment programs' translation, so those players re-translate on their first start. On RDNA2/RDNA3, only vertex programs change (plus the shuffle fallback below), because their other graphics stages are pinned to 32 lanes. An RX 6000/7000 result would still be welcome before merging. NVIDIA and Intel are unaffected by the warp part. The shuffle part is limited to
VK_DRIVER_ID_AMD_PROPRIETARY.Tests
tests/test_amd_fragment_warp.py(new) checks the profile, the per-stage choice (pinned stages keep the short path;RX_VK_WARP64still sets them all), the pinned profile's uses, the stamp, the shuffle fallback and the depth-compare rule.Tested on