3
0
Fork 0
forked from suyu/suyu

glasm: Fix clamps so the min value has priority on NAN on GLASM

This commit is contained in:
ReinUsesLisp 2021-05-10 01:37:30 -03:00 committed by ameerj
parent 8eb72ff0dc
commit 6237300e36

View file

@ -9,11 +9,10 @@
#include "shader_recompiler/frontend/ir/value.h" #include "shader_recompiler/frontend/ir/value.h"
namespace Shader::Backend::GLASM { namespace Shader::Backend::GLASM {
namespace {
template <typename InputType> template <typename InputType>
static void Compare(EmitContext& ctx, IR::Inst& inst, InputType lhs, InputType rhs, void Compare(EmitContext& ctx, IR::Inst& inst, InputType lhs, InputType rhs, std::string_view op,
std::string_view op, std::string_view type, bool ordered, std::string_view type, bool ordered, bool inequality = false) {
bool inequality = false) {
const Register ret{ctx.reg_alloc.Define(inst)}; const Register ret{ctx.reg_alloc.Define(inst)};
ctx.Add("{}.{} RC.x,{},{};", op, type, lhs, rhs); ctx.Add("{}.{} RC.x,{},{};", op, type, lhs, rhs);
if (ordered && inequality) { if (ordered && inequality) {
@ -35,6 +34,16 @@ static void Compare(EmitContext& ctx, IR::Inst& inst, InputType lhs, InputType r
} }
} }
template <typename InputType>
void Clamp(EmitContext& ctx, Register ret, InputType value, InputType min_value,
InputType max_value) {
// Call MAX first to properly clamp nan to min_value instead
ctx.Add("MAX.F {}.x,{},{};"
"MIN.F {}.x,{},{};",
ret, min_value, value, ret, ret, max_value);
}
} // Anonymous namespace
void EmitFPAbs16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, void EmitFPAbs16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
[[maybe_unused]] Register value) { [[maybe_unused]] Register value) {
throw NotImplementedException("GLASM instruction"); throw NotImplementedException("GLASM instruction");
@ -171,18 +180,12 @@ void EmitFPClamp16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register
void EmitFPClamp32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value, ScalarF32 min_value, void EmitFPClamp32(EmitContext& ctx, IR::Inst& inst, ScalarF32 value, ScalarF32 min_value,
ScalarF32 max_value) { ScalarF32 max_value) {
const Register ret{ctx.reg_alloc.Define(inst)}; Clamp(ctx, ctx.reg_alloc.Define(inst), value, min_value, max_value);
ctx.Add("MIN.F {}.x,{},{};"
"MAX.F {}.x,{},{};",
ret, max_value, value, ret, ret, min_value);
} }
void EmitFPClamp64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value, ScalarF64 min_value, void EmitFPClamp64(EmitContext& ctx, IR::Inst& inst, ScalarF64 value, ScalarF64 min_value,
ScalarF64 max_value) { ScalarF64 max_value) {
const Register ret{ctx.reg_alloc.LongDefine(inst)}; Clamp(ctx, ctx.reg_alloc.LongDefine(inst), value, min_value, max_value);
ctx.Add("MIN.F64 {}.x,{},{};"
"MAX.F64 {}.x,{},{};",
ret, max_value, value, ret, ret, min_value);
} }
void EmitFPRoundEven16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) { void EmitFPRoundEven16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register value) {