Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SPU/GUI: Add MFC Delay Command checkbox to GUI, Add one more MFC Shuffle setting #10884

Merged
merged 3 commits into from Sep 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 5 additions & 14 deletions Utilities/Thread.cpp
Expand Up @@ -1231,19 +1231,15 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no

bool handled = rsx::g_access_violation_handler(addr, is_writing);

if (handled)
if (cpu && (cpu->state += cpu_flag::temp, cpu->test_stopped()))
{
g_tls_fault_rsx++;
if (cpu && cpu->test_stopped())
{
//
}

return true;
//
}

if (cpu && cpu->test_stopped())
if (handled)
{
g_tls_fault_rsx++;
return true;
}
}

Expand Down Expand Up @@ -1389,11 +1385,6 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no

if (vm::check_addr(addr, is_writing ? vm::page_writable : vm::page_readable))
{
if (cpu && cpu->test_stopped())
{
//
}

return true;
}

Expand Down
29 changes: 25 additions & 4 deletions rpcs3/Emu/Cell/SPUThread.cpp
Expand Up @@ -1657,14 +1657,20 @@ void spu_thread::cpu_task()

void spu_thread::cpu_work()
{
if (std::exchange(in_cpu_work, true))
{
return;
}

const auto timeout = +g_cfg.core.mfc_transfers_timeout;

// If either MFC size exceeds limit or timeout has been reached execute pending MFC commands
if (mfc_size > g_cfg.core.mfc_transfers_shuffling || (timeout && get_system_time() - mfc_last_timestamp >= timeout))
{
do_mfc(false);
check_mfc_interrupts(pc + 4);
do_mfc(false, false);
}

in_cpu_work = false;
}

struct raw_spu_cleanup
Expand Down Expand Up @@ -2960,7 +2966,7 @@ void spu_thread::do_putlluc(const spu_mfc_cmd& args)
vm::reservation_notifier(addr).notify_all(-128);
}

void spu_thread::do_mfc(bool can_escape)
void spu_thread::do_mfc(bool can_escape, bool must_finish)
{
u32 removed = 0;
u32 barrier = 0;
Expand Down Expand Up @@ -3106,6 +3112,14 @@ void spu_thread::do_mfc(bool can_escape)
{
break;
}

if (!must_finish && g_cfg.core.mfc_shuffling_in_steps)
{
// Exit early, not all pending commands have to be executed at a single iteration
// Update last timestamp so the next MFC timeout check will use the current time
mfc_last_timestamp = get_system_time();
return;
}
}

if (state & cpu_flag::pending)
Expand Down Expand Up @@ -3171,12 +3185,19 @@ bool spu_thread::process_mfc_cmd()
// Reset MFC timestamp in the case of full queue
mfc_last_timestamp = 0;

// Process MFC commands
if (test_stopped())
{
return false;
}

// Process MFC commands
do_mfc();

if (mfc_size < 16)
{
break;
}

auto old = state.add_fetch(cpu_flag::wait);

if (is_stopped(old))
Expand Down
4 changes: 3 additions & 1 deletion rpcs3/Emu/Cell/SPUThread.h
Expand Up @@ -778,6 +778,8 @@ class spu_thread : public cpu_thread
u64 mfc_dump_idx = 0;
static constexpr u32 max_mfc_dump_idx = 2048;

bool in_cpu_work = false;

std::array<v128, 0x4000> stack_mirror; // Return address information

const char* current_func{}; // Current STOP or RDCH blocking function
Expand All @@ -791,7 +793,7 @@ class spu_thread : public cpu_thread
bool do_list_transfer(spu_mfc_cmd& args);
void do_putlluc(const spu_mfc_cmd& args);
bool do_putllc(const spu_mfc_cmd& args);
void do_mfc(bool can_escape = true);
void do_mfc(bool can_escape = true, bool must_finish = true);
u32 get_mfc_completed() const;

