Browse Source
shader: Implement FCMP
shader: Implement FCMP
still need to configure some settings for NV denorm flush and intel NaNpull/15/merge
9 changed files with 203 additions and 50 deletions
-
1src/shader_recompiler/CMakeLists.txt
-
1src/shader_recompiler/backend/spirv/emit_spirv.h
-
4src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp
-
80src/shader_recompiler/frontend/ir/ir_emitter.cpp
-
19src/shader_recompiler/frontend/ir/ir_emitter.h
-
2src/shader_recompiler/frontend/ir/opcodes.inc
-
116src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_compare.cpp
-
16src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp
-
14src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp
@ -0,0 +1,116 @@ |
|||
// Copyright 2021 yuzu Emulator Project
|
|||
// Licensed under GPLv2 or any later version
|
|||
// Refer to the license.txt file included.
|
|||
|
|||
#include "common/bit_field.h"
|
|||
#include "common/common_types.h"
|
|||
#include "shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h"
|
|||
#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
|
|||
|
|||
namespace Shader::Maxwell { |
|||
namespace { |
|||
enum class FPCompareOp : u64 { |
|||
F, |
|||
LT, |
|||
EQ, |
|||
LE, |
|||
GT, |
|||
NE, |
|||
GE, |
|||
NUM, |
|||
Nan, |
|||
LTU, |
|||
EQU, |
|||
LEU, |
|||
GTU, |
|||
NEU, |
|||
GEU, |
|||
T, |
|||
}; |
|||
|
|||
bool IsCompareOpOrdered(FPCompareOp op) { |
|||
switch (op) { |
|||
case FPCompareOp::LTU: |
|||
case FPCompareOp::EQU: |
|||
case FPCompareOp::LEU: |
|||
case FPCompareOp::GTU: |
|||
case FPCompareOp::NEU: |
|||
case FPCompareOp::GEU: |
|||
return false; |
|||
default: |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
IR::U1 FloatingPointCompare(IR::IREmitter& ir, const IR::F32& operand_1, const IR::F32& operand_2, |
|||
FPCompareOp compare_op, IR::FpControl control) { |
|||
const bool ordered{IsCompareOpOrdered(compare_op)}; |
|||
switch (compare_op) { |
|||
case FPCompareOp::F: |
|||
return ir.Imm1(false); |
|||
case FPCompareOp::LT: |
|||
case FPCompareOp::LTU: |
|||
return ir.FPLessThan(operand_1, operand_2, control, ordered); |
|||
case FPCompareOp::EQ: |
|||
case FPCompareOp::EQU: |
|||
return ir.FPEqual(operand_1, operand_2, control, ordered); |
|||
case FPCompareOp::LE: |
|||
case FPCompareOp::LEU: |
|||
return ir.FPLessThanEqual(operand_1, operand_2, control, ordered); |
|||
case FPCompareOp::GT: |
|||
case FPCompareOp::GTU: |
|||
return ir.FPGreaterThan(operand_1, operand_2, control, ordered); |
|||
case FPCompareOp::NE: |
|||
case FPCompareOp::NEU: |
|||
return ir.FPNotEqual(operand_1, operand_2, control, ordered); |
|||
case FPCompareOp::GE: |
|||
case FPCompareOp::GEU: |
|||
return ir.FPGreaterThanEqual(operand_1, operand_2, control, ordered); |
|||
case FPCompareOp::NUM: |
|||
return ir.FPOrdered(operand_1, operand_2); |
|||
case FPCompareOp::Nan: |
|||
return ir.FPUnordered(operand_1, operand_2); |
|||
case FPCompareOp::T: |
|||
return ir.Imm1(true); |
|||
default: |
|||
throw NotImplementedException("Invalid compare op {}", compare_op); |
|||
} |
|||
} |
|||
|
|||
void FCMP(TranslatorVisitor& v, u64 insn, const IR::U32& src_a, const IR::F32& operand) { |
|||
union { |
|||
u64 insn; |
|||
BitField<0, 8, IR::Reg> dest_reg; |
|||
BitField<8, 8, IR::Reg> src_reg; |
|||
BitField<47, 1, u64> ftz; |
|||
BitField<48, 4, FPCompareOp> compare_op; |
|||
} const fcmp{insn}; |
|||
|
|||
const IR::F32 zero{v.ir.Imm32(0.0f)}; |
|||
const IR::F32 neg_zero{v.ir.Imm32(-0.0f)}; |
|||
IR::FpControl control{.fmz_mode{fcmp.ftz != 0 ? IR::FmzMode::FTZ : IR::FmzMode::None}}; |
|||
const IR::U1 cmp_result{FloatingPointCompare(v.ir, operand, zero, fcmp.compare_op, control)}; |
|||
const IR::U32 src_reg{v.X(fcmp.src_reg)}; |
|||
const IR::U32 result{v.ir.Select(cmp_result, src_reg, src_a)}; |
|||
|
|||
v.X(fcmp.dest_reg, result); |
|||
} |
|||
} // Anonymous namespace
|
|||
|
|||
void TranslatorVisitor::FCMP_reg(u64 insn) { |
|||
FCMP(*this, insn, GetReg20(insn), GetFloatReg39(insn)); |
|||
} |
|||
|
|||
void TranslatorVisitor::FCMP_rc(u64 insn) { |
|||
FCMP(*this, insn, GetReg39(insn), GetFloatCbuf(insn)); |
|||
} |
|||
|
|||
void TranslatorVisitor::FCMP_cr(u64 insn) { |
|||
FCMP(*this, insn, GetCbuf(insn), GetFloatReg39(insn)); |
|||
} |
|||
|
|||
void TranslatorVisitor::FCMP_imm(u64 insn) { |
|||
FCMP(*this, insn, GetReg39(insn), GetFloatImm20(insn)); |
|||
} |
|||
|
|||
} // namespace Shader::Maxwell
|
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue