Skip to content

perf(agc): reuse image tables that hold storage-viewed entries - #15563

Open
XatiX wants to merge 2 commits into
boykopovar:mainfrom
XatiX:perf/agc-image-table-live-entries
Open

XatiX wants to merge 2 commits into
boykopovar:mainfrom
XatiX:perf/agc-image-table-live-entries

Conversation

@XatiX

@XatiX XatiX commented Nov 3, 2026 •

Copy link
Copy Markdown

What

An image table was reused across draws only if every one of its entries was provably unchanged. One entry that failed the check, for example a sampled texture viewed through its cached storage image (SampledFromStorageEligible: host-imported memory and a storage-capable, uncompressed format), made the whole table resolve again on every draw.

Now such an entry is marked live in the remembered table. When the table is reused, a live entry is resolved through cachedTexture on every draw, as a fresh table resolves it, and the remaining entries are reused as before. CachedTableTextures and the revalidation path skip live entries in the same way. Entries that are rejected, written by the dispatch, or past the table capacity are handled as before.

PPSA18653 binds a table of about 14,200 entries in each of about 730 draws per frame. About 1.6% of each table (about 229 entries) are storage-viewed, so no table was ever reused, and Resources.Complete took about 5.5 s per frame.

The new step in agc_driver_image_table_reuse host-imports a guest block, so its entries are storage-viewed, and then checks three things:

  • the table is reused across three dispatches;
  • the texels written by two image stores, which leave results pending over one entry between those dispatches, are sampled;
  • the stores reach guest memory after a flush.

On main it fails with 0 reused and 3 resolved tables, expected 3 and 0.

Tested

  • Windows 11 Pro 26300, NVIDIA GeForce RTX 5080, driver 617.42.
  • ctest -V -R "table|texture|storage|sampled|bindless" with VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, ANYPS5_NO_SHADER_CACHE=1 and ANYPS5_REQUIRE_VULKAN=1. Both runs were on the same machine, with the related execution tests built (ANYPS5_AGC_EXECUTION_TESTS):
    • this change: 117/117 passed;
    • main: 115/117 passed. Only agc_driver_image_table_reuse and agc_driver_image_table_reuse_draw_pipeline fail;
    • neither log reports the layer as not found, and neither has a VUID- error. The same 4 tests skip in both runs (multisampled pass order and 3 packed16 storage formats). Logs attached.
  • Performance: PPSA18653 (Age of Mythology: Retold v01.043) on the first-run welcome screen, idle, 3840x2160. Captured with APS5_TRACE_SECONDS=20:60 after a warm run, with no other trace or profile switch and the log not redirected. main cannot reach this screen on its own, so both builds carry fix(agc): copy GPU-side indirect draw records when the packet is processed #15327 (GPU hang) and the opt-in clock change, run with APS5_FAIL_UNKNOWN_CLOCKS=1. The base is 68a15ec229 and the change is 12ed9524c8, the same tree plus this commit. Traces attached.
base change
presents in the window 9 20
frame p50 / p90 7965 / 8423 ms 3178 / 3370 ms
Resources.Complete per frame 5495 ms 1206 ms
GPU busy per present 397 ms 298 ms
{"commit":"68a15ec2299e","dirty":false,"env":{"APS5_FAIL_UNKNOWN_CLOCKS":"1","APS5_TRACE_SECONDS":"20:60"},"gpu":"NVIDIA GeForce RTX 5080","driver":"NVIDIA 617.42","os":"Windows 10.0.26300","cpu":"AMD Ryzen 7 9800X3D 8-Core Processor","cpu_threads":16,"memory_mib":32404,"title_id":"PPSA18653","title":"Age of Mythology: Retold","content_version":"01.043.000","resolution":"3840x2160","window":{"spec":"seconds 20:60","first_present":505,"ms":65172.035},"presents":9,"frame_ms":{"p50":7965.365,"p90":8422.926,"p99":8422.926,"max":8422.926},"gpu_busy_ms_per_present":396.860,"worker_busy_pct":{"queue worker 0x0":99.978},"top_phases_ms_per_frame":{"Driver.Packet":7239.496,"Driver.Packet.draw":7108.396,"Driver.Draw":7107.726,"Driver.Draw.draw_and_resource_release":5623.944,"Graphics.Draw":5599.273,"Graphics.Draw.draw_and_resource_release":5589.065,"Resources.Complete":5494.540,"Driver.Draw.shader_compile_and_link":1463.332},"trace_dropped":false,"trace":"aps5-trace-68a15ec2299e-15048.json.gz"}
{"commit":"12ed9524c874","dirty":false,"env":{"APS5_FAIL_UNKNOWN_CLOCKS":"1","APS5_TRACE_SECONDS":"20:60"},"gpu":"NVIDIA GeForce RTX 5080","driver":"NVIDIA 617.42","os":"Windows 10.0.26300","cpu":"AMD Ryzen 7 9800X3D 8-Core Processor","cpu_threads":16,"memory_mib":32404,"title_id":"PPSA18653","title":"Age of Mythology: Retold","content_version":"01.043.000","resolution":"3840x2160","window":{"spec":"seconds 20:60","first_present":506,"ms":60279.308},"presents":20,"frame_ms":{"p50":3178.079,"p90":3369.582,"p99":3401.643,"max":3401.643},"gpu_busy_ms_per_present":298.053,"worker_busy_pct":{"queue worker 0x0":99.953},"top_phases_ms_per_frame":{"Driver.Packet":3012.245,"Driver.Packet.draw":2941.594,"Driver.Draw":2941.148,"Driver.Draw.shader_compile_and_link":1574.332,"Driver.Draw.draw_and_resource_release":1349.491,"Graphics.Draw":1324.282,"Graphics.Draw.draw_and_resource_release":1315.625,"Resources.Complete":1205.909},"trace_dropped":false,"trace":"aps5-trace-12ed9524c874-25392.json.gz"}