bool process_mfc_cmd();
Expand Down
5 changes: 3 additions & 2 deletions rpcs3/Emu/system_config.h
Expand Up @@ -47,8 +47,9 @@ struct cfg_root : cfg::node
cfg::_bool spu_verification{ this, "SPU Verification", true }; // Should be enabled
cfg::_bool spu_cache{ this, "SPU Cache", true };
cfg::_bool spu_prof{ this, "SPU Profiler", false };
cfg::uint<0, 16> mfc_transfers_shuffling{ this, "MFC Transfers Shuffling Max Commands", 0 };
cfg::uint<0, 10000> mfc_transfers_timeout{ this, "MFC Transfers Timeout", 0, true};
cfg::uint<0, 16> mfc_transfers_shuffling{ this, "MFC Commands Shuffling Limit", 0 };
cfg::uint<0, 10000> mfc_transfers_timeout{ this, "MFC Commands Timeout", 0, true };
cfg::_bool mfc_shuffling_in_steps{ this, "MFC Commands Shuffling In Steps", false, true };
cfg::_enum<tsx_usage> enable_TSX{ this, "Enable TSX", has_rtm() ? tsx_usage::enabled : tsx_usage::disabled }; // Enable TSX. Forcing this on Haswell/Broadwell CPUs should be used carefully
cfg::_bool spu_accurate_xfloat{ this, "Accurate xfloat", false };
cfg::_bool spu_approx_xfloat{ this, "Approximate xfloat", true };
Expand Down
2 changes: 2 additions & 0 deletions rpcs3/rpcs3qt/emu_settings_type.h
Expand Up @@ -29,6 +29,7 @@ enum class emu_settings_type
AccurateRSXAccess,
AccurateXFloat,
AccuratePPU128Loop,
MFCCommandsShuffling,
NumPPUThreads,
SetDAZandFTZ,
SPUBlockSize,
Expand Down Expand Up @@ -188,6 +189,7 @@ inline static const QMap<emu_settings_type, cfg_location> settings_location =
{ emu_settings_type::AccurateVectorNaN, { "Core", "PPU LLVM Accurate Vector NaN values"}},
{ emu_settings_type::AccurateRSXAccess, { "Core", "Accurate RSX reservation access"}},
{ emu_settings_type::AccurateXFloat, { "Core", "Accurate xfloat"}},
{ emu_settings_type::MFCCommandsShuffling, { "Core", "MFC Commands Shuffling Limit"}},
{ emu_settings_type::SetDAZandFTZ, { "Core", "Set DAZ and FTZ"}},
{ emu_settings_type::SPUBlockSize, { "Core", "SPU Block Size"}},
{ emu_settings_type::SPUCache, { "Core", "SPU Cache"}},
Expand Down
8 changes: 8 additions & 0 deletions rpcs3/rpcs3qt/settings_dialog.cpp
Expand Up @@ -1027,6 +1027,14 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
m_emu_settings->EnhanceCheckBox(ui->disableOnDiskShaderCache, emu_settings_type::DisableOnDiskShaderCache);
SubscribeTooltip(ui->disableOnDiskShaderCache, tooltips.settings.disable_on_disk_shader_cache);

ui->mfcDelayCommand->setChecked(m_emu_settings->GetSetting(emu_settings_type::MFCCommandsShuffling) == "1");
SubscribeTooltip(ui->mfcDelayCommand, tooltips.settings.mfc_delay_command);
connect(ui->mfcDelayCommand, &QCheckBox::stateChanged, [&](int val)
{
const std::string str = val != Qt::Unchecked ? "1" : "0";
m_emu_settings->SetSetting(emu_settings_type::MFCCommandsShuffling, str);
});

// Comboboxes

m_emu_settings->EnhanceComboBox(ui->maxSPURSThreads, emu_settings_type::MaxSPURSThreads, true);
Expand Down
7 changes: 7 additions & 0 deletions rpcs3/rpcs3qt/settings_dialog.ui
Expand Up @@ -2036,6 +2036,13 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="mfcDelayCommand">
<property name="text">
<string>Delay each odd MFC Command</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="silenceAllLogs">
<property name="text">
Expand Down
1 change: 1 addition & 0 deletions rpcs3/rpcs3qt/tooltips.h
Expand Up @@ -85,6 +85,7 @@ class Tooltips : public QObject
const QString accurate_llvm_dfma = tr("Provides extra accuracy on FMA instructions at the cost of performance.\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 can't disable it if your CPU supports FMA.");
const QString accurate_vector_nan = tr("Forces the floating point NaN (Not A Number) values outputted from PPU vector instructions to be accurate to the real hardware. (0x7FC00000)");
const QString accurate_rsx_access = tr("Forces RSX pauses on SPU MFC_GETLLAR and SPU MFC_PUTLLUC operations.");
const QString mfc_delay_command = tr("Forces delaying any odd MFC command, waits for at least 2 pending commands to execute them in a random order.\nMust be used with either SPU interpreters currently.\nSeverely degrades performance! If unsure, don't use this option.");
const QString hook_static_functions = tr("Allows to hook some functions like 'memcpy' replacing them with high-level implementations. May do nothing or break things. Experimental.");
const QString renderdoc_compatibility = tr("Enables use of classic OpenGL buffers which allows capturing tools to work with RPCS3 e.g RenderDoc.\nAlso allows vulkan to use debug markers for nicer Renderdoc captures.\nIf unsure, don't use this option.");
const QString force_high_pz = tr("Only useful when debugging differences in GPU hardware.\nNot necessary for average users.\nIf unsure, don't use this option.");
Expand Down