Repository navigation
perf(agc): refresh only the layers a use of an array color target covers - #6202
MiguelAdolfsen wants to merge 1 commit into
Conversation
A color view of one slice of a 2D array target refreshed the whole array image before each draw, sampled lookup and present. When the array's unused slices lie over other live targets (ps5-opengl declares every target as a two-slice array and allocates the next one over its second slice), each refresh stored the other targets' pending results, wrote back its own and uploaded the whole image from guest memory again, on every pass. StorageTexture::RefreshLayers refreshes the tracked layers that hold the given array layers alone: it flushes and compares their memory only, and results of other images pending over the other layers stay pending. A layer outside the range whose memory changed or that holds another image's pending results is left behind; GenerationFor reports it as never current, so a use over it takes the whole Refresh. It falls back to Refresh for volumes, single-layer and DCC images, an alias, or results of the image pending outside the range. A draw into an array slice, a 2D view of one layer of an array image and a present of one layer use it. The compare memo of untracked memory is kept per range, so a layer refresh's compare is memoized like the whole image's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3a39b6c to
60229fa
Compare
|
Tested on Linux x86-64 (Release build, lavapipe / llvmpipe LLVM 20.1.2), with 60229fa merged into main 44df216:
AI-assisted: yes (Claude Code) |
|
An AMD run, for the iGPU side: about 1.5x on PS5 OpenGL Showcase on a Radeon 860M, no new failure. Setup: Windows 11 Home 26300, AMD Radeon 860M (RDNA 3.5,
The title's own overlay agrees: 262–273 ms per frame on
Not tested: Linux, NVIDIA, other ps5-opengl titles. AI-assisted: yes (Claude Code) |
|
A Linux/NVIDIA run, which the description hasn't covered: Ubuntu 24.04, RTX 4070 Ti (NVIDIA 595.99.02), GCC 13.3, Release. Head 60229fa merged onto Both builds also have #6814. Without it these apps segfault 0 s in on a warm cache on that
So on Linux the Showcase goes from about 9.4 to 20 FPS. PS5MC is at vsync either way, but it stops moving about 20 GiB per 10 s. OpenNOW (PPSA99082) runs to the limit with both builds, but its log goes to its own console, so there is no summary for it. Not checked: whether the frames match (no frame dumps in these runs), AMD/Intel on Linux. AI-assisted: yes |
|
Cross-validation on Windows 11 Pro 26220, NVIDIA GeForce RTX 4070 (driver 596.21), WinLibs MinGW-w64 GCC 15.2 r7, Release. Head
Titles, 60 s each, no input, order PR / main / PR / main,
None of the eight runs printed a stop line (all were still running at 60 s). The Most of this is CPU-side. Frame dumps (12 per run, every 30 presents): no black frame. The Showcase's mean brightness is 78-116 with this PR and 83-121 on main. It is animated, so I can't compare pixels between runs. PS5MC: every dump has mean 31.5. Between this PR and main 0.02-0.03 % of pixels differ, which is less than between two main runs (0.05 %). Not checked: AMD or Intel, Linux, OpenNOW, a count of refreshed layers (this PR doesn't log one), an idle host. Written with Claude Code assistance (validation by a subagent, reviewed in this session). |
|
Linux data for this head (60229fa), from OliSe Player (PPSA01153). It's a single-preset copy with Rovastar's Dark Ritual, the preset whose two-slice 1920x1080 targets screamm measured on Windows in #6530. Square once, 120 s,
Per present, the linear-target write-backs stay at 2 (88/44.5 before, 115/57.5 after). On Linux, the CPU round trip of the whole two-slice image goes away entirely, and the visualiser runs about 29% faster. On Windows, screamm saw this PR remove the refresh write-backs, but the AI-assisted: yes (Claude Code) |
|
A data point from Windows, on a different machine and GPU. PS5 OpenGL Showcase (PPSA99005), RTX 4060 Laptop, driver 591.86,
The title's own counter goes from about 5.0 fps to 9.7. Together with #6486 it is 46 ms and about 19.5 fps; that table is in #6486. |
What
Fixes #6189.
ps5-opengl declares every color target as a 2D array of two slices and allocates the next target over the second one. A color view of slice 0, a 2D texture of it and a present of it each refreshed the whole array image (
StorageTexture::Refresh), so every pass:StorageTexture::RefreshLayers(first, count)refreshes only the tracked layers that hold the given array layers. It flushes and compares their memory alone, and results of other images pending over the other layers stay pending. A layer outside the range whose memory changed, or that holds another image's pending results, is left behind:StorageTexture::GenerationFor(address, bytes)reports a range over it as never current, so a later use over it takes the wholeRefresh. The sampled-texture caches and the present checkGenerationForof the range they read instead ofGeneration(). It falls back toRefreshfor volumes, single-layer and DCC images, an alias, or results of the image itself pending outside the range.It is used by:
DrawWithRecipe, and the resident lookup through the newCachedStorageLayers);refreshForViewinShaderResources.cpp);VulkanDevice::PresentDisplayBuffer).The compare memo of untracked memory (
compareUntracked, #4878) now keeps four entries keyed by range, so a layer refresh's compare is memoized like the whole image's.No switch. No change for single-layer targets.
Tested
Windows 11 Home 26200, NVIDIA GeForce RTX 4070 (driver 595.79), WinLibs GCC 15.2.0 r7, Release,
BUILD_TESTING=ON,ANYPS5_ENABLE_SPIRV_TOOLS=OFF. Tests, homebrew runs and frame dumps at60229fae6onmain92e50418f.agc_driver_array_layer_targetgainsOverlappingArrays: two two-slice arrays, the second starting at the first one's slice 1, with the second one's draw pending. A draw into slice 0 of the first array and a 2D texture sampled from that slice leave the second one's results pending; reading slice 1 of the first array then sees them, and every slice holds the right color.mainthe draw check fails.refreshForViewrefreshing the whole image, the 2D-texture check fails.60229fae6merged intomain44df21632: it passes, and onmainthe draw check fails (run by @coltken95).ctest -R agc_driver: 452 of 452 pass;agc_driver_sparse_dma_buf_importandagc_driver_stencil_ref_exportare skipped, as onmain.tools/check_conventions.py --base origin/main: passes.Three ps5-opengl homebrews, standing on their first screen without input:
Each run is the performance-report capture: a 30 s warm-up run without switches, then a run with
APS5_TRACE_SECONDS=15:10only. One build tree, built atmainand at this PR in turn, in the order PR,main, PR,main. Unrelated single-threaded jobs kept 2 to 3 of the 16 logical cores busy during all four runs.main, 1st pairmain, 2nd pairmain, 1st pairmain, 2nd pairmain, 1st pairmain, 2nd pairmainhas had perf(agc): keep Windows host imports of write-watched private memory watched #6060 since this PR was first measured: on Windows, host imports of write-watched private memory stay watched instead of being compared (its probe says yes on this machine). Onmain8cd937e29, before it, the three homebrews ran at 336 / 366, 66 / 59 and 48 / 50 ms p50, and this PR at 97 / 95, 21 / 20 and 34 / 27 ms.Frame dumps of
mainand of this PR (a separate 45 s run each,APS5_DUMP_FRAMES=5,APS5_DUMP_FRAMES_EVERY=20, five frames per homebrew):Summary lines (
aps5-summary.jsonl;APS5_TRACE_DIRpoints at the run's folder):{"commit":"60229fae6469","dirty":false,"env":{"APS5_TRACE_DIR":"<path>","APS5_TRACE_SECONDS":"15:10"},"gpu":"NVIDIA GeForce RTX 4070","driver":"NVIDIA 595.79","os":"Windows 10.0.26200","resolution":"3840x2160","window":{"spec":"seconds 15:10","first_present":192,"ms":10005.976},"presents":133,"frame_ms":{"p50":74.617,"p90":80.905,"p99":88.395,"max":94.287},"gpu_busy_ms_per_present":57.331,"worker_busy_pct":{"queue worker 0x0":9.033},"top_phases_ms_per_frame":{"Driver.Packet":6.336,"Driver.Packet.draw":3.534,"Driver.Draw":3.504,"Driver.Present":2.666,"Driver.Draw.draw_enqueued":2.315,"Driver.Present.render_fence_wait":2.310,"Vulkan.Retire":2.309,"Vulkan.Retire.wait":2.286},"trace_dropped":false,"trace":"aps5-trace-60229fae6469-22964.json.gz"} {"commit":"60229fae6469","dirty":false,"env":{"APS5_TRACE_DIR":"<path>","APS5_TRACE_SECONDS":"15:10"},"gpu":"NVIDIA GeForce RTX 4070","driver":"NVIDIA 595.79","os":"Windows 10.0.26200","resolution":"3840x2160","window":{"spec":"seconds 15:10","first_present":800,"ms":10009.845},"presents":599,"frame_ms":{"p50":16.656,"p90":17.044,"p99":19.478,"max":30.006},"gpu_busy_ms_per_present":7.421,"worker_busy_pct":{"queue worker 0x0":32.802},"top_phases_ms_per_frame":{"Driver.Packet":5.478,"Driver.Packet.draw":4.270,"Driver.Draw":4.227,"Driver.Draw.draw_enqueued":2.080,"Driver.Present":2.045,"Driver.Draw.shader_compile_and_link":1.826,"Driver.Present.render_fence_wait":1.689,"Vulkan.Retire":1.689},"trace_dropped":false,"trace":"aps5-trace-60229fae6469-40524.json.gz"} {"commit":"60229fae6469","dirty":false,"env":{"APS5_TRACE_DIR":"<path>","APS5_TRACE_SECONDS":"15:10"},"gpu":"NVIDIA GeForce RTX 4070","driver":"NVIDIA 595.79","os":"Windows 10.0.26200","resolution":"3840x2160","window":{"spec":"seconds 15:10","first_present":485,"ms":10007.120},"presents":341,"frame_ms":{"p50":28.451,"p90":36.542,"p99":41.133,"max":43.527},"gpu_busy_ms_per_present":1.211,"worker_busy_pct":{"queue worker 0x0":3.412},"top_phases_ms_per_frame":{"Driver.Present":1.395,"Driver.Present.render_fence_wait":1.057,"Vulkan.Retire":1.056,"Vulkan.Retire.wait":1.041,"Driver.Packet":0.998,"Driver.Packet.device_lock":0.766,"Driver.Present.present_display_buffer":0.200,"Driver.Packet.draw":0.117},"trace_dropped":false,"trace":"aps5-trace-60229fae6469-40800.json.gz"} {"commit":"92e50418f33b","dirty":false,"env":{"APS5_TRACE_DIR":"<path>","APS5_TRACE_SECONDS":"15:10"},"gpu":"NVIDIA GeForce RTX 4070","driver":"NVIDIA 595.79","os":"Windows 10.0.26200","resolution":"3840x2160","window":{"spec":"seconds 15:10","first_present":85,"ms":10153.502},"presents":56,"frame_ms":{"p50":180.646,"p90":210.853,"p99":227.219,"max":227.219},"gpu_busy_ms_per_present":70.937,"worker_busy_pct":{"queue worker 0x0":27.297},"top_phases_ms_per_frame":{"Driver.Packet":48.954,"Driver.Packet.device_lock":28.377,"Driver.Packet.draw":19.416,"Driver.Draw":19.386,"Driver.Draw.draw_enqueued":18.707,"Graphics.Wait":5.263,"Graphics.Wait.fence_wait":5.247,"Driver.Present":3.324},"trace_dropped":false,"trace":"aps5-trace-92e50418f33b-40108.json.gz"} {"commit":"92e50418f33b","dirty":false,"env":{"APS5_TRACE_DIR":"<path>","APS5_TRACE_SECONDS":"15:10"},"gpu":"NVIDIA GeForce RTX 4070","driver":"NVIDIA 595.79","os":"Windows 10.0.26200","resolution":"3840x2160","window":{"spec":"seconds 15:10","first_present":299,"ms":10025.486},"presents":182,"frame_ms":{"p50":54.267,"p90":67.012,"p99":72.934,"max":73.289},"gpu_busy_ms_per_present":10.112,"worker_busy_pct":{"queue worker 0x0":75.521},"top_phases_ms_per_frame":{"Driver.Packet":41.597,"Driver.Packet.draw":40.293,"Driver.Draw":40.244,"Driver.Draw.draw_enqueued":37.862,"Driver.Present":10.309,"Driver.Present.render_fence_wait":9.884,"Vulkan.Retire":9.883,"Vulkan.Retire.wait":9.859},"trace_dropped":false,"trace":"aps5-trace-92e50418f33b-40072.json.gz"} {"commit":"92e50418f33b","dirty":false,"env":{"APS5_TRACE_DIR":"<path>","APS5_TRACE_SECONDS":"15:10"},"gpu":"NVIDIA GeForce RTX 4070","driver":"NVIDIA 595.79","os":"Windows 10.0.26200","resolution":"3840x2160","window":{"spec":"seconds 15:10","first_present":286,"ms":10023.429},"presents":160,"frame_ms":{"p50":63.023,"p90":79.537,"p99":88.469,"max":93.946},"gpu_busy_ms_per_present":1.280,"worker_busy_pct":{"queue worker 0x0":31.388},"top_phases_ms_per_frame":{"Driver.Packet":19.656,"Driver.Packet.device_lock":19.435,"Driver.Present":1.552,"Driver.Present.render_fence_wait":1.166,"Vulkan.Retire":1.165,"Vulkan.Retire.wait":1.149,"Driver.Present.present_display_buffer":0.226,"Graphics.Wait":0.180},"trace_dropped":false,"trace":"aps5-trace-92e50418f33b-36020.json.gz"} {"commit":"60229fae6469","dirty":false,"env":{"APS5_TRACE_DIR":"<path>","APS5_TRACE_SECONDS":"15:10"},"gpu":"NVIDIA GeForce RTX 4070","driver":"NVIDIA 595.79","os":"Windows 10.0.26200","resolution":"3840x2160","window":{"spec":"seconds 15:10","first_present":187,"ms":10029.735},"presents":126,"frame_ms":{"p50":79.327,"p90":84.211,"p99":95.338,"max":95.992},"gpu_busy_ms_per_present":60.345,"worker_busy_pct":{"queue worker 0x0":9.334},"top_phases_ms_per_frame":{"Driver.Packet":6.933,"Driver.Packet.draw":3.812,"Driver.Draw":3.786,"Driver.Present":3.127,"Driver.Present.render_fence_wait":2.738,"Vulkan.Retire":2.736,"Vulkan.Retire.wait":2.712,"Driver.Draw.draw_enqueued":2.531},"trace_dropped":false,"trace":"aps5-trace-60229fae6469-45960.json.gz"} {"commit":"60229fae6469","dirty":false,"env":{"APS5_TRACE_DIR":"<path>","APS5_TRACE_SECONDS":"15:10"},"gpu":"NVIDIA GeForce RTX 4070","driver":"NVIDIA 595.79","os":"Windows 10.0.26200","resolution":"3840x2160","window":{"spec":"seconds 15:10","first_present":762,"ms":10013.145},"presents":542,"frame_ms":{"p50":17.838,"p90":20.997,"p99":29.208,"max":34.818},"gpu_busy_ms_per_present":8.569,"worker_busy_pct":{"queue worker 0x0":36.155},"top_phases_ms_per_frame":{"Driver.Present":7.230,"Driver.Present.render_fence_wait":6.842,"Vulkan.Retire":6.841,"Vulkan.Retire.wait":6.809,"Driver.Packet":6.675,"Driver.Packet.draw":5.266,"Driver.Draw":5.215,"Driver.Draw.draw_enqueued":2.691},"trace_dropped":false,"trace":"aps5-trace-60229fae6469-22948.json.gz"} {"commit":"60229fae6469","dirty":false,"env":{"APS5_TRACE_DIR":"<path>","APS5_TRACE_SECONDS":"15:10"},"gpu":"NVIDIA GeForce RTX 4070","driver":"NVIDIA 595.79","os":"Windows 10.0.26200","resolution":"3840x2160","window":{"spec":"seconds 15:10","first_present":460,"ms":10025.002},"presents":316,"frame_ms":{"p50":31.182,"p90":39.224,"p99":49.608,"max":53.253},"gpu_busy_ms_per_present":1.569,"worker_busy_pct":{"queue worker 0x0":3.124},"top_phases_ms_per_frame":{"Driver.Present":1.818,"Driver.Present.render_fence_wait":1.474,"Vulkan.Retire":1.473,"Vulkan.Retire.wait":1.458,"Driver.Packet":0.988,"Driver.Packet.device_lock":0.741,"Driver.Present.present_display_buffer":0.200,"Driver.Packet.draw":0.128},"trace_dropped":false,"trace":"aps5-trace-60229fae6469-4524.json.gz"} {"commit":"92e50418f33b","dirty":false,"env":{"APS5_TRACE_DIR":"<path>","APS5_TRACE_SECONDS":"15:10"},"gpu":"NVIDIA GeForce RTX 4070","driver":"NVIDIA 595.79","os":"Windows 10.0.26200","resolution":"3840x2160","window":{"spec":"seconds 15:10","first_present":79,"ms":10069.121},"presents":57,"frame_ms":{"p50":174.829,"p90":198.616,"p99":224.671,"max":224.671},"gpu_busy_ms_per_present":74.029,"worker_busy_pct":{"queue worker 0x0":26.940},"top_phases_ms_per_frame":{"Driver.Packet":47.221,"Driver.Packet.device_lock":27.812,"Driver.Packet.draw":18.304,"Driver.Draw":18.278,"Driver.Draw.draw_enqueued":17.504,"Graphics.Wait":5.288,"Graphics.Wait.fence_wait":5.277,"Driver.Present":3.673},"trace_dropped":false,"trace":"aps5-trace-92e50418f33b-38504.json.gz"} {"commit":"92e50418f33b","dirty":false,"env":{"APS5_TRACE_DIR":"<path>","APS5_TRACE_SECONDS":"15:10"},"gpu":"NVIDIA GeForce RTX 4070","driver":"NVIDIA 595.79","os":"Windows 10.0.26200","resolution":"3840x2160","window":{"spec":"seconds 15:10","first_present":285,"ms":10015.270},"presents":214,"frame_ms":{"p50":48.134,"p90":56.675,"p99":66.756,"max":70.020},"gpu_busy_ms_per_present":8.887,"worker_busy_pct":{"queue worker 0x0":75.006},"top_phases_ms_per_frame":{"Driver.Packet":35.099,"Driver.Packet.draw":33.934,"Driver.Draw":33.884,"Driver.Draw.draw_enqueued":31.524,"Driver.Present":9.020,"Driver.Present.render_fence_wait":8.694,"Vulkan.Retire":8.693,"Vulkan.Retire.wait":8.674},"trace_dropped":false,"trace":"aps5-trace-92e50418f33b-43436.json.gz"} {"commit":"92e50418f33b","dirty":false,"env":{"APS5_TRACE_DIR":"<path>","APS5_TRACE_SECONDS":"15:10"},"gpu":"NVIDIA GeForce RTX 4070","driver":"NVIDIA 595.79","os":"Windows 10.0.26200","resolution":"3840x2160","window":{"spec":"seconds 15:10","first_present":335,"ms":10007.967},"presents":231,"frame_ms":{"p50":43.109,"p90":65.078,"p99":74.028,"max":80.978},"gpu_busy_ms_per_present":1.185,"worker_busy_pct":{"queue worker 0x0":40.766},"top_phases_ms_per_frame":{"Driver.Packet":17.659,"Driver.Packet.device_lock":17.420,"Driver.Present":1.404,"Driver.Present.render_fence_wait":1.099,"Vulkan.Retire":1.098,"Vulkan.Retire.wait":1.087,"Driver.Present.present_display_buffer":0.181,"Driver.Packet.draw":0.131},"trace_dropped":false,"trace":"aps5-trace-92e50418f33b-43152.json.gz"}The traces are linked from the table above.
Runs by others, with
60229fae6merged into a newermain:main5d9dcc42d: PS5 OpenGL Showcase at 3.64 and 3.75 FPS onmainand 5.47, 5.55 and 5.93 FPS with this PR (60 s runs; a thirdmainrun exited after 4 s on a cold shader cache).agc_driver_array_layer_targetpasses, and frame dumps show the same scene on both builds; both also draw a white band across the instanced cubes on this GPU (run by @LeandroLP23).main82ddae75bwith fix(agc): drain library prebuilds before device replacement #6814 in both builds: PS5 OpenGL Showcase at 106.2 ms p50 onmainand 50.0 ms with this PR. PS5MC stays at vsync on both, but this PR drops its 600 uploads and 300 storage-refresh write-backs (about 20 GiB) per 10 s (run by @milescoviello).Not tested: Intel, AMD on Linux; on lavapipe only
agc_driver_array_layer_targetwas run, and on Linux with NVIDIA only the homebrews, without frame dumps.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file.mdfiles or images added to the repository (attach them to this PR)main)agc_driver_array_layer_target, by @coltken95); AMD Radeon 860M, driver 32.0.13058.8001, Windows 11 26300 (the test and the Showcase, by @LeandroLP23); NVIDIA GeForce RTX 4070 Ti, driver 595.99.02, Ubuntu 24.04 (the Showcase and PS5MC, by @milescoviello)🤖 Generated with Claude Code