Checklist

🤖 Generated with Claude Code

@XairRrR XairRrR left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed — approved

The change marks entries that cannot be proven unchanged as live and re-resolves them through cachedTexture on every reuse. That path does the same work as a fresh resolve. The new test step fails on main and passes with the change, and I found nothing blocking.

What I ran

Head 38e7f40892e428811467e05ede279911e15151e0, main 1e658521a0a599872612bb91949311e2956b5283, merged tree 48eb641f852164cb1e1a8b7d4575de365ac2b81c. Debian 13 VM, 2× Xeon Gold 6136, GCC 14.2.0, lavapipe (Mesa 26.1.6, LLVM 19).

git diff --check 1e658521a0a599872612bb91949311e2956b5283...38e7f40892e428811467e05ede279911e15151e0
python3 tools/check_conventions.py --base 1e658521a0a599872612bb91949311e2956b5283
env VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation ANYPS5_NO_SHADER_CACHE=1 ANYPS5_REQUIRE_VULKAN=1 ctest --test-dir build -V -R image_table_reuse
# negative control
git show 1e658521a0a599872612bb91949311e2956b5283:core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp > core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
ninja -C build agc_driver_image_table_reuse_tests
ctest --test-dir build --output-on-failure -R image_table_reuse
git show 48eb641f852164cb1e1a8b7d4575de365ac2b81c:core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp > core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
ninja -C build libSceAgcDriver agc_driver_image_table_reuse_tests
git status --porcelain
ctest --test-dir build -R image_table_reuse

Results

Check Result
git diff --check clean
check_conventions.py All conventions checks passed
Build of the merged tree (script) ok
Selected tests (script, 2151 ran) no new failures and no timeouts. The 7 known failures also fail on main (agc_driver_division, the denormal-mode tests, vector_constant_factor_tininess and one unwrap test)
Validation comparison (script, 772 Vulkan tests) the layer loaded in 771 tests and was missing in none; no new VUID- lines compared with main
agc_driver_image_table_reuse (validation on) passed, 0.76 s
agc_driver_image_table_reuse_draw_pipeline (validation on) passed, 0.74 s

Host imports are available on lavapipe here, so RunViewedStore actually ran. The "host imports are unavailable" skip line does not appear in the output.

Negative control

I restored ShaderResources.cpp from main and kept the new test. Both tests then fail with the message the description quotes:

output
1/2 Test #1276: agc_driver_image_table_reuse .................***Failed    0.67 sec
AGC graphics: image table reuse: a table of storage-viewed entries, image stores leaving results pending over one between dispatches: 0 reused and 3 resolved tables, expected 3 and 0
2/2 Test #1822: agc_driver_image_table_reuse_draw_pipeline ...***Failed    0.65 sec
AGC graphics: image table reuse: a table of storage-viewed entries, image stores leaving results pending over one between dispatches: 0 reused and 3 resolved tables, expected 3 and 0

After I restored the merged file and rebuilt, both tests pass again, and git status --porcelain is empty.

Findings

Blocking

None.

Non-blocking

  1. A table with no reusable entries now takes a reuse slot. In the fresh path, an entry that fails the lookup-log check is pushed as live (core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp:5649-5651), and reusable stays true. So a table whose entries are all live is still remembered at ShaderResources.cpp:5656-5665. Two examples are a table of DCC-compressed entries and a table of entries with looked->source != nullptr.

    • On main such a table was never remembered.
    • Now every later draw runs TableCurrent and CachedTableTextures and then resolves every entry again anyway, so it gains nothing.
    • It also takes one of the ReusedTableCount = 4 thread-local slots (ShaderResources.cpp:2032), which can push out a table that does benefit from reuse.

    Suggested fix: skip RememberTable when no element is non-live and non-rejected (for example, when fresh.queries is empty).

  2. The live branch in revalidateFull repeats the fallback loop. The new branch at ShaderResources.cpp:3827-3836 repeats the decode and cachedTexture comparison of the fallback loop at ShaderResources.cpp:3847-3855. A small shared lambda would keep the two from drifting apart, for example if the fallback later gains layerRowsBinding the way the non-table walk at ShaderResources.cpp:3795 has it.

