From b6bd9ecae4ad29d26447ee2c5675bead4cbf0d80 Mon Sep 17 00:00:00 2001 From: Nawid3333 <102778966+Nawid3333@users.noreply.github.com> Date: Sat, 17 Oct 2026 05:05:40 +0200 Subject: [PATCH] shader: read float inline constants on 16-bit operands as half bits (#1582) The 16-bit encodings of the float inline constants are fixed: the exact halves of 0.5, 1.0, 2.0 and 4.0 and their negations, and 0x3118 for 1/(2*pi). Read16LaneBits converted the 32-bit value at run time instead, through PackHalf2x16, which the AMD driver rounds toward zero, so 1/(2*pi) became 0x3117. Use the encodings directly. Co-authored-by: Claude Opus 5.5 --- .../shader/recompiler/frontend/translate/Translate.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/graphics/shader/recompiler/frontend/translate/Translate.cpp b/src/graphics/shader/recompiler/frontend/translate/Translate.cpp index ff142684c..03a7f629c 100644 --- a/src/graphics/shader/recompiler/frontend/translate/Translate.cpp +++ b/src/graphics/shader/recompiler/frontend/translate/Translate.cpp @@ -546,9 +546,11 @@ IR::U32 Translator::Read16LaneBits(const Decoder::Operand& operand, bool high_la auto bits = ReadRawU32(operand); if (operand.kind == Decoder::OperandKind::FloatInlineConstant) { // Inline floats encode the operand's width before SDWA or OP_SEL selects bits. - const auto half = IR::F16(ir.Emit(IR::ValueOpcode::ConvertF16F32, {ir.BitCastF32(bits)})); - const auto half_bits = IR::U16(ir.Emit(IR::ValueOpcode::BitCastU16F16, {half})); - bits = IR::U32(ir.Emit(IR::ValueOpcode::ConvertU32U16, {half_bits})); + const auto value = operand.value; + bits = IR::U32(IR::Value(value == 0x3e22f983u + ? 0x3118u + : ((value >> 16u) & 0x8000u) | + ((((value >> 23u) & 0xffu) - 112u) << 10u))); } bits = ApplyBitSourceModifiers(raw_operand, bits); uint32_t offset = (high_lane ? operand.op_sel_hi : operand.op_sel) ? 16u : 0u;