perf(vk): the Arc B-series compiles shaders side by side by default: a new area no longer freezes the picture for minutes #500

Merged
HumanBean merged 2 commits from nyannoying/Longshot:perf/battlemage-compiles-side-by-side into main 2026-11-15 18:31:01 +00:00
Contributor

Type: perf · Risk: medium · Tested on: Windows 11, Intel Arc B580 (driver 32.0.101.9154) · Needs: an Arc B570 or a B580 on a newer driver, and any other Intel GPU on Windows (test requests T-DFNY and T-WW92, both still open)

Why

On an Intel Arc B580 the picture freezes for four to seven minutes the first time an area is entered, while its shaders are compiled one at a time. Compiled side by side, the same card does not freeze at all.

See #407 (the same contrast on an Arc iGPU in the preparation).

What changed

On the Arc B-series (Battlemage) with Intel's Windows driver 101.9154 or newer, shaders are now compiled side by side by default. The Debug tab's Intel shader compiles row gets a new default value, Auto, which means side by side on that family and one at a time on every other Intel GPU, as before. Side by side and One at a time can still be chosen by hand.

  • vk: the Debug tab's Intel shader compiles row gets a third value, Auto, its default. gpu/vk/intel_compiles.h (new) says where Auto is side by side: the Arc B-series (Battlemage, PCI device 0xE2xx) from Intel's Windows driver 101.9154, the family and driver it was run on. On every other Intel GPU Auto is one at a time, as before. intel_compiles_side_by_side() in gpu/vk/vk_menu.cpp asks it with the row, the GPU and its driver; IntelDriverGate (gpu/vk/vk_internal.h) is unchanged but for a log line that says when the compiler is entered side by side.
  • menu: Side by side keeps its value 1 and One at a time becomes 2, so a saved Side by side stays one. A saved 0, what every options file has today, now reads as Auto. RX_VK_NO_INTEL_SERIAL=1 is side by side for a run and =0 one at a time.
  • rebase onto main 2b1d38c6: conflicts next to main's new Intel quick compute builds row and weak laptop button (docs/development.md, gpu/vk/vk_menu.cpp, gpu/vk/vk_menu.h), both sides kept. One change beyond the conflicts: weak_laptop_apply() sets opts.intel_compiles = 2 (One at a time) instead of 0, because 0 now means Auto; tests/test_intel_quick_compute.py reads that line.
  • tests: tests/test_intel_compiles_auto.py (new) compiles the rule alone against 39 cases (B580 and B570 from 101.9154, an older driver, Arc A-series, Meteor Lake, Arrow Lake, Lunar Lake, Iris Xe, UHD, and the row's three values) and checks the row in the source; it fails on main. tests/test_intel_compiler_gate.py reads the gate's new question.
  • docs: the README's five passages on the row and the RX_VK_NO_INTEL_SERIAL row in docs/development.md; seven files in docs/tested/, one for each launch below.

Measurements

Verdict: it helped. On the B580, in the two launches of one build, the picture was under 5 fps for 0 s with the new default (side by side) against 181 s one at a time. Over all the areas the median time until the frame rate is steady fell from 154 s (one at a time) to 27 s (side by side). No device loss and no fault line either way.

main: 9c9d69ed (2026-11-14)
this PR: perf/battlemage-compiles-side-by-side @ dc47a621
Since then the PR was rebased onto main 2b1d38c6. The game was not run again after the rebase: every number here is from the commits named in this section. Beyond the conflicts the rebase changed one line, in the weak laptop button (weak_laptop_apply()), and these launches used the default and the environment switch.
Hardware: Intel Arc B580 12 GB (PCI device 0xE20B), driver 32.0.101.9154; Core i5-13600K (20 threads, 6 background workers); 64 GB; Windows 11 Pro (26100-series Insider, 10.0.29704)
Scene: areas entered by the debug teleport for the first time on this PC, in a game folder never prepared (RX_VK_PRECOMPILE=0), frame generation off
Method: an area can be new only once (the driver keeps what it compiled), so no area was run twice: each launch teleports to areas not visited before and stands there. New programs are the log's vk: in play: lines; "under 5 fps" is the sum of the log's vi: ... frames presented (... fps over the last ... s) windows below 5 fps; "steady after" is the time from the teleport until the control bridge's status reads 25 fps or more four times in a row. The last two launches are one build, the default against RX_VK_NO_INTEL_SERIAL=0.
How to reproduce: on a B-series card, with a game folder not prepared, enter an area for the first time with the row on One at a time and another with it on Side by side; the log's vi: lines show the freeze.

Baseline: this PR @ dc47a621, RX_VK_NO_INTEL_SERIAL=0 (One at a time, main's default). main itself was not the comparison because on the B580 it loses the device entering Kokiri Forest (#444). The build that ran is this PR's change applied to main cf605c85 with four changes not merged yet (#444, #446, #443, #459), since a main-based build has another shader stamp than this card's caches. The change touches vk_menu.cpp, vk_menu.h, vk_internal.h and the new header only, and applies to both bases unchanged.

Before, RX_VK_NO_INTEL_SERIAL=0 (One at a time, main's default): this PR @ dc47a621 After, Auto (side by side on this card): this PR @ dc47a621
Areas entered on the B580 Fire Temple, Water Temple Death Mountain Crater, Inside Jabu-Jabu's Belly, Ice Cavern
New programs 372 373
Picture under 5 fps 181 s 0 s
Steady (25 fps or more) after the teleport 73 s, 154 s 21 s, 27 s, 39 s
Device loss, fault lines 0, 0 0, 0

Before the change, with the switch on the same base (main cf605c85 with the four changes; RX_VK_NO_INTEL_SERIAL=1 is what Auto now chooses on this card):

Setting Areas New programs Under 5 fps Steady after
One at a time (main's default) Hyrule Field 398 248 s about 250 s
One at a time (main's default) Market 322 409 s about 410 s
One at a time, RX_VK_TRANSLATE_WAIT_MS=8 Graveyard 134 73 s 134 s
Side by side Kakariko Village 155 0 s 52 s
Side by side, RX_VK_TRANSLATE_WAIT_MS=8 Goron City 106 0 s 30 s
Side by side, one launch Zora's River, Zora's Domain, Death Mountain Trail, Lost Woods, Gerudo Valley, Inside the Deku Tree, Dodongo's Cavern, Desert Colossus 850 0 s 20 to 80 s each
U1 (default): [hos Presentation Thread] vk: Intel's compiler is entered side by side (Intel shader compiles row: Side by side, its Auto on the Arc B-series, or RX_VK_NO_INTEL_SERIAL=1)
U1 (default): 1197 pipelines (385937 ms), 373 programs (11 failed); translation 3177 ms in all; under 5 fps 0 s
U2 (=0):      [hos Presentation Thread] vk: Intel's compiler is entered by one thread (Intel shader compiles row, RX_VK_NO_INTEL_SERIAL: side by side)
U2 (=0):      1574 pipelines (357803 ms), 372 programs (11 failed); translation 98605 ms in all; under 5 fps 181 s
A0 (one at a time, Hyrule Field then the Market) vi windows: [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] ... [email protected] [email protected] [email protected] [email protected] [email protected] [email protected]
A0: 1358 pipelines (327777 ms), 398 programs after Hyrule Field; 1990 pipelines (1047022 ms), 720 programs after the Market; translation 158713 ms, then 541531 ms in all
F2 (side by side, Kakariko) vi windows: [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected]; 1441 pipelines (176624 ms), 155 programs; translation 1636 ms in all

Over all the areas, the median time until steady is 154 s one at a time (five areas in three launches: 250, 410, 134, 73, 154) and 27 s side by side (thirteen areas in four launches); the launches of the two settings were alternated over the afternoon, not paired area by area, for the reason under Method.

The usual figures of a perf change (average fps, 1% low, frame time) do not describe this one: what it moves is how long a first visit stops the picture, so that and the time until the frame rate is back are what is measured. The frame rate once an area's shaders exist is the same either way. Both timers in the log start before the gate, so with one thread in the compiler most of "translation" is queueing at the lock.

Flags and settings

One menu row with its options file key changes its values and its default, and one switch gets a second value.

Flag What it is Before this PR After this PR Effect Helps / doesn't help / untested Recommendation
Debug > Intel shader compiles (intel_shader_compiles= in longshot_options.ini) A menu row and its options file key: how many shaders Intel's Windows compiler is given at once 0 One at a time (the default), 1 Side by side 0 Auto (the default), 1 Side by side, 2 One at a time Auto is side by side on the Arc B-series from driver 101.9154 and one at a time elsewhere Helps: Arc B580 (no freeze at an area's first visit). Doesn't help: every other Intel GPU, unchanged. Untested: Arc B570; a B580 on other drivers; the up-front preparation on a B-series card Auto by default
RX_VK_NO_INTEL_SERIAL=0/1 A switch for a run, over the row unset; 1 side by side; 0 one at a time, the same as the default then unset; 1 side by side; 0 one at a time, which now differs from Auto on the Arc B-series 1 side by side, 0 one at a time, for a run, whatever the row says - for testing

Testing

Tested:

  • In the game, Arc B580, 101.9154, Windows 11: the seven launches above (seven files in docs/tested/; the Kokiri, Hyrule Field and Market fixes of #443, #444 and #446 in the build). Side by side in four launches through thirteen areas: 1,484 programs first compiled, no VK_ERROR_DEVICE_LOST, no "driver faulted" line, no exit; Kakariko Village, Zora's Domain and Dodongo's Cavern looked at and drawn right. With the default the log says side by side; with RX_VK_NO_INTEL_SERIAL=0 it says one thread. These runs were on the build the Baseline line names, before the rebase.
  • Game-free checks, before the rebase: python -I -B tests/run_all.py: 496 passed, 5 failed, 70 skipped; the 5 were test_fpx_sticky, test_walk_key, test_spawn_emit, test_tested_configurations and test_oot_state_tap, which failed the same way on main 9c9d69ed here.
  • Game-free checks, after the rebase onto main 2b1d38c6: python -I -B tests/run_all.py: 15 checks fail on this Windows PC and fail the same on main 2b1d38c6 alone (test_fpx_sticky, test_appimage_player_build, test_cpm_discovery, test_crash_dialog, test_env_on, test_lift_cleanup_error, test_make_game_cache, test_linux_preflight, test_oot_state_tap, test_readback_late, test_spawn_emit, test_tested_configurations, test_vk_pgo, test_vram_budget_row, test_walk_key).
  • A tester's result (ertomas, a comment on this PR), on another GPU and without this PR: Intel Arc B390 (Panther Lake iGPU, PCI device 0xB080, driver 32.0.101.9150, Core Ultra X7 358H, 32 GB), main 414f56e2, longshot.exe --prepare-shaders --compile-shaders most. Side by side (RX_VK_NO_INTEL_SERIAL=1): 24,456 pipelines in 1,476 s, none not made, no igvk64.dll fault. One at a time: 10,833 of 24,450 after 3,512 s, when it was stopped. About 30 minutes of play side by side with no driver fault. On that GPU this PR's Auto is One at a time (not 0xE2xx, and the driver is older than 101.9154), so this measures the switch there, not this PR's default.

Not tested:

  • The game after the rebase: the head as it is now was not run in the game, and neither was the head before the rebase (see Baseline).
  • The row changed in the menu itself: the runs used the default and the environment switch.
  • The up-front preparation on the B580, side by side or not.
  • A long play session side by side on the B580.
  • RX_VK_COMPUTE_SERIAL=0 (left at its default: compute pipelines stay one at a time).
  • First visits in play on the tester's B390: only the preparation and play without a fault were reported there.
  • A Linux build: there is no Linux compiler on this PC, and the gate is Windows only. The template's box "Host code builds on both Windows and Linux" is left out, not ticked.

Must be tested:

  • Windows, an Arc B570, or a B580 on another driver (101.9175 or newer): enter two or three areas for the first time with the default, expecting the log line "entered side by side", no long freeze and no crash; if it crashes in igvk64.dll, say so and which driver (by hand, test request T-DFNY, still open: look at the log line and for a freeze or a crash)
  • Windows, any other Intel GPU (Arc A-series, an iGPU): start the game with the default, expecting the log line "entered by one thread" and nothing else changed (by hand, test request T-WW92, still open: look at the log line)

Risks

What could break: only Arc B-series cards on driver 101.9154 or newer change by default: their shaders are compiled side by side. One at a time has a net that side by side has not: a shader Intel's compiler faults on is left out there, and side by side such a fault closes the game. None came in 1,484 first compiles on the B580, but that is one card and one driver.

Turning it off: set the Debug tab's Intel shader compiles row to One at a time, or start with RX_VK_NO_INTEL_SERIAL=0. Reverting the commit is enough; a saved 2 then reads as Side by side under the old row's clamp, so a revert should say so.

Compatibility: longshot_options.ini: the key intel_shader_compiles changes meaning. 0 was One at a time and is Auto now; 1 stays Side by side; 2 is One at a time. A player with an existing options file has 0 or 1. With 0 they get Auto: side by side on an Arc B-series card from driver 101.9154, one at a time on every other Intel GPU, as before. With 1 they keep Side by side. A B-series owner who had chosen One at a time on purpose must choose it again, since the old value 0 now reads as Auto. The shader and pipeline caches are kept: the diff touches none of the files the shader stamp is made of (nx2/translator_files.py: gpu/vk/eden, sirit, compat, vk_shader.cpp, vk_bank.cpp, vk_state.h). The vk ABI is unchanged: gpu/vk/vk_api.h is not touched and MKWVK_API_VERSION stays 22. Saves and the builder's tools are not touched.

Reviewer notes

  • #407 has the same contrast on an Arc iGPU in the preparation (544 against 1,746 in 240 s) and the B580 numbers above as a comment. This PR does not change that GPU: it was not run here.
  • Why Auto and not a new default of Side by side for one family: the row's saved value could not tell "never chosen" from "chosen", and every options file holds 0.
  • RX_VK_TRANSLATE_WAIT_MS=8 alone took a third off a first visit's freeze and left draws out in only six reports; it is not part of this.
  • Whether to add the tester's B390 (0xB080) to Auto is an open question on this PR. It is not part of the change now.

Issues

See #407

Checklist

Everyone

  • One topic.
  • The title is a Conventional Commit (type(scope): description) of the status line's type.
  • Why gives the reason plainly and links the issues that fit (the tracker searched).
  • Measurements has a verdict, or one line saying why there is nothing to measure.
  • Testing names what was tested, what wasn't, and what must still be tested, where and how.
  • Rebased on current main.
  • python -I -B tests/run_all.py passes (any failure that also fails on main is named): 15 checks fail on this Windows PC and fail the same on main 2b1d38c6 alone (test_fpx_sticky, test_appimage_player_build, test_cpm_discovery, test_crash_dialog, test_env_on, test_lift_cleanup_error, test_make_game_cache, test_linux_preflight, test_oot_state_tap, test_readback_late, test_spawn_emit, test_tested_configurations, test_vk_pgo, test_vram_budget_row, test_walk_key).
  • No game files, dumps, build output or generated files.
  • third_party/ untouched (a new folder with a PROVENANCE.md instead).
  • The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled.

When it applies

  • AI assistance recorded with Assisted-by: / Co-Authored-By: trailers.
  • Numbers from the same PC, scene and settings, at least 2 interleaved runs each, the median reported (the same PC and settings; the areas differ between launches because an area can be new only once, see Method).
  • Switches documented (docs/development.md; the README for a menu row) and shipped at their recommended value.
  • A file in docs/tested/ for each new measured run (format in docs/tested-configurations.md).
  • A game-free test added for the fix, failing on main and passing here.
  • A check under tests/ that reads changed source updated in this PR, not weakened.
  • Docs updated.

🤖 Generated with Claude Code

**Type:** perf · **Risk:** medium · **Tested on:** Windows 11, Intel Arc B580 (driver 32.0.101.9154) · **Needs:** an Arc B570 or a B580 on a newer driver, and any other Intel GPU on Windows (test requests T-DFNY and T-WW92, both still open) ## Why On an Intel Arc B580 the picture freezes for four to seven minutes the first time an area is entered, while its shaders are compiled one at a time. Compiled side by side, the same card does not freeze at all. See #407 (the same contrast on an Arc iGPU in the preparation). ## What changed On the Arc B-series (Battlemage) with Intel's Windows driver 101.9154 or newer, shaders are now compiled side by side by default. The Debug tab's **Intel shader compiles** row gets a new default value, **Auto**, which means side by side on that family and one at a time on every other Intel GPU, as before. Side by side and One at a time can still be chosen by hand. - vk: the Debug tab's **Intel shader compiles** row gets a third value, **Auto**, its default. `gpu/vk/intel_compiles.h` (new) says where Auto is side by side: the Arc B-series (Battlemage, PCI device 0xE2xx) from Intel's Windows driver 101.9154, the family and driver it was run on. On every other Intel GPU Auto is one at a time, as before. `intel_compiles_side_by_side()` in `gpu/vk/vk_menu.cpp` asks it with the row, the GPU and its driver; `IntelDriverGate` (`gpu/vk/vk_internal.h`) is unchanged but for a log line that says when the compiler is entered side by side. - menu: Side by side keeps its value 1 and One at a time becomes 2, so a saved Side by side stays one. A saved 0, what every options file has today, now reads as Auto. `RX_VK_NO_INTEL_SERIAL=1` is side by side for a run and `=0` one at a time. - rebase onto main 2b1d38c6: conflicts next to main's new Intel quick compute builds row and weak laptop button (`docs/development.md`, `gpu/vk/vk_menu.cpp`, `gpu/vk/vk_menu.h`), both sides kept. One change beyond the conflicts: `weak_laptop_apply()` sets `opts.intel_compiles = 2` (One at a time) instead of 0, because 0 now means Auto; `tests/test_intel_quick_compute.py` reads that line. - tests: `tests/test_intel_compiles_auto.py` (new) compiles the rule alone against 39 cases (B580 and B570 from 101.9154, an older driver, Arc A-series, Meteor Lake, Arrow Lake, Lunar Lake, Iris Xe, UHD, and the row's three values) and checks the row in the source; it fails on `main`. `tests/test_intel_compiler_gate.py` reads the gate's new question. - docs: the README's five passages on the row and the `RX_VK_NO_INTEL_SERIAL` row in `docs/development.md`; seven files in `docs/tested/`, one for each launch below. ## Measurements **Verdict:** it helped. On the B580, in the two launches of one build, the picture was under 5 fps for 0 s with the new default (side by side) against 181 s one at a time. Over all the areas the median time until the frame rate is steady fell from 154 s (one at a time) to 27 s (side by side). No device loss and no fault line either way. main: 9c9d69ed (2026-11-14) this PR: perf/battlemage-compiles-side-by-side @ dc47a621 Since then the PR was rebased onto main 2b1d38c6. The game was not run again after the rebase: every number here is from the commits named in this section. Beyond the conflicts the rebase changed one line, in the weak laptop button (`weak_laptop_apply()`), and these launches used the default and the environment switch. Hardware: Intel Arc B580 12 GB (PCI device 0xE20B), driver 32.0.101.9154; Core i5-13600K (20 threads, 6 background workers); 64 GB; Windows 11 Pro (26100-series Insider, 10.0.29704) Scene: areas entered by the debug teleport for the first time on this PC, in a game folder never prepared (`RX_VK_PRECOMPILE=0`), frame generation off Method: an area can be new only once (the driver keeps what it compiled), so no area was run twice: each launch teleports to areas not visited before and stands there. New programs are the log's `vk: in play:` lines; "under 5 fps" is the sum of the log's `vi: ... frames presented (... fps over the last ... s)` windows below 5 fps; "steady after" is the time from the teleport until the control bridge's status reads 25 fps or more four times in a row. The last two launches are one build, the default against `RX_VK_NO_INTEL_SERIAL=0`. How to reproduce: on a B-series card, with a game folder not prepared, enter an area for the first time with the row on One at a time and another with it on Side by side; the log's `vi:` lines show the freeze. Baseline: this PR @ dc47a621, `RX_VK_NO_INTEL_SERIAL=0` (One at a time, main's default). main itself was not the comparison because on the B580 it loses the device entering Kokiri Forest (https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/444). The build that ran is this PR's change applied to main cf605c85 with four changes not merged yet (#444, https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/446, https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/443, https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/459), since a main-based build has another shader stamp than this card's caches. The change touches `vk_menu.cpp`, `vk_menu.h`, `vk_internal.h` and the new header only, and applies to both bases unchanged. | | Before, `RX_VK_NO_INTEL_SERIAL=0` (One at a time, main's default): this PR @ dc47a621 | After, Auto (side by side on this card): this PR @ dc47a621 | |---|---|---| | Areas entered on the B580 | Fire Temple, Water Temple | Death Mountain Crater, Inside Jabu-Jabu's Belly, Ice Cavern | | New programs | 372 | 373 | | Picture under 5 fps | 181 s | 0 s | | Steady (25 fps or more) after the teleport | 73 s, 154 s | 21 s, 27 s, 39 s | | Device loss, fault lines | 0, 0 | 0, 0 | Before the change, with the switch on the same base (main cf605c85 with the four changes; `RX_VK_NO_INTEL_SERIAL=1` is what Auto now chooses on this card): | Setting | Areas | New programs | Under 5 fps | Steady after | |---|---|---|---|---| | One at a time (main's default) | Hyrule Field | 398 | 248 s | about 250 s | | One at a time (main's default) | Market | 322 | 409 s | about 410 s | | One at a time, `RX_VK_TRANSLATE_WAIT_MS=8` | Graveyard | 134 | 73 s | 134 s | | Side by side | Kakariko Village | 155 | 0 s | 52 s | | Side by side, `RX_VK_TRANSLATE_WAIT_MS=8` | Goron City | 106 | 0 s | 30 s | | Side by side, one launch | Zora's River, Zora's Domain, Death Mountain Trail, Lost Woods, Gerudo Valley, Inside the Deku Tree, Dodongo's Cavern, Desert Colossus | 850 | 0 s | 20 to 80 s each | ``` U1 (default): [hos Presentation Thread] vk: Intel's compiler is entered side by side (Intel shader compiles row: Side by side, its Auto on the Arc B-series, or RX_VK_NO_INTEL_SERIAL=1) U1 (default): 1197 pipelines (385937 ms), 373 programs (11 failed); translation 3177 ms in all; under 5 fps 0 s U2 (=0): [hos Presentation Thread] vk: Intel's compiler is entered by one thread (Intel shader compiles row, RX_VK_NO_INTEL_SERIAL: side by side) U2 (=0): 1574 pipelines (357803 ms), 372 programs (11 failed); translation 98605 ms in all; under 5 fps 181 s A0 (one at a time, Hyrule Field then the Market) vi windows: [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] ... [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] A0: 1358 pipelines (327777 ms), 398 programs after Hyrule Field; 1990 pipelines (1047022 ms), 720 programs after the Market; translation 158713 ms, then 541531 ms in all F2 (side by side, Kakariko) vi windows: [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected]; 1441 pipelines (176624 ms), 155 programs; translation 1636 ms in all ``` Over all the areas, the median time until steady is 154 s one at a time (five areas in three launches: 250, 410, 134, 73, 154) and 27 s side by side (thirteen areas in four launches); the launches of the two settings were alternated over the afternoon, not paired area by area, for the reason under Method. The usual figures of a `perf` change (average fps, 1% low, frame time) do not describe this one: what it moves is how long a first visit stops the picture, so that and the time until the frame rate is back are what is measured. The frame rate once an area's shaders exist is the same either way. Both timers in the log start before the gate, so with one thread in the compiler most of "translation" is queueing at the lock. ### Flags and settings One menu row with its options file key changes its values and its default, and one switch gets a second value. | Flag | What it is | Before this PR | After this PR | Effect | Helps / doesn't help / untested | Recommendation | |---|---|---|---|---|---|---| | Debug > Intel shader compiles (`intel_shader_compiles=` in `longshot_options.ini`) | A menu row and its options file key: how many shaders Intel's Windows compiler is given at once | 0 One at a time (the default), 1 Side by side | 0 Auto (the default), 1 Side by side, 2 One at a time | Auto is side by side on the Arc B-series from driver 101.9154 and one at a time elsewhere | Helps: Arc B580 (no freeze at an area's first visit). Doesn't help: every other Intel GPU, unchanged. Untested: Arc B570; a B580 on other drivers; the up-front preparation on a B-series card | Auto by default | | `RX_VK_NO_INTEL_SERIAL=0/1` | A switch for a run, over the row | unset; 1 side by side; 0 one at a time, the same as the default then | unset; 1 side by side; 0 one at a time, which now differs from Auto on the Arc B-series | 1 side by side, 0 one at a time, for a run, whatever the row says | - | for testing | ## Testing **Tested:** - In the game, Arc B580, 101.9154, Windows 11: the seven launches above (seven files in `docs/tested/`; the Kokiri, Hyrule Field and Market fixes of #443, #444 and #446 in the build). Side by side in four launches through thirteen areas: 1,484 programs first compiled, no `VK_ERROR_DEVICE_LOST`, no "driver faulted" line, no exit; Kakariko Village, Zora's Domain and Dodongo's Cavern looked at and drawn right. With the default the log says side by side; with `RX_VK_NO_INTEL_SERIAL=0` it says one thread. These runs were on the build the Baseline line names, before the rebase. - Game-free checks, before the rebase: `python -I -B tests/run_all.py`: 496 passed, 5 failed, 70 skipped; the 5 were `test_fpx_sticky`, `test_walk_key`, `test_spawn_emit`, `test_tested_configurations` and `test_oot_state_tap`, which failed the same way on main 9c9d69ed here. - Game-free checks, after the rebase onto main 2b1d38c6: `python -I -B tests/run_all.py`: 15 checks fail on this Windows PC and fail the same on main 2b1d38c6 alone (`test_fpx_sticky`, `test_appimage_player_build`, `test_cpm_discovery`, `test_crash_dialog`, `test_env_on`, `test_lift_cleanup_error`, `test_make_game_cache`, `test_linux_preflight`, `test_oot_state_tap`, `test_readback_late`, `test_spawn_emit`, `test_tested_configurations`, `test_vk_pgo`, `test_vram_budget_row`, `test_walk_key`). - A tester's result (ertomas, a comment on this PR), on another GPU and without this PR: Intel Arc B390 (Panther Lake iGPU, PCI device 0xB080, driver 32.0.101.9150, Core Ultra X7 358H, 32 GB), main 414f56e2, `longshot.exe --prepare-shaders --compile-shaders most`. Side by side (`RX_VK_NO_INTEL_SERIAL=1`): 24,456 pipelines in 1,476 s, none not made, no `igvk64.dll` fault. One at a time: 10,833 of 24,450 after 3,512 s, when it was stopped. About 30 minutes of play side by side with no driver fault. On that GPU this PR's Auto is One at a time (not 0xE2xx, and the driver is older than 101.9154), so this measures the switch there, not this PR's default. **Not tested:** - The game after the rebase: the head as it is now was not run in the game, and neither was the head before the rebase (see Baseline). - The row changed in the menu itself: the runs used the default and the environment switch. - The up-front preparation on the B580, side by side or not. - A long play session side by side on the B580. - `RX_VK_COMPUTE_SERIAL=0` (left at its default: compute pipelines stay one at a time). - First visits in play on the tester's B390: only the preparation and play without a fault were reported there. - A Linux build: there is no Linux compiler on this PC, and the gate is Windows only. The template's box "Host code builds on both Windows and Linux" is left out, not ticked. **Must be tested:** - Windows, an Arc B570, or a B580 on another driver (101.9175 or newer): enter two or three areas for the first time with the default, expecting the log line "entered side by side", no long freeze and no crash; if it crashes in `igvk64.dll`, say so and which driver (by hand, test request T-DFNY, still open: look at the log line and for a freeze or a crash) - Windows, any other Intel GPU (Arc A-series, an iGPU): start the game with the default, expecting the log line "entered by one thread" and nothing else changed (by hand, test request T-WW92, still open: look at the log line) ## Risks **What could break:** only Arc B-series cards on driver 101.9154 or newer change by default: their shaders are compiled side by side. One at a time has a net that side by side has not: a shader Intel's compiler faults on is left out there, and side by side such a fault closes the game. None came in 1,484 first compiles on the B580, but that is one card and one driver. **Turning it off:** set the Debug tab's **Intel shader compiles** row to **One at a time**, or start with `RX_VK_NO_INTEL_SERIAL=0`. Reverting the commit is enough; a saved 2 then reads as Side by side under the old row's clamp, so a revert should say so. **Compatibility:** `longshot_options.ini`: the key `intel_shader_compiles` changes meaning. 0 was One at a time and is Auto now; 1 stays Side by side; 2 is One at a time. A player with an existing options file has 0 or 1. With 0 they get Auto: side by side on an Arc B-series card from driver 101.9154, one at a time on every other Intel GPU, as before. With 1 they keep Side by side. A B-series owner who had chosen One at a time on purpose must choose it again, since the old value 0 now reads as Auto. The shader and pipeline caches are kept: the diff touches none of the files the shader stamp is made of (`nx2/translator_files.py`: `gpu/vk/eden`, `sirit`, `compat`, `vk_shader.cpp`, `vk_bank.cpp`, `vk_state.h`). The vk ABI is unchanged: `gpu/vk/vk_api.h` is not touched and `MKWVK_API_VERSION` stays 22. Saves and the builder's tools are not touched. ## Reviewer notes - https://git.magicbean.dev/MagicBeanDev/Longshot/issues/407 has the same contrast on an Arc iGPU in the preparation (544 against 1,746 in 240 s) and the B580 numbers above as a comment. This PR does not change that GPU: it was not run here. - Why Auto and not a new default of Side by side for one family: the row's saved value could not tell "never chosen" from "chosen", and every options file holds 0. - `RX_VK_TRANSLATE_WAIT_MS=8` alone took a third off a first visit's freeze and left draws out in only six reports; it is not part of this. - Whether to add the tester's B390 (0xB080) to Auto is an open question on this PR. It is not part of the change now. ## Issues See #407 ## Checklist ### Everyone - [x] One topic. - [x] The title is a Conventional Commit (`type(scope): description`) of the status line's type. - [x] Why gives the reason plainly and links the issues that fit (the tracker searched). - [x] Measurements has a verdict, or one line saying why there is nothing to measure. - [x] Testing names what was tested, what wasn't, and what must still be tested, where and how. - [x] Rebased on current `main`. - [x] `python -I -B tests/run_all.py` passes (any failure that also fails on `main` is named): 15 checks fail on this Windows PC and fail the same on main 2b1d38c6 alone (`test_fpx_sticky`, `test_appimage_player_build`, `test_cpm_discovery`, `test_crash_dialog`, `test_env_on`, `test_lift_cleanup_error`, `test_make_game_cache`, `test_linux_preflight`, `test_oot_state_tap`, `test_readback_late`, `test_spawn_emit`, `test_tested_configurations`, `test_vk_pgo`, `test_vram_budget_row`, `test_walk_key`). - [x] No game files, dumps, build output or generated files. - [x] `third_party/` untouched (a new folder with a `PROVENANCE.md` instead). - [x] The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled. ### When it applies - [x] AI assistance recorded with `Assisted-by:` / `Co-Authored-By:` trailers. - [x] Numbers from the same PC, scene and settings, at least 2 interleaved runs each, the median reported (the same PC and settings; the areas differ between launches because an area can be new only once, see Method). - [x] Switches documented (docs/development.md; the README for a menu row) and shipped at their recommended value. - [x] A file in `docs/tested/` for each new measured run (format in `docs/tested-configurations.md`). - [x] A game-free test added for the fix, failing on `main` and passing here. - [x] A check under `tests/` that reads changed source updated in this PR, not weakened. - [x] Docs updated. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
On Windows, Intel's compiler is entered by one thread (IntelDriverGate), because igvk64 faulted with two in it on an Arc
A750 and a UHD. On an Arc B580 (driver 32.0.101.9154, a Core i5-13600K, six background workers) that froze the picture at
every area's first visit: 248 s in Hyrule Field (398 programs), 409 s in the Market (322). Side by side, three launches
through ten other areas first compiled 1,111 programs with no frame under 5 fps and no fault, device loss or exit.

The Intel shader compiles row gets a third value, Auto, its default: side by side on the Arc B-series from driver
101.9154 (gpu/vk/intel_compiles.h, the family and driver it was run on), one at a time on every other Intel GPU, as
before. Side by side keeps the value 1 and One at a time is 2, so a saved Side by side stays; a saved 0, what every
options file has, is Auto. RX_VK_NO_INTEL_SERIAL=1 is side by side and =0 one at a time for a run. With this build, the
default against =0: 373 programs with no freeze against 372 with 181 s of it.

tests/test_intel_compiles_auto.py compiles the rule against 39 cases and checks the row; test_intel_compiler_gate.py
reads the gate's new question.

Co-Authored-By: Claude Fable 5.2 <[email protected]>
docs(tested): first visits one at a time and side by side on an Arc B580, seven files
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 4s
Website / Website on Cloudflare (pull_request_target) Has been skipped
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
Website / Website on Cloudflare (pull_request) Has been cancelled
9a3fee81f7
Co-Authored-By: Claude Fable 5.2 <[email protected]>
Author
Contributor

The two test requests are open (T-DFNY: an Arc B570, or a B580 on a newer driver; T-WW92: any other Intel GPU on Windows, expecting no change) and named in the description; they wait for a maintainer's testing wanted label.

The two test requests are open (T-DFNY: an Arc B570, or a B580 on a newer driver; T-WW92: any other Intel GPU on Windows, expecting no change) and named in the description; they wait for a maintainer's testing wanted label.
nyannoying changed title from WIP: perf(vk): the Arc B-series compiles shaders side by side by default: a new area no longer freezes the picture for minutes to perf(vk): the Arc B-series compiles shaders side by side by default: a new area no longer freezes the picture for minutes 2026-11-14 16:53:16 +00:00
First-time contributor

Arc B390 (Panther Lake iGPU): one at a time makes the shader preparation about 2.8x slower, and side by side ran with no driver fault. Worth adding to Auto.

On this laptop intel_compiles.h's rule gives One at a time: the device is 0xB080, not 0xE2xx, and the driver is 101.9150, older than 101.9154. I prepared the same build's shaders both ways.

Hardware: Intel Arc B390 (Panther Lake iGPU, PCI VEN_8086&DEV_B080, no VRAM mirror), driver 32.0.101.9150, Core Ultra X7 358H (16 threads), 32 GB, Windows 11 Pro Insider Preview build 26220.
Build: main 414f56e2 (v3.0.0-rc.3-82-g414f56e2, with #252), a scripts/dev_packs.py base. This PR isn't in it: on this GPU Auto would give One at a time, the same as main's default.
Command: longshot.exe --prepare-shaders --compile-shaders most in the base's game folder, once with the default (One at a time) and once with RX_VK_NO_INTEL_SERIAL=1 (Side by side).

Noted pipelines (of 24450) after One at a time (default) Side by side (RX_VK_NO_INTEL_SERIAL=1)
60 s 1925 5779
300 s 3466 10237
600 s 4956 13970
900 s 5818 16218
3512 s 10833 (stopped here) done
Whole preparation not finished after 58 min; ~1.4 pipelines/s at the end, so about 2.7 h more at that rate 24456 pipelines in 1476 s (25 min), 0 not made
CPU while compiling ~1.3 cores busy ~14 cores busy
Shader programs (before the pipelines) 38809 in 77.0 s 38809 in 77.0 s, the same
igvk64.dll faults, device loss, longshot_driver_faults.txt none none
  • About 2.8x slower over the first 15 minutes, and getting worse: One at a time slowed from ~6.5 pipelines/s to ~1.4/s in its last 15 minutes.
  • Not a cache effect. The side-by-side run went second, so the driver's cache already held the 10833 pipelines the first run built. A side-by-side preparation of an earlier main (f647a072, before #252, so the cache was nearly cold) tracked it closely: 5146, 9782, 13193 and 15727 pipelines at 60, 300, 600 and 900 s. That run stopped at 16002 when the laptop went into Modern Standby (System log, Kernel-Power 506/507, although the log blamed the driver), and a second side-by-side run finished the rest with no fault.
  • Play, side by side: about 30 minutes over four runs of the f647a072 and fbd42024 builds (#189's A/B) had no fault in igvk64.dll. The two hangs on main there were GPU hangs at a compute dispatch, the split-submission problem #189 fixed.

Suggestion: Auto side by side on Panther Lake too: 0xB080, its sibling IDs if Intel's list has them, from driver 101.9150. On this laptop One at a time doesn't buy safety: Side by side ran without a single fault. And it costs a lot: a preparation of about 3.5 hours instead of 25 minutes.

Not tested yet: the freeze in play that this PR measures on the B580, i.e. new areas entered for the first time in an unprepared folder with each mode. Glad to run it if that's needed to widen the rule.

Logs on request: the three preparations' longshot_log.txt.

**Arc B390 (Panther Lake iGPU): one at a time makes the shader preparation about 2.8x slower, and side by side ran with no driver fault. Worth adding to Auto.** On this laptop `intel_compiles.h`'s rule gives One at a time: the device is `0xB080`, not `0xE2xx`, and the driver is 101.9150, older than 101.9154. I prepared the same build's shaders both ways. Hardware: Intel Arc B390 (Panther Lake iGPU, PCI `VEN_8086&DEV_B080`, no VRAM mirror), driver 32.0.101.9150, Core Ultra X7 358H (16 threads), 32 GB, Windows 11 Pro Insider Preview build 26220. Build: main 414f56e2 (`v3.0.0-rc.3-82-g414f56e2`, with #252), a `scripts/dev_packs.py` base. This PR isn't in it: on this GPU Auto would give One at a time, the same as main's default. Command: `longshot.exe --prepare-shaders --compile-shaders most` in the base's game folder, once with the default (One at a time) and once with `RX_VK_NO_INTEL_SERIAL=1` (Side by side). | Noted pipelines (of 24450) after | One at a time (default) | Side by side (`RX_VK_NO_INTEL_SERIAL=1`) | |---|---|---| | 60 s | 1925 | 5779 | | 300 s | 3466 | 10237 | | 600 s | 4956 | 13970 | | 900 s | 5818 | 16218 | | 3512 s | 10833 (stopped here) | done | | **Whole preparation** | **not finished after 58 min**; ~1.4 pipelines/s at the end, so about 2.7 h more at that rate | **24456 pipelines in 1476 s (25 min)**, 0 not made | | CPU while compiling | ~1.3 cores busy | ~14 cores busy | | Shader programs (before the pipelines) | 38809 in 77.0 s | 38809 in 77.0 s, the same | | `igvk64.dll` faults, device loss, `longshot_driver_faults.txt` | none | none | - **About 2.8x slower over the first 15 minutes**, and getting worse: One at a time slowed from ~6.5 pipelines/s to ~1.4/s in its last 15 minutes. - **Not a cache effect.** The side-by-side run went second, so the driver's cache already held the 10833 pipelines the first run built. A side-by-side preparation of an earlier main (f647a072, before #252, so the cache was nearly cold) tracked it closely: 5146, 9782, 13193 and 15727 pipelines at 60, 300, 600 and 900 s. That run stopped at 16002 when the laptop went into Modern Standby (System log, Kernel-Power 506/507, although the log blamed the driver), and a second side-by-side run finished the rest with no fault. - **Play, side by side:** about 30 minutes over four runs of the f647a072 and fbd42024 builds (#189's A/B) had no fault in `igvk64.dll`. The two hangs on main there were GPU hangs at a compute dispatch, the split-submission problem #189 fixed. **Suggestion:** Auto side by side on Panther Lake too: `0xB080`, its sibling IDs if Intel's list has them, from driver 101.9150. On this laptop One at a time doesn't buy safety: Side by side ran without a single fault. And it costs a lot: a preparation of about 3.5 hours instead of 25 minutes. **Not tested yet:** the freeze in play that this PR measures on the B580, i.e. new areas entered for the first time in an unprepared folder with each mode. Glad to run it if that's needed to widen the rule. Logs on request: the three preparations' `longshot_log.txt`.
nyannoying force-pushed perf/battlemage-compiles-side-by-side from 9a3fee81f7
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 4s
Website / Website on Cloudflare (pull_request_target) Has been skipped
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
Website / Website on Cloudflare (pull_request) Has been cancelled
to 19bdc53b96
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 14s
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
Website / Website on Cloudflare (pull_request) Has been cancelled
2026-11-14 23:36:03 +00:00
Compare
Author
Contributor

Rebased onto main 2b1d38c6 (head 19bdc53b); it conflicted with the Intel quick compute builds row and the weak laptop button.

  • Conflicts: docs/development.md, gpu/vk/vk_menu.cpp and gpu/vk/vk_menu.h, each next to the new intel_quick lines. Both sides kept.
  • One change beyond the conflicts: weak_laptop_apply() set opts.intel_compiles = 0, which meant one at a time on main and means Auto here. It sets 2 (One at a time) now, so the button still does what its help says on every GPU; tests/test_intel_quick_compute.py reads that line.
  • Checked after the rebase: the Windows build of the renderer (llvm-mingw, 0 failed) and tests/run_all.py: 494 passed, 15 failed, 70 skipped. The same 15 fail on main 2b1d38c6 alone on this PC (run one by one there: test_env_on, test_vk_pgo, test_vram_budget_row, test_tested_configurations, test_make_game_cache, test_linux_preflight and nine more), none of them reads a file this PR changes except through main's own lines.
  • Not run again: the game. The Measurements are from the commits named there (main cf605c85 with the open Arc fixes); the gate and the row's reading are the same lines after the rebase.

@ertomas thank you, that is a clear result: 24,456 pipelines in 25 minutes side by side against under half of them in 58 minutes one at a time, and no fault. The rule here is "side by side where it was run", and your B390 (0xB080, 101.9150) now has a preparation and 30 minutes of play behind it. I would add it to Auto on that evidence. Two things first, so the rule says exactly what was run:

  1. If you can, one first visit in play each way on an unprepared folder (any area: the seconds the picture stands still, from the log's vi: lines, and whether longshot_driver_faults.txt appears). The description's Tested section has the steps.
  2. Which device IDs to name: only 0xB080, or do you know the B390's siblings from Intel's list? I can only test the B580 here, so I would name just the ID that was run.

Without the play run I would still add 0xB080 from 101.9150 with your comment as its source, if a maintainer prefers that in this PR instead of a follow-up.

Rebased onto main 2b1d38c6 (head 19bdc53b); it conflicted with the Intel quick compute builds row and the weak laptop button. - **Conflicts:** `docs/development.md`, `gpu/vk/vk_menu.cpp` and `gpu/vk/vk_menu.h`, each next to the new `intel_quick` lines. Both sides kept. - **One change beyond the conflicts:** `weak_laptop_apply()` set `opts.intel_compiles = 0`, which meant one at a time on main and means Auto here. It sets 2 (One at a time) now, so the button still does what its help says on every GPU; `tests/test_intel_quick_compute.py` reads that line. - **Checked after the rebase:** the Windows build of the renderer (llvm-mingw, 0 failed) and `tests/run_all.py`: 494 passed, 15 failed, 70 skipped. The same 15 fail on main 2b1d38c6 alone on this PC (run one by one there: `test_env_on`, `test_vk_pgo`, `test_vram_budget_row`, `test_tested_configurations`, `test_make_game_cache`, `test_linux_preflight` and nine more), none of them reads a file this PR changes except through main's own lines. - **Not run again:** the game. The Measurements are from the commits named there (main cf605c85 with the open Arc fixes); the gate and the row's reading are the same lines after the rebase. @ertomas thank you, that is a clear result: 24,456 pipelines in 25 minutes side by side against under half of them in 58 minutes one at a time, and no fault. The rule here is "side by side where it was run", and your B390 (`0xB080`, 101.9150) now has a preparation and 30 minutes of play behind it. I would add it to Auto on that evidence. Two things first, so the rule says exactly what was run: 1. If you can, one first visit in play each way on an unprepared folder (any area: the seconds the picture stands still, from the log's `vi:` lines, and whether `longshot_driver_faults.txt` appears). The description's Tested section has the steps. 2. Which device IDs to name: only `0xB080`, or do you know the B390's siblings from Intel's list? I can only test the B580 here, so I would name just the ID that was run. Without the play run I would still add `0xB080` from 101.9150 with your comment as its source, if a maintainer prefers that in this PR instead of a follow-up.
HumanBean force-pushed perf/battlemage-compiles-side-by-side from 19bdc53b96
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 14s
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
Website / Website on Cloudflare (pull_request) Has been cancelled
to a1682c6e02
Some checks failed
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been skipped
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been skipped
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been skipped
Third-party parts / The same as upstream (pull_request) Has been skipped
Website / Website on Cloudflare (pull_request) Has been skipped
PR description / Description follows the template (pull_request_target) Successful in 6s
CI / Conventional Commit title (pull_request) Successful in 5s
CI / Workflow lint (actionlint) (pull_request) Successful in 8s
Guide screenshots / Guide images and local UI source review (pull_request) Failing after 6s
Third-party parts / As their notes say (pull_request) Successful in 8s
2026-11-15 18:04:29 +00:00
Compare
Owner

Rebased onto main ced37d40 (head a1682c6e). The only conflict was in gpu/vk/vk_menu.cpp's weak_laptop_apply(): main changed the comment on opts.preset = 0; ("Minimum's memory budgets kept" became "Minimum's mip trimming kept"). I kept this PR's opts.intel_compiles = 2, ... line and main's comment. Nothing else changed. No tests were run here. The test and run boxes are still yours to settle.

Rebased onto main ced37d40 (head a1682c6e). The only conflict was in `gpu/vk/vk_menu.cpp`'s `weak_laptop_apply()`: main changed the comment on `opts.preset = 0;` ("Minimum's memory budgets kept" became "Minimum's mip trimming kept"). I kept this PR's `opts.intel_compiles = 2, ...` line and main's comment. Nothing else changed. No tests were run here. The test and run boxes are still yours to settle.
HumanBean left a comment

The code is right, and the default is picked from the hardware. I'm leaving a comment review rather than approving: the side-by-side default has one cost the description doesn't give, which is memory. Code review only: no tests were run here.

Rebase: the PR conflicted with main, so I rebased it onto main ced37d40 and pushed it (head a1682c6e, see the comment above). The conflict was one comment in weak_laptop_apply(). I kept your opts.intel_compiles = 2 line and main's new comment on opts.preset = 0;.

Detection: exact, and no other GPU changes.

  • intel_side_by_side_measured() is (device & 0xFF00) == 0xE200, with driver >= 101 << 14 | 9154. That is Intel's Windows encoding of 32.0.101.9154.
  • As far as I know, every Battlemage PCI ID is in 0xE2xx and no other Intel GPU is. That includes the Arc Pro B50/B60, so those get Auto too, untested; worth one word in the Flags row.
  • The rule itself doesn't check the vendor. Its only caller, intel_gate_on(), checks 0x8086 and is _WIN32 only, so AMD, NVIDIA and Linux can't reach it.
  • The Arc A-series (0x56xx), Meteor Lake and Arrow Lake (0x7Dxx), Lunar Lake, Panther Lake (ertomas's 0xB080) and the older iGPUs all keep one at a time.
  • env_override(..., env_value_off(e) ? 2 : 1), the 0..2 row range, the hints table and the weak-laptop button's 2 all read right.
  • The options file reads as described: a saved 0 becomes Auto, 1 stays Side by side.

Memory: what's missing. Compiling side by side costs host RAM in the driver's compiler, not VRAM. The card's 10 GB (B570) or 12 GB (B580) doesn't come into it: the pipelines it receives are small. RAM is what grows.

  • With one at a time, one thread at a time is inside igvk64. With Auto on a B-series, every background compile worker can be in it at once. That was six workers on your i5-13600K, and the count follows the CPU (half_cpus), not the RAM.
  • The only per-worker figure in the tree is in gpu/vk/prepare_workers.h: 0.4 to 0.5 GB more at the peak for each worker in AMD's compiler. That is why the preparation adds workers only as free memory allows.
  • On that figure, six workers side by side could mean about 2 to 3 GB more peak private memory during a first visit. That is nothing on your 64 GB PC, but it matters on a 16 GB PC with a B570, which is a common build for that card.
  • The log already has what's needed. Please add the peak of the vk: memory: working set ... (peak ...), private ... MB lines from U1 (Auto) and U2 (=0) to the Measurements.
  • If the difference is large, Auto could also require enough free RAM, the way prepare_workers::count does. If it's small, one line in Risks saying so settles it.

Other points, none blocking:

  • ertomas's B390 (0xB080) result belongs in a follow-up, as you propose. The rule should name only what has been run in play.
  • Reverting: a saved 2 would read as Side by side under the old clamp. The Risks section says so already. Keep that in the release notes if this ever goes back.

Before merge: a run in the game is still needed, by hand.

  • T-DFNY: a B570, or a B580 on a newer driver. Enter areas for the first time, check the "entered side by side" line, and look for no igvk64.dll crash.
  • T-WW92: another Intel GPU, which should show the "entered by one thread" line.

Both are open. Neither the rebased head nor the pre-rebase head was run in the game. The measured build was this change on cf605c85, as the Baseline says.

The code is right, and the default is picked from the hardware. I'm leaving a comment review rather than approving: the side-by-side default has one cost the description doesn't give, which is memory. Code review only: no tests were run here. **Rebase:** the PR conflicted with main, so I rebased it onto main ced37d40 and pushed it (head a1682c6e, see the comment above). The conflict was one comment in `weak_laptop_apply()`. I kept your `opts.intel_compiles = 2` line and main's new comment on `opts.preset = 0;`. **Detection: exact, and no other GPU changes.** - `intel_side_by_side_measured()` is `(device & 0xFF00) == 0xE200`, with driver `>= 101 << 14 | 9154`. That is Intel's Windows encoding of 32.0.101.9154. - As far as I know, every Battlemage PCI ID is in 0xE2xx and no other Intel GPU is. That includes the Arc Pro B50/B60, so those get Auto too, untested; worth one word in the Flags row. - The rule itself doesn't check the vendor. Its only caller, `intel_gate_on()`, checks `0x8086` and is `_WIN32` only, so AMD, NVIDIA and Linux can't reach it. - The Arc A-series (0x56xx), Meteor Lake and Arrow Lake (0x7Dxx), Lunar Lake, Panther Lake (ertomas's 0xB080) and the older iGPUs all keep one at a time. - `env_override(..., env_value_off(e) ? 2 : 1)`, the 0..2 row range, the hints table and the weak-laptop button's `2` all read right. - The options file reads as described: a saved 0 becomes Auto, 1 stays Side by side. **Memory: what's missing.** Compiling side by side costs host RAM in the driver's compiler, not VRAM. The card's 10 GB (B570) or 12 GB (B580) doesn't come into it: the pipelines it receives are small. RAM is what grows. - With one at a time, one thread at a time is inside `igvk64`. With Auto on a B-series, every background compile worker can be in it at once. That was six workers on your i5-13600K, and the count follows the CPU (`half_cpus`), not the RAM. - The only per-worker figure in the tree is in `gpu/vk/prepare_workers.h`: 0.4 to 0.5 GB more at the peak for each worker in AMD's compiler. That is why the preparation adds workers only as free memory allows. - On that figure, six workers side by side could mean about 2 to 3 GB more peak private memory during a first visit. That is nothing on your 64 GB PC, but it matters on a 16 GB PC with a B570, which is a common build for that card. - The log already has what's needed. Please add the peak of the `vk: memory: working set ... (peak ...), private ... MB` lines from U1 (Auto) and U2 (`=0`) to the Measurements. - If the difference is large, Auto could also require enough free RAM, the way `prepare_workers::count` does. If it's small, one line in Risks saying so settles it. **Other points, none blocking:** - ertomas's B390 (0xB080) result belongs in a follow-up, as you propose. The rule should name only what has been run in play. - Reverting: a saved 2 would read as Side by side under the old clamp. The Risks section says so already. Keep that in the release notes if this ever goes back. **Before merge:** a run in the game is still needed, by hand. - T-DFNY: a B570, or a B580 on a newer driver. Enter areas for the first time, check the "entered side by side" line, and look for no `igvk64.dll` crash. - T-WW92: another Intel GPU, which should show the "entered by one thread" line. Both are open. Neither the rebased head nor the pre-rebase head was run in the game. The measured build was this change on cf605c85, as the Baseline says.
@ -0,0 +14,4 @@
/// Whether the row's Auto means side by side on this Intel GPU and Windows driver (deviceID, driverVersion as Vulkan
/// reports them: Intel's Windows driverVersion is major << 14 | minor, 101 << 14 | 9154 for 32.0.101.9154)
inline bool intel_side_by_side_measured(uint32_t device, uint32_t version) {
return (device & 0xFF00u) == 0xE200u && version >= (101u << 14 | 9154u);
Owner

This matches every Battlemage ID I know of, the Arc Pro B50/B60 workstation cards (0xE211/0xE212) included, and no other Intel GPU. The rule has no vendor check of its own: it is safe only because intel_gate_on(), its one caller, checks 0x8086. That's fine as it is, but a // (Intel only: the caller checks the vendor) here would keep a later caller from asking it about an AMD or NVIDIA ID that happens to be in 0xE2xx.

This matches every Battlemage ID I know of, the Arc Pro B50/B60 workstation cards (0xE211/0xE212) included, and no other Intel GPU. The rule has no vendor check of its own: it is safe only because `intel_gate_on()`, its one caller, checks `0x8086`. That's fine as it is, but a `// (Intel only: the caller checks the vendor)` here would keep a later caller from asking it about an AMD or NVIDIA ID that happens to be in 0xE2xx.
HumanBean deleted branch perf/battlemage-compiles-side-by-side 2026-11-15 18:31:01 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
3 participants
Notifications
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/Longshot!500
No description provided.