I also checked these and found no problem:

  • Reuse matches a fresh resolve. resolveLive does the same steps as the fresh path (decodeEntry, prepareSampled with CompletePendingCpuWrites, lookupSampled, bind). In the reuse path, storageTable and item != nullptr already exclude the imageWritten and missing-binding branches.
  • The cached-texture cursor stays in step. next advances the same way in CachedTableTextures, in the capacity branch and in the reuse loop.
  • The aggregate initialiser {{}, {}, {}, 0, firstLayer, false, {}, true} is correct. It matches the field order (live comes after message).
  • Every pass through the fresh loop either adds one element or clears reusable. So fresh.elements keeps its size equal to binding.count.

Not verified

  • I did not check the PPSA18653 performance numbers or the attached traces, and I did not launch any title. The trace commits (68a15ec229 / 12ed9524c8) also carry #15327 and are not the PR head, as the description says.
  • I did not check the claimed line overlap with #9508.
  • I could not check behaviour on non-lavapipe GPUs. The author reports an NVIDIA RTX 5080 run.

@oneandonlydean oneandonlydean self-assigned this Nov 3, 2026
@github-actions github-actions Bot added the perf Performance change label Nov 3, 2026
@XatiX

XatiX commented Nov 3, 2026

Copy link
Copy Markdown
Author

Thanks @XairRrR, both non-blocking points are taken in b2ca8fa:

  • A table whose entries are all live is no longer remembered, so it does not take a reuse slot. The check is "any element that is not live", so a table of rejected entries is still remembered as before. RunViewedStore now points half of its records at a second, non-imported block, so its table mixes kept and live entries, and a new step binds a table of only storage-viewed entries and expects 0 reused and 2 resolved. Without the check that step fails with 1 reused and 1 resolved tables, expected 0 and 2.
  • The live branch and the fallback in revalidateFull share one lambda, currentTableEntry.

Re-run on the same machine: ctest -R "table|texture|storage|sampled|bindless" 117/117, tools/check_conventions.py passes.

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head 38e7f40 merged onto main 1e65852 · tested 2026-11-03 19:36 UTC · 19 min

GPU NVIDIA RTX 2000 Ada Generation, driver 595.99.02, Vulkan 1.4.329
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-38-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 2,691 passed · 6 failed (0 new, 3 also fail on main, 3 unstable on main) · 48 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 2,745 of 3,818 tests run: the ones this change can reach, chosen by tools/select_tests.py from main's build graph
Vulkan validation ✅ no new validation IDs vs main (928 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.3 s, ⚠️ agc_driver_interpolation_modes 56.0 s, ⚠️ agc_driver_lazy_resolved_abi 39.7 s
Unstable on main (3, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_pipeline_journal: failed in 4 of the last 10 main runs
agc_submit_progress: failed in 6 of the last 10 main runs
agc_submit_progress_no_timeline: failed in 5 of the last 10 main runs
Failing on main too (3, not counted against this PR)
agc_driver_image_table
guest_mmap_executable
guest_socket_options_multicast
Validation IDs already present on main (4 IDs in 517 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (517 tests): agc_driver, agc_driver_address_passes, agc_driver_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, agc_driver_bc_block_copy, agc_driver_bda_anchor_reads, agc_driver_bda_span_reads, and 509 more
VUID-vkCmdCopyImage-srcImage-01548 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-vkCmdCopyImage-srcImage-01551 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (1 test): agc_driver_srgb8_color_target
Skipped (48)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_sample_order_grid_reference: skipped, the device does not keep depth drawn at custom sample locations at those locations, even after a transition that names them: the composite of uniform renders holds the guest's depth in 0 of 3005 sloped samples, so no path can be compared with it bit for bit
agc_driver_scattered_runs: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_stencil_ref_export: skipped, the device lacks VK_EXT_shader_stencil_export
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_import_settle_initial_dcc: skipped, the device has no deferred settle of host imports: imports under 1 MiB wait for one only on Windows
agc_unit_shadow_completion_store: skipped, the device reports watched host memory written when it imports or reads it
guest_http_uri_locale: 
guest_net_ctl: skipped, the host has no IPv4 address
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_output_mode: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_resolution_status: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_wqhd_detection: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
video_out_flip_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_backtoback: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_controls: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip_in_order: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_dcc: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_deferred: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop_main: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not co
Reproduce
git fetch origin 38e7f40892e428811467e05ede279911e15151e0 1e658521a0a599872612bb91949311e2956b5283
git checkout 1e658521a0a599872612bb91949311e2956b5283 && git merge --no-ff 38e7f40892e428811467e05ede279911e15151e0
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 32 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 4 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1

Automated 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.

@github-actions github-actions Bot added the agc libSceAgc* label Nov 3, 2026

@XairRrR XairRrR left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-checked — approved

Commit b2ca8faf64 resolves both non-blocking points from my last review. A table whose entries are all live is no longer remembered, and the two revalidateFull paths share currentTableEntry. The tests and the negative control behave as expected.

What changed since my last review

  • New commit b2ca8faf64 ("keep tables with nothing to reuse out of the reuse slots"). Commit 38e7f40892 is unchanged.
    • ShaderResources.cpp:5677-5678 adds anyKept. A table is remembered only when at least one element is not live. Rejected elements count as not live, so a table of rejected entries is still remembered, as on main.
    • ShaderResources.cpp:3812-3820 adds the currentTableEntry lambda, which is now used by the live branch (:3838) and by the fallback loop (:3853).
  • Test changes. RunViewedStore now points records Viewed..Records at a second block that is not imported (plain). The table therefore mixes kept and live entries, and the expected count goes from 3 reused / 0 resolved to 4 / 0. A new step at ImageTableReuse.cpp:296-301 binds a table of only storage-viewed entries and expects 0 reused and 2 resolved.
  • Author reply in the discussion, describing the above.

What I ran

Head b2ca8faf642de09526cd5d4a7b98574d7e7a7b5f, main 086c0686c8adff3ee648fdbe34e0b0b647e1d511, merged tree 0a25af341deac165d5a9ded01ebc7082aa852e88. Debian 13 VM, 2× Xeon Gold 6136, GCC 14.2.0, lavapipe (Mesa 26.1.6, LLVM 19).

git diff --check 086c0686c8adff3ee648fdbe34e0b0b647e1d511...b2ca8faf642de09526cd5d4a7b98574d7e7a7b5f
python3 tools/check_conventions.py --base 086c0686c8adff3ee648fdbe34e0b0b647e1d511
env VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation ANYPS5_NO_SHADER_CACHE=1 ANYPS5_REQUIRE_VULKAN=1 ctest --test-dir build -V -R image_table_reuse
# negative control 1: drop only the new anyKept condition
sed -i "s/if (reusable && anyKept && CurrentTableState() == state)/if (reusable \&\& CurrentTableState() == state)/" core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
ninja -C build agc_driver_image_table_reuse_tests
ctest --test-dir build --output-on-failure -R image_table_reuse
# negative control 2: all production code from main
git show 086c0686c8adff3ee648fdbe34e0b0b647e1d511:core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp > core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
ninja -C build agc_driver_image_table_reuse_tests
ctest --test-dir build --output-on-failure -R image_table_reuse
# validation lines of agc_driver_image_gather_volume, with the PR's file and with main's file
env VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation ANYPS5_NO_SHADER_CACHE=1 ANYPS5_REQUIRE_VULKAN=1 ctest --test-dir build -V -R "^agc_driver_image_gather_volume$"
# restore
git show 0a25af341deac165d5a9ded01ebc7082aa852e88:core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp > core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
ninja -C build libSceAgcDriver agc_driver_image_gather_volume_tests agc_driver_image_table_reuse_tests
git status --porcelain
ctest --test-dir build -R image_table_reuse
Check Result
git diff --check clean
check_conventions.py All conventions checks passed
Build of the merged tree (script) ok
Selected tests (script, 2171 ran) no new failures and no timeouts. The 7 known failures also fail on the baseline main
agc_driver_image_table_reuse / _draw_pipeline (validation on) both passed, 0.80 s and 0.76 s; host imports are available, so RunViewedStore ran
Validation comparison (script, 783 tests, layer loaded in 782, missing in none) one test with new lines, agc_driver_image_gather_volume. These lines come from main, not from this PR (see below)
Negative control 1 (anyKept removed) both tests fail: a table of only storage-viewed entries, which has nothing to reuse: 1 reused and 1 resolved tables, expected 0 and 2 (the message the author quoted)
Negative control 2 (ShaderResources.cpp from main) both tests fail: a table of storage-viewed and other entries, ...: 0 reused and 4 resolved tables, expected 4 and 0
After restore both tests pass; git status --porcelain is empty

About the agc_driver_image_gather_volume lines. The script marks them "(test not run on main)" because the test was added to main after the validation baseline 1e65852. I ran it with validation on, once with the PR's ShaderResources.cpp and once with main's. Both runs give the same IDs, so they come from main, not from this PR:

VUID counts, the same with either file
2 VUID-VkSamplerCreateInfo-addressModeU-01079
2 VUID-VkSamplerCreateInfo-addressModeU-parameter
2 VUID-VkSamplerCreateInfo-addressModeV-parameter
2 VUID-VkSamplerCreateInfo-addressModeW-parameter

Previous findings

  1. A table with no reusable entries takes a reuse slot: Resolved. ShaderResources.cpp:5677-5678 now remembers a table only if some element is not live. With that condition removed, the new step fails with 1 reused and 1 resolved tables, expected 0 and 2; with it, the step passes. The author chose "any element not live" instead of my suggested fresh.queries empty, so tables of rejected entries are still remembered as on main. That keeps their rejection messages from being decoded again, which is reasonable.
  2. The live branch in revalidateFull repeats the fallback loop: Resolved. Both paths now call currentTableEntry (ShaderResources.cpp:3812-3820, used at :3838 and :3853). The fallback condition is equivalent to the old one: the textureIndex >= textures.size() guard moved into the lambda, and the comparison is the same || chain. The lambda captures textureIndex by reference, and both callers advance it after the call, as before.

New findings

Blocking

None.

Non-blocking

None.

Not verified

  • I did not check the PPSA18653 performance numbers or traces, and launched no title. They were captured on 68a15ec229 / 12ed9524c8, which carry #15327 and the first commit only. The second commit only narrows when a table is remembered, so it should not slow the measured scene, but I have not measured that.
  • I could not check behaviour on non-lavapipe GPUs. The author reports a 117/117 rerun on the NVIDIA RTX 5080, which I accept as author-reported.

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head b2ca8fa merged onto main 1e65852 · tested 2026-11-03 20:30 UTC · 25 min

GPU NVIDIA RTX 2000 Ada Generation, driver 595.99.02, Vulkan 1.4.329
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-38-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 2,690 passed · 7 failed (0 new, 3 also fail on main, 4 unstable on main) · 48 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 2,745 of 3,818 tests run: the ones this change can reach, chosen by tools/select_tests.py from main's build graph
Vulkan validation ✅ no new validation IDs vs main (928 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.1 s
Unstable on main (4, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_pipeline_journal: failed in 4 of the last 10 main runs
agc_driver_submit_progress: failed in 5 of the last 10 main runs
agc_submit_progress: failed in 6 of the last 10 main runs
agc_submit_progress_no_timeline: failed in 5 of the last 10 main runs
Failing on main too (3, not counted against this PR)
agc_driver_image_table
guest_mmap_executable
guest_socket_options_multicast
Validation IDs already present on main (4 IDs in 517 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (517 tests): agc_driver, agc_driver_address_passes, agc_driver_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, agc_driver_bc_block_copy, agc_driver_bda_anchor_reads, agc_driver_bda_span_reads, and 509 more
VUID-vkCmdCopyImage-srcImage-01548 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-vkCmdCopyImage-srcImage-01551 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (1 test): agc_driver_srgb8_color_target
Skipped (48)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_sample_order_grid_reference: skipped, the device does not keep depth drawn at custom sample locations at those locations, even after a transition that names them: the composite of uniform renders holds the guest's depth in 0 of 3005 sloped samples, so no path can be compared with it bit for bit
agc_driver_scattered_runs: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_stencil_ref_export: skipped, the device lacks VK_EXT_shader_stencil_export
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_import_settle_initial_dcc: skipped, the device has no deferred settle of host imports: imports under 1 MiB wait for one only on Windows
agc_unit_shadow_completion_store: skipped, the device reports watched host memory written when it imports or reads it
guest_http_uri_locale: 
guest_net_ctl: skipped, the host has no IPv4 address
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_output_mode: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_resolution_status: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_wqhd_detection: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
video_out_flip_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_backtoback: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_controls: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip_in_order: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_dcc: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_deferred: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop_main: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not co
Reproduce
git fetch origin b2ca8faf642de09526cd5d4a7b98574d7e7a7b5f 1e658521a0a599872612bb91949311e2956b5283
git checkout 1e658521a0a599872612bb91949311e2956b5283 && git merge --no-ff b2ca8faf642de09526cd5d4a7b98574d7e7a7b5f
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 32 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 4 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1

Automated 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.

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ AMD GPU test: passed

PR head b2ca8fa merged onto main 1e65852 · tested 2026-11-03 22:28 UTC · 20 min

GPU AMD Radeon RX 6300 (RADV NAVI24), driver Mesa 25.2.8-0ubuntu0.24.04.4, Vulkan 1.4.318
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-42-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 2,678 passed · 10 failed (0 new, 9 also fail on main, 1 unstable on main) · 57 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 2,745 of 3,818 tests run: the ones this change can reach, chosen by tools/select_tests.py from main's build graph
Vulkan validation ✅ no new validation IDs vs main (928 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.4 s, ⚠️ public_headers 73.6 s, ⚠️ conventions_pr_template 32.1 s
Unstable on main (1, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_pipeline_journal: failed in 7 of the last 9 main runs
Failing on main too (9, not counted against this PR)
agc_driver_image_table
agc_driver_native_depth_bda_clear
agc_driver_native_multisample_depth
agc_driver_store_over_untracked
agc_driver_submit_progress
agc_submit_progress
agc_submit_progress_no_timeline
guest_mmap_executable
guest_socket_options_multicast
Validation IDs already present on main (4 IDs in 517 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (517 tests): agc_driver, agc_driver_address_passes, agc_driver_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, agc_driver_bc_block_copy, agc_driver_bda_anchor_reads, agc_driver_bda_span_reads, and 509 more
VUID-vkCmdCopyImage-srcImage-01548 (4 tests): agc_driver_depth_clear_hle, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-vkCmdCopyImage-srcImage-01551 (4 tests): agc_driver_depth_clear_hle, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (1 test): agc_driver_srgb8_color_target
Skipped (57)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_copied_writer_label_order: skipped, the device reports a minStorageBufferOffsetAlignment of 4, so the dispatch binds its record at +0x1004 in place and nothing is written back; the test needs an alignment above 4
agc_driver_float16_unused_nan_payloads: skipped, the device has no native f16 conversions with RTE rounding and kept f16 denormals
agc_driver_image_table_vouched_lookups: skipped, the device reports 4 of 4 host-imported pages written after a GPU read, so a watched imported table cannot be vouched for
agc_driver_linear_target_direct_write_completion: skipped, the device does not keep host imports write-watched, so no completion stamp over the target is tracked
agc_driver_ngg_vertex_wave_reduction: skipped, s3 describes a 32-lane wave only on 32-lane subgroups, and the device has 64 lanes
agc_driver_scattered_runs: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_unit_shadow: skipped, the device does not import watched host memory for unit shadows
agc_driver_unit_shadow_budget: skipped, the device does not import watched host memory for unit shadows
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_idle_publish_wait: skipped, the device reports 4 of 4 host-imported pages written after a GPU read, so a forced watch of the import reads its submissions as CPU stores
agc_import_settle_initial_dcc: skipped, the device has no deferred settle of host imports: imports under 1 MiB wait for one only on Windows
agc_shadowed_key_stores: skipped, the device imports no watched host memory under a unit shadow
agc_small_tiled_shadow_label: skipped, host imports are unavailable: the test block is not imported and watched
agc_unit_shadow: skipped, the device does not import watched host memory for unit shadows
agc_unit_shadow_completion_store: skipped, the device reports watched host memory written when it imports or reads it
guest_http_uri_locale: 
guest_net_ctl: skipped, the host has no IPv4 address
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_output_mode: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_resolution_status: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_wqhd_detection: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
video_out_flip_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_backtoback: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_controls: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscree
Reproduce
git fetch origin b2ca8faf642de09526cd5d4a7b98574d7e7a7b5f 1e658521a0a599872612bb91949311e2956b5283
git checkout 1e658521a0a599872612bb91949311e2956b5283 && git merge --no-ff b2ca8faf642de09526cd5d4a7b98574d7e7a7b5f
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 12 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 16 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1

Automated 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.

JamesPSlater and others added 2 commits November 4, 2026 09:54
A table entry viewed through a cached storage image, or otherwise not
provably unchanged, no longer stops the whole table from being reused.
Such entries are marked live and resolved through the texture cache on
every draw; the rest of the table is reused as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A table whose entries are all live gains nothing from reuse, so it no
longer takes one of the reuse slots. The live entry check in
revalidateFull and its fallback now share one lambda.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@XatiX
XatiX force-pushed the perf/agc-image-table-live-entries branch from b2ca8fa to ec5cbbd Compare November 4, 2026 10:49
@XatiX

XatiX commented Nov 4, 2026

Copy link
Copy Markdown
Author

Rebased onto main b11c7bf84f (now f53a1ae8d4 + ec5cbbd69b); no other change. @XairRrR, this moves your approval off the head, sorry for the churn.

The conflict was in resolveImageTable: main added the dynamic-resolution variant substitutes in the same loop this PR splits into decodeEntry / prepareSampled. Resolution keeps main's early substitutes check before decoding, and records the representative from the narrowed sample (sampled.resource, sampled.guestBytes), as main did with its reassigned resource.

Re-run on the rebased head (RTX 5080, 617.42, Windows 11, WinLibs GCC 15.2.0 Release, VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation ANYPS5_NO_SHADER_CACHE=1 ANYPS5_REQUIRE_VULKAN=1):

  • ctest -R "table|texture|storage|sampled|bindless|variant": 128/128, 0 VUID- lines;
  • ctest -R image_table with ImageTableVariants added to the build: 11/11, agc_driver_image_table_variants included;
  • tools/check_conventions.py --base upstream/main: passed.

@XatiX

XatiX commented Nov 4, 2026 •

Copy link
Copy Markdown
Author

Paired runs for the rebased head ec5cbbd69b, attached below (file names start with pr15563-):

  • pr15563-change-ec5cbbd69b-ctest.log: the PR head, 128/128 passed.
  • pr15563-main-b11c7bf84f-control-ctest.log: the control, the same tree with core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp from main b11c7bf84f. 126/128: agc_driver_image_table_reuse and agc_driver_image_table_reuse_draw_pipeline fail with a table of storage-viewed and other entries, ...: 0 reused and 4 resolved tables, expected 4 and 0.
  • pr15563-build-settings.txt: the tested commits, compiler, CMake options, the full ANYPS5_AGC_EXECUTION_TESTS list and the ctest command.

ImageTableVariants (added on main, in the loop this rebase had to merge) is in the build list for both runs, and agc_driver_image_table_variants passes in both. Each log starts with its tested revision and VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation ANYPS5_NO_SHADER_CACHE=1 ANYPS5_REQUIRE_VULKAN=1; neither reports the layer as not found or has a VUID- line. The same 4 tests skip in both runs, because their fixtures are not in this build's list.
pr15563-build-settings.txt
pr15563-change-ec5cbbd69b-ctest.log
pr15563-main-b11c7bf84f-control-ctest.log

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Nov 4, 2026
@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head ec5cbbd merged onto main b11c7bf · tested 2026-11-04 14:53 UTC · 27 min

GPU NVIDIA RTX 2000 Ada Generation, driver 595.99.02, Vulkan 1.4.329
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-38-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 2,767 passed · 6 failed (0 new, 3 also fail on main, 3 unstable on main) · 49 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 2,822 of 3,894 tests run: the ones this change can reach, chosen by tools/select_tests.py from main's build graph
Vulkan validation ✅ no new validation IDs vs main (974 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.1 s
Unstable on main (3, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_pipeline_journal: failed in 3 of the last 10 main runs
agc_driver_submit_progress: failed in 3 of the last 10 main runs
agc_submit_progress: failed in 4 of the last 10 main runs
Failing on main too (3, not counted against this PR)
agc_driver_image_table
guest_mmap_executable
guest_socket_options_multicast
Validation IDs already present on main (13 IDs in 549 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (549 tests): agc_driver, agc_driver_address_draw_space_reuse, agc_driver_address_passes, agc_driver_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, agc_driver_bc_block_copy, agc_driver_bda_anchor_reads, and 541 more
VUID-VkShaderModuleCreateInfo-pCode-08737 (8 tests): agc_driver_dpp16_operands, agc_driver_dpp8_pk_fmac, agc_driver_dx10_clamp, agc_driver_float16_fma_rounding, agc_driver_float16_unused_nan_payloads, agc_driver_packed_alu, agc_driver_packed_f16_denormal_modes, agc_driver_packed_float16_native
VUID-VkShaderModuleCreateInfo-pCode-08739 (8 tests): agc_driver_dpp16_operands, agc_driver_dpp8_pk_fmac, agc_driver_dx10_clamp, agc_driver_float16_fma_rounding, agc_driver_float16_unused_nan_payloads, agc_driver_packed_alu, agc_driver_packed_f16_denormal_modes, agc_driver_packed_float16_native
VUID-VkShaderModuleCreateInfo-pCode-08741 (8 tests): agc_driver_dpp16_operands, agc_driver_dpp8_pk_fmac, agc_driver_dx10_clamp, agc_driver_float16_fma_rounding, agc_driver_float16_unused_nan_payloads, agc_driver_packed_alu, agc_driver_packed_f16_denormal_modes, agc_driver_packed_float16_native
VUID-vkCmdCopyImage-srcImage-01548 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-vkCmdCopyImage-srcImage-01551 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (1 test): agc_driver_srgb8_color_target
VUID-VkPipelineShaderStageCreateInfo-module-parameter (1 test): agc_driver_float16_unused_nan_payloads
VUID-VkPipelineShaderStageCreateInfo-pSpecializationInfo-06849 (1 test): agc_driver_float16_unused_nan_payloads
VUID-VkSamplerCreateInfo-addressModeU-01079 (1 test): agc_driver_image_gather_volume
VUID-VkSamplerCreateInfo-addressModeU-parameter (1 test): agc_driver_image_gather_volume
VUID-VkSamplerCreateInfo-addressModeV-parameter (1 test): agc_driver_image_gather_volume
VUID-VkSamplerCreateInfo-addressModeW-parameter (1 test): agc_driver_image_gather_volume
Skipped (49)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_gcn_display_present: skipped, no display: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
agc_driver_sample_order_grid_reference: skipped, the device does not keep depth drawn at custom sample locations at those locations, even after a transition that names them: the composite of uniform renders holds the guest's depth in 0 of 3005 sloped samples, so no path can be compared with it bit for bit
agc_driver_scattered_runs: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_stencil_ref_export: skipped, the device lacks VK_EXT_shader_stencil_export
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_import_settle_initial_dcc: skipped, the device has no deferred settle of host imports: imports under 1 MiB wait for one only on Windows
agc_unit_shadow_completion_store: skipped, the device reports watched host memory written when it imports or reads it
guest_http_uri_locale: 
guest_net_ctl: skipped, the host has no IPv4 address
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_output_mode: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_resolution_status: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_wqhd_detection: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
video_out_flip_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_backtoback: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_controls: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip_in_order: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_dcc: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_deferred: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not av
Reproduce
git fetch origin ec5cbbd69b2bcdb9eebecd57d328bc6044023b1a b11c7bf84f5d2f636ff60166cc3371bd071e24d5
git checkout b11c7bf84f5d2f636ff60166cc3371bd071e24d5 && git merge --no-ff ec5cbbd69b2bcdb9eebecd57d328bc6044023b1a
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 32 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 4 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1

Automated 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.

@SleglJan

SleglJan commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

One non-blocking point on the new test step. I ran it ported onto our tree (described below) on two Linux hosts, not the PR head itself.

RunViewedStore guards host imports but not the write watch. RunTests in the same file reads AgcDriver::GuestMemory::WriteWatched() and, without a watch, expects 0 reused / 3 resolved, prints "guest memory has no write watch: image table reuse is not tested" and returns. On a Linux host with lavapipe (host imports) and no userfaultfd (no write watch), the step runs with every entry live. Both agc_driver_image_table_reuse and agc_driver_image_table_reuse_draw_pipeline failed there at Expect(before, 4, 0, ...) with "0 reused and 4 resolved tables, expected 4 and 0". The test lines were the PR's, unchanged. A check after the host-import check would fix it (or, as RunTests does, keep the dispatches and expect 0 / 4 without a watch):

if (!AgcDriver::GuestMemory::WriteWatched()) {
    std::puts("guest memory has no write watch: a table of storage-viewed entries is not tested");
    return;
}

With that, the step skips on that host. It passes on a desktop with the watch (RX 9070 XT, RADV Mesa 26.2.4, Linux, run with ANYPS5_REQUIRE_VULKAN=1): the Expect(4, 0) and Expect(0, 2) checks hold.

Timing on 007

Setup:

Six 20-minute runs in one session, alternated base / port. The figure is seconds per frame over presents 5 to 1,005 after the first lit frame of the scripted opening walk:

pair base port port / base
1 0.606 0.552 0.911
2 0.601 0.581 0.967
3 0.704 0.592 0.840
  • Ratios are from unrounded values; their mean is 0.906.
  • Pair 3's base run is the slowest of the three base runs. Pairs 1-2 alone read 0.911 / 0.967.
  • An earlier series that evening, on the same two trees, gave two valid pairs (0.910, 0.944). Its other two port runs were invalid by our shader-cache rule (misses in the first 10 s) and are not shown.
  • Peak RSS was within 0.2 GB per pair, except the port's third run (+0.4 GB).
  • No reuse counters here: timing runs carry no profile.

AI-assisted: yes (Claude Code)

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ AMD GPU test: passed

PR head ec5cbbd merged onto main 4639eff · tested 2026-11-05 07:23 UTC · 26 min

GPU AMD Radeon RX 6300 (RADV NAVI24), driver Mesa 25.2.8-0ubuntu0.24.04.4, Vulkan 1.4.318
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-42-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 2,792 passed · 8 failed (0 new, 7 also fail on main, 1 unstable on main) · 67 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 2,867 of 3,962 tests run: the ones this change can reach, chosen by tools/select_tests.py from main's build graph
Vulkan validation ✅ no new validation IDs vs main (986 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.5 s, ⚠️ public_headers 56.7 s, ⚠️ agc_driver_image_sample_unnormalized 30.8 s
Unstable on main (1, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_pipeline_journal: failed in 9 of the last 10 main runs
Failing on main too (7, not counted against this PR)
agc_driver_image_table
agc_driver_native_depth_bda_clear
agc_driver_native_multisample_depth
agc_driver_submit_progress
agc_submit_progress
agc_submit_progress_no_timeline
guest_mmap_executable
Validation IDs already present on main (4 IDs in 556 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (556 tests): agc_driver, agc_driver_address_draw_space_reuse, agc_driver_address_passes, agc_driver_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, agc_driver_bc_block_copy, agc_driver_bda_anchor_reads, and 548 more
VUID-vkCmdCopyImage-srcImage-01548 (4 tests): agc_driver_depth_clear_hle, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-vkCmdCopyImage-srcImage-01551 (4 tests): agc_driver_depth_clear_hle, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (2 tests): agc_driver_prepared_exports, agc_driver_srgb8_color_target
Skipped (67)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_copied_writer_label_order: skipped, the device reports a minStorageBufferOffsetAlignment of 4, so the dispatch binds its record at +0x1004 in place and nothing is written back; the test needs an alignment above 4
agc_driver_float16_unused_nan_payloads: skipped, the device has no native f16 conversions with RTE rounding and kept f16 denormals
agc_driver_gcn_display_present: skipped, no display: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
agc_driver_image_table_vouched_lookups: skipped, the device reports 4 of 4 host-imported pages written after a GPU read, so a watched imported table cannot be vouched for
agc_driver_linear_target_direct_write_completion: skipped, the device does not keep host imports write-watched, so no completion stamp over the target is tracked
agc_driver_ngg_vertex_wave_reduction: skipped, s3 describes a 32-lane wave only on 32-lane subgroups, and the device has 64 lanes
agc_driver_recorded_draw_staging: skipped, the device does not keep host imports write-watched, so the target is never resident
agc_driver_scattered_runs: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_unit_shadow: skipped, the device does not import watched host memory for unit shadows
agc_driver_unit_shadow_budget: skipped, the device does not import watched host memory for unit shadows
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_idle_publish_wait: skipped, the device reports 4 of 4 host-imported pages written after a GPU read, so a forced watch of the import reads its submissions as CPU stores
agc_import_settle_initial_dcc: skipped, the device has no deferred settle of host imports: imports under 1 MiB wait for one only on Windows
agc_shadowed_key_stores: skipped, the device imports no watched host memory under a unit shadow
agc_small_tiled_shadow_label: skipped, host imports are unavailable: the test block is not imported and watched
agc_storage_clear_hand_over: skipped, the device imports no watched host memory for the clear-key hand-over
agc_unit_shadow: skipped, the device does not import watched host memory for unit shadows
agc_unit_shadow_completion_store: skipped, the device reports watched host memory written when it imports or reads it
guest_http_uri_locale: 
guest_net_ctl: skipped, the host has no IPv4 address
guest_net_ctl_disconnected: skipped, the host has no IPv4 address
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_disabled: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_four_k: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_height_only: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_limit: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_malformed: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | 
Reproduce
git fetch origin ec5cbbd69b2bcdb9eebecd57d328bc6044023b1a 4639eff7f4c23325a916875a0e37f1e312fa18f4
git checkout 4639eff7f4c23325a916875a0e37f1e312fa18f4 && git merge --no-ff ec5cbbd69b2bcdb9eebecd57d328bc6044023b1a
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 12 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 16 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1

Automated 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.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc* perf Performance change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants