Implement proper clamping and handling for V_RCP_CLAMP_F32, V_RSQ_CLAMP_F32, V_RSQ_LEGACY_F32, V_LOG_CLAMP_F32 (#5346)

* Implement proper clamping and handling for V_RCP_CLAMP_F32, V_RSQ_CLAMP_F32, V_RSQ_LEGACY_F32, V_LOG_CLAMP_F32, and V_CVT_PK_U8_F32.

* -
This commit is contained in:
DanielSvoboda
2026-10-11 13:48:49 +03:00
committed by GitHub
parent 443f022450
commit 1c2b8f97af
2 changed files with 44 additions and 4 deletions
@@ -225,11 +225,15 @@ public:
void V_RNDNE_F32(const GcnInst& inst);
void V_FLOOR_F32(const GcnInst& inst);
void V_EXP_F32(const GcnInst& inst);
void V_LOG_CLAMP_F32(const GcnInst& inst);
void V_LOG_F32(const GcnInst& inst);
void V_RCP_F32(const GcnInst& inst);
void V_RCP_CLAMP_F32(const GcnInst& inst);
void V_RCP_LEGACY_F32(const GcnInst& inst);
void V_RCP_F64(const GcnInst& inst);
void V_RSQ_LEGACY_F32(const GcnInst& inst);
void V_RSQ_F32(const GcnInst& inst);
void V_RSQ_CLAMP_F32(const GcnInst& inst);
void V_SQRT_F32(const GcnInst& inst);
void V_SIN_F32(const GcnInst& inst);
void V_COS_F32(const GcnInst& inst);
@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2024-2026 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <limits>
#include "shader_recompiler/frontend/opcodes.h"
#include "shader_recompiler/frontend/translate/translate.h"
#include "shader_recompiler/ir/attribute.h"
@@ -170,7 +171,7 @@ void Translator::EmitVectorAlu(const GcnInst& inst) {
case Opcode::V_EXP_F32:
return V_EXP_F32(inst);
case Opcode::V_LOG_CLAMP_F32:
return V_LOG_F32(inst);
return V_LOG_CLAMP_F32(inst);
case Opcode::V_LOG_F32:
return V_LOG_F32(inst);
case Opcode::V_RCP_F32:
@@ -182,11 +183,11 @@ void Translator::EmitVectorAlu(const GcnInst& inst) {
case Opcode::V_RCP_IFLAG_F32:
return V_RCP_F32(inst);
case Opcode::V_RCP_CLAMP_F32:
return V_RCP_F32(inst);
return V_RCP_CLAMP_F32(inst);
case Opcode::V_RSQ_CLAMP_F32:
return V_RSQ_F32(inst);
return V_RSQ_CLAMP_F32(inst);
case Opcode::V_RSQ_LEGACY_F32:
return V_RSQ_F32(inst);
return V_RSQ_LEGACY_F32(inst);
case Opcode::V_RSQ_F32:
return V_RSQ_F32(inst);
case Opcode::V_SQRT_F32:
@@ -1046,6 +1047,14 @@ void Translator::V_EXP_F32(const GcnInst& inst) {
SetDst(inst.dst[0], ir.FPExp2(src0));
}
void Translator::V_LOG_CLAMP_F32(const GcnInst& inst) {
const IR::F32 src0{GetSrc<IR::F32>(inst.src[0])};
const IR::F32 result{ir.FPLog2(src0)};
const IR::F32 max_val{ir.Imm32(std::numeric_limits<float>::max())};
const IR::F32 min_val{ir.Imm32(-std::numeric_limits<float>::max())};
SetDst(inst.dst[0], ir.FPClamp(result, min_val, max_val));
}
void Translator::V_LOG_F32(const GcnInst& inst) {
const IR::F32 src0{GetSrc<IR::F32>(inst.src[0])};
SetDst(inst.dst[0], ir.FPLog2(src0));
@@ -1075,11 +1084,38 @@ void Translator::V_RCP_F64(const GcnInst& inst) {
SetDst64(inst.dst[0], ir.FPRecip(src0));
}
void Translator::V_RSQ_LEGACY_F32(const GcnInst& inst) {
const IR::F32 src0{GetSrc<IR::F32>(inst.src[0])};
const IR::F32 result{ir.FPRecipSqrt(src0)};
const IR::F32 max_val{ir.Imm32(std::numeric_limits<float>::max())};
const IR::F32 min_val{ir.Imm32(-std::numeric_limits<float>::max())};
const IR::F32 clamped{ir.FPClamp(result, min_val, max_val)};
const IR::F32 zero{ir.Imm32(0.0f)};
const IR::F32 output{ir.Select(ir.FPEqual(src0, zero), zero, clamped)};
SetDst(inst.dst[0], output);
}
void Translator::V_RSQ_F32(const GcnInst& inst) {
const IR::F32 src0{GetSrc<IR::F32>(inst.src[0])};
SetDst(inst.dst[0], ir.FPRecipSqrt(src0));
}
void Translator::V_RCP_CLAMP_F32(const GcnInst& inst) {
const IR::F32 src0{GetSrc<IR::F32>(inst.src[0])};
const IR::F32 result{ir.FPRecip(src0)};
const IR::F32 max_val{ir.Imm32(std::numeric_limits<float>::max())};
const IR::F32 min_val{ir.Imm32(-std::numeric_limits<float>::max())};
SetDst(inst.dst[0], ir.FPClamp(result, min_val, max_val));
}
void Translator::V_RSQ_CLAMP_F32(const GcnInst& inst) {
const IR::F32 src0{GetSrc<IR::F32>(inst.src[0])};
const IR::F32 result{ir.FPRecipSqrt(src0)};
const IR::F32 max_val{ir.Imm32(std::numeric_limits<float>::max())};
const IR::F32 min_val{ir.Imm32(-std::numeric_limits<float>::max())};
SetDst(inst.dst[0], ir.FPClamp(result, min_val, max_val));
}
void Translator::V_SQRT_F32(const GcnInst& inst) {
const IR::F32 src0{GetSrc<IR::F32>(inst.src[0])};
SetDst(inst.dst[0], ir.FPSqrt(src0));