Skip to content

feat(shader): allow directed rounding modes for packed f16 minmax - #14793

Open
AlexWhitehouse wants to merge 2 commits into
boykopovar:mainfrom
AlexWhitehouse:feat/shader-packed-f16-minmax-directed-rounding
Open

AlexWhitehouse wants to merge 2 commits into
boykopovar:mainfrom
AlexWhitehouse:feat/shader-packed-f16-minmax-directed-rounding

Conversation

@AlexWhitehouse

@AlexWhitehouse AlexWhitehouse commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

What

TranslationContext::packedFloat16 (core/shader/recompiler/Translation/src/FloatInstructions.cpp) threw packed f16 at pc … in FLOAT_MODE … (f16 rounding not to nearest even) is not implemented for every packed f16 instruction whenever the f16 round field of FLOAT_MODE is not nearest even. This PR exempts v_pk_min_f16 and v_pk_max_f16 from that throw.

  • These two select one operand's bits per lane, through the existing minMaxF16Bits path, so no rounding step happens. AMD's RDNA 2 ISA guide, §12.10 (printed p. 164, VOP3P opcodes 17 and 18), defines them as componentwise FP16 minimum and maximum.
  • Their NaN, signed-zero, denormal-flush, op_sel, negation and clamp handling is unchanged.
  • v_pk_add/mul/fma/fmac_f16, which do round, still throw.
  • Reachability: the FLOAT_MODE 0xcc that the v_fma_mixlo_f16 debt entry records for ps5-opengl has the f16 round field set to toward zero, so every packed f16 instruction in such a shader threw before.

Debt. docs/dev/debt/shader.md, two edits:

  • The packed-f16 entry now says min/max are exempt from the directed-rounding throw and are not measured in those modes.
  • The v_fma_mixlo_f16 entry's note about packed f16 rounding names the exception.

Both entries were already over 1,000 characters on main, so check_conventions warns on them; the PR changes only those clauses and keeps their measurement records.

Tested

  • agc_driver_float16_min_max_bits (tests/execution/Float16MinMaxBits.cpp) gains packed-only runs in every f16 round mode (0 to 3), crossed with:

    • IEEE 0 and 1;
    • DX10_CLAMP 0 and 1;
    • f16 denormal modes 0 to 3.

    The packed runs use the test's existing PackedCode, selector and negation checks, and CPU bit model. Rows now include signed zeros, infinities, quiet and signalling NaNs, denormals and minimum normals in every mode. The change passes 696,320 bit-exact comparisons.

  • Mutation check: swapping the min and max selection fails (actual 0x00010000, expected 0x00018000); restoring it passes.

  • Required focused comparison: ctest -R "^agc_driver_float16_min_max_bits$" -V on main (f2d874c) and this PR, with the same test source and ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1 and VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation:

    • NVIDIA RTX 3060, Windows 11: main fails with packed f16 at pc 20 in FLOAT_MODE 52 (f16 rounding not to nearest even) is not implemented; this PR passes. VK_LOADER_DEBUG=layer showed the validation layer loaded and inserted. Neither log has a missing-layer warning or a VUID- error. This run used 4534907, which differs from this PR only in the debt text.
    • lavapipe, Ubuntu 26.04: main fails at the same throw and this PR passes. The layer was inserted, and neither log has a missing-layer warning or a VUID- error.
    • Rerun at 67a16bf, after dropping the packed add throw check as requested in review, on both GPUs with the same variables: main fails at the same throw and this PR passes with 696,320 comparisons. The layer was inserted, and none of the four logs has a missing-layer warning or a VUID- error.
    • Rerun after rebasing onto main d2ce337, which changed the add/mul/fma path of packedFloat16 (perf(shader): drop f16 NaN payload rebuilds that the result never uses #11368), with the same variables on both GPUs: main fails at the same throw and this PR (3533527) passes with 696,320 comparisons. The layer was inserted, and none of the four logs has a missing-layer warning or a VUID- error.
    • Rerun after rebasing onto main 6f1d2c7, which added a native fma path to packedFloat16 (perf(shader): skip impossible NaN repair for normal multipliers #14892), with the same variables on both GPUs: main fails at the same throw and this PR (8281e58) passes with 696,320 comparisons. The layer was inserted, and none of the four logs has a missing-layer warning or a VUID- error.
  • Wider runs of -R "agc_driver_.*(f16|float16|half|mode|sdwa|packed)|agc_shader_mode" with the same variables:

    • RTX 3060: 31/31;
    • lavapipe: 79/79.

    Neither run has a VUID- error.

  • python3 tools/check_conventions.py --base origin/main: no errors; two debt-length warnings on the two entries above, which were already over the limit.

  • python3 tools/pr_overlap.py: no confirmed overlap. The tool could not compare 23 open PRs that conflict with main, all through docs/dev/debt/shader.md. None of their diffs touches the packed-f16 or v_fma_mixlo_f16 entries, packedFloat16, v_pk_min/max_f16 or Float16MinMaxBits.cpp. feat(aot): consolidate native ARM64 compiler, runtime and consumers #5021 also edits FloatInstructions.cpp, but only one line in vLdexpF16.

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: none
  • GPUs tested: NVIDIA GeForce RTX 3060, driver 610.88, Windows 11 Pro 10.0.26300; lavapipe (llvmpipe, Mesa 26.0.8, LLVM 21.1.8), Ubuntu 26.04 x86-64
  • AI-assisted: yes

🤖 Generated with Claude Code

@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 — no blocking findings

The directed-rounding exemption is limited to packed min/max opcodes, while other packed arithmetic remains guarded; the added cases exercise the min/max path across the configured mode combinations.

What I ran

Reviewed head 97c53a1d091b3ac085e1adf011485edddc8f6935 against base f2d874c1fdccf781c0fa5d86619bb5dd8894b958; the merge preview is clean. Environment: Linux x86-64, GCC 12.2.0, Python 3.11.2. I reviewed the source diff, test-mode construction, test registration and debt edits. No build or GPU test was run locally.

python3 tools/pr_precheck.py --repo boykopovar/AnyPS5 --pr 14793
git diff --check f2d874c1fdccf781c0fa5d86619bb5dd8894b958...97c53a1d091b3ac085e1adf011485edddc8f6935

Results

Check Result Note
Diff and conventions passed Two existing debt-length warnings; no convention errors.
Source and test review passed Only packed min/max bypass the rounding guard; add remains guarded.
CTest registration passed The existing execution-test glob registers Float16MinMaxBits.cpp.
Hosted CI not run Six checks are queued on this head.
GPU execution and mutation check not run The PR reports them passing; I did not reproduce them.
Raw precheck output
/tmp/anyps5-pr-precheck/boykopovar-AnyPS5-pr-14793-97c53a1d091b/report.md
/tmp/anyps5-pr-precheck/boykopovar-AnyPS5-pr-14793-97c53a1d091b/report.json
Conclusion: checks failed

The report's diff check passed. Its convention check passed with these warnings:

docs/dev/debt/shader.md:140: warning: [debt-length] Technical debt entry over 1000 characters: state the gap first (what differs from the console, what is unverified, what throws) and keep only the behaviour it needs: 1160 characters
docs/dev/debt/shader.md:145: warning: [debt-length] Technical debt entry over 1000 characters: state the gap first (what differs from the console, what is unverified, what throws) and keep only the behaviour it needs: 1652 characters
2 findings, 0 errors; GitHub shows at most 10 error annotations, the job summary lists all

The overall precheck could not launch its workspace-only pr_abi_audit.py and pr_test_quality.py helpers from the isolated exact-head checkout. Those helper launch errors are not code or test failures. The live stack check passed.

Negative control

Not run by me. The PR reports that swapping the min/max selection made the test fail with an output mismatch; I did not repeat that mutation.

Findings

Blocking

None found in the reviewed changes.

Non-blocking

None.

Sources

Not verified

The reported RTX 3060 and lavapipe runs, the 696,320 comparisons, the mutation result, and validation-layer output were read from the PR description but not independently reproduced. No console behavior was tested. Hosted checks remain queued.

To get this to a good state

No source change is requested. Once the hosted checks complete, I can recheck this head and approve if they pass.

@oneandonlydean

Copy link
Copy Markdown
Collaborator

Thanks. Letting v_pk_min_f16/v_pk_max_f16 through in the directed modes looks right: they return one operand's bits, so the f16 rounding mode can't change the result, and the existing bit-selection lowering is kept. The debt entry says it isn't measured.

One request on the test: core/libs/prx/libSceAgcDriver/tests/execution/Float16MinMaxBits.cpp:270-281 compiles v_pk_add_f16 in each directed f16 rounding mode and requires the compile to throw ("directed packed add did not throw"). That throw is there because directed rounding isn't implemented for packed add yet, so the test would fail once it is, and it reads as if the throw were intended. Tests here check what is implemented or measured, never that an unimplemented case throws. Could you drop that loop? The new min/max checks across the rounding, denormal, IEEE and clamp modes and the special halves are good and can stay as they are.

Reviewed at 97c53a1d09.

@AlexWhitehouse

Copy link
Copy Markdown
Contributor Author

Dropped the packed add throw loop and its stdexcept include in 67a16bf; the min/max checks are unchanged. On an RTX 3060 and lavapipe with the validation layer, main fails at the directed-rounding throw and this head passes 696,320 comparisons, with no VUID errors.

@github-actions

github-actions Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
PR 14085 docs/dev/debt/shader.md L147-148

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 5021 core/shader/recompiler/Translation/src/FloatInstructions.cpp
docs/dev/debt/shader.md
PR 5371 docs/dev/debt/shader.md
PR 6235 docs/dev/debt/shader.md
PR 6280 docs/dev/debt/shader.md
PR 6412 docs/dev/debt/shader.md
PR 6488 docs/dev/debt/shader.md
PR 6924 docs/dev/debt/shader.md
PR 7085 docs/dev/debt/shader.md
PR 7223 docs/dev/debt/shader.md
PR 7392 docs/dev/debt/shader.md
PR 7410 docs/dev/debt/shader.md
PR 7684 docs/dev/debt/shader.md
PR 8004 docs/dev/debt/shader.md
PR 9020 docs/dev/debt/shader.md
PR 9183 docs/dev/debt/shader.md
PR 9335 docs/dev/debt/shader.md
PR 9387 docs/dev/debt/shader.md
PR 9748 docs/dev/debt/shader.md
PR 9889 core/shader/recompiler/Translation/src/FloatInstructions.cpp
docs/dev/debt/shader.md
PR 10233 docs/dev/debt/shader.md
PR 10867 docs/dev/debt/shader.md
PR 11483 docs/dev/debt/shader.md
PR 12548 docs/dev/debt/shader.md
PR 12790 docs/dev/debt/shader.md
PR 12944 docs/dev/debt/shader.md
PR 14212 docs/dev/debt/shader.md
PR 14217 docs/dev/debt/shader.md
PR 14218 docs/dev/debt/shader.md
PR 14853 docs/dev/debt/shader.md

@github-actions github-actions Bot added shader core/shader docs agc libSceAgc* labels Nov 1, 2026
@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ AMD GPU test: passed

PR head 67a16bf merged onto main f2d874c · tested 2026-11-01 18:48 UTC · 15 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,429 passed · 13 failed (0 new, 9 also fail on main, 4 unstable on main) · 55 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,497 of 3,168 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 (936 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.0 s, ⚠️ agc_driver_graphics_maps_fallback 108.3 s, ⚠️ agc_driver_graphics 106.0 s, ⚠️ agc_driver_lazy_resolved_abi_switch_set 38.2 s, ⚠️ public_headers 36.0 s
Unstable on main (4, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_job_manager_compute_capacity: failed in 4 of the last 5 main runs
agc_driver_pipeline_journal: failed in 3 of the last 5 main runs
agc_submit_progress: failed in 4 of the last 5 main runs
agc_submit_progress_no_timeline: failed in 4 of the last 5 main runs
Failing on main too (9, not counted against this PR)
agc_driver_guest_memory_lifetime_direct
agc_driver_image_table
agc_driver_native_depth_bda_clear
agc_driver_native_depth_buffer_clear
agc_driver_native_depth_clears
agc_driver_native_multisample_depth
agc_idle_publish_wait
guest_mmap_executable
guest_socket_options_multicast
Validation IDs already present on main (5 IDs in 484 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (484 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 476 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
VUID-VkShaderModuleCreateInfo-pCode-08737 (1 test): agc_driver_image_sample_derivatives
Skipped (55)
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_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_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_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_pipeline_binary_vulkan: skipped, the device lacks VK_KHR_pipeline_binary
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_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 
Reproduce
git fetch origin 67a16bfa4003957fe0648197946f492e9f3c66d2 f2d874c1fdccf781c0fa5d86619bb5dd8894b958
git checkout f2d874c1fdccf781c0fa5d86619bb5dd8894b958 && git merge --no-ff 67a16bfa4003957fe0648197946f492e9f3c66d2
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.

@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 — no blocking findings

The exemption is sound: v_pk_min_f16 and v_pk_max_f16 select operand bits and never round, so the rounding-mode throw does not apply to them. Approval waits for the macOS relinker jobs, which were queued at review time.

What I ran

  • Head 67a16bfa4003957fe0648197946f492e9f3c66d2; base f2d874c1fd (merge base is the same commit). 3 files, +26/-7: FloatInstructions.cpp (1/1), Float16MinMaxBits.cpp (23/4), docs/dev/debt/shader.md (2/2). I read the whole diff.
  • Checked the call sites: FPMin32 and FPMax32 reach packedFloat16 only from the packed min and max opcodes, with quietSnan set (VectorInstructions.cpp lines 956-958). That branch takes packU16Lanes(minMaxLane(...)) (FloatInstructions.cpp lines 61 and 68), which selects 16-bit lanes through minMaxF16Bits with no rounding step. The add, multiply and fma opcodes still take the throw.
  • Read the test diff: packed-only runs in every f16 round mode, crossed with IEEE, DX10 clamp and f16 denormal modes, and special-value rows. I did not rerun it.
  • Precheck report at this exact head (head and base unchanged at completion). Its ABI and test-quality rows failed because their helpers are not in the head tree. This PR changes no export.

Results

Check Result Note
Diff check passed
Conventions and PR template passed
Mergeability and dependencies passed depends on none
Packed min and max rounding exemption passed min and max take the bit-selection path with no rounding
Test registration passed existing registered test
Build and runtime tests not run no build; GPU runs are author-reported
Negative controls not run the PR reports a mutation check (author-reported)
Hosted CI not run all completed jobs passed except one cancelled conventions run; macOS relinker queued
Commands and unedited precheck output

Commands:

  • Precheck: python3 tools/pr_precheck.py --repo boykopovar/AnyPS5 --pr 14793 --output-dir <scratch>/precheck/14793 (report.md in that directory).
  • Head fetched by URL (objects only): git fetch https://github.com/boykopovar/AnyPS5.git pull/14793/head.
  • Call sites: git grep -n 'packedFloat16(' 67a16bfa4003957fe0648197946f492e9f3c66d2.
  • Hosted checks: gh api repos/boykopovar/AnyPS5/commits/67a16bfa4003957fe0648197946f492e9f3c66d2/check-runs.

Precheck table (unedited):

Check Status Command / reason
build_and_compile not_applicable The precheck deliberately does not configure, build, or compile AnyPS5.
diff_check passed git diff --check f2d874c1fdccf781c0fa5d86619bb5dd8894b958...67a16bfa4003957fe0648197946f492e9f3c66d2
conventions_and_pr_template passed /marc/Conlyse-VIEJO/.venv/bin/python3 tools/check_conventions.py --base f2d874c1fdccf781c0fa5d86619bb5dd8894b958 --head 67a16bfa4003957fe0648197946f492e9f3c66d2 --title feat(shader): allow directed rounding modes for packed f16 minmax --body /dev/shm/reviewer-run/precheck/14793/pr-body.md
changed_export_abi_audit failed /marc/Conlyse-VIEJO/.venv/bin/python3 tools/pr_abi_audit.py --base f2d874c1fdccf781c0fa5d86619bb5dd8894b958 --head 67a16bfa4003957fe0648197946f492e9f3c66d2 --json
python_syntax not_applicable No changed Python implementation files.
related_python_unit_tests not_applicable No changed tools/ module has an existing sibling tools/tests/test_<module>.py suite.
python_test_registration not_applicable No changed test_*.py files.
live_dependency_and_mergeability_check passed /marc/Conlyse-VIEJO/.venv/bin/python3 /marc/AnyPS5/tools/pr_stack_check.py 14793 --repo boykopovar/AnyPS5 --output-dir /dev/shm/reviewer-run/precheck/14793/stack
build_dependent_cpp_tests not_applicable Not run: C++ tests need exact-head binaries, which require a build; the precheck does not build.
test_quality_heuristics failed /marc/Conlyse-VIEJO/.venv/bin/python3 /dev/shm/reviewer-run/precheck/14793/head-67a16bfa4003-785579a1/tools/pr_test_quality.py --root /dev/shm/reviewer-run/precheck/14793/head-67a16bfa4003-785579a1 --json core/libs/prx/libSceAgcDriver/tests/execution/Float16MinMaxBits.cpp core/shader/recompiler/Translation/src/FloatInstructions.cpp docs/dev/debt/shader.md
negative_controls not_applicable No changed Python test module in tools/ can be run as a no-build base-source control.

Negative control

Not run here. The PR reports a mutation check (swapping min and max fails the test; restoring passes); I did not rerun it.

Findings

Blocking

None.

Non-blocking

  • The packed f16 entry and the v_fma_mixlo_f16 entry in docs/dev/debt/shader.md were already over 1,000 characters, so check_conventions warns on them. The PR keeps that length and says so.

Sources

  • Exemption:
    bool TranslationContext::packedFloat16(const RdnaInstruction& inst, IrOpcode opcode, bool accumulator, bool quietSnan) {
    if (opcode != IrOpcode::FPMin32 && opcode != IrOpcode::FPMax32 && floatMode.has_value() && (floatMode->floatMode & 0x0cu) != 0u) {
    throw std::runtime_error("packed f16 at pc " + std::to_string(inst.programCounter) + " in FLOAT_MODE " + std::to_string(floatMode->floatMode) + " (f16 rounding not to nearest even) is not implemented");
    }
  • Min and max lane path:
    const auto minMaxLane = [&](bool high) { return minMaxF16Bits(opcode == IrOpcode::FPMax32, sourceLaneBits(0u, high), sourceLaneBits(1u, high)); };
    const bool native = nativeFloat16 && !flushResults && inst.destination.omod == 0u && (opcode == IrOpcode::FPAdd32 || opcode == IrOpcode::FPMul32);
    const auto nativeResult = [&]() {
    const IrU32 lhs = packU16Lanes(sourceLaneBits(0u, false), sourceLaneBits(0u, true));
    const IrU32 rhs = packU16Lanes(sourceLaneBits(1u, false), sourceLaneBits(1u, true));
    return IrU32(ir.Emit(opcode == IrOpcode::FPAdd32 ? IrOpcode::FPAdd16x2 : IrOpcode::FPMul16x2, IrType::U32, {&lhs.Value(), &rhs.Value()}));
    };
    IrU32 result = quietSnan ? packU16Lanes(minMaxLane(false), minMaxLane(true)) : native ? nativeResult() : packHalf2x16(translateLane(false), translateLane(true));
  • Opcode call sites:
    return packedFloat16(inst, IrOpcode::FPAdd32, false, false);
    case RdnaOpcode::VPkMulF16:
    return packedFloat16(inst, IrOpcode::FPMul32, false, false);
    case RdnaOpcode::VPkMinF16:
    return packedFloat16(inst, IrOpcode::FPMin32, false, true);
    case RdnaOpcode::VPkMaxF16:
    return packedFloat16(inst, IrOpcode::FPMax32, false, true);
    case RdnaOpcode::VPkFmaF16:
    return packedFloat16(inst, IrOpcode::FPFma32, false, false);
    case RdnaOpcode::VPkFmacF16:
    return packedFloat16(inst, IrOpcode::FPFma32, true, false);
  • Tests: https://github.com/boykopovar/AnyPS5/blob/67a16bfa4003957fe0648197946f492e9f3c66d2/core/libs/prx/libSceAgcDriver/tests/execution/Float16MinMaxBits.cpp

Not verified

  • The RDNA 2 ISA citation (§12.10, opcodes 17 and 18) was not re-read; the non-rounding behaviour was checked against the code.
  • The GPU runs (NVIDIA RTX 3060 on Windows, lavapipe on Ubuntu) and the mutation check are author-reported.
  • Denormal flushing for min and max is unchanged by this PR and was not re-derived.
  • The macOS relinker jobs had not finished at review time.

To get this to a good state

  • Nothing blocking. Approval waits for the macOS jobs on this head.

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head 67a16bf merged onto main f2d874c · tested 2026-11-02 00:17 UTC · 21 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,443 passed · 8 failed (0 new, 4 also fail on main, 4 unstable on main) · 46 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,497 of 3,168 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 (936 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.1 s, ⚠️ agc_driver_graphics_maps_fallback 31.5 s, ⚠️ agc_driver_graphics 30.8 s
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)
agc_driver_depth_clear_hle: VUID-vkCmdCopyBuffer-commonparent (6x)
Unstable on main (4, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_depth_clear_hle: failed in 1 of the last 10 main runs
agc_driver_pipeline_journal: failed in 1 of the last 10 main runs
agc_submit_progress: failed in 5 of the last 10 main runs
agc_submit_progress_no_timeline: failed in 7 of the last 10 main runs
Failing on main too (4, not counted against this PR)
agc_driver_dcc_keys_first_write
agc_driver_image_table
guest_mmap_executable
guest_socket_options_multicast
Validation IDs already present on main (5 IDs in 484 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (484 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 476 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_prepared_exports
VUID-VkShaderModuleCreateInfo-pCode-08737 (1 test): agc_driver_image_sample_derivatives
Skipped (46)
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_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_pipeline_binary_vulkan: skipped, the device lacks VK_KHR_pipeline_binary
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 configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_fps_limit: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL
Reproduce
git fetch origin 67a16bfa4003957fe0648197946f492e9f3c66d2 f2d874c1fdccf781c0fa5d86619bb5dd8894b958
git checkout f2d874c1fdccf781c0fa5d86619bb5dd8894b958 && git merge --no-ff 67a16bfa4003957fe0648197946f492e9f3c66d2
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 needs rebase Conflicts with main, rebase needed label Nov 2, 2026
@AlexWhitehouse
AlexWhitehouse force-pushed the feat/shader-packed-f16-minmax-directed-rounding branch from 67a16bf to 3533527 Compare November 2, 2026 10:40
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Nov 2, 2026
@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head 3533527 merged onto main f06d7fd · tested 2026-11-02 16:22 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,617 passed · 5 failed (0 new, 2 also fail on main, 3 unstable on main) · 44 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,666 of 3,544 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 (981 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.5 s, ⚠️ agc_driver_graphics_maps_fallback 30.8 s, ⚠️ agc_driver_graphics 30.3 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_submit_progress: failed in 8 of the last 10 main runs
agc_submit_progress_no_timeline: failed in 7 of the last 10 main runs
Failing on main too (2, not counted against this PR)
agc_driver_image_table
guest_socket_options_multicast
Validation IDs already present on main (4 IDs in 510 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (510 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 502 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_prepared_exports
Skipped (44)
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_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_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 configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_fps_limit: 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_fresh: skipped, no display or Vulkan device: 
Reproduce
git fetch origin 35335272aecb7d078f005006fac23cd4828b5b18 f06d7fdcee89af69f69f5d807ea5a34279f4285c
git checkout f06d7fdcee89af69f69f5d807ea5a34279f4285c && git merge --no-ff 35335272aecb7d078f005006fac23cd4828b5b18
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.

@oneandonlydean oneandonlydean self-assigned this Nov 5, 2026
AlexWhitehouse and others added 2 commits November 6, 2026 15:39
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Tests check implemented or measured behaviour, not that an
unimplemented path throws.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@AlexWhitehouse
AlexWhitehouse force-pushed the feat/shader-packed-f16-minmax-directed-rounding branch from 3533527 to 8281e58 Compare November 6, 2026 15:59

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* docs shader core/shader

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants