Repository navigation
fix(shader): apply cube output modifiers whenever IEEE mode is off - #5799
Conversation
|
Run on an Apple GPU, as a third device next to the RTX 3080 and lavapipe. GPUs tested: Apple M2 Max, MoltenVK 1.4.2 (Vulkan 1.4.357), macOS 27.2, x86-64 under Rosetta
Written with AI assistance (Claude Code). I ran the builds and tests above on my machine. |
v_cubeid_f32, v_cubesc_f32, v_cubetc_f32 and v_cubema_f32 refused any output modifier with "VOP3 source modifiers are not implemented"; PPSA11386 stops there on v_cubeid_f32 v, v, -v, -v div:2. On RDNA2 (gfx1036), over 2048 inputs in every combination of IEEE mode, the four f32 denormal values and f16/f64 denormals flushed or kept, with round to nearest even, the four instructions apply mul:2, mul:4 and div:2 whenever IEEE mode is off, also with f32 output denormals kept, where v_mul_f32_e64 in the same kernels ignores them, and ignore them with IEEE mode on. Where applied, the result is the existing bit-level f32 output modifier result, and clamp is applied after it. The decoder accepts the modifier on the four instructions. floatCube applies the shared f32 scaling, now scaleF32Result, in those modes and writes with the modifier cleared, so clamp is still applied after it. With IEEE mode on the signaling NaN quieting applies and the modifier is ignored; with it off the quieting does nothing and the modifier is applied. agc_driver_vop3_cube_clamp checks each instruction with each modifier against tables captured on gfx1036. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fnrk5Dazjb2tLooVSpdRQq
2acac08 to
e32f5e1
Compare
|
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.
|
|
Windows cross-test on current main 4524944: author-preserved e32f5e1 port at df0e8a7, followed by #6317 and #6332, integration head 00abe7e. GCC 15.2 / Release / SPIRV-Tools OFF / RTX 5070 Ti, Vulkan required. Fresh patched libraries and fixtures built successfully.
007 is currently preparing a cold shader cache without the earlier cube stop; no rendered-gameplay or FPS claim yet. AI-assisted: Codex; title data stays local. |
|
The Windows run (@Scramblrrrr, RTX 5070 Ti, |
What
v_cubeid_f32,v_cubesc_f32,v_cubetc_f32andv_cubema_f32refuse any output modifier (mul:2,mul:4,div:2) withVOP3 source modifiers are not implemented. PPSA11386 (007 First Light) stops there on currentmain, within seconds of start, onv_cubeid_f32 v, v, -v, -v div:2.Measured on RDNA2 (Ryzen 9 7950X3D iGPU, gfx1036, not the PS5's gfx1013) with
tools/hw-oracle, 2048 inputs (edge cases and random), all four instructions with each modifier, in all 16 combinations of IEEE mode, the four f32 denormal values and f16/f64 denormals flushed or kept, with round to nearest even and DX10_CLAMP=1:v_mul_f32_e64 ... div:2in the same kernels follows fix(shader): apply the output modifier only in the float modes where the hardware does #1851's rule (ignored with f32 output denormals kept). With IEEE mode on it is ignored.main's bit-level f32 output modifier result on every row: of the 24,576 results per mode, 21,768 differ from the unmodified value and all of them match; NaN and infinity pass unchanged, denormal and zero results become +0,div:2below 2^-125 gives a signed zero,muloverflow a signed infinity.clampapplies after the modifier. The negated-source form 007 uses behaves the same.Changes:
scaleF32Result.floatCubeapplies it whenever IEEE mode is off and then writes with the modifier cleared, soclampis still applied after it.floatCubedoes not use the generic gate (outputModifierApplies), which drops the modifier with IEEE mode off and f32 output denormals kept; for these four the hardware applies it there. In the usual mode (IEEE off, f32 denormals flushed) the two agree.Vop3CubeClamp.cppbecomes an execution test, and its run and check helpers take the kernel, rows and names instead of being duplicated. The output modifier entry indocs/dev/debt/shader.mdrecords the cube rule.Only round to nearest even is modelled. The same 2048 rows in the other three round modes (IEEE mode off, f32 denormals flushed and kept) differ from round to nearest even where a result overflows to infinity: the hardware rounds the overflow as the mode says (to the largest finite value when rounding toward zero), in
v_cubema_f32's own result as well as inmul:2andmul:4. The translation gives infinity there, asmainalready does forv_cubema_f32without a modifier. The only other difference is the sign of three zerov_cubema_f32results with a NaN input when rounding toward negative infinity. The debt entry records both.Overlap: #2463 (closed by the intake pause) accepted the modifier with the generic gate.
Tested
BUILD_TESTING=ON. The measurements below were made with this branch onmain23e93c0; it was then rebased without conflicts ontomain145cb82, wheretools/check_conventions.py --base upstream/mainandgit diff --checkpass and the 19vop3execution tests,agc_driver_vop3_cube_clampincluded, pass on lavapipe.ANYPS5_ENABLE_SPIRV_TOOLS=ONas in CI: 1107/1121;main23e93c0 built the same way fails the same 14 (hardware_oracle,guest_syslog,guest_allocator_failures,agc_driver_bc_block_copy,agc_driver_depth_compare_copy,agc_compute_pipeline_replay,autorun_exit_status,guest_none_relocations,guest_module_args,linux_executable_exports,linux_entry_argv,linux_program_header_order,linux_input_program_headers,linux_guest_stack).agc_driver_stencil_ref_export).agc_driver_vop3_cube_clamp: a 16-instruction kernel (all four instructions with each modifier, the negated-source form, clamp with each modifier) over 32 rows (two of them with a signaling NaN input), compiled with no float mode, IEEE=0 with f32 denormals flushed (0xc0) and kept (0xf0), and IEEE=1 with both, against two tables captured on gfx1036 (IEEE=0 and IEEE=1; the hardware gives the same results with f32 denormals flushed or kept). With only the test applied tomain23e93c0 it fails on the decoder refusal. Mutations caught: the generic f32 gate (fix(shader): accept cube output modifiers #2463's behaviour; fails at IEEE=0 with f32 denormals kept), applying the modifier in IEEE mode, never applying it, and skipping the signaling NaN quieting when a modifier is present (fails on a signaling NaN row with IEEE=1).main23e93c0 every run ends on the decoder refusal (terminatewithVOP3 source modifiers are not implemented). With this change every run gets past it, compiles about a thousand shaders and stops at its first presentation onbindless image table has 18960 entries (0 materials), limit 16. Along the way 63 to 72 shaders are logged as not prepared after registration; none of the reasons names a cube instruction or an output modifier (GetImageResource dword 0 is not a valid runtime value, the clip distance limit, static bindless image capacity, bindless storage image tables).Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file.mdfiles or images added to the repository (attach them to this PR)tools/hw-oracle🤖 Generated with Claude Code