perf(vk): copy captured pages with non-temporal stores #1619
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!1619
Loading…
Reference in a new issue
No description provided.
Delete branch "perf/capture-nt-copy"
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?
The game thread copies the pages the CPU wrote into a capture buffer at every submit (~29 MB a frame in Kokiri Forest), and a plain copy of that size costs more than it needs: it reads every line of the buffer before overwriting it, then leaves the copy in the caches, where nothing reads it again.
What changed
gpu/vk/vk_memory.cpp, the capture's guarded copy:copy_ntcopies whole 64-byte lines of the destination with streaming stores (_mm256_stream_si256with AVX2,_mm_stream_si128without), prefetching the source a few lines ahead. The head up to the destination's next line and the tail are plain copies.sfence;copy_partnow also fences after its page-by-page retry, whose copies can leave at a fault before reaching their own.guarded_copy's handler as before (copy_ntis a call inside the__try, not inlined).RX_VK_CAPTURE_NT=0:memcpy, as before. Other CPUs:memcpy.tests/test_capture_copy_nt.pycompilescopy_ntout of the source with SSE2 and with AVX2 and checks it againstmemcpyfor sizes 0-9000 at every alignment of source and destination, with guard bytes around the destination. It also checks that the guarded copy uses it and thatcopy_partfences after its retry.Testing
Ryzen 7 5800X3D, RTX 4080 SUPER (driver 616.92), Windows 11, 4K output, DLSS, Auto resolution. Kokiri Forest, 16 camera swings from the spawn, 130 s runs (the summary is of the camera part). The same
hookshot_vk.dllwith the copy off and on, alternating, two runs each:RX_VK_CAPTURE_NT=0The capture column is the "vk: capture: a submit" log line. No flash lines in the runs' logs.
python -I -B tests/run_all.pyon Windows: everything passes butnx2/test_nup_paths.py, which needs the right to make symbolic links on this PC (WinError 1314) and does not touch this code.Notes
copy_pagesandtake_capture's texture shadow pass around this code; the two should merge without trouble. One interaction to keep in mind: the shadow pass reads the texture storage's pages back from the capture buffer, which after a streaming copy come from memory rather than the cache. Kokiri Forest copies no texture storage pages ("0 texture pages copied" in the take's log line), so the runs above do not measure that; a scene that writes texture storage every frame would be the one to check.Looks good. I read copy_nt through: head/line/tail split is right (stream stores only on whole destination-aligned lines, the unaligned source uses loadu), the sfence before the tail is fine, and it stays a real call inside the __try so a source fault still goes through the handler. The extra fence after the page-by-page retry covers the case where a copy leaves at a fault before reaching its own sfence. The test is registered in run_all.py and CI is green.
Nits, none blocking:
#include <immintrin.h>under the x86-64 guard would keep it from breaking if those headers change.getenv(...)is called twice in capture_nt(); a single local would read a bit cleaner. Also for getenv/atoi is not included explicitly.