mirror of
https://github.com/mihawk-99/PS5_RetroArch.git
synced 2026-10-18 23:09:29 -05:00
Emulated swap intervals ask for images enough to keep their lookahead
RetroArch emulates a swap interval above 1 by presenting each frame that many times, so each frame takes that many of the queue's images. At 119.88 Hz with the automatic interval of 2, the default three images held one frame instead of two; the second present of every frame waited for a vblank on the thread that runs the core, and Dolphin's frame-stepped emulation ran Wind Waker under ubershaders at 80-99%. Patch 0091 asks for (video_max_swapchain_images - 1) * interval + 1 images, five by default at 120 Hz: two frames and 33 ms of lookahead, as three images give at 60 Hz. ../PS5_Vulkan R74 provides them. Patch count 199 -> 200 (0091's one block). Evidence: evidence/dolphin-p2-swapchain-before and -after (python3 tools/evidence.py compare). Title 5beca7cc: Profiles 1 and 2 (1x, 6x) on RE4, Melee and Wind Waker at 100% in every steady window. verify.sh: all gates pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d4c07f71e8
commit
99503e7b2a
9 files changed
+193
-9
No files matched your search
+12
-8
@@ -45,14 +45,18 @@ The acceptance goal (2026-09-25): Resident Evil 4, Super Smash Bros. Melee and
|
||||
Wind Waker correct, full speed, with audio, input and states, then stable and
|
||||
measured through the profiles in `tooling/dolphin-profiles/` (docs/PHASE_LOG.md).
|
||||
|
||||
1. Profiles 0 and 1 pass on all three games: correct pictures, full speed,
|
||||
display-paced frames (docs/PHASE_LOG.md, 2026-09-25). Tolerated: a
|
||||
screenshot's 55 ms read-back leaves its audio window ~0.4% short.
|
||||
2. The driver's copy throughput: the 55 ms read-back of the 4K output and a
|
||||
218 ms copy in RE4's load; Profile 5's EFB copies to RAM depend on it.
|
||||
3. Profiles 2-11 on all three games: ubershaders, 6x torture, GPU and RAM EFB,
|
||||
the scaling ladder, MSAA, cold/warm shader cache, reloads, state stress,
|
||||
long soak.
|
||||
1. Profiles 0, 1 and 2 (1x and 6x) pass on all three games: correct
|
||||
pictures, full speed, display-paced frames, five swapchain images at 120 Hz
|
||||
(docs/PHASE_LOG.md, 2026-09-25). Tolerated: a screenshot's 55 ms read-back
|
||||
leaves its audio window ~0.4% short.
|
||||
2. The driver's copy throughput: the 55 ms read-back of the 4K output, a
|
||||
218 ms copy in RE4's load, and Wind Waker's 40-90 read-backs a second, each
|
||||
done by the CPU after a wait for the GPU; Profile 5's EFB copies to RAM
|
||||
depend on it.
|
||||
3. Profiles 3-11 on all three games: 6x torture, GPU and RAM EFB, the scaling
|
||||
ladder, MSAA, cold/warm shader cache (a new build's first pipelines cost
|
||||
30-95 ms each), reloads with the menu's three-image swapchain and the game's
|
||||
five, state stress, long soak.
|
||||
3. The dual-core FIFO playback stall (single core plays).
|
||||
|
||||
## Accepted baselines
|
||||
|
||||
@@ -3287,3 +3287,40 @@ that long now empties it; before, a screenshot window was ~750 frames short in
|
||||
RE4 and Wind Waker and 2000-3800 in Melee. The driver's copy throughput (the
|
||||
55 ms read-back, a 218 ms copy in RE4's load) is the next lead, and matters
|
||||
most for Profile 5's EFB copies to RAM.
|
||||
|
||||
## 2026-09-25 — Profile 2: five swapchain images at 120 Hz
|
||||
|
||||
Profile 2 (synchronous ubershaders, 1x and 6x) ran RE4 and Melee at full speed
|
||||
at both resolutions, and Wind Waker at 89-99% at 1x and 80-84% at 6x with the
|
||||
GPU busy 0.7 and 2.2 ms a present: slow at 1x, so CPU or presentation, not GPU
|
||||
throughput.
|
||||
|
||||
- The driver's new `cpu_copies` profile field showed Wind Waker reading back
|
||||
40-90 images a second (EFB copies encoded to RAM, and the EFB peeks its game
|
||||
settings enable), each a wait for the GPU; ubershaders lengthen what each
|
||||
wait covers.
|
||||
- The CPU sampler at a 1 ms threshold found neither thread busy: the main
|
||||
thread waited in vkAcquireNextImageKHR and the CPU thread between frame
|
||||
steps.
|
||||
- A one-shot timeline of retro_run (removed since) showed why. RetroArch
|
||||
emulates a swap interval of 2 at 119.88 Hz by presenting each frame twice,
|
||||
and three images leave room for two queued flips: one frame. A new frame's
|
||||
run took 7 ms and queued both presents at once; the repeated field's run
|
||||
then waited 13-14 ms for two vblanks inside its present, and Dolphin's GPU
|
||||
thread -- the thread that waits -- cannot drain the FIFO while it does, so
|
||||
the CPU thread stalled behind it. The pair of runs crossed 33.4 ms often
|
||||
enough to lose 4-12%.
|
||||
- A temporary driver with five images and `video_max_swapchain_images = 5`
|
||||
ran the same state at 100%.
|
||||
|
||||
../PS5_Vulkan R74 gives a swapchain the images it asks for, three to five, and
|
||||
patch 0091 has RetroArch ask for (video_max_swapchain_images - 1) * interval + 1
|
||||
when it emulates an interval. The default of three becomes five at 120 Hz with an
|
||||
interval of 2: two frames of lookahead, the same frames and the same 33 ms as three
|
||||
images at 60 Hz, so the latency is what a 60 Hz display has.
|
||||
|
||||
Title 5beca7cc (`evidence/dolphin-p2-swapchain-before`, `-after`): Profile 1 and
|
||||
Profile 2 at 1x and 6x on all three games, 1,200 presents per 10 s and every
|
||||
steady window at 100% (99% in one screenshot window). Melee's first run on a new
|
||||
build still stalls 30-95 ms on each pipeline it compiles for the first time: the
|
||||
driver's shader cache is per build, and Profile 8 is where that is measured.
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"step": "dolphin-p2-swapchain-after",
|
||||
"recorded": "2026-09-25",
|
||||
"console_run": "not read this run",
|
||||
"revision": "title 5beca7cc: driver R74 (up to five images) and RetroArch patch 0091",
|
||||
"command": "tooling/dolphin-profiles/p2-ubershaders-1x.txt as /app0/dolphin-options.txt; Wind Waker from my entry state; driver profile armed",
|
||||
"raw_capture": "klog/ww-p2-r74-trace.txt",
|
||||
"raw_lines": 106,
|
||||
"raw_bytes": 16201,
|
||||
"lines": [
|
||||
"build identity: 5beca7cccd834b7c46bcc76900e15956f0f7eacc9eb6d2e7676b36cb3d49d86a",
|
||||
"[ps5vk] output: 119.88 Hz selected",
|
||||
"audio ps5: ready requested_rate=48000 rate=48000 channels=2 s16 grain=256 buffer_bytes=12288",
|
||||
"[ps5vk] hitch period_ms=1099.782 app_ms=1091.192 queue_ms=8.557 copy_ms=4.571",
|
||||
"[ps5vk] hitch period_ms=156.733 app_ms=137.499 queue_ms=19.202 copy_ms=18.807",
|
||||
"[ps5vk] hitch period_ms=255.465 app_ms=255.176 queue_ms=0.052 copy_ms=0.000",
|
||||
"[ps5vk] hitch period_ms=5810.600 app_ms=5804.438 queue_ms=5.908 copy_ms=1.694",
|
||||
"[ps5vk] profile frames=329",
|
||||
"[ps5vk] profile2 frame_ms=30.432 frame_max_ms=5810.600 hitches=4 presents=65/66 periods=0:163 4:78 8:2 12:1 16:4 20:3 24:73 32:1 64:4",
|
||||
"audio ps5: window played=132185 silence=347815",
|
||||
"[ps5vk] profile frames=1201",
|
||||
"[ps5vk] profile2 frame_ms=8.328 frame_max_ms=25.019 hitches=0 presents=241/240 periods=0:498 4:309 8:74 12:24 16:50 20:160 24:86",
|
||||
"audio ps5: window played=480000 silence=0",
|
||||
"[ps5vk] profile frames=1197",
|
||||
"[ps5vk] profile2 frame_ms=8.355 frame_max_ms=26.307 hitches=0 presents=239/240 periods=0:584 4:307 8:6 16:6 20:65 24:229",
|
||||
"audio ps5: window played=480000 silence=0",
|
||||
"[ps5vk] profile frames=1200",
|
||||
"[ps5vk] profile2 frame_ms=8.342 frame_max_ms=25.324 hitches=0 presents=240/240 periods=0:491 4:409 24:300",
|
||||
"audio ps5: window played=480000 silence=0",
|
||||
"[ps5vk] profile frames=1200",
|
||||
"[ps5vk] profile2 frame_ms=8.342 frame_max_ms=25.049 hitches=0 presents=240/240 periods=0:599 4:301 20:1 24:299",
|
||||
"audio ps5: window played=480000 silence=0",
|
||||
"[ps5vk] profile frames=1200",
|
||||
"[ps5vk] profile2 frame_ms=8.339 frame_max_ms=25.360 hitches=0 presents=240/240 periods=0:520 4:357 8:18 12:5 16:12 20:99 24:189",
|
||||
"audio ps5: window played=480000 silence=0",
|
||||
"[ps5vk] profile frames=1200",
|
||||
"[ps5vk] profile2 frame_ms=8.334 frame_max_ms=26.859 hitches=0 presents=240/240 periods=0:554 4:281 8:46 12:20 16:36 20:134 24:129",
|
||||
"audio ps5: window played=480000 silence=0",
|
||||
"audio ps5: closed accepted=3121669 played=3121669 discarded=0 silence=384251 calls=13695 errors=0 peak=2470 capacity=3072 drain=00000100 close=00000000",
|
||||
"[ps5vk] output: default mode restored",
|
||||
"[INFO] [PS5] build identity: 5beca7cccd834b7c46bcc76900e15956f0f7eacc9eb6d2e7676b36cb3d49d86a",
|
||||
"[INFO] [Vulkan] Got 5 swapchain images."
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"step": "dolphin-p2-swapchain-after",
|
||||
"note": "After: RetroArch asks for (3 - 1) * 2 + 1 = 5 images for its emulated swap interval of 2 and the driver gives them; the same run is 100% in every steady window, 1,200 presents per 10 s.",
|
||||
"must_contain": [
|
||||
"Got 5 swapchain images",
|
||||
"[ps5vk] output: 119.88 Hz selected",
|
||||
"audio ps5: window played=480000 silence=0"
|
||||
],
|
||||
"must_not_contain": [
|
||||
"Got 3 swapchain images"
|
||||
],
|
||||
"human_check": ""
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"step": "dolphin-p2-swapchain-before",
|
||||
"recorded": "2026-09-25",
|
||||
"console_run": "not read this run",
|
||||
"revision": "title f2585b8f: driver R73, three swapchain images at 119.88 Hz with a swap interval of 2",
|
||||
"command": "tooling/dolphin-profiles/p2-ubershaders-1x.txt as /app0/dolphin-options.txt; Wind Waker from my entry state; driver profile armed",
|
||||
"raw_capture": "klog/p2-ubershaders-1x-ww-trace.txt",
|
||||
"raw_lines": 112,
|
||||
"raw_bytes": 16467,
|
||||
"lines": [
|
||||
"build identity: f2585b8fcbf26c8f63d4651abdfeb7020167fffaac0868f1c0d04b3dcbaeec24",
|
||||
"[ps5vk] output: 119.88 Hz selected",
|
||||
"audio ps5: ready requested_rate=48000 rate=48000 channels=2 s16 grain=256 buffer_bytes=12288",
|
||||
"[ps5vk] hitch period_ms=1044.742 app_ms=1036.333 queue_ms=8.374 copy_ms=4.556",
|
||||
"[ps5vk] hitch period_ms=219.937 app_ms=219.651 queue_ms=0.052 copy_ms=0.000",
|
||||
"[ps5vk] hitch period_ms=102.392 app_ms=96.902 queue_ms=5.245 copy_ms=1.732",
|
||||
"audio ps5: window played=386656 silence=93344",
|
||||
"[ps5vk] profile frames=969",
|
||||
"[ps5vk] profile2 frame_ms=10.343 frame_max_ms=1044.742 hitches=3 presents=323/323 periods=0:356 4:292 8:72 12:3 16:7 20:72 24:162 32:1 36:1 64:3",
|
||||
"audio ps5: window played=477015 silence=2985",
|
||||
"[ps5vk] profile frames=1190",
|
||||
"[ps5vk] profile2 frame_ms=8.413 frame_max_ms=26.668 hitches=0 presents=396/397 periods=0:531 4:260 8:83 12:22 16:49 20:148 24:97",
|
||||
"[ps5vk] hitch period_ms=63.659 app_ms=8.107 queue_ms=55.492 copy_ms=55.212",
|
||||
"[ps5vk] hitch period_ms=52.922 app_ms=43.976 queue_ms=8.902 copy_ms=2.070",
|
||||
"audio ps5: window played=452215 silence=27785",
|
||||
"[ps5vk] profile frames=1108",
|
||||
"[ps5vk] profile2 frame_ms=9.027 frame_max_ms=63.659 hitches=2 presents=370/369 periods=0:437 4:317 8:73 16:2 20:1 24:276 52:1 60:1",
|
||||
"audio ps5: window played=427837 silence=52163",
|
||||
"[ps5vk] profile frames=1064",
|
||||
"[ps5vk] profile2 frame_ms=9.400 frame_max_ms=25.412 hitches=0 presents=354/355 periods=0:361 4:302 8:135 24:266",
|
||||
"[ps5vk] hitch period_ms=55.275 app_ms=0.063 queue_ms=55.155 copy_ms=54.882",
|
||||
"[ps5vk] hitch period_ms=52.767 app_ms=43.939 queue_ms=8.795 copy_ms=2.039",
|
||||
"audio ps5: window played=452533 silence=27467",
|
||||
"[ps5vk] profile frames=1109",
|
||||
"[ps5vk] profile2 frame_ms=9.019 frame_max_ms=55.275 hitches=2 presents=370/370 periods=0:483 4:272 8:71 12:1 16:1 20:2 24:277 52:2",
|
||||
"[ps5vk] hitch period_ms=59.729 app_ms=4.392 queue_ms=55.283 copy_ms=55.014",
|
||||
"[ps5vk] hitch period_ms=47.645 app_ms=38.135 queue_ms=9.477 copy_ms=2.659",
|
||||
"audio ps5: window played=451832 silence=28168",
|
||||
"[ps5vk] profile frames=1113",
|
||||
"[ps5vk] profile2 frame_ms=8.989 frame_max_ms=59.729 hitches=2 presents=371/371 periods=0:398 4:287 8:115 12:31 16:45 20:126 24:109 44:1 56:1",
|
||||
"audio ps5: window played=473100 silence=6900",
|
||||
"audio ps5: closed accepted=3123802 played=3123802 discarded=0 silence=281766 calls=13303 errors=0 peak=3072 capacity=3072 drain=00000100 close=00000000",
|
||||
"[ps5vk] output: default mode restored",
|
||||
"[INFO] [PS5] build identity: f2585b8fcbf26c8f63d4651abdfeb7020167fffaac0868f1c0d04b3dcbaeec24",
|
||||
"[INFO] [Vulkan] Got 3 swapchain images."
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"step": "dolphin-p2-swapchain-before",
|
||||
"note": "Before: Wind Waker under synchronous ubershaders ran at 89-99% (a window as short as 427837 of 480000 audio frames) with the GPU busy 0.7 ms a present. RetroArch presented every frame twice into three images, and the second present waited for a vblank on the thread that runs the frame-stepped core.",
|
||||
"must_contain": [
|
||||
"Got 3 swapchain images",
|
||||
"[ps5vk] output: 119.88 Hz selected",
|
||||
"audio ps5: window played=427837 silence=52163"
|
||||
],
|
||||
"must_not_contain": [],
|
||||
"human_check": ""
|
||||
}
|
||||
@@ -157,3 +157,9 @@
|
||||
# viewport, and a save-state thumbnail of Dolphin's frame overran by ~1 MB
|
||||
# gfx/drivers/vulkan.c
|
||||
0090-readback-within-caller-viewport
|
||||
|
||||
# 0091 an emulated swap interval (each frame presented swap_interval times)
|
||||
# asks for (video_max_swapchain_images - 1) * interval + 1 images, so
|
||||
# the setting's frames of lookahead hold at 120 Hz as at 60 Hz
|
||||
# gfx/common/vulkan_common.c
|
||||
0091-swap-interval-images
|
||||
@@ -342,7 +342,7 @@ class PortPatches(unittest.TestCase):
|
||||
change deliberately, in a commit that says why.
|
||||
"""
|
||||
self.assertEqual(
|
||||
len(self.blocks()), 199,
|
||||
len(self.blocks()), 200,
|
||||
"the patch count changed: if a block was added or removed on purpose, "
|
||||
"update this number in the same commit and say why in its message")
|
||||
|
||||
|
||||
@@ -2856,6 +2856,28 @@ EDITS = [
|
||||
" vp_height = caller_height;\n",
|
||||
"patches/series, 0090): never more than the",
|
||||
),
|
||||
(
|
||||
# 0091: a swap interval above 1 is emulated by presenting each frame
|
||||
# that many times (vulkan.c), so each frame takes that many of the
|
||||
# queue's images, and video_max_swapchain_images' lookahead in frames
|
||||
# shrinks by the interval. At 120 Hz with an automatic interval of 2,
|
||||
# three images held one frame (16.7 ms) where they hold two (33 ms) at
|
||||
# 60 Hz; the second present of every frame then waited on the thread
|
||||
# that runs the core, and Dolphin's frame-stepped emulation lost 4-12%
|
||||
# of Wind Waker's speed under ubershaders (2026-09-25, ../PS5_Vulkan
|
||||
# R74). (images - 1) * interval + 1 keeps the frames of lookahead the
|
||||
# setting names, within the surface's maxImageCount (clamped below).
|
||||
"gfx/common/vulkan_common.c",
|
||||
" desired_swapchain_images = settings->uints.video_max_swapchain_images;\n",
|
||||
" desired_swapchain_images = settings->uints.video_max_swapchain_images;\n"
|
||||
" /* Changed by this port (patches/series, 0091): an emulated swap\n"
|
||||
" * interval presents each frame swap_interval times, so the frames of\n"
|
||||
" * lookahead the setting names need that many images each. */\n"
|
||||
" if (swap_interval > 1 && desired_swapchain_images > 1)\n"
|
||||
" desired_swapchain_images = (desired_swapchain_images - 1)\n"
|
||||
" * (uint32_t)swap_interval + 1;\n",
|
||||
"patches/series, 0091): an emulated swap",
|
||||
),
|
||||
]
|
||||
|
||||
# Changes that are withdrawn rather than deleted, by marker.
|
||||
|
||||
Reference in new issue
Block a user