Repository navigation
feat(agc): scale the presentation with FSR 1 under ANYPS5_UPSCALE=fsr - #10043
EagleBearerYS wants to merge 17 commits into
Conversation
3rdparty/FidelityFX-FSR holds ffx-fsr/ffx_a.h, ffx-fsr/ffx_fsr1.h and license.txt, copied unmodified from GPUOpen's FidelityFX-FSR at tag v1.0.2 (a21ffb8f6c), the MIT-licensed reference of FidelityFX Super Resolution 1.0. The two headers are compiled into the presentation's EASU and RCAS shaders. README.md names the source, the tag and each file's SHA-256. The files are copied rather than added as a submodule because every release tag of that repository carries two submodules for AMD's sample (Cauldron and Cauldron-Media) that a recursive checkout would fetch: about 337 MB at depth 1 and 1.47 GB with full history, for 243 KB of headers.
With ANYPS5_UPSCALE=fsr the presentation draws or blits what it would show into a stage image of the swapchain's format and presents it through AMD's EASU and RCAS (ffx_fsr1.h, compiled by glslang like the other presentation shaders). When the fitted image is larger than the display buffer on either axis, the stage holds the display buffer at its own size and EASU upscales it into an image of the fitted size; otherwise the stage holds today's scaled image and only RCAS runs. RCAS writes the fitted rectangle and black letterbox bands. The stage holds today's decode of the display buffer (the presentation pass, or the blit of a resident or uploaded image), so FSR works on the values the display receives: sRGB-encoded for SDR and PQ code values for HDR10. RCAS output is clamped to [0, 1], so PQ never exceeds its range. ANYPS5_FSR_SHARPNESS sets the RCAS sharpness in stops, 0.0 to 2.0, default 0.2. Without ANYPS5_UPSCALE no upscaler is created and the presentation records the same commands as before. FSR runs only for a presentation it can upscale: a fitted image larger than the display buffer on either axis. Any other presentation is recorded exactly as without ANYPS5_UPSCALE, since RCAS alone would cost frame rate there without adding detail. The stage's render pass ends with a dependency that orders its writes and final layout transition before EASU and RCAS sample it.
agc_driver_presentation_fsr runs agc_driver_presentation_pass_tests --fsr on lavapipe. It checks the variables' parsing, the stage size decision, EASU from 960x540 to 1920x1080 (finite values within [0, 1], flat regions unchanged, edge transitions narrower than the bilinear scaler's), RCAS at 1:1 (sharpness 2.0 close to the input, 0.2 raising edge contrast, flat regions uniform, sharpness 0.0 within [0, 1]), that the default path's output stays bit-identical next to FSR and matches the FSR stage inside the image, and SDR and HDR10 presentations through the presentation pass with letterbox bands. It also checks the presentation render passes' exit dependencies: one that ends in SHADER_READ_ONLY_OPTIMAL orders its writes and final layout transition before a fragment-shader read, one that ends in TRANSFER_SRC_OPTIMAL before a transfer read, and the one that ends in PRESENT_SRC_KHR keeps its dependency. The test's drawn FSR presentations rely on that dependency alone, with no barrier after the render pass. agc_driver_present_upscale presents through a VK_EXT_headless_surface swapchain and checks VulkanDevice::UpscaledPresents, the count of presentations that ran FSR: - 3840x2160 and 1920x1080 into 1084x610 don't run FSR; - 1084x610 at 1:1 doesn't run it; - 960x540 into 1084x610 does; - with ANYPS5_UPSCALE empty, none do. The test skips without the extension. agc_driver_present_upscale also presents in all four combinations of FSR and the performance overlay, and agc_performance_overlay checks the overlay drawn over an FSR presentation (960x540 upscaled to 1280x720), with its FPS digits drawn bit for bit.
agc_driver_presentation_pass_tests --fsr-cost is a cost mode and is not registered with ctest. It records the production upscaler's passes into B8G8R8A8 images and brackets each part with Vulkan timestamps: - the stage write; - EASU and RCAS together, as RecordPresent records them; - EASU alone (RecordUpscale); - RCAS alone (a stage at the fitted size); - today's bilinear blit. It prints one line per case with the device name and the median and 95th percentile over 200 frames after 20 warm-up frames. Each line also gives the CPU time spent recording and releasing the FSR presentation next to the blit's. The cases: - 1920x1080 into 2560x1440 and into 3840x2160; - 1920x1080 and 3840x2160 at 1:1; - 1280x720 into 3840x2160; - 3840x2160 into 2560x1440. A queue without timestamps exits 77.
MarcZX10
left a comment
There was a problem hiding this comment.
Reviewed the current implementation and reported validation for head 672308b453c902d8434842e8bb8e9779eba33da3. The feature has substantial focused coverage and evidence across lavapipe and the RTX 3070, including default-off bit identity and presentation-path checks. One integration blocker remains: check_main_sync.py shows this head is 4 ahead/209 behind fetched upstream/main at 0db47b263, with four changed paths also modified after the merge base: core/libs/prx/libSceAgcDriver/CMakeLists.txt, Execution/src/VulkanDevice.cpp, and both usage/environment docs. The reported full Linux suite and tests are on base 7e69be679, so they do not establish the combined current-main tree. Please rebase/merge current main, resolve these shared paths, rerun overlap and the focused presentation/upscale/overlay/VideoOut tests on the resulting head, and report any changed failures. This request is for current-main integration evidence required by the repository contribution checklist; it is not about queue size. Local conventions pass; hosted checks currently cover policy only and skip product builds.
|
Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.
|
|
@adriadam10 a question about the merge queue, since you wrote on #9790 that MarcZX10's CHANGES_REQUESTED blocks it until it's addressed. On this PR, and on #10159, his latest review asks only for a refresh against |
|
@EagleBearerYS one more from #10807's overlap list. Here the only conflict is in AI-assisted: yes (Claude Code) |
|
@milescoviello Agreed, #10807 goes first here too, merge order only. The one conflict is in |
|
@EagleBearerYS thanks, noted on #10807's checklist. AI-assisted: yes (Claude Code) |
# Conflicts: # core/libs/prx/libSceAgcDriver/Execution/include/PresentationPass.hpp # core/libs/prx/libSceAgcDriver/Execution/src/PresentationPass.cpp # core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp # docs/dev/ENVIRONMENT.md
|
@jotitadev thanks for checking on NVIDIA as well. The
So the PR and its test stay as they are. A lavapipe version check in the test would only work around a Mesa bug that's already fixed. |
The conflict in core/libs/prx/libSceAgcDriver/CMakeLists.txt from boykopovar#12862's split is resolved with tools/agc_test_split.py resolve, which moves this PR's test registrations into tests/cmake/.
✅ NVIDIA GPU test: passedPR head
Unstable on main (1, these also failed in recent main runs on this machine; not counted against this PR)Failing on main too (4, not counted against this PR)Passed on retry (1, failed in the parallel run, passed when re-run with a 360 s timeout; not counted against this PR)Validated but not compared (2, not in the main baseline's validation pass)Validation IDs already present on main (5 IDs in 708 tests)Skipped (51)ReproduceAutomated build and test on a contributor's NVIDIA machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs. |
MarcZX10
left a comment
There was a problem hiding this comment.
Re-checked — new head, changes requested
The sampled-view usage fix is present, but the required validation-layer evidence is from the previous head; the current head still needs a focused run with the layer version that reported the error.
What I ran
- Reviewed PR head
affd3b1699a0037511b3781626906969dd06add2, based on0836dfdf4fecb1e0326100c490476e15d3a74da5. - The merge preview onto current
main8a4fc62318a4b73b6895bf20a024c625efeb7c3bis clean. - Environment: Debian 12, Linux 6.1 x86_64, Python 3.11.2, GCC 12.2.0. I did not build or run C++/GPU tests locally.
- Commands:
python3 tools/pr_precheck.py --repo boykopovar/AnyPS5 --pr 10043
python3 tools/pr_stack_check.py 10043 --repo boykopovar/AnyPS5 --output-dir /tmp/anyps5-stack-10043-latest
git diff --check 0836dfdf4fecb1e0326100c490476e15d3a74da5...affd3b1699a0037511b3781626906969dd06add2
git diff --exit-code bef132589ce213bbf5ffa6c1472f415d6ecd4557 affd3b1699a0037511b3781626906969dd06add2 -- core/libs/prx/libSceAgcDriver/Execution/src/PresentationPass.cpp core/libs/prx/libSceAgcDriver/Execution/src/PresentationUpscaler.cpp core/libs/prx/libSceAgcDriver/tests/PresentationPass.cpp core/libs/prx/libSceAgcDriver/tests/execution/PresentUpscale.cppResults
| Check | Result |
|---|---|
| Diff check | Failed on trailing whitespace in the two imported FSR headers. |
| Conventions and PR template | Passed. |
| Current-main merge preview | Clean against 8a4fc62318a4b73b6895bf20a024c625efeb7c3b. |
Fix/test files since validation head bef132589ce213bbf5ffa6c1472f415d6ecd4557 |
Unchanged at affd3b1699a0037511b3781626906969dd06add2. |
| Hosted CI | Windows passed; Linux and specialized jobs were skipped. The NVIDIA report for the current head used validation layer 1.3.275; it lists agc_driver_present_upscale as skipped because the runner lacks VK_EXT_headless_surface. |
| Build and GPU tests run locally | None. |
Unedited local check output
All conventions checks passed.
3rdparty/FidelityFX-FSR/ffx-fsr/ffx_a.h:252: trailing whitespace.
+// - Replace transcendentals with manual versions.
3rdparty/FidelityFX-FSR/ffx-fsr/ffx_a.h:313: trailing whitespace.
+ // These follow the convention that A integer types don't have signage, until they are operated on.
3rdparty/FidelityFX-FSR/ffx-fsr/ffx_fsr1.h:38: trailing whitespace.
+//
Findings
Blocking
- The reported
VUID-vkCmdBeginRenderPass-initialLayout-00897is fixed in source by adding sampled usage to views used withVK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL. The supporting Khronos 1.4.341 run is onbef132589ce213bbf5ffa6c1472f415d6ecd4557, while the current head isaffd3b1699a0037511b3781626906969dd06add2. The current-head NVIDIA run uses layer 1.3.275, which the author says does not report this VUID, and it skipsagc_driver_present_upscale. Please provide the same focused validation on the current head and currentmain, with the layer inserted and no new VUIDs. The repository requires paired focused AGC validation onmainand the change.
Non-blocking
git diff --checkreports trailing whitespace in the imported FSR headers. The PR says they are copied byte-for-byte from upstream; stripping whitespace and updating the recorded hashes would make the patch check clean if preserving the exact upstream bytes is not required.
Sources
- Framebuffer view usage in the reviewed head, upscaler view usage.
- AGC paired-validation requirement.
- Author's 1.4.341 report on
bef132589c; NVIDIA report onaffd3b1699a0.
Not verified
- No local build, C++ tests, or GPU tests were run. The 1.4.341 validation run was reported by the author on the previous head, not independently reproduced on
affd3b1699a0037511b3781626906969dd06add2. - Linux and console behavior were not verified in this session.
To get this to a good state
Run the relevant presentation, FSR, overlay, and headless-upscale tests on current main and affd3b1699a0037511b3781626906969dd06add2 on the same machine/GPU with VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, ANYPS5_NO_SHADER_CACHE=1, and ANYPS5_REQUIRE_VULKAN=1, using a validation layer version that reports 00897. Include the exact commits, GPU/driver/OS, layer insertion check, commands, and logs; I will re-run the same review checks on the new head.
|
@MarcZX10 here's the comparison you asked for: current
On the trailing whitespace: it's in AMD's headers as published. It's in the description's Tested section. Could you take another look? |
MarcZX10
left a comment
There was a problem hiding this comment.
Reviewed — changes requested
The new lavapipe comparison is useful, but it uses a main revision older than today’s base and misses a later change in VulkanDevice.cpp, which this PR also modifies.
What I ran
Reviewed PR head affd3b1699a0037511b3781626906969dd06add2 against PR base 0836dfdf4fecb1e0326100c490476e15d3a74da5; the merge preview against current main cf79276fee2f042feb6a7c71d0d6a27e9cfe2592 is clean. Environment: Debian Linux x86-64, Python 3.11.2; no local build or GPU tests.
python3 tools/pr_precheck.py --repo boykopovar/AnyPS5 --pr 10043
git diff --name-only cbcb37b3140db682277a9c51d950b90ce75de784 cf79276fee2f042feb6a7c71d0d6a27e9cfe2592 -- core/libs/prx/libSceAgcDriver/CMakeLists.txt core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp docs/dev/ENVIRONMENT.md docs/user/USAGE.mdResults
| Check | Result |
|---|---|
| Conventions and current-main merge preview | Passed; preview is clean. |
| Author’s paired validation report | On lavapipe, the author reports zero VUIDs on both cbcb37b314 and this head, and 20 00897 messages in a red control with the usage fix reverted. This is useful evidence, but it does not use the current base. |
| Current-main changes since the reported baseline | Four paths changed, including VulkanDevice.cpp and the AGC CMake file; both are changed by this PR. |
git diff --check |
Reports trailing whitespace in the imported FidelityFX headers; the PR records that these are unmodified upstream files. This is non-blocking. |
| Hosted checks | Windows passed; Linux and specialized product jobs were skipped. |
Unedited paths changed on main since the reported baseline
core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/ENVIRONMENT.md
docs/user/USAGE.md
Negative control
| Assertion | Change to code under test | Did the test fail? |
|---|---|---|
The sampled-usage fix removes the reported 00897 validation messages. |
Author reports reverting that fix on this PR head. | Yes; the author reports 20 messages in the red control. I did not run it. |
Findings
Blocking
The baseline is not current. The report compares cbcb37b3140db682277a9c51d950b90ce75de784 with this PR head. Current main is cf79276fee2f042feb6a7c71d0d6a27e9cfe2592; since the reported baseline, main changed VulkanDevice.cpp, which this PR also changes. The report therefore does not establish the result with the current integration. Please rerun the paired validation on exact current main and this head, with the same layer and environment, and update the report with both SHAs and layer-insertion evidence.
Non-blocking
The whitespace findings are confined to the imported FidelityFX headers whose upstream bytes and hashes are recorded in the PR.
Sources
- Author’s paired validation report and red control
- Current
mainVulkan-device change - PR’s sampled-view usage fix
Not verified
I did not run a local build, GPU tests, or performance capture. The paired validation and negative control are author-reported and use lavapipe rather than a physical GPU.
To get this to a good state
Repeat the relevant paired validation against current main and this head on the same machine, using the validation layer that reports 00897, and include the exact SHAs and layer insertion evidence. I’ll recheck the same paths and report when the new evidence is available.
|
@MarcZX10 here's the rerun on exact current
It's in the description's Tested section. Could you take another look? |
MarcZX10
left a comment
There was a problem hiding this comment.
Re-checked — new head, looks good
The requested paired Vulkan validation is now reported for PR head affd3b1699a0037511b3781626906969dd06add2, and the author’s negative control reproduces the original validation error when the fix is reverted.
What I ran
- PR head
affd3b1699a0037511b3781626906969dd06add2; PR base0836dfdf4fecb1e0326100c490476e15d3a74da5. - Environment: Debian 12, Linux x86-64, Python 3.11.2. No compiler was invoked; I did not build or run C++/GPU tests locally.
- Commands:
python3 tools/pr_precheck.py --repo boykopovar/AnyPS5 --pr 10043
python3 tools/pr_stack_check.py 10043 --repo boykopovar/AnyPS5 --output-dir /tmp/anyps5-stack-10043-final
gh api repos/boykopovar/AnyPS5/compare/cf79276fee2f042feb6a7c71d0d6a27e9cfe2592...b6bd6e7bf7b97ad00b3315fd26c1d4e76497f452 --jq '[.files[].filename | select(test("Presentation|libSceAgcDriver/CMakeLists|PerformanceOverlay"))]'The author reports a clean merge of the PR head onto main cf79276fee2f042feb6a7c71d0d6a27e9cfe2592 as merge commit caa72b2703; this is author-provided, not a local merge/build. main has since advanced to b6bd6e7bf7b97ad00b3315fd26c1d4e76497f452. The intervening changes do not touch the FSR presentation implementation, its test registration, or the performance overlay paths.
Results
| Check | Result |
|---|---|
| Repository conventions and PR template | Passed locally on the exact PR head/base. |
git diff --check |
Reports trailing whitespace in the two vendored FidelityFX headers, which the PR identifies as byte-identical upstream files. |
| ABI and test-quality helpers | Could not run in the isolated precheck worktree because those workspace-local scripts are absent there; no exports are changed. |
| Current-base merge preview | The stack check reported a clean preview, but main advanced while it ran, so the tool marked the report stale. I do not count that preview as verified against the final tip. |
| Hosted CI | Windows and conventions passed. Linux and specialized product jobs were skipped; a labels job was queued at the last snapshot. |
| Paired Vulkan validation | The author reports zero validation messages on main cf79276fee2f042feb6a7c71d0d6a27e9cfe2592, the PR head, and their clean merge, using the same lavapipe host and validation layer. This was not run by me. |
Unedited output excerpts
All conventions checks passed.
3rdparty/FidelityFX-FSR/ffx-fsr/ffx_a.h:252: trailing whitespace.
+// - Replace transcendentals with manual versions.
3rdparty/FidelityFX-FSR/ffx-fsr/ffx_fsr1.h:38: trailing whitespace.
+//
Target branch tip: `30989cb45bd8435022d2a39672e3308b60bdd47e`
All heads unchanged: **False**
- PR #10043: **clean** against current base; head `affd3b1699a0037511b3781626906969dd06add2`
- PR #10043: Base advanced during checks (30989cb45bd8435022d2a39672e3308b60bdd47e → 97ca8c87517817ad84b441629d074eea9cf9bfd8); discard merge results.
Negative control
| Assertion | Change to code under test | Did the test fail? |
|---|---|---|
The sampled-image usage fix removes VUID-vkCmdBeginRenderPass-initialLayout-00897. |
Author reports reverting only that fix on the clean merge. | Yes: 20 00897 messages; with the fix restored, zero. Author-reported, not independently run. |
Sources
- Author’s exact-main paired validation and negative control
- Sampled-view usage fix at the reviewed head
- Upscaler view usage at the reviewed head
Not verified
I did not build locally or independently run C++ tests, validation-layer tests, GPU tests, Windows runtime, or console behavior. Linux and specialized product CI jobs were skipped. The local current-base merge preview raced with main advancement, so I cannot report a verified merge preview against the final observed tip.
The conflicts with boykopovar#12536 keep both sides. In VulkanDevice::present, the overlay's NotePresent gets main's frame limit argument, and its Record and the else branch keep this PR's upscaled condition. docs/dev/ENVIRONMENT.md keeps both rows.
✅ NVIDIA GPU test: passedPR head
Intermittent validation messages (1, seen once in the parallel run, not reproduced when the test was re-run alone 2 times; not counted against this PR)Unstable on main (4, these also failed in recent main runs on this machine; not counted against this PR)Failing on main too (3, not counted against this PR)Validated but not compared (2, not in the main baseline's validation pass)Validation IDs already present on main (5 IDs in 717 tests)Skipped (52)ReproduceAutomated build and test on a contributor's NVIDIA machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs. |
# Conflicts: # core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp # docs/dev/ENVIRONMENT.md
✅ NVIDIA GPU test: passedPR head
Unstable on main (3, these also failed in recent main runs on this machine; not counted against this PR)Failing on main too (3, not counted against this PR)Validated but not compared (2, not in the main baseline's validation pass)Validation IDs already present on main (5 IDs in 741 tests)Skipped (53)ReproduceAutomated build and test on a contributor's NVIDIA machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs. |
|
RADV/RX 9060 XT: the FSR offscreen test and the headless presentation test passed, including the latter's FSR/overlay combinations (3 runs each); the NVIDIA CI report says its headless test skipped because Tested head Sensitivity check: on the merged tree only, disabling upscaler creation ( Host: CachyOS, Linux ReproductionBuild the presentation and overlay test targets on main and on the PR merged onto that same main. On each tree run three times: export ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1
export VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation VK_LOADER_DEBUG=layer
export VK_LAYER_PATH="$HOME/.local/share/anyps5-tester/vk-layers/usr/share/vulkan/explicit_layer.d"
ctest --test-dir build-main -V -R '^(agc_driver_presentation_pass|agc_performance_overlay)$'On the merged tree also run three times: ctest --test-dir build-main -V -R '^(agc_driver_presentation_fsr|agc_driver_present_upscale)$'Limits: synthetic test inputs, not a game or a visual quality/performance comparison; no PS5 hardware. The counter-test checks FSR selection, not every shader calculation. AI-assisted independent hardware test run (GPT-6.1 Terra). |
✅ AMD GPU test: passedPR head
Unstable on main (6, these also failed in recent main runs on this machine; not counted against this PR)Failing on main too (11, not counted against this PR)Passed on retry (1, failed in the parallel run, passed when re-run with a 360 s timeout; not counted against this PR)Validated but not compared (2, not in the main baseline's validation pass)Validation IDs already present on main (8 IDs in 783 tests)Skipped (62)ReproduceAutomated build and test on a contributor's AMD machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs. |
On the AMD GPU bot's RX 6300 (RADV), under VK_LAYER_KHRONOS_validation, the test takes 19.95 s run alone, and in the bot's 4-way parallel run it hit its 30 s timeout with its checks already passed. 60 s leaves room for validation runs under load.
✅ AMD GPU test: passedPR head
Unstable on main (4, these also failed in recent main runs on this machine; not counted against this PR)Failing on main too (11, not counted against this PR)Passed on retry (2, failed in the parallel run, passed when re-run with a 360 s timeout; not counted against this PR)Validated but not compared (5, not in the main baseline's validation pass)Validation IDs already present on main (8 IDs in 783 tests)Skipped (62)ReproduceAutomated build and test on a contributor's AMD machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs. |
✅ NVIDIA GPU test: passedPR head
Unstable on main (2, these also failed in recent main runs on this machine; not counted against this PR)Failing on main too (3, not counted against this PR)Validated but not compared (2, not in the main baseline's validation pass)Validation IDs already present on main (13 IDs in 801 tests)Skipped (54)ReproduceAutomated build and test on a contributor's NVIDIA machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs. |
✅ NVIDIA GPU test: passedPR head
Unstable on main (1, these also failed in recent main runs on this machine; not counted against this PR)Failing on main too (4, not counted against this PR)Validated but not compared (2, not in the main baseline's validation pass)Validation IDs already present on main (9 IDs in 819 tests)Skipped (62)ReproduceAutomated build and test on a contributor's NVIDIA machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs. |
What
An optional scaler for the presented image: AMD FidelityFX Super Resolution 1.0, EASU upscaling plus RCAS sharpening.
ANYPS5_UPSCALE=fsrturns it on. The default stays today's bilinear scaler.No title needs this to run, and nothing changes unless it's set. With
ANYPS5_UPSCALEunset, no upscaler object exists. The present path records exactly what it records today, and a test checks the output is bit-identical.Where it helps: a display buffer shown in a larger window, for example a 1920x1080 buffer in a 2560x1440 or 3840x2160 window, which today is a bilinear stretch. Here is Planet of Lana (PPSA19450) with
platform-ps5-video-out-width=1920in itsapp0/Media/boot.config, maximized on a 2560x1440 panel, where the 1920x1080 buffer is presented at 2372x1334. The main menu at 1:1, bilinear on the left and FSR at the default sharpness 0.2 on the right:The crops on their own: bilinear and FSR. The full frames: bilinear and FSR. That one-line edit of the title's own data file isn't part of this PR. megood's run of Bendy and the Ink Machine at 1920x1080 in a larger window, shared in the AnyPS5 Discord dev chat, is what pointed us at Unity's resolution settings. Titles that present 3840x2160 buffers in play, such as Resident Evil Village (PPSA01556) and Animal Well (PPSA22520), keep today's scaler in any smaller window, since FSR stays off where it can't upscale.
How to try it on a title: for Planet of Lana (PPSA19450), set
platform-ps5-video-out-width=1920in the dump'sapp0/Media/boot.config(it ships with 3840), run it in a window larger than 1920x1080, and compareANYPS5_UPSCALEunset withANYPS5_UPSCALE=fsr. Other Unity titles may have the same line, but none has been checked yet.The test's synthetic pattern shows the difference in numbers. It's a 960x540 pattern upscaled to 1920x1080, shown as a 320x180 crop at 2x, with bilinear on the left and FSR at 0.2 on the right:
The one-pixel grid lines peak at 179 under bilinear and at 219 with FSR (the source line is 230). A 51/204 edge goes 89 → 166 under bilinear and 65 → 190 with FSR.
Sharpness 0.2 (left) against 2.0, the weakest (right). EASU is the same in both; RCAS's halo is 5-9 levels at 0.2 and 1 level at 2.0:
The whole synthetic FSR frame at half size, for context: image. These three are rendered by this PR's own code on lavapipe.
How:
ANYPS5_UPSCALEandANYPS5_FSR_SHARPNESS(0.0 sharpest to 2.0 weakest, default 0.2) are read once when the window's device is created, likeANYPS5_PRESENT_MODE. An empty value is the same as unset; any other bad value stops the start with a message naming the variable.With
fsr, a presentation whose fitted image is larger than the display buffer on either axis goes through FSR:present()renders today's output at the buffer's own size into a per-slot stage image;FsrEasu.frag) scales it to the fitted size;FsrRcas.frag) sharpens it into the swapchain image, with the black letterbox around it.This covers the drawn, direct and shared present paths. Clear-only presents skip it.
With the performance overlay (feat(agc,videoout): show an optional performance overlay with F10 #6012) on: RCAS ends in
COLOR_ATTACHMENT_OPTIMAL, and the overlay records from there when the frame was drawn or upscaled. Otherwise the overlay records fromTRANSFER_DST_OPTIMALas it does today. The overlay's entry dependency orders it after RCAS's writes, so its text is neither scaled nor sharpened.With
main's overlay plane (feat(videoout): composite the overlay bus over the main output #10507) and system keyboard (feat(libSceImeDialog): type with the controller on an on-screen keyboard #11207): they draw after RCAS too, over the upscaled output at display resolution. RCAS ends inCOLOR_ATTACHMENT_OPTIMALwhenever the plane, the keyboard or the performance overlay draws next, and each of them starts from that layout after an upscale; with nothing drawn over it, RCAS ends inPRESENT_SRC_KHR.Where it can't upscale (1:1 or a smaller window), FSR stays off for that frame, which is presented exactly as without
ANYPS5_UPSCALE. RCAS alone would cost frame rate there without adding detail.QueuePresentwaits for the presentation's rendering inside it.[present] ANYPS5_UPSCALE=fsr: FSR 1 EASU and RCAS when the window is larger than the display buffer, the normal scaler otherwise; RCAS sharpness 0.20.HDR10 (feat(videoout): present PQ display buffers through an HDR10 swapchain #5697) and SDR: FSR runs on the values the display receives, sRGB-encoded for SDR and PQ code values for HDR10, never on linear light. Both are perceptual encodings, which is what FSR 1 expects. EASU's deringing keeps each output inside its 2x2 neighbourhood. RCAS limits its negative lobe to stay inside [0, 1], and the shader clamps its result to [0, 1] after AMD's approximate reciprocal, so PQ output stays a valid code.
Cost when upscaling: two images per presentation in flight (7.9 + 31.6 MiB per slot for a 1080p buffer in a 4K window) and two extra passes per frame. The table gives FSR's GPU time per frame (the stage write, EASU and RCAS) against today's bilinear blit, as the median over 200 frames from
agc_driver_presentation_pass_tests --fsr-cost. The times are GPU timestamps of 200 back-to-back frames after 20 warm-up frames, offscreen with no other GPU work. The RTX 3070 column is from this head. Its clocks weren't held: during the measured frames nvidia-smi (every 100 ms) showed it in P3 and P0, at 780 to 945 MHz graphics and 5,501 to 6,001 MHz memory. So these are mid-clock figures, upper bounds for both passes at full clock. FSR and the blit were timed in the same frames at the same clocks, so the comparison is like for like at those clocks. lavapipe runs on the CPU, so only its ratios mean anything. Recording FSR costs 45-55 µs of CPU per frame on the RTX 3070 when it upscales (median; 89-101 at p95), against 3-4 µs for the blit.The cost mode measures RCAS alone too, which is what FSR would run where it can't upscale. At 1920x1080 1:1 it costs 0.12 ms against the blit's 0.05 on the RTX 3070 (20.6 against 5.0 on lavapipe), at 3840x2160 1:1 0.46 against 0.20, and for 3840x2160 into 2560x1440 0.29 against 0.15 (34.7 against 9.2 on lavapipe). That gives no detail for the cost, so FSR stays off there.
The shaders derive the EASU and RCAS constants per pixel from the sizes and the sharpness in their push constants, about 20 ALU per pixel; AMD's samples compute them once on the CPU, which would save that at the cost of a larger push-constant block. When off, the cost is two
getenvcalls at device creation and one bool per present.Things to know:
APrxMedRcpF1), so it darkens flat areas by a fixed fraction of their value that depends only on the sharpness: 0.17% at the default 0.2 (0.5 → 0.4992), 0.32% at 0.0 and 0.07% at 2.0. That's at most one 8-bit level in SDR and three 10-bit codes in HDR10. Fixing it would mean editing AMD's header, so it's left as is; USAGE says so, and the tests bound it.2.0is RCAS's weakest setting, not off. Withfsrselected, RCAS always runs.ANYPS5_FSR_SHARPNESSstops the start even withoutfsr, like any invalid setting.Third-party code: the FSR headers are vendored, not a submodule, which departs from AGENTS.md's submodule rule. A maintainer agreed in the dev chat that vendoring these two headers is fine.
3rdparty/FidelityFX-FSR/holdsffx-fsr/ffx_a.h,ffx-fsr/ffx_fsr1.handlicense.txt(MIT), copied unmodified from tag v1.0.2 (a21ffb8f6c). Its README gives the source, the commit and each file's SHA-256..gitmodulescan't stop recursion into a submodule's own submodules.Commits:
build(agc): the vendored FSR 1.0.2 headers and license, with the README.feat(agc):PresentationUpscaler,UpscaleMode, the EASU and RCAS shaders, and the hooks intoPresentationPass,PresentationScalerandVulkanDevice::present.PresentationPass::ExitDependency, shared with the upscaler's passes).Graphics::CreateShaderModule, asmain's presentation pass and overlay create theirs.docs/dev/ENVIRONMENT.mdgets rows forANYPS5_UPSCALEandANYPS5_FSR_SHARPNESS.test(agc):agc_driver_presentation_fsr, with the exit dependency's three layouts;agc_driver_present_upscale, which presents throughVulkanDeviceon a headless surface in all four combinations of FSR and the overlay and counts the presentations that ran FSR; andagc_performance_overlay's over-FSR case.test(agc): the--fsr-costmode ofagc_driver_presentation_pass_tests(30febcf), not registered with ctest.Tested
Planet of Lana (PPSA19450) with
platform-ps5-video-out-width=1920inapp0/Media/boot.config, built at this head, on the RTX 3070 Laptop GPU (driver 617.42, Windows 11), maximized on a 2560x1440 panel, with the performance overlay on. Six runs: four in the order bilinear, FSR, FSR, bilinear, then a later pair, FSR then bilinear (ANYPS5_UPSCALEunset orfsr). Clocks weren't held; nvidia-smi logged them every second.guest 1920x1080 presented at 2372x1334, and withfsrthe start line[present] ANYPS5_UPSCALE=fsr: FSR 1 EASU and RCAS when the window is larger than the display buffer, the normal scaler otherwise; RCAS sharpness 0.20. The performance overlay readsRES: 1920X1080 / 2560X1334.agc_driver_presentation_fsr(Vulkan; it runsagc_driver_presentation_pass_tests --fsr) covers:ANYPS5_UPSCALEunset the output is bit-identical, and the stage equals today's fitted image when FSR doesn't upscale;agc_driver_present_upscalepresents throughVulkanDeviceon aVK_EXT_headless_surfaceswapchain (1084x610) and counts the presentations that ran FSR. Withfsr, 3840x2160, 1084x610 and 1920x1080 buffers don't run it and a 960x540 buffer does; with the variable empty, nothing does. With the gate removed it fails: "FSR ran on a 3840x2160 display buffer in a 1084x610 window, where it cannot upscale". It skips where the extension is missing.Linux, CI's Linux job (Ubuntu 24.04, GCC 13.3, CI's configure flags, lavapipe, an unprivileged user), at the head, against
main7e69be6 built the same way:main.mainhas the same status here. The two new tests,agc_driver_presentation_fsrandagc_driver_present_upscale, pass.guest_net_buffer_validation, which fails onmainthere too.check_test_registration.pyfinds nothing unregistered on either.check_skips.pyflags onlyguest_sce_neton both, as on every branch on that machine.agc_driver_presentation_pass,agc_driver_presentation_fsr,agc_driver_present_upscale,agc_performance_overlayandagc_performance_overlay_statisticspass 10 of 10, headless and under Xvfb.Validation with
VK_LAYER_KHRONOS_validationand synchronization validation. The layer reports a planted write-after-write hazard on that machine, so validation was on.video_out_hdr_present's 259x137 buffer is presented at 1152x609.main, plus the 18 on X11.main, then this PR unset, withfsr, withfsrat sharpness 2.0, and withfsrand the performance overlay on (ANYPS5_OVERLAY=1).VUID-VkDeviceCreateInfo-pNext-pNext, once per device, from a device struct that layer version doesn't know. Every testmainhas gets the same count here. The 6 extra come fromagc_driver_present_upscale, which opens a device per case.agc_driver_presentation_fsrhad 10.fsr, FSR's start line appears 13 times in each configuration, fromvideo_out_hdr_present, sixguest_video_out_*tests,agc_driver_present_upscaleand three X11 flip and frame-dump tests. With the overlay on as well, the overlay tests pass, and the screen capture below shows the overlay drawn over an FSR presentation.Off is bit-identical on screen too: X screen captures at the third present of
video_out_hdr_present, compared pixel by pixel.ANYPS5_UPSCALEunset,mainand this PR differ in 0 of 2,073,600 pixels, in three capture pairs.fsr, 679,356 pixels differ, all in the presented image: the frame is sharper at the band edges. Adding the overlay tofsrchanges only the panel (11,023 pixels).GitHub's runners at 672308b (run): the presentation, present-upscale and overlay tests pass 10 runs in a row on Linux, with none skipped. On Windows they build and pass, with 5 of the 8 skipping: the runner has no Vulkan device, so the RTX 3070 run below covers those. The libc and libkernel suites pass on both, run with
APS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.Validation,
mainagainst this PR, on GitHub's Linux runner (run):VK_LAYER_KHRONOS_validationwithANYPS5_NO_SHADER_CACHE=1andANYPS5_REQUIRE_VULKAN=1on llvmpipe, for the same tests plusagc_driver_image_table_vouched_lookups. The loader inserted the layer 5 times onmainand 12 with this PR. Both logs report onlyVUID-VkDeviceCreateInfo-pNext-pNext, so this PR adds noVUID-message.RTX 3070 Laptop GPU at this head (driver 617.42, Windows 11 10.0.26300), offscreen, no other GPU work:
agc_driver_presentation_pass(3.7 s),agc_driver_presentation_fsr(10.9 s) andagc_performance_overlay(2.5 s) pass.agc_driver_present_upscaleskips: NVIDIA's Windows driver has noVK_EXT_headless_surface, which it needs. The figures match lavapipe's: EASU's edge rise is 1.52 px against bilinear's 2.20 on both axes, RCAS at sharpness 2.0 changes the image by at most 0.0241, and edge contrast goes 0.2331 → 0.2482 at 0.2. The tests take the first Vulkan device, which on this laptop is the integrated GPU, so the loader was limited to NVIDIA's driver for that run. The cost mode (--fsr-cost) gives the RTX 3070 column above.HDR10 is tested at the component level only: no HDR10 swapchain was available. lavapipe's offers only SRGB_NONLINEAR, and this PC's displays run SDR.
7ed09f9, a merge of
main5b85225 (run), which brings fix(agc): bound the sampled depth-plane copies #7705, fix(agc): recognise the copy kernel as Demon's Souls 01.007.000 compiles it #8552 and milescoviello's fix(agc): place the presentation source in host memory when device memory runs out #10807. fix(agc): place the presentation source in host memory when device memory runs out #10807 adds a test of the presentation source in host memory totests/PresentationPass.cppwhere this PR adds its FSR tests; the merge keeps both, and nothing else conflicted. That test usesPresentationScaler's constructor and source-image calls, which this PR leaves unchanged. This PR's changed lines are the same as before the merge. The present, upscale, FSR, presentation-pass and performance overlay tests pass 10 runs in a row. Linux: 8 run, 8 pass, 0 skip, 0 fail. Windows: 8 run, 3 pass, 5 skip, 0 fail; the device tests skip, since that runner has no Vulkan device. Suites: libc and libkernel pass on Linux (144 and 209), and libc passes on Windows (171). Windows' libkernel suite runs 227 tests and failsguest_timed_join_import_libkernel_sysandguest_timed_join_import_libkernel_web, which this PR doesn't touch;main88f9967 fails the same two in this verify's Windows job (run), andmain's own Windows CI passes them. The suites ran withAPS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.711dd2a: 59245df, a merge of
main0cd07dc, and a test commit (sweep run, validation run).mainnow has orezraey's feat(videoout): composite the overlay bus over the main output #10507, which composites the overlay plane over the main output, our feat(libSceImeDialog): type with the controller on an on-screen keyboard #11207, which draws the system keyboard over the presented frame, and feat(agc): toggle runtime switches in alternating phases of one run #8160, feat(tools): split the periodic reports of an APS5_AB run by phase #8161 and feat(relinker): trace function imports on macOS #9408. The conflicts were inPresentationPass.hpp,PresentationPass.cpp,VulkanDevice.cppanddocs/dev/ENVIRONMENT.md.PresentationPass: this PR'srecordInto, which FSR's last pass uses, now draws throughmain'starget,destinationFramebufferand scissoreddraw. The pass keeps bothmain's entry dependency and this PR's exit dependency.VulkanDevice: the plane, keyboard and overlay order after an upscale as in What. The upscaler, the keyboard and the plane pass are all kept in the device and retired with its slots, and this PR'sUpscaledPresentsandmain'sPresentCountsboth count.ENVIRONMENT.mdkeeps both rows.agc_driver_present_upscale: a 960x540 display buffer with a 960x540 overlay plane, presented into its 1084x610 headless window withANYPS5_UPSCALE=fsr, must be upscaled with the plane composited.^agc,^video_outand^guest_video_out, with no before arm. Linux: 1121 run, 1022 pass, 99 skip, 0 fail. Windows: 1143 run, 328 pass, 811 skip, 4 fail:agc_driver_pipelined_metadata_pass,agc_driver_pipelined_metadata_pass_draw_pipeline,agc_submit_progressandagc_submit_progress_no_timelineneed a Vulkan device and fail creating it on GitHub's device-less runner, asmain's do there (run). The libc and libkernel suites run 166 and 264 tests on Linux and 194 and 286 on Windows, with 0 failed. The suites ran withAPS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.VK_LAYER_KHRONOS_validationon llvmpipe,mainagainst this head, for the present, upscale, FSR, presentation-pass, overlay and VideoOut tests: the one message isVUID-VkDeviceCreateInfo-pNext-pNext, fromagc_driver_present_upscale's devices, a device struct this layer version doesn't know, as in the validation run above.main's tree has no such test, and neither side reports any otherVUID-message.platform-ps5-video-out-width=1920boot.config change, maximized on the 2560x1440 panel. Environment:ANYPS5_UPSCALE=fsr, the performance overlay on (ANYPS5_OVERLAY=1),APS5_STORAGE_CACHE_ENTRIES=1024andAPS5_THREAD_PRIORITY=high.APS5_STORAGE_CACHE_ENTRIESis the variable fix(agc): cap the storage-image cache by entry count #14220 adds: neither this PR normainreads it, so it had no effect in this run.guest 1920x1080 presented at 2372x1334, and the overlay readsRES: 1920X1080 / 2560X1334.439f672, a merge of
mainedf6804 (×10 run, validation run). The merge was clean:CMakeLists.txt,VulkanDevice.hpp,VulkanDevice.cpp,tests/PerformanceOverlay.cpp,ENVIRONMENT.mdandUSAGE.mdmerged without conflicts. The PR's patch-id is unchanged, so the vendored FidelityFX headers are byte-identical. The Planet of Lana (PPSA19450) screenshot above is from 711dd2a, whose patch this merge doesn't change.agc_driver_present_upscale,agc_driver_presentation_fsr,^agc_driver_presentation_pass,^agc_performance_overlay,^video_outand^guest_video_out. Linux: 40 run, 13 pass, 27 skip, 0 fail. Windows: 38 run, 8 pass, 30 skip, 0 fail. The libc and libkernel suites run 191 and 291 tests on Linux and 220 and 314 on Windows, with 0 failed. The suites ran withAPS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.VK_LAYER_KHRONOS_validationon llvmpipe,mainagainst this head, for the same tests as the validation run above. One VUID appears only with this PR:VUID-VkDeviceCreateInfo-pNext-pNext, from the devicesagc_driver_present_upscalecreates, whose device struct this layer version doesn't know.maincan't show it, because its tree has noagc_driver_present_upscale. Neither side reports any otherVUID-message.c88633c, a merge of
main0afe7a4 (×10 run, validation run), as MarcZX10 asked.mainnow has Get-fix's feat(libSceAgcDriver): draw PS4 (GCN) command buffers #9431, which adds a GCN check (tile mode, pitch and display height) toResidentPresentableinVulkanDevice.cpp. This PR changespresent()and the device's state setup, notResidentPresentable. The merge was clean, and this PR's own diff is unchanged.agc_resident_present, the resident-present tests. Linux: 41 run, 14 pass, 27 skip, 0 fail. Windows: 39 run, 8 pass, 31 skip, 0 fail. The libc and libkernel suites run 193 and 292 tests on Linux and 223 and 315 on Windows, with 0 failed. The suites ran withAPS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.agc_resident_presentadded. The loader inserted the layer 4 times onmainand 12 with this PR. The one VUID that appears only with this PR is againVUID-VkDeviceCreateInfo-pNext-pNext, from the devicesagc_driver_present_upscalecreates, a testmain's tree doesn't have. Neither side reports any otherVUID-message.5165558, a merge of
main1a21775, which brings f0d5ff5, the system dialog drawn in the presentation.RecordRectscall inVulkanDevice.cpp. The merge keepsmain's*systemLayoutand this PR'supscaledin the layout condition.APS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.main1a21775 against this head, the same tests plusagc_driver_sample_multisample_target, amaintest that opens a real device:VK_LAYER_KHRONOS_validation5 times onmainand 13 with this PR.VUID-VkDeviceCreateInfo-pNext-pNext: once onmain, 8 times with this PR, all for VkStructureType 1000574000. This PR adds no VUID.VkPhysicalDeviceMaintenance8FeaturesKHR, whichmain'sVulkanDevice.cppchains into every device it creates. The runner'svulkan-validationlayers1.3.275.0-1 doesn't know it.d0bd686, a merge of
main2b1ae87, which brings MarcZX10's feat(overlay): show controller status on demand or on connect, disconnect and battery drop #12702 (the pad status overlay) (run).VulkanDevice::present, where this PR addsupscaled(FSR) whereverdrawnmeans "the swapchain image is already inCOLOR_ATTACHMENT_OPTIMAL", and feat(overlay): show controller status on demand or on connect, disconnect and battery drop #12702 addspadStatusShown. The merge keeps both:planePass->RecordOverlay: initial layoutdrawn || upscaled, finaloverlay || keyboard || padStatusShown;overlay->Record: initialdrawn || upscaled || plane != nullptr || keyboard || padStatusShown, and theelse ifthe negation of all five.padStatus->RecordRectsgets the sameupscaledthis PR gives the keyboard overlay'sRecordRects, so its initial layout isdrawn || upscaled || plane != nullptr. Without it, an upscaled frame that shows the pad status records the wrong initial layout. The merge commit's message names it.main'sdrawsOveralready includespadStatusShown, and this PR'supscaler->RecordPresentuses it.^video_out,^guest_video_out,agc_resident_presentandagc_driver_sample_multisample_target.APS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.agc_pad_status_overlay,_shared,_eventsand_invalid,agc_keyboard_overlay,agc_performance_overlay_statistics,agc_resident_present,video_out_flip_overlayandvideo_out_flip_padstatuspass 10 of 10, 15 tests in all; the twovideo_out_flip_*tests skip without a display.ctest -R '^(agc|shader)': 1,157 passed, 0 failed.bef1325, jotitadev's fix for
VUID-vkCmdBeginRenderPass-initialLayout-00897(review), with jotitadev as co-author.SHADER_READ_ONLY_OPTIMAL, butPresentationPass::destinationFramebufferandPresentationUpscaler::transientFramebuffernarrowed their views' usage throughVkImageViewUsageCreateInfotoCOLOR_ATTACHMENTand transfer bits. The commit addsSAMPLEDto the view when the pass uses that layout. Both images were already created withSAMPLED.vulkan-sdk-1.4.341.0tag (14de3c0d7b) and loaded throughVK_LAYER_PATH. The 44 tests of the ×10 set below ran 3 times per tree, as an unprivileged user, withANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1:00897messages per run, in all 3 runs:agc_driver_presentation_fsr10,agc_driver_present_upscale8,agc_performance_overlay2.guest_video_out_high_frame_rateskips, since Xvfb has no 120 Hz mode.vulkan-validationlayers, the one GitHub's runner and the NVIDIA bot use): neither tree logs00897. Both log the same 8VUID-VkDeviceCreateInfo-pNext-pNextmessages, forVkPhysicalDeviceMaintenance8FeaturesKHR, which that layer predates.^video_out,^guest_video_out,agc_resident_presentandagc_driver_sample_multisample_target.APS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.VK_LAYER_KHRONOS_validation13 times in each.VUID-VkDeviceCreateInfo-pNext-pNext, so the fix adds none.affd3b1, a merge of
main0836dfd (run). build(agc): register each AGC test executable in its own CMake fragment #12862 movedlibSceAgcDriver's test registrations intotests/cmake/; the conflict inCMakeLists.txtis resolved withtools/agc_test_split.py resolve, which moves this PR's registrations intotests/cmake/agc_driver_presentation_pass_tests.cmake(+6 lines). Nothing else conflicted. Its FSR shader build rules andPresentationUpscaler.cppstay inCMakeLists.txt, unchanged, since they aren't test registrations. Apart from the move, this PR's diff is unchanged. With-DBUILD_TESTING=ON,ctest -Ngives 3077 tests:main's 3075 plus its 2 tests, each listed once. The 54 tests of this PR's verify set pass 10 runs in a row. Linux: 54 run, 18 pass, 36 skip, 0 fail. Windows: 52 run, 11 pass, 41 skip (no Vulkan device), 0 fail. Suites: libc and libkernel pass on Linux (199 and 308) and on Windows (226 and 330). The suites ran withAPS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.Layer 1.4.341 on this head and current
main, as MarcZX10 asked (review):maincbcb37b against affd3b1 on one cloud Linux machine (Ubuntu 24.04.5, lavapipe: Mesa 25.2.8, LLVM 20.1.2), both built with CI's Linux configure.vulkan-sdk-1.4.341.0tag (14de3c0d7b) and loaded throughVK_LAYER_PATH.VK_LOADER_DEBUG=layershows it inserted inside a test process on each tree.ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1.00897.main: 52 run. Offscreen: 16 pass, 36 skip, 0 fail. Xvfb: 51 pass, 1 skip, 0 fail.main's 52 plus this PR's two. Offscreen: 18 pass, 36 skip, 0 fail. Xvfb: 53 pass, 1 skip, 0 fail.guest_video_out_high_frame_rateskips, since Xvfb has no 120 Hz mode.00897messages:agc_driver_presentation_fsr10,agc_driver_present_upscale8,agc_performance_overlay2. Those are d0bd686's counts. With the fix restored, it logs 0.Layer 1.4.341 again, on
maincf79276, as MarcZX10 asked (review), since cbcb37b predates fix(shader): run tessellation evaluation stages one lane per invocation on devices without subgroups there #13807'sVulkanDevice::buildTarget()line.maincf79276, affd3b1, and their clean local merge caa72b2703, which brings that line into this PR. They used the same machine, layer, insertion check and command as the bullet above.00897.main: 52 run. Offscreen: 16 pass, 36 skip, 0 fail. Xvfb: 51 pass, 1 skip, 0 fail.00897messages, the same counts; with the fix restored, 0.NVIDIA RTX 2000 Ada Generation at affd3b1, from TechLevelZero's NVIDIA bot (report): driver 595.99.02, Ubuntu 26.04.1, validation layer 1.3.275.
main, and 1 is unstable onmain.agc_driver_present_upscaleskips there, since that runner has noVK_EXT_headless_surface.57f34f0, a merge of
main4a58bc2, which brings MarcZX10's feat(videoout): add ANYPS5_FPS_LIMIT to cap the rate the window presents #12536 (ANYPS5_FPS_LIMIT) (×10, validation).VulkanDevice::presentanddocs/dev/ENVIRONMENT.md. The merge keeps both sides in each, and this PR's other changed lines are the same:present, the overlay'sNotePresenttakesmain's frame limit argument, and itsRecordand theelsebranch keep this PR's upscaled condition;ENVIRONMENT.mdkeeps both rows.APS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.VK_LAYER_KHRONOS_validationon GitHub's Linux runner),main4a58bc2 against this merge, for the same tests:mainand 13 with this merge;VUID-VkDeviceCreateInfo-pNext-pNext, so the merge adds none.NVIDIA RTX 2000 Ada Generation at 57f34f0, from TechLevelZero's NVIDIA bot (report): this head merged onto
maine6f5730, driver 595.99.02, Ubuntu 26.04.1.main, and 4 are unstable onmain.VK_LAYER_KHRONOS_validation, no new validation IDs over 1,241 GPU tests.agc_driver_presentation_fsrpassed.agc_driver_present_upscaleskips again, since that runner's Vulkan loader has noVK_EXT_headless_surface. Neither is inmain's baseline, so neither was compared.03c1bad, a merge of
main88e804b (run). Two conflicts, each a pair of additions at the same place, and the merge keeps both: this PR'sVulkanDevice::UpscaledPresentsinVulkanDevice.cppbesidemain's newFillCompletionSyncCount, and this PR'sANYPS5_UPSCALErow indocs/dev/ENVIRONMENT.mdbesidemain's newANYPS5_TEST_HOST_IMPORT_ALIGNMENTrow. This PR's diff overmainis unchanged.agc_driver_present_upscale,agc_driver_presentation_fsr,agc_driver_sample_multisample_targetandagc_resident_present, with the presentation-pass, performance-overlay and VideoOut tests, ran 10 times with no failure. Linux: 55 run, 18 pass, 37 skip (the VideoOut flip and guest VideoOut tests, which need a display), 0 fail. Windows: 53 run, 11 pass, 42 skip (the same VideoOut tests, and the AGC presentation and overlay tests, this PR's four among them; no Vulkan device), 0 fail. Suites: libc and libkernel pass on Linux (210 and 310) and on Windows (237 and 331). The suites ran withAPS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.AMD Radeon RX 6300 (RADV NAVI24) at 03c1bad, from TechLevelZero's AMD bot (report): this head merged onto
main1c8c0ef, Mesa 25.2.8, Ubuntu 26.04.1, the full suite, since this PR changes3rdparty/FidelityFX-FSR.main, and 6 are unstable onmain.VK_LAYER_KHRONOS_validation, no new validation IDs over 1,367 GPU tests.agc_driver_present_upscale(29.78 s),agc_driver_presentation_passand the performance-overlay tests passed on the GPU.agc_driver_presentation_fsrprinted its passed line and then hit its 30 s timeout in the bot's 4-way parallel run, at 30.03 s. Run alone underVK_LAYER_KHRONOS_validationon the RX 6300, in the bot's retry, it passed in 19.95 s. 933b263, below, gives it 60 s.AMD Radeon RX 9060 XT (RADV GFX1200), by @RNK123 (comment): Mesa 26.2.5, CachyOS, this head 03c1bad merged onto
main1c8c0ef.agc_driver_presentation_passandagc_performance_overlaypass onmainand on the merge.agc_driver_presentation_fsrpasses 3 of 3, andagc_driver_present_upscale3 of 3 with real headless swapchains, the overlay cases included. TechLevelZero's NVIDIA bot skips that test, since its loader has noVK_EXT_headless_surface.VUID-orSYNC-HAZARD-message.maincomparison): withif (false && upscale.fsr)on the merge,agc_driver_present_upscalefails 3 of 3 at "FSR without the overlay ... was not upscaled".933b263:
agc_driver_presentation_fsrgets 60 s (×10). ItsTIMEOUTintests/cmake/agc_driver_presentation_pass_tests.cmakegoes from 30 to 60, and nothing else changes. The test takes 19.95 s alone underVK_LAYER_KHRONOS_validationon the RX 6300, against a 30.03 s timeout in the bot's 4-way parallel run.APS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.d7a519d, a merge of
main06a9092, which brings SuarezPM's feat(agc): name draws in device-lost fault reports via token ring #14943 (draw names in device-lost fault reports) (×10, validation).VulkanDevice.cpp, where feat(agc): name draws in device-lost fault reports via token ring #14943 addsSubmissionSnapshots.hppandTraceRevision.hppand this PR addsUpscaleMode.hppat the same place. The merge keeps all three. This PR's diff overmainis unchanged.APS5_SKIP_TIMING_TESTS=1, which relaxesprecise_wait's median bounds on GitHub's hosted runners.VK_LAYER_KHRONOS_validationon GitHub's Linux runner),main06a9092 against this merge, for the same tests:mainand 13 with this merge;VUID-VkDeviceCreateInfo-pNext-pNext, so the merge adds none.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)Overlap:
VulkanDevice::present(commit 2) and covers both on together (commit 3), as described under How.docs/dev/ENVIRONMENT.md.libSceAgcDriver/CMakeLists.txt.docs/user/USAGE.md.PresentationPass.hpp. perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508 makesdraw()'sSlot&non-const, and this PR addsrecordInto()next to it; both apply.main. fix(agc): bound the sampled depth-plane copies #7705, fix(agc): recognise the copy kernel as Demon's Souls 01.007.000 compiles it #8552 and fix(agc): place the presentation source in host memory when device memory runs out #10807 merged first, and this branch now has them. Against perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508, which is much larger, it can go first; if perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508 lands first, this PR keeps its non-constSlot&.