WIP: perf(vk): sparse VRAM mirrors, memory only where a game pool is (RX_VK_MIRROR_SPARSE=1) #250
No reviewers
Labels
No labels
area/accessibility
area/audio
area/input
area/install
area/menu
area/renderer
area/saves
area/upscaling
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/steam-deck
platform/windows
preview
priority
critical
priority
high
priority
low
status
blocked
status
confirmed
status
duplicate
status
invalid
status
needs-info
status
wontfix
testing wanted
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Longshot!250
Loading…
Reference in a new issue
No description provided.
Delete branch "GummiNaomi/Longshot:perf/sparse-mirror"
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
On cards short of video memory, the buffer pools' VRAM mirrors hold hundreds of MB that no game pool is in: 243-533 MB of 1.1-1.6 GB at 2560x1440 DLAA. That pushes textures out and costs frame rate on 6-8 GB cards. This makes the mirrors sparse, opt-in, so memory is held only in the 64 KB blocks a game pool is in. It was NotRexed/Hookshot#2794 before the move; it may also help #130 (a GPU reset at the VRAM limit on an 8 GB RX 6600).
What changed
gpu/vk/sparse_mirror.h(new): which blocks a game pool is in, block spans, runs, and copies clipped to blocks with memory.gpu/vk/vk_vma.cpp: a sparse buffer, and its blocks' memory from VMA (counted in its budget).vmaFreeMemoryjoins the recorder's drain boundaries (gpu/vk/vk_recorder.h).gpu/vk/vk_memory.cpp:mirror_make: a sparse buffer with memory for the blocks a game pool is in. The page table points blocks with none at guest memory, as for a pool with no mirror.gpu_buffer_bind: a binding that reaches a block with no memory is served from guest memory for that submission, and the block is wanted.sparse_grow: at each submission's start, the wanted blocks and the blocks newly in a pool get memory in one batched bind, filled as a new mirror is.sparse_release: a block no pool or binding has reached for 600 submissions gives its memory back, once the GPU is past it.RX_VK_SPARSE_WAIT=1: on the CPU, as before).gpu/vk/vk_replay.cpp: submissions of recordings wait for the binds' semaphore.tests/test_sparse_mirror.py(+tests/test_sparse_mirror.cpp).test_direct_buffer_writesandtest_readback_partwere updated for the new code they slice.Flags and settings
RX_VK_MIRROR_SPARSE=1: sparse VRAM mirrors, memory only in the blocks a game pool is in (needs strict sparse residency for buffers; off otherwise, logged)RX_VK_SPARSE_WAIT=1: each sparse bind waited for on the CPU, as beforeDocumented in
docs/development.md's switch reference.Measurements
WIP: the Longshot A/B (main @
2e1e2e8cagainst this PR withRX_VK_MIRROR_SPARSE=1) is queued. The numbers below are from Hookshot: the same code, one build, the switch off and on.Baseline:
Hookshot perf/sparse-mirror @ 130ee5e6, RX_VK_MIRROR_SPARSE unsetWhy not main: measured on Hookshot before the move.
Hardware: RTX 4070 SUPER 12 GB, NVIDIA 617.42, i7-14700K, 32 GB, Windows 11 Pro 26200 (6 and 8 GB cards simulated with
RX_VK_TEST_ALLOWED_MB)Scene: Hyrule Field walk, Castle Town to the field, Kokiri Forest; 2560x1440 DLAA, unattended
Method: frame trace and VRAM log lines, three pairs per scene where stated
RX_VK_MIRROR_SPARSE=1RX_VK_TEST_ALLOWED_MB=6144,RX_VK_MIRROR_MB=1536), field walk, three pairs: fps=6900), field walk: fps / VRAM peakA real 8 GB card (klikso, on NotRexed/Hookshot#2794): RTX 3060 Ti 8 GB, 2560x1440 DLSS K. About 430 MB less in the mirrors, 120-370 MB less VRAM in Castle Town Market, and a higher texture budget. Frame rate and long frames were the same within three pairs; nothing broke.
Testing
Tested:
test_audio_volume,test_oot_fov,test_opening_skip,test_present_aspect_vulkan,test_present_thread,test_readback_wait_bounded,test_text_size,test_texture_staging_publication. They don't build with this PC's compilers.Not tested:
Needs other testers:
Screenshots
Same spot, off and on: identical. To add from the Longshot A/B.
Risk and rollback
Off by default. When on, a block that is wanted but not bound yet is served from guest memory for one submission, as a pool with no mirror always is. A driver bug in sparse binding could lose the device. Unset
RX_VK_MIRROR_SPARSEto turn it off.Reviewer notes
Start with
gpu/vk/sparse_mirror.h, thensparse_growandsparse_releaseinvk_memory.cpp.Issues
See #130
Checklist
For everyone
type(scope): description).main.python -I -B tests/run_all.pyrun and passing: the checks reading the changed files ran. 8 fail here and fail on main here too (named above). The full run is still to do.third_party/untouched (a new folder with aPROVENANCE.mdinstead).If applicable
Assisted-by:/Co-Authored-By:trailers.docs/tested-configurations.mdfor each measured run (the Hookshot runs; Longshot rows to add with the A/B).tests/that reads changed source updated in this PR, not weakened.View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.