PPU LLVM: Accelerate NJ handling in FTZ environment
This commit is contained in:
@@ -7354,7 +7354,7 @@ ppu_interpreter_rt_base::ppu_interpreter_rt_base() noexcept
|
||||
selected += set_sat;
|
||||
if (g_cfg.core.ppu_use_nj_bit)
|
||||
selected += use_nj + fix_nj;
|
||||
if (g_cfg.core.ppu_llvm_nj_fixup)
|
||||
if (!g_cfg.core.set_daz_and_ftz)
|
||||
selected += fix_nj;
|
||||
if (g_cfg.core.ppu_set_vnan)
|
||||
selected += set_vnan + fix_vnan;
|
||||
|
||||
@@ -5144,7 +5144,7 @@ bool ppu_initialize(const ppu_module<lv2_obj>& info, bool check_only, u64 file_s
|
||||
platform_bit,
|
||||
accurate_dfma,
|
||||
fixup_vnan,
|
||||
fixup_nj_denormals,
|
||||
_reserved_for_backwards_compatibility,
|
||||
accurate_cache_line_stores,
|
||||
reservations_128_byte,
|
||||
greedy_mode,
|
||||
@@ -5160,6 +5160,7 @@ bool ppu_initialize(const ppu_module<lv2_obj>& info, bool check_only, u64 file_s
|
||||
|
||||
be_t<bs_t<ppu_settings>> settings{};
|
||||
|
||||
settings += ppu_settings::_reserved_for_backwards_compatibility;
|
||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||
settings += ppu_settings::platform_bit;
|
||||
#endif
|
||||
@@ -5167,8 +5168,6 @@ bool ppu_initialize(const ppu_module<lv2_obj>& info, bool check_only, u64 file_s
|
||||
settings += ppu_settings::accurate_dfma;
|
||||
if (g_cfg.core.ppu_fix_vnan)
|
||||
settings += ppu_settings::fixup_vnan;
|
||||
if (g_cfg.core.ppu_llvm_nj_fixup)
|
||||
settings += ppu_settings::fixup_nj_denormals;
|
||||
if (has_dcbz == 2)
|
||||
settings += ppu_settings::accurate_cache_line_stores;
|
||||
if (g_cfg.core.ppu_128_reservations_loop_max_length)
|
||||
@@ -5182,7 +5181,7 @@ bool ppu_initialize(const ppu_module<lv2_obj>& info, bool check_only, u64 file_s
|
||||
if (g_cfg.core.ppu_set_vnan)
|
||||
settings += ppu_settings::accurate_vnan, settings -= ppu_settings::fixup_vnan, fmt::throw_exception("VNAN Not implemented");
|
||||
if (g_cfg.core.ppu_use_nj_bit)
|
||||
settings += ppu_settings::accurate_nj_mode, settings -= ppu_settings::fixup_nj_denormals, fmt::throw_exception("NJ Not implemented");
|
||||
settings += ppu_settings::accurate_nj_mode, fmt::throw_exception("NJ Not implemented");
|
||||
if (fpos >= info.get_funcs().size() || module_counter % c_moudles_per_jit == c_moudles_per_jit - 1)
|
||||
settings += ppu_settings::contains_symbol_resolver; // Avoid invalidating all modules for this purpose
|
||||
if (g_cfg.core.set_daz_and_ftz)
|
||||
|
||||
@@ -482,10 +482,10 @@ Value* PPUTranslator::VecHandleDenormal(Value* val)
|
||||
return bitcast(result, type);
|
||||
}
|
||||
|
||||
Value* PPUTranslator::VecHandleResult(Value* val)
|
||||
Value* PPUTranslator::VecHandleResult(Value* val, bool flush_denormals_manually)
|
||||
{
|
||||
val = g_cfg.core.ppu_fix_vnan ? VecHandleNan(val) : val;
|
||||
val = g_cfg.core.ppu_llvm_nj_fixup ? VecHandleDenormal(val) : val;
|
||||
val = flush_denormals_manually || !g_cfg.core.set_daz_and_ftz ? VecHandleDenormal(val) : val;
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -995,8 +995,7 @@ void PPUTranslator::MTVSCR(ppu_opcode_t op)
|
||||
const auto vscr = m_ir->CreateExtractElement(GetVr(op.vb, VrType::vi32), m_ir->getInt32(m_is_be ? 3 : 0));
|
||||
const auto nj = Trunc(m_ir->CreateLShr(vscr, 16), GetType<bool>());
|
||||
RegStore(nj, m_nj);
|
||||
if (g_cfg.core.ppu_llvm_nj_fixup)
|
||||
RegStore(m_ir->CreateSelect(nj, m_ir->getInt32(0x7f80'0000), m_ir->getInt32(0x7fff'ffff)), m_jm_mask);
|
||||
RegStore(m_ir->CreateSelect(nj, m_ir->getInt32(0x7f80'0000), m_ir->getInt32(0x7fff'ffff)), m_jm_mask);
|
||||
if (g_cfg.core.ppu_set_sat_bit)
|
||||
RegStore(m_ir->CreateInsertElement(ConstantAggregateZero::get(GetType<u32[4]>()), m_ir->CreateAnd(vscr, 1), m_ir->getInt32(0)), m_sat);
|
||||
}
|
||||
@@ -1295,13 +1294,13 @@ void PPUTranslator::VCTUXS(ppu_opcode_t op)
|
||||
void PPUTranslator::VEXPTEFP(ppu_opcode_t op)
|
||||
{
|
||||
const auto b = get_vr<f32[4]>(op.vb);
|
||||
set_vr(op.vd, vec_handle_result(llvm_calli<f32[4], decltype(b)>{"llvm.exp2.v4f32", {b}}));
|
||||
set_vr(op.vd, vec_handle_result(llvm_calli<f32[4], decltype(b)>{"llvm.exp2.v4f32", {b}}, true));
|
||||
}
|
||||
|
||||
void PPUTranslator::VLOGEFP(ppu_opcode_t op)
|
||||
{
|
||||
const auto b = get_vr<f32[4]>(op.vb);
|
||||
set_vr(op.vd, vec_handle_result(llvm_calli<f32[4], decltype(b)>{"llvm.log2.v4f32", {b}}));
|
||||
set_vr(op.vd, vec_handle_result(llvm_calli<f32[4], decltype(b)>{"llvm.log2.v4f32", {b}}, true));
|
||||
}
|
||||
|
||||
void PPUTranslator::VMADDFP(ppu_opcode_t op)
|
||||
@@ -1345,9 +1344,9 @@ void PPUTranslator::VMAXFP(ppu_opcode_t op)
|
||||
{
|
||||
const auto [a, b] = get_vrs<f32[4]>(op.va, op.vb);
|
||||
#ifdef ARCH_ARM64
|
||||
set_vr(op.vd, vec_handle_result(fmax(a, b)));
|
||||
set_vr(op.vd, vec_handle_result(fmax(a, b), true));
|
||||
#else
|
||||
set_vr(op.vd, vec_handle_result(select(fcmp_ord(a < b) | fcmp_uno(b != b), b, a)));
|
||||
set_vr(op.vd, vec_handle_result(select(fcmp_ord(a < b) | fcmp_uno(b != b), b, a), true));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1411,9 +1410,9 @@ void PPUTranslator::VMINFP(ppu_opcode_t op)
|
||||
{
|
||||
const auto [a, b] = get_vrs<f32[4]>(op.va, op.vb);
|
||||
#ifdef ARCH_ARM64
|
||||
set_vr(op.vd, vec_handle_result(fmin(a, b)));
|
||||
set_vr(op.vd, vec_handle_result(fmin(a, b), true));
|
||||
#else
|
||||
set_vr(op.vd, vec_handle_result(select(fcmp_ord(a > b) | fcmp_uno(b != b), b, a)));
|
||||
set_vr(op.vd, vec_handle_result(select(fcmp_ord(a > b) | fcmp_uno(b != b), b, a), true));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -116,13 +116,13 @@ public:
|
||||
|
||||
llvm::Value* VecHandleNan(llvm::Value* val);
|
||||
llvm::Value* VecHandleDenormal(llvm::Value* val);
|
||||
llvm::Value* VecHandleResult(llvm::Value* val);
|
||||
llvm::Value* VecHandleResult(llvm::Value* val, bool flush_denormals_manually = false);
|
||||
|
||||
template <typename T>
|
||||
auto vec_handle_result(T&& expr)
|
||||
auto vec_handle_result(T&& expr, bool flush_denormals_manually = false)
|
||||
{
|
||||
value_t<typename T::type> result;
|
||||
result.value = VecHandleResult(expr.eval(m_ir));
|
||||
result.value = VecHandleResult(expr.eval(m_ir), flush_denormals_manually);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,6 @@ struct cfg_root : cfg::node
|
||||
cfg::_int<-1, 14> ppu_128_reservations_loop_max_length{ this, "Accurate PPU 128-byte Reservation Op Max Length", 0, true }; // -1: Always accurate, 0: Never accurate, 1-14: max accurate loop length
|
||||
cfg::_int<-64, 64> stub_ppu_traps{ this, "Stub PPU Traps", 0, true }; // Hack, skip PPU traps for rare cases where the trap is continueable (specify relative instructions to skip)
|
||||
cfg::_bool precise_spu_verification{ this, "Precise SPU Verification", false }; // Disables use of xorsum based spu verification if enabled.
|
||||
cfg::_bool ppu_llvm_nj_fixup{ this, "PPU LLVM Java Mode Handling", true }; // Partially respect current Java Mode for alti-vec ops by PPU LLVM
|
||||
cfg::_bool ppu_fix_vnan{ this, "PPU Vector NaN Handling", true }; // Accuracy. Partial.
|
||||
cfg::_bool use_accurate_dfma{ this, "Use Accurate DFMA", true }; // Enable accurate double-precision FMA for CPUs which do not support it natively
|
||||
cfg::_bool ppu_set_sat_bit{ this, "PPU Set Saturation Bit", false }; // Accuracy. If unset, completely disable saturation flag handling.
|
||||
|
||||
@@ -47,7 +47,6 @@ const std::map<emu_settings_type, cfg_location> settings_location =
|
||||
{ emu_settings_type::AccuratePPU128Loop, get_cfg_location(local_cfg.core.ppu_128_reservations_loop_max_length) },
|
||||
{ emu_settings_type::PerformanceReport, get_cfg_location(local_cfg.core.perf_report) },
|
||||
{ emu_settings_type::NumPPUThreads, get_cfg_location(local_cfg.core.ppu_threads) },
|
||||
{ emu_settings_type::PPUNJFixup, get_cfg_location(local_cfg.core.ppu_llvm_nj_fixup) },
|
||||
{ emu_settings_type::PPUVNANFixup, get_cfg_location(local_cfg.core.ppu_fix_vnan) },
|
||||
{ emu_settings_type::AccurateDFMA, get_cfg_location(local_cfg.core.use_accurate_dfma) },
|
||||
{ emu_settings_type::AccuratePPUSAT, get_cfg_location(local_cfg.core.ppu_set_sat_bit) },
|
||||
|
||||
@@ -41,7 +41,6 @@ enum class emu_settings_type
|
||||
SleepTimersAccuracy,
|
||||
ClocksScale,
|
||||
PerformanceReport,
|
||||
PPUNJFixup,
|
||||
PPUVNANFixup,
|
||||
AccurateDFMA,
|
||||
AccuratePPUSAT,
|
||||
|
||||
@@ -1525,9 +1525,6 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
|
||||
m_emu_settings->EnhanceCheckBox(ui->accurateSpuDMA, emu_settings_type::AccurateSpuDMA);
|
||||
SubscribeTooltip(ui->accurateSpuDMA, tooltips.settings.accurate_spu_dma);
|
||||
|
||||
m_emu_settings->EnhanceCheckBox(ui->ppuNJFixup, emu_settings_type::PPUNJFixup);
|
||||
SubscribeTooltip(ui->ppuNJFixup, tooltips.settings.fixup_ppunj);
|
||||
|
||||
m_emu_settings->EnhanceCheckBox(ui->PPUVNANfixup, emu_settings_type::PPUVNANFixup);
|
||||
SubscribeTooltip(ui->PPUVNANfixup, tooltips.settings.fixup_ppuvnan);
|
||||
|
||||
@@ -1558,6 +1555,9 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
|
||||
m_emu_settings->EnhanceCheckBox(ui->handleTiledMemory, emu_settings_type::HandleRSXTiledMemory);
|
||||
SubscribeTooltip(ui->handleTiledMemory, tooltips.settings.handle_tiled_memory);
|
||||
|
||||
m_emu_settings->EnhanceCheckBox(ui->setDAZandFTZ, emu_settings_type::SetDAZandFTZ);
|
||||
SubscribeTooltip(ui->setDAZandFTZ, tooltips.settings.set_daz_and_ftz);
|
||||
|
||||
m_emu_settings->EnhanceCheckBox(ui->vblankNTSCFixup, emu_settings_type::VBlankNTSCFixup);
|
||||
|
||||
ui->mfcDelayCommand->setChecked(m_emu_settings->GetSetting(emu_settings_type::MFCCommandsShuffling) == "1");
|
||||
@@ -2497,9 +2497,6 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
|
||||
m_emu_settings->EnhanceCheckBox(ui->mfcDebug, emu_settings_type::MFCDebug);
|
||||
SubscribeTooltip(ui->mfcDebug, tooltips.settings.mfc_debug);
|
||||
|
||||
m_emu_settings->EnhanceCheckBox(ui->setDAZandFTZ, emu_settings_type::SetDAZandFTZ);
|
||||
SubscribeTooltip(ui->setDAZandFTZ, tooltips.settings.set_daz_and_ftz);
|
||||
|
||||
m_emu_settings->EnhanceCheckBox(ui->accuratePPUSAT, emu_settings_type::AccuratePPUSAT);
|
||||
SubscribeTooltip(ui->accuratePPUSAT, tooltips.settings.accurate_ppusat);
|
||||
|
||||
|
||||
@@ -2491,6 +2491,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="setDAZandFTZ">
|
||||
<property name="text">
|
||||
<string>PPU Set DAZ and FTZ</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="mfcDelayCommand">
|
||||
<property name="text">
|
||||
@@ -4526,13 +4533,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="setDAZandFTZ">
|
||||
<property name="text">
|
||||
<string>PPU Set DAZ and FTZ</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="spuDebug">
|
||||
<property name="text">
|
||||
@@ -4611,13 +4611,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="ppuNJFixup">
|
||||
<property name="text">
|
||||
<string>Approximate PPU Non-Java Mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="PPUVNANfixup">
|
||||
<property name="text">
|
||||
|
||||
@@ -29,7 +29,6 @@ public:
|
||||
const QString accurate_rsx_access = tr("Forces RSX pauses on SPU MFC_GETLLAR and SPU MFC_PUTLLUC operations.");
|
||||
const QString accurate_spu_dma = tr("Accurately processes SPU DMA operations.");
|
||||
const QString accurate_dfma = tr("Use accurate double-precision FMA instructions in PPU and SPU backends.\nWhile disabling it might give a decent performance boost if your CPU doesn't support FMA, it may also introduce subtle bugs that otherwise do not occur.\nYou shouldn't disable it if your CPU supports FMA.");
|
||||
const QString fixup_ppunj = tr("Legacy option. Fixup result vector values in Non-Java Mode in PPU LLVM.\nIf unsure, do not modify this setting.");
|
||||
const QString fixup_ppuvnan = tr("Fixup NaN results in vector instructions in PPU backends.\nIf unsure, do not modify this setting.");
|
||||
const QString silence_all_logs = tr("Stop writing any logs after game startup. Don't use unless you believe it's necessary.");
|
||||
const QString read_color = tr("Initializes render target memory using vm memory.");
|
||||
@@ -104,7 +103,7 @@ public:
|
||||
const QString ppu_debug = tr("Creates PPU logs.\nOnly useful to developers.\nNever use this.");
|
||||
const QString spu_debug = tr("Creates SPU logs.\nOnly useful to developers.\nNever use this.");
|
||||
const QString mfc_debug = tr("Creates MFC logs.\nOnly useful to developers.\nNever use this.");
|
||||
const QString set_daz_and_ftz = tr("Sets special MXCSR flags to debug errors in SSE operations.\nOnly used in PPU thread when it's not precise.\nOnly useful to developers.\nNever use this.");
|
||||
const QString set_daz_and_ftz = tr("Sets special MXCSR flags to debug errors in SSE operations.\nAccelerates PPU performance at the cost of accuracy.");
|
||||
const QString accurate_ppusat = tr("Accurately set Saturation Bit values in PPU backends.\nIf unsure, do not modify this setting.");
|
||||
const QString accurate_ppunj = tr("Respect Non-Java Mode Bit values for vector ops in PPU backends.\nIf unsure, do not modify this setting.");
|
||||
const QString accurate_ppuvnan = tr("Accurately set NaN results in vector instructions in PPU backends.\nIf unsure, do not modify this setting.");
|
||||
|
||||
Reference in New Issue
Block a user