WIP: fix(shader): narrow global stores find their word's page and declare 8/16-bit storage #520
No reviewers
Labels
No labels
area/accessibility
area/audio
area/input
area/install
area/menu
area/renderer
area/saves
area/upscaling
beanstalk: approved @ 1697603
beanstalk: approved @ 2c5a62e
beanstalk: approved @ 4fd82b7
beanstalk: approved @ 64d6d09
beanstalk: approved @ 6f91fae
beanstalk: approved @ 70a78f9
beanstalk: approved @ 8d361dc
beanstalk: approved @ 9d8356e
beanstalk: approved @ abf2227
beanstalk: approved @ d82f202
beanstalk: approved @ e5f1e40
beanstalk: approved @ ee8ab5f
ci: approved
good first issue
gpu/amd
gpu/igpu
gpu/intel
gpu/nvidia
help wanted
kind
bug
kind
chore
kind
docs
kind
feature
kind
performance
kind
question
needs measurements
platform/linux
platform/macos
platform/steam-deck
platform/windows
preview
priority
critical
priority
high
priority
low
regression
status
blocked
status
confirmed
status
duplicate
status
invalid
status
needs-info
status
wontfix
testing wanted
ci: approved
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Longshot!520
Loading…
Reference in a new issue
No description provided.
Delete branch "Amateurwizrd/Longshot:fix/narrow-store-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?
Why
A shader's 8- or 16-bit store to the game's memory could land in the wrong 32-bit word, or be dropped in a page's last
three bytes, and every module that made 8- or 16-bit views of a storage buffer was invalid SPIR-V that drivers happened
to accept: a stricter driver or the validator could reject those shaders.
What changed
EmitContext::DefineGlobalMemoryFunctions(
gpu/vk/eden/shader_recompiler/backend/spirv/spirv_emit_context.cpp) looks up the aligned word's address in the pagetable (
addr & ~3); the bit offset in the word still comes from the byte's own address.DefineStorageBuffersdeclaresStorageBuffer8BitAccesswithSPV_KHR_8bit_storage, andStorageBuffer16BitAccesswithSPV_KHR_16bit_storage, where it makes the u8/s8 and u16/s16 views(
DeclareNarrowStorage, new).tests/test_narrow_global_store.pyandtests/narrow_global_store_ir.cpp(new) run the real emitter onhand-built modules and read the SPIR-V: the loop's lookup takes
addr & ~3; an 8-bit and a 16-bit storage view eachdeclare their capability and extension and nothing of the other size; narrow global stores alone declare nothing.
Flags and settings
None.
Measurements
main:
9c9d69ed(2026-11-14)this PR: fix/narrow-store-spirv @
9ab36d7bHardware: RTX 5070 Ti 16 GB, driver 621.01, Ryzen 7 7800X3D, 32 GB, Windows 11 Pro 26200
Scene: none (game-free check)
Method: the new test, run 2 times on each side, interleaved (main, this PR, main, this PR); main gets this PR's test files only
How to reproduce:
python -I -B tests/run_all.py narrow_global_storeon this branch, and on main withtests/test_narrow_global_store.pyandtests/narrow_global_store_ir.cppcopied in9c9d69ed9ab36d7bTesting
Tested:
python -I -B tests/run_all.pyon Windows 11 (llvm-mingw): main @9c9d69ed531 passed, 5 failed; this PR531 passed and the same 5 failing on main (
test_oot_state_tap,test_portable_builder_home,test_portable_builder_startup,test_tested_configurations,test_walk_key), plustest_gpu_hang_watch, whichfails and passes on reruns of main @
9c9d69editself (a 4 s timing bound) and passed alone on this branch. The rendererbuilds. In the game, an earlier build carrying this fix together with other changes not in this PR prepared every
program on the RTX 5070 Ti and ran Kokiri Forest and a Hyrule Field walk with no device loss; that run is not a
measurement of this PR.
Not tested:
spirv-valover the game's own programs, AMD and Intel drivers, a Linux build (no Linux machine here).Needs other testers:
Screenshots
Nothing on screen
Risk and rollback
The translation changes for every program, so each player's shaders are prepared once more after the update. A driver
that lacks 8- or 16-bit storage is unaffected: the views, and so the declarations, are made only where the profile
reports both. Reverting the commit restores the old translation.
Reviewer notes
Found while reading Hookshot-old's 358e7c3f, whose direct narrow store took the capabilities as given; only the two
fixes are here (no direct store), written for Longshot.
Issues
None
Checklist
For everyone
type(scope): description).main.python -I -B tests/run_all.pyrun and passing (any failure that also fails onmainis named above).third_party/untouched (a new folder with aPROVENANCE.mdinstead).If applicable
Assisted-by:/Co-Authored-By:trailers.mainand passing here.View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.