From 31bd702e39be31f63e2d8540de6fd2de35d7bcf8 Mon Sep 17 00:00:00 2001 From: izcarti <191240052+izcarti@users.noreply.github.com> Date: Sat, 10 Oct 2026 16:06:15 +0100 Subject: [PATCH] PPU: Add accurate vector estimates option vrefp and vrsqrtefp are hardware exact only when enabled. vexptefp and vlogefp are now exact by default. --- rpcs3/Emu/Cell/PPUInterpreter.cpp | 41 ++++++++++++++++++++++------- rpcs3/Emu/Cell/PPUThread.cpp | 3 +++ rpcs3/Emu/Cell/PPUTranslator.cpp | 16 +++++++++-- rpcs3/Emu/system_config.h | 1 + rpcs3/rpcs3qt/emu_settings_type.cpp | 1 + rpcs3/rpcs3qt/emu_settings_type.h | 1 + rpcs3/rpcs3qt/settings_dialog.cpp | 1 + rpcs3/rpcs3qt/settings_dialog.ui | 7 +++++ rpcs3/rpcs3qt/tooltips.h | 1 + 9 files changed, 60 insertions(+), 12 deletions(-) diff --git a/rpcs3/Emu/Cell/PPUInterpreter.cpp b/rpcs3/Emu/Cell/PPUInterpreter.cpp index fc201a947f..95e629d758 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.cpp +++ b/rpcs3/Emu/Cell/PPUInterpreter.cpp @@ -65,6 +65,7 @@ enum class ppu_exec_bit : u64 fix_nj, set_vnan, fix_vnan, + set_vest, set_fpcc, use_dfma, set_cr_stats, @@ -2177,17 +2178,26 @@ template auto VREFP() { if constexpr (Build == 0xf1a6) - return ppu_exec_select::template select<>(); + return ppu_exec_select::template select(); - static const auto exec = [](auto&& d, auto&& b, auto&& nj) + static const auto exec = [](auto&& d, auto&& b_, auto&& jm_mask, auto&& nj) { - for (u32 i = 0; i < 4; i++) + if constexpr (((Flags == set_vest) || ...)) { - d._u32[i] = ppu_vrefp(b._u32[i], nj); + for (u32 i = 0; i < 4; i++) + { + d._u32[i] = ppu_vrefp(b_._u32[i], nj); + } + } + else + { + auto m = gv_bcst32(jm_mask, &ppu_thread::jm_mask); + auto b = ppu_flush_denormal(m, std::move(b_)); + d = ppu_flush_denormal(std::move(m), ppu_set_vnan(gv_divfs(gv_bcstfs(1.0f), b), b)); } }; - RETURN_(ppu.vr[op.vd], ppu.vr[op.vb], ppu.nj); + RETURN_(ppu.vr[op.vd], ppu.vr[op.vb], ppu.jm_mask, ppu.nj); } template @@ -2298,17 +2308,26 @@ template auto VRSQRTEFP() { if constexpr (Build == 0xf1a6) - return ppu_exec_select::template select<>(); + return ppu_exec_select::template select(); - static const auto exec = [](auto&& d, auto&& b, auto&& nj) + static const auto exec = [](auto&& d, auto&& b_, auto&& jm_mask, auto&& nj) { - for (u32 i = 0; i < 4; i++) + if constexpr (((Flags == set_vest) || ...)) { - d._u32[i] = ppu_vrsqrtefp(b._u32[i], nj); + for (u32 i = 0; i < 4; i++) + { + d._u32[i] = ppu_vrsqrtefp(b_._u32[i], nj); + } + } + else + { + auto m = gv_bcst32(jm_mask, &ppu_thread::jm_mask); + auto b = ppu_flush_denormal(m, std::move(b_)); + d = ppu_flush_denormal(std::move(m), ppu_set_vnan(gv_divfs(gv_bcstfs(1.0f), gv_sqrtfs(b)), b)); } }; - RETURN_(ppu.vr[op.vd], ppu.vr[op.vb], ppu.nj); + RETURN_(ppu.vr[op.vd], ppu.vr[op.vb], ppu.jm_mask, ppu.nj); } template @@ -7368,6 +7387,8 @@ ppu_interpreter_rt_base::ppu_interpreter_rt_base() noexcept selected += fix_vnan; if (g_cfg.core.ppu_set_fpcc) selected += set_fpcc; + if (g_cfg.core.ppu_set_vest) + selected += set_vest; if (g_cfg.core.use_accurate_dfma) selected += use_dfma; if (g_cfg.core.ppu_debug) diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 551a8da0b0..d2c7da6bf8 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -5569,6 +5569,7 @@ bool ppu_initialize(const ppu_module& info, bool check_only, u64 file_s accurate_nj_mode, contains_symbol_resolver, daz_and_ftz, + accurate_vest, __bitset_enum_max }; @@ -5599,6 +5600,8 @@ bool ppu_initialize(const ppu_module& info, bool check_only, u64 file_s settings += ppu_settings::contains_symbol_resolver; // Avoid invalidating all modules for this purpose if (g_cfg.core.set_daz_and_ftz) settings += ppu_settings::daz_and_ftz; + if (g_cfg.core.ppu_set_vest) + settings += ppu_settings::accurate_vest; // Write version, hash, CPU, settings fmt::append(obj_name, "v9-kusa-%s-%s-%s.obj", fmt::base57(output, 16), fmt::base57(settings), jit_compiler::cpu(g_cfg.core.llvm_cpu.to_string())); diff --git a/rpcs3/Emu/Cell/PPUTranslator.cpp b/rpcs3/Emu/Cell/PPUTranslator.cpp index 386ab31da3..628a016eb5 100644 --- a/rpcs3/Emu/Cell/PPUTranslator.cpp +++ b/rpcs3/Emu/Cell/PPUTranslator.cpp @@ -1780,7 +1780,13 @@ void PPUTranslator::VPKUWUS(ppu_opcode_t op) void PPUTranslator::VREFP(ppu_opcode_t op) { - SetVr(op.vd, VecEstimate("__vrefp", op.vb)); + if (g_cfg.core.ppu_set_vest) + { + SetVr(op.vd, VecEstimate("__vrefp", op.vb)); + return; + } + + set_vr(op.vd, vec_handle_result(fsplat(1.0) / get_vr(op.vb))); } void PPUTranslator::VRFIM(ppu_opcode_t op) @@ -1823,7 +1829,13 @@ void PPUTranslator::VRLW(ppu_opcode_t op) void PPUTranslator::VRSQRTEFP(ppu_opcode_t op) { - SetVr(op.vd, VecEstimate("__vrsqrtefp", op.vb)); + if (g_cfg.core.ppu_set_vest) + { + SetVr(op.vd, VecEstimate("__vrsqrtefp", op.vb)); + return; + } + + set_vr(op.vd, vec_handle_result(fsplat(1.0) / callf(get_intrinsic(Intrinsic::sqrt), get_vr(op.vb)))); } void PPUTranslator::VSEL(ppu_opcode_t op) diff --git a/rpcs3/Emu/system_config.h b/rpcs3/Emu/system_config.h index df4bdc6343..d8ab5d3132 100644 --- a/rpcs3/Emu/system_config.h +++ b/rpcs3/Emu/system_config.h @@ -71,6 +71,7 @@ struct cfg_root : cfg::node cfg::_bool ppu_use_nj_bit{ this, "PPU Accurate Non-Java Mode", false }; // Accuracy. If set, accurately emulate NJ flag. Implies NJ fixup. cfg::_bool ppu_set_vnan{ this, "PPU Accurate Vector NaN Values", false }; // Accuracy. Implies ppu_fix_vnan. cfg::_bool ppu_set_fpcc{ this, "PPU Set FPCC Bits", false }; // Accuracy. + cfg::_bool ppu_set_vest{ this, "PPU Accurate Vector Estimates", false }; // Accuracy. Hardware exact vrefp and vrsqrtefp. cfg::_bool debug_console_mode{ this, "Debug Console Mode", false }; // Debug console emulation, not recommended cfg::_bool hook_functions{ this, "Hook static functions" }; diff --git a/rpcs3/rpcs3qt/emu_settings_type.cpp b/rpcs3/rpcs3qt/emu_settings_type.cpp index aecfe4f307..be7ebca83a 100644 --- a/rpcs3/rpcs3qt/emu_settings_type.cpp +++ b/rpcs3/rpcs3qt/emu_settings_type.cpp @@ -53,6 +53,7 @@ const std::map settings_location = { emu_settings_type::AccuratePPUNJ, get_cfg_location(local_cfg.core.ppu_use_nj_bit) }, { emu_settings_type::AccuratePPUVNAN, get_cfg_location(local_cfg.core.ppu_set_vnan) }, { emu_settings_type::AccuratePPUFPCC, get_cfg_location(local_cfg.core.ppu_set_fpcc) }, + { emu_settings_type::AccuratePPUVEST, get_cfg_location(local_cfg.core.ppu_set_vest) }, { emu_settings_type::MaxPreemptCount, get_cfg_location(local_cfg.core.max_cpu_preempt_count_per_frame) }, { emu_settings_type::SPUProfiler, get_cfg_location(local_cfg.core.spu_prof) }, { emu_settings_type::DisableSpinOptimization, get_cfg_location(local_cfg.core.spu_getllar_spin_optimization_disabled) }, diff --git a/rpcs3/rpcs3qt/emu_settings_type.h b/rpcs3/rpcs3qt/emu_settings_type.h index 9e44ec3031..271a732861 100644 --- a/rpcs3/rpcs3qt/emu_settings_type.h +++ b/rpcs3/rpcs3qt/emu_settings_type.h @@ -47,6 +47,7 @@ enum class emu_settings_type AccuratePPUNJ, AccuratePPUVNAN, AccuratePPUFPCC, + AccuratePPUVEST, MaxPreemptCount, SPUProfiler, DisableSpinOptimization, diff --git a/rpcs3/rpcs3qt/settings_dialog.cpp b/rpcs3/rpcs3qt/settings_dialog.cpp index 516ae828a5..8d9b0654f8 100644 --- a/rpcs3/rpcs3qt/settings_dialog.cpp +++ b/rpcs3/rpcs3qt/settings_dialog.cpp @@ -1442,6 +1442,7 @@ settings_dialog::settings_dialog(std::shared_ptr gui_settings, std // Checkboxes EnhanceCheckBox(emu_settings_type::DebugConsoleMode, ui->debugConsoleMode, tooltips.settings.debug_console_mode); + EnhanceCheckBox(emu_settings_type::AccuratePPUVEST, ui->accuratePPUVEST, tooltips.settings.accurate_ppuvest); EnhanceCheckBox(emu_settings_type::AccurateRSXAccess, ui->accurateRSXAccess, tooltips.settings.accurate_rsx_access); EnhanceCheckBox(emu_settings_type::AccurateSpuDMA, ui->accurateSpuDMA, tooltips.settings.accurate_spu_dma); EnhanceCheckBox(emu_settings_type::LLVMPrecompilation, ui->llvmPrecompilation, tooltips.settings.llvm_precompilation); diff --git a/rpcs3/rpcs3qt/settings_dialog.ui b/rpcs3/rpcs3qt/settings_dialog.ui index 8f75315052..15a4fdb44e 100644 --- a/rpcs3/rpcs3qt/settings_dialog.ui +++ b/rpcs3/rpcs3qt/settings_dialog.ui @@ -2538,6 +2538,13 @@ Core + + + + Accurate PPU Vector Estimates + + + diff --git a/rpcs3/rpcs3qt/tooltips.h b/rpcs3/rpcs3qt/tooltips.h index b6e1581bd5..70afa7a136 100644 --- a/rpcs3/rpcs3qt/tooltips.h +++ b/rpcs3/rpcs3qt/tooltips.h @@ -26,6 +26,7 @@ public: const QString lib_default_lle = tr("Select to HLE. (LLE by default)"); const QString debug_console_mode = tr("Increases the amount of usable system memory to match a DECR console and more.\nCauses some software to behave differently than on retail hardware."); + const QString accurate_ppuvest = tr("Computes PPU vector reciprocal and reciprocal square root estimates exactly as the PS3 does.\nSome games compare these results with a real console, for example in online play. Comes at a performance cost.\nIf unsure, do not modify this setting."); 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 silence_all_logs = tr("Stop writing any logs after game startup. Don't use unless you believe it's necessary.");