mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-30 22:49:53 +08:00
3574a3b145
The decoder recognises the VOP3P mix ops (0x20 V_FMA_MIX_F32, 0x21 V_FMA_MIXLO_F16, 0x22 V_FMA_MIXHI_F16) but left them opaque (Vop3pRaw20/21/22), so at SPIR-V emission they fell through the vector-ALU switch to the default and failed with "unsupported vector opcode". A single unhandled instruction fails the whole compile, so any shader using fma_mix was dropped entirely. Unity's built-in-RP / PostProcessing v2 HDR, tone-mapping and auto-exposure shaders emit V_FMA_MIX_F32, so those passes never translated (this is what kept Superliminal's auto-exposure luminance chain from running). Name the three opcodes in DecodeVop3p (like the packed v_pk_* ops) and lower them in the SPIR-V translator. Each mix op computes a single f32 fma(a, b, c) where every source is read *independently* as either a full f32 register/constant or one f16 half widened to f32. Per operand, op_sel_hi selects f16-vs-f32 and op_sel picks which f16 half; the neg_hi field is repurposed as an absolute-value modifier and neg negates, applied abs-then-neg. This reuses the VOP3P op_sel/op_sel_hi/neg/neg_hi bit layout with the mix-specific meaning, not the packed-math meaning. The result is a scalar f32 for V_FMA_MIX_F32; _MIXLO/_MIXHI narrow it back to f16 (exact round-to-nearest-even, via the existing EmitFloatToHalf) and write it into the low/high 16 bits of vdst, preserving the other half. The clamp modifier saturates to [0, 1] consistently with the other VOP3P ops. Per-operand F16/F32 select and the abs/neg modifiers follow shadPS4's GetSrcMix, the authoritative reference for the mix semantics. Adds Gen5FmaMixSpirvTests: assembles V_FMA_MIX_F32 (with a representative op_sel/op_sel_hi/neg/abs) and V_FMA_MIXLO_F16 compute shaders and asserts they translate to GPU SPIR-V without hitting the drop path and emit a GLSL.std.450 Fma (and an FAbs for the neg_hi modifier). Both fail against the pre-fix tree with "unsupported vector opcode Vop3pRaw20/21".