Skip to content

fix(libSceNgs2): buffer sampler filter params sent during processing - #14242

Merged
oneandonlydean merged 1 commit into
boykopovar:mainfrom
viktorhantosi:fix/ngs2-buffer-sampler-filter
Nov 3, 2026
Merged

oneandonlydean merged 1 commit into
boykopovar:mainfrom
viktorhantosi:fix/ngs2-buffer-sampler-filter

Conversation

@viktorhantosi

Copy link
Copy Markdown
Contributor

What

A sampler voice filter param (0x1000000a) that a title sends while the NGS2 system renders, or while earlier controls on the voice are still buffered, ended the process:

terminate called after throwing an instance of 'std::runtime_error'
  what():  NGS2: this buffered voice parameter is not implemented

Controls sent during processing have been buffered since #12995 (CaptureParamControl), but the PS5 sampler filter param, which ApplySamplerParam has handled since 52be0d5, was not on the buffered list. Red Dead Redemption (PPSA30528) sends one about 20 s after start, during the opening, so on current main it stops there; the earlier reports in its thread predate #12995 and reached gameplay.

  • CaptureParamControl now accepts the filter param on a sampler voice: it runs the same checks as the immediate path, with the same return codes (custom sampler rack, another rack, size, filter index, type, location), and buffers a copy that ApplyPendingControls passes to ApplyParam, as setups and patches already are.
  • The four filter checks move from Ngs2SetFilter into CheckFilter, and the PS4/PS5 layout handling from ApplySamplerParam into SamplerFilterParam, so both paths share them. The immediate path's behaviour is unchanged.
  • ngs2_jobbuffer gains a filter scenario: during processing, each rejected filter returns the code the immediate path returns for it, and a 1 kHz low-pass sent then is applied (a Nyquist-rate signal drops below 1/1000 of its energy). Without the change the scenario stops with the error above.

Not in this PR: the custom-rack filter param (0x400013xx), the sampler exit-loop and peak-meter params are not on the buffered list either and would throw the same way. No title is known to send them during processing.

Tested

CachyOS Linux (kernel 7.3.0-4-cachyos), GCC 16.2.1, Release; AMD Ryzen 7 5800X; NVIDIA GeForce RTX 2060 (615.78.08).

  • ctest -R ngs2: 45 of 45 pass, including the new filter scenario (182 ngs2_jobbuffer scenarios in all) and the ngs2_core_* PS4 tests. The filter scenario fails on main with the error above.
  • Red Dead Redemption (PPSA30528, 01.002.000), relinked on main dc9dc7eaae: on main it stops ~20 s in with the error above (2 of 2 runs); with this change it runs through the opening into gameplay (3 runs, the longest 240 s), with no terminate, not implemented or driver failure in the log.

tools/pr_overlap.py could not compare seven open NGS2 PRs that conflict with main. Checked by hand: none changes the filter handling; #13857, #13938 and #14119 edit other branches of CaptureParamControl, and #13857 and #13938 also add scenarios to Ngs2JobBuffer.cpp, so whichever lands second needs a small rebase there.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: none
  • Unblocks: PPSA30528 Red Dead Redemption (PPSA30528) #9914
  • GPUs tested: n/a
  • AI-assisted: yes (Claude Code)

🤖 Generated with Claude Code

@github-actions github-actions Bot added prx unblocks title Names a title ID on the Unblocks line labels Nov 1, 2026
@github-actions

github-actions Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

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.

Pull request Shared files not compared
PR 1384 core/libs/prx/libSceNgs2.native/src/Voice.cpp
PR 5548 core/libs/prx/libSceNgs2.native/src/Voice.cpp
PR 11388 core/libs/prx/libSceNgs2.native/src/Voice.cpp

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Nov 1, 2026

@MarcZX10 MarcZX10 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 — conflicts with current main; needs a rebase before merge

This PR buffers sampler filter parameters that the game sends while a voice is processing. The stack check reports a merge conflict against the current base, because main has changed the same libSceNgs2.native files since this PR's base. The code was read in part, and no hosted test has run on this head. The conflict has to be resolved first.

What I ran

  • Head c31a358b1c0221205f7eba41a9aa73b32eb71ea7; base b5705afa47849dd56ef268929edab06352e4f078. 2 files, +106/-28: libSceNgs2.native/src/Voice.cpp (the filter parameter checks and the PS4 and PS5 parameter layouts) and libSceNgs2.native/tests/Ngs2JobBuffer.cpp (the test).
  • Read the production diff in part: the new CheckFilter and SamplerFilterParam functions, and the branch that handles SCE_NGS2_SAMPLER_VOICE_PARAM_FILTER. Did not read the buffering logic that sends the parameters during processing, or the test.
  • Stack check: PR #14242: conflict against current base (current main 4569fe654a). Main changed seven libSceNgs2.native files (646 insertions) after this PR's base. Individual previews: conflict. No declared dependencies.
  • Hosted: the check runs for this head are conventions, intake and labels only. Windows and the relinkers did not run.
  • Read-only checks from the trusted main checkout: diff check and conventions passed. The stack check exited 1 (the conflict). ABI audit passed with warnings: 22 public-declaration-not-found findings (for example CountBlockEnd, RaceComplete, RunPeerAction, SetupPeer), not compared with the base.
  • No MarcZX10 review at this head.

Results

Check Result Note
Diff check passed
Conventions and PR template passed conventions check from the main checkout
Mergeability conflict the stack check reports a conflict against current main; main has changed both of this PR's files (Voice.cpp and Ngs2JobBuffer.cpp) since the base
Filter parameter checks (read in part) passed by reading sizes, the filter index, the type, and the location checks follow the PS4 and PS5 layouts as written
Buffering during processing (not read) not verified the logic that holds parameters while a voice processes was not read
The test Ngs2JobBuffer not run no hosted run on this head
ABI audit (main-checkout tool) passed with warnings 22 public-declaration-not-found findings; whether they predate this PR was not checked
Hosted CI not run conventions, intake and labels only; Windows and the relinkers did not run
Read-only check output

Precheck was not run: no PR-head code is run here. Diff check: passed. Conventions: passed. ABI audit: passed with warnings (22). Stack check: exit 1, individual preview in conflict. Hosted: gh api repos/boykopovar/AnyPS5/commits/c31a358b1c0221205f7eba41a9aa73b32eb71ea7/check-runs.

Negative control

Not run here. A negative control needs a local build, and code from this head is not run here.

Findings

Blocking

  • The PR conflicts with the current base. Rebase onto current main, resolve the conflicts in Voice.cpp and Ngs2JobBuffer.cpp (both changed on main since this PR's base), and push.

Non-blocking

  • The buffering logic and the test were not read in this pass, so there is no verdict on them.
  • The ABI audit's 22 warnings need a look against the base.

Sources

Not verified

  • The buffering logic during processing and the test.
  • Whether the ABI warnings predate this PR.
  • Behaviour after the rebase (the rebased head will need a fresh review).

To get this to a good state

  • Rebase onto current main and push. Then request a fresh review at the new head.

A sampler voice param 0x1000000a (filter) sent while the system renders,
or while earlier controls are still buffered, went to the buffered path,
which did not list it and threw "this buffered voice parameter is not
implemented". The filter is now validated as the immediate path does,
with the same return codes, and buffered as a copy that ApplyParam
applies with the other buffered controls.

The filter checks move out of Ngs2SetFilter into CheckFilter, and the
PS4 and PS5 layout handling into SamplerFilterParam, so both paths use
the same code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@viktorhantosi

Copy link
Copy Markdown
Contributor Author

Rebased onto current main (88e804b0a7). Voice.cpp merged cleanly; in Ngs2JobBuffer.cpp the filter test now sits beside main's renamed TestBufferedAppendAfterDrain and the new waveform-code test (case count 7). All 46 ngs2 tests pass locally; conventions check passes. Negative control at the new head: with Voice.cpp reverted to main, the filter scenario stops with NGS2: this buffered voice parameter is not implemented; with the change it passes. The 22 ABI public-declaration-not-found warnings name existing test helpers on main (CountBlockEnd, RaceComplete, RunPeerAction, SetupPeer); this PR adds none of them. Ready for a fresh look at the new head.

@viktorhantosi
viktorhantosi force-pushed the fix/ngs2-buffer-sampler-filter branch from c31a358 to f0ed4cb Compare November 2, 2026 09:44
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Nov 2, 2026
@B-Howell

B-Howell commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

Tester run of f0ed4cb817, merged locally onto current main 9090972b7e. The merge is clean. main is 1446 commits past this PR's base and has since changed libSceNgs2.native (#10599 custom Reverb, #12864 PitchShift exp2f), so this rechecks the author's 09:44Z results on today's tree and on Linux.

Setup: Windows 11, WinLibs GCC 15.2.0 r7, and WSL2 Ubuntu 22.04, GCC 11.4. Both are Release builds with BUILD_TESTING=ON, on a Ryzen 7 7800X3D.

Tests: ctest -R '^ngs2' --repeat until-fail:3 (47 tests on current main):

arm Windows Linux
main 47/47 x3 47/47 x3
main + PR 47/47 x3 47/47 x3
control: main + PR with Voice.cpp from main ngs2_jobbuffer fails (0xc0000409, NGS2: this buffered voice parameter is not implemented), 46 pass same (Subprocess aborted)

The control gives the same result as the author's own on current main, on both OSes. check_skips.py reports 0 skipped tests.

Buffering path (read at f0ed4cb817): while the voice is processing, capture of SCE_NGS2_SAMPLER_VOICE_PARAM_FILTER rejects a custom sampler first, then another rack. After that it runs the same size check (SamplerFilterParam) and CheckFilter as the immediate path, in the same order. ApplyPendingControls replays the copied param through ApplyParam -> Ngs2SetFilter, which runs CheckFilter again. The PS5 size check therefore runs twice on the buffered path, which is harmless.

PS4 library: the registered ngs2_core_jobbuffer test runs only the over scenario, and the new filter scenario builds the PS5 Ngs2SamplerVoiceFilterParam. So no test sends the 0x30-byte Ngs2Ps4SamplerVoiceFilterParam while the system renders. I ran a local probe (not pushed) that does the same flow in ngs2_core_jobbuffer_tests with the PS4 layout. While the system rendered, each rejected param returned the same code as the immediate path:

  • index 8: 0x804a0600
  • location 18: 0x804a0602
  • size 0x28: 0x804a030a
  • custom sampler: 0x804a0308

A 1 kHz low-pass was accepted (0x0) and applied: energy went from 3.64 to 5.2e-14. The probe passed 3/3 on Windows and on Linux. With Voice.cpp from main it aborts with the error above. A PS4 variant of filter registered on ngs2_core_jobbuffer_tests would cover this path.

Overlap: the open NGS2 PRs #13491, #15039, #9149, #14119, #12673, #14379 and #13703 each merge cleanly on top of main + this PR. #1384, #5548 and #11388, which the overlap bot could not compare, and #12107 already conflict with main on their own.

The Build, Emscripten library portability and Progress report runs on this head are action_required, so hosted Windows and relinker CI have not run yet.

AI-assisted: yes (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

When a sampler filter param arrives during processing, the change now checks it and buffers it the same way the immediate path handles it. The new filter scenario passes on the merged tree. With Voice.cpp restored from main, it aborts with the reported error.

What I ran

Head f0ed4cb8171a9ebe2fd524e69529600198352dd8, main 9090972b7e91fd266819cbd77a8b058e177b5682, merged tree 26df95f13e28e746730e05e0907b5fe992da5197. Debian 13 VM (Xeon Gold 6136), GCC 14.2.0, Release, Ninja, BUILD_TESTING=ON.

git diff --check 9090972b7e91fd266819cbd77a8b058e177b5682...f0ed4cb8171a9ebe2fd524e69529600198352dd8
python3 tools/check_conventions.py --base 9090972b7e91fd266819cbd77a8b058e177b5682
ctest --test-dir build -j8 --test-load 32 -R ngs2 --output-on-failure
# negative control
git show 9090972b7e:core/libs/prx/libSceNgs2.native/src/Voice.cpp > core/libs/prx/libSceNgs2.native/src/Voice.cpp
ninja -C build -j32 -l32 ngs2_jobbuffer_tests
build/tests/ngs2_jobbuffer_tests
build/tests/ngs2_jobbuffer_tests filter
git show 26df95f13e:core/libs/prx/libSceNgs2.native/src/Voice.cpp > core/libs/prx/libSceNgs2.native/src/Voice.cpp
ninja -C build -j32 -l32 ngs2_jobbuffer_tests
build/tests/ngs2_jobbuffer_tests filter
git status --porcelain

Results

Check Result
Merge into main clean
git diff --check passed
check_conventions.py passed
Build (selected targets and libs) passed
Script's selected tests (750) 748 passed, 1 expected skip, 1 known failure on main (unwrap_self, unrelated); no new failures or timeouts
ctest -R ngs2 47/47 passed, 7.1 s in total
Negative control ngs2_jobbuffer_tests aborts with NGS2: this buffered voice parameter is not implemented
Restored merged tree filter scenario passes, git status --porcelain is empty
Negative control output (Voice.cpp from main)
[libc] unhandled exception 'St13runtime_error' thrown from 0x7f5dd63e5167
terminate called after throwing an instance of 'std::runtime_error'
  what():  NGS2: this buffered voice parameter is not implemented
Aborted

The filter scenario on its own gives the same output.

Negative control

I restored only core/libs/prx/libSceNgs2.native/src/Voice.cpp from main and rebuilt ngs2_jobbuffer_tests. Both the full run and the filter scenario abort with the error quoted in the description. After I restored the merged file, the scenario passes again and the worktree matches the merged tree. This agrees with the author's control and B-Howell's control on current main.

Findings

Blocking

None.

Non-blocking

  • No registered test covers the PS4 buffered filter path. The filter scenario builds only the PS5 Ngs2SamplerVoiceFilterParam, and ngs2_core_jobbuffer runs only over. As a result, the PS4 branch of SamplerFilterParam (core/libs/prx/libSceNgs2.native/src/Voice.cpp:559-572) is never tested on the buffered path. B-Howell already raised this and showed it with a local probe; I confirm the gap by reading the code only. A follow-up could register a PS4 variant of filter on ngs2_core_jobbuffer_tests.

Code reading of the new branch (core/libs/prx/libSceNgs2.native/src/Voice.cpp:647-654):

  • It rejects a custom sampler and another rack in the same order and with the same codes as ApplyParam (Voice.cpp:1019-1022). It then runs SamplerFilterParam and CheckFilter, the same code the immediate path reaches through Ngs2SetFilter.
  • The capture-time checks cannot go stale before ApplyPendingControls replays the copy:
    • maxFilters is a rack property.
    • voice.ports is sized only at voice creation (Rack.cpp:207).
    • So CheckFilter cannot newly throw when the copy is applied.
  • CopyParam copies param.size bytes, and that size was already checked against the layout, so the replay reads no more than was validated.
  • The refactor of Ngs2SetFilter and ApplySamplerParam only moves code.

Not verified

  • PS4-layout filter params sent during processing: no test exercises this path (see above). I checked it only by reading the code.
  • Red Dead Redemption (PPSA30528): I did not run the title, by policy.
  • Windows/MinGW build: not built here. B-Howell reports 47/47 on Windows.
  • Vulkan validation comparison: skipped by the script, because no file under the AGC driver, shader recompiler or VideoOut paths changed.

@BunnyFl BunnyFl 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.

Reads right, and here's a Windows run next to XairRrR's Linux one. In core/libs/prx/libSceNgs2.native/src/Voice.cpp, the immediate path keeps its behaviour: the four filter checks move unchanged into CheckFilter, and the PS4/PS5 layout handling (with its size checks and codes) moves into SamplerFilterParam. The buffered path runs the same checks before CopyParam, rejects the custom sampler rack with the same codes, and treats another rack as an error, as for the other buffered params.

Tested on Windows 11, WinLibs GCC 15.2.0, with this head merged onto current main: ngs2_jobbuffer and ngs2_core_jobbuffer pass, nothing skipped. With main's Voice.cpp, ngs2_jobbuffer aborts with NGS2: this buffered voice parameter is not implemented, the error PPSA30528 stops on.

@github-actions github-actions Bot added the review queue Next in the maintainer review queue: checks pass, no open change request, no conflict label Nov 2, 2026
@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ AMD GPU test: passed

PR head f0ed4cb merged onto main a4eca2a · tested 2026-11-03 00:23 UTC · 29 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 ✅ 947 passed · 4 failed (0 new, 3 also fail on main, 1 unstable on main) · 3 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 954 of 3,591 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 (452 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.4 s, ⚠️ public_headers 55.7 s, ⚠️ agc_driver_image_sample_unnormalized 46.3 s, ⚠️ unwrap_self 43.9 s, ⚠️ agc_driver_lazy_resolved_abi 36.3 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 4 of the last 6 main runs
Failing on main too (3, not counted against this PR)
agc_driver_image_table
agc_driver_native_depth_bda_clear
agc_driver_native_multisample_depth
Validation IDs already present on main (4 IDs in 380 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (380 tests): 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, agc_driver_bindless_images, and 372 more
VUID-vkCmdCopyImage-srcImage-01548 (6 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-vkCmdCopyImage-srcImage-01551 (6 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (1 test): agc_driver_prepared_exports
Skipped (3)
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_ngg_vertex_wave_reduction: skipped, s3 describes a 32-lane wave only on 32-lane subgroups, and the device has 64 lanes
Reproduce
git fetch origin f0ed4cb8171a9ebe2fd524e69529600198352dd8 a4eca2a056bf3bbbec98ab42e9d28163e4ea9cb8
git checkout a4eca2a056bf3bbbec98ab42e9d28163e4ea9cb8 && git merge --no-ff f0ed4cb8171a9ebe2fd524e69529600198352dd8
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.

@github-actions github-actions Bot removed the review queue Next in the maintainer review queue: checks pass, no open change request, no conflict label Nov 3, 2026
@oneandonlydean oneandonlydean self-assigned this Nov 3, 2026
@oneandonlydean
oneandonlydean merged commit 91ecd2d into boykopovar:main Nov 3, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

prx unblocks title Names a title ID on the Unblocks line

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants