Repository navigation
fix(shader): keep the output modifier of the f16 min3, max3, med3 and div_fixup ops - #4097
Conversation
… div_fixup ops Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
The decode fix is exactly scoped — these four opcodes join Worth being explicit about the trade, since it's real: for these four ops, in the one One gap in the new test: it checks that the default and Written with AI assistance. |
|
On the value check: in the default float mode and with On
Written with AI assistance. |
What
The decoder drops the VOP3 output modifier (
mul:2,mul:4,div:2) ofv_min3_f16,v_max3_f16,v_med3_f16andv_div_fixup_f16.checkNativeVop3Modifiersaccepts any modifier on these four ops, butsupportsNativeVop3ResultModifiersdoesn't list them, sodestination.omodis set to 0. The f32 versions (v_min3_f32,v_max3_f32,v_med3_f32,v_div_fixup_f32) andv_fma_f16keep it.d3f2611 applies the output modifier only in the float modes where the hardware does. On f16 results it is ignored, and in the modes where the hardware applies it (IEEE off, f16 output denormals flushed) the translator throws "output modifier on an f16 or f64 result with f16/f64 output denormals flushed is not implemented". These four ops never reach that check. In those modes they compute without the modifier instead of refusing.
This adds the native f16 ternary ops (
isNativeVop3F16TernaryOpcode, which already includesVFmaF16) tosupportsNativeVop3ResultModifiers. Their results already go throughclampF16Bits, which ignores the modifier in the other modes and throws in these. Nothing changes in the default float mode.LLVM 23.1.3
llvm-mc -mcpu=gfx1013disassembles all four with the modifier, for exampled7570001 14020100asv_med3_f16 v1, v0, v0, v0 mul:4. I found this by comparing the decoder against LLVM's disassembler over random VOP3 modifier fields.Tested
Windows 11 (26200), WinLibs GCC 15.2.0 r7, CI configure flags,
main325e0a8.maincurrently doesn't build on Windows (HostPollinSocket.cpp, fixed by #4021), so #4021 was applied locally for these runs and isn't part of this change.agc_driver_float16_modifiersgets four one-instruction shaders:v_min3_f16 div:2,v_max3_f16 mul:2,v_med3_f16 mul:4andv_div_fixup_f16 mul:2. Each must compile and run in the default float mode and withFLOAT_MODE0xf0, and must be refused with f16 output denormals flushed (FLOAT_MODE0x00, IEEE off).Runnow takes the shader code so the existing shader and the new ones share it.mainthe test fails on the RTX 4070 Laptop GPU and the Intel Raptor Lake-S iGPU withv_min3_f16 div:2 with f16 output denormals flushed was not refused. A decode dump of the four instructions givesdestination.omod0 for all four onmain(and 1 forv_fma_f16), and 3, 1, 2, 1 with the change.--repeat until-fail:2.agc_driverand decoder test whose name matches f16, float16, half, vop3, fma, div_fixup, output_modifier, sdwa or dpp, includingagc_driver_f32_output_modifier,agc_driver_float16_result_modifiers,agc_driver_float16_ternary_clamp,agc_driver_div_fixup_f16andagc_driver_division_output_modifiers.cmake --build, thelibstarget, thenctest --timeout 120 --parallel 4): 913 of 916 pass on the RTX 4070 and 912 of 916 on the Intel iGPU. The failures also fail onmainwith the decoder change reverted, on both GPUs:agc_write_tracking(Windows: agc_write_tracking fails since #3594, StoredOver still trusts block stamps for arena host holes #4087) andguest_kernel_stack_protect(Windows: guest_kernel_stack_protect aborts since #3788, sceKernelMprotect accepts a range crossing a guest stack's lower bound #4088);agc_driver_prepared_shaders_registered_workgroup_sync: "expected preparation failure";agc_driver_f32_dot2_rounding: the iGPU has noshaderFloat64.tools/check_conventions.py --base origin/mainpasses.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt.mdfiles or images added to the repository (attach them to this PR)🤖 Generated with Claude Code