mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-10-12 02:09:17 +00:00
PPU: Add accurate vector estimates option
vrefp and vrsqrtefp are hardware exact only when enabled. vexptefp and vlogefp are now exact by default.
This commit is contained in:
@@ -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 <u32 Build, ppu_exec_bit... Flags>
|
||||
auto VREFP()
|
||||
{
|
||||
if constexpr (Build == 0xf1a6)
|
||||
return ppu_exec_select<Flags...>::template select<>();
|
||||
return ppu_exec_select<Flags...>::template select<set_vest, use_nj, fix_nj, set_vnan, fix_vnan>();
|
||||
|
||||
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<false, Flags...>(m, std::move(b_));
|
||||
d = ppu_flush_denormal<true, Flags...>(std::move(m), ppu_set_vnan<Flags...>(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 <u32 Build, ppu_exec_bit... Flags>
|
||||
@@ -2298,17 +2308,26 @@ template <u32 Build, ppu_exec_bit... Flags>
|
||||
auto VRSQRTEFP()
|
||||
{
|
||||
if constexpr (Build == 0xf1a6)
|
||||
return ppu_exec_select<Flags...>::template select<>();
|
||||
return ppu_exec_select<Flags...>::template select<set_vest, use_nj, fix_nj, set_vnan, fix_vnan>();
|
||||
|
||||
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<false, Flags...>(m, std::move(b_));
|
||||
d = ppu_flush_denormal<true, Flags...>(std::move(m), ppu_set_vnan<Flags...>(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 <u32 Build, ppu_exec_bit... Flags>
|
||||
@@ -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)
|
||||
|
||||
@@ -5569,6 +5569,7 @@ bool ppu_initialize(const ppu_module<lv2_obj>& 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<lv2_obj>& 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()));
|
||||
|
||||
@@ -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<f32[4]>(1.0) / get_vr<f32[4]>(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<f32[4]>(1.0) / callf<f32[4]>(get_intrinsic<f32[4]>(Intrinsic::sqrt), get_vr<f32[4]>(op.vb))));
|
||||
}
|
||||
|
||||
void PPUTranslator::VSEL(ppu_opcode_t op)
|
||||
|
||||
@@ -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" };
|
||||
|
||||
@@ -53,6 +53,7 @@ const std::map<emu_settings_type, cfg_location> 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) },
|
||||
|
||||
@@ -47,6 +47,7 @@ enum class emu_settings_type
|
||||
AccuratePPUNJ,
|
||||
AccuratePPUVNAN,
|
||||
AccuratePPUFPCC,
|
||||
AccuratePPUVEST,
|
||||
MaxPreemptCount,
|
||||
SPUProfiler,
|
||||
DisableSpinOptimization,
|
||||
|
||||
@@ -1442,6 +1442,7 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> 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);
|
||||
|
||||
@@ -2538,6 +2538,13 @@
|
||||
<string>Core</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="gb_advanced_core_layout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="accuratePPUVEST">
|
||||
<property name="text">
|
||||
<string>Accurate PPU Vector Estimates</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="accurateRSXAccess">
|
||||
<property name="text">
|
||||
|
||||
@@ -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.");
|
||||
|
||||
Reference in New Issue
Block a user