Skip to content

Commit

Permalink
RSX/SPU: Accurate reservation access
Browse files Browse the repository at this point in the history
  • Loading branch information
elad335 committed Feb 14, 2020
1 parent 0d7aa5e commit 27b37ef
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 36 deletions.
87 changes: 63 additions & 24 deletions rpcs3/Emu/Cell/SPUThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "Emu/System.h"

#include "Emu/IdManager.h"
#include "Emu/RSX/RSXThread.h"
#include "Emu/Cell/PPUThread.h"
#include "Emu/Cell/ErrorCodes.h"
#include "Emu/Cell/lv2/sys_spu.h"
Expand Down Expand Up @@ -68,6 +69,24 @@ static FORCE_INLINE void mov_rdata(decltype(spu_thread::rdata)& dst, const declt
}
}

// Returns nullptr if rsx does not need pausing on reservations op, rsx ptr otherwise
static FORCE_INLINE rsx::thread* is_need_rsx_reservations_pause(u32 addr)
{
if (!g_cfg.core.rsx_accurate_res_access)
{
return {};
}

const auto render = rsx::get_current_renderer();

if (render->iomap_table.io[addr >> 20] == -1)
{
return {};
}

return render;
}

extern u64 get_timebased_time();
extern u64 get_system_time();

Expand Down Expand Up @@ -1655,12 +1674,19 @@ void spu_thread::do_putlluc(const spu_mfc_cmd& args)

if (g_cfg.core.spu_accurate_putlluc)
{
// Full lock (heavyweight)
// TODO: vm::check_addr
const auto render = is_need_rsx_reservations_pause(addr);
if (render) render->pause();

auto& super_data = *vm::get_super_ptr<decltype(rdata)>(addr);
vm::writer_lock lock(addr);
mov_rdata(super_data, to_write);
res.release(res.load() + 127);
{
// Full lock (heavyweight)
// TODO: vm::check_addr
vm::writer_lock lock(addr);
mov_rdata(super_data, to_write);
res.release(res.load() + 127);
}

if (render) render->unpause();
}
else
{
Expand Down Expand Up @@ -1868,15 +1894,22 @@ bool spu_thread::process_mfc_cmd()
if (g_cfg.core.spu_accurate_getllar)
{
*reinterpret_cast<atomic_t<u32>*>(&data) += 0;

const auto render = is_need_rsx_reservations_pause(addr);
if (render) render->pause();

const auto& super_data = *vm::get_super_ptr<decltype(rdata)>(addr);
{
// Full lock (heavyweight)
// TODO: vm::check_addr
vm::writer_lock lock(addr);

// Full lock (heavyweight)
// TODO: vm::check_addr
vm::writer_lock lock(addr);
ntime = old_time;
mov_rdata(dst, super_data);
res.release(old_time);
}

ntime = old_time;
mov_rdata(dst, super_data);
res.release(old_time);
if (render) render->unpause();
}
else
{
Expand Down Expand Up @@ -1969,22 +2002,28 @@ bool spu_thread::process_mfc_cmd()
{
*reinterpret_cast<atomic_t<u32>*>(&data) += 0;

auto& super_data = *vm::get_super_ptr<decltype(rdata)>(addr);

// Full lock (heavyweight)
// TODO: vm::check_addr
vm::writer_lock lock(addr);
const auto render = is_need_rsx_reservations_pause(addr);
if (render) render->pause();

if (cmp_rdata(rdata, super_data))
{
mov_rdata(super_data, to_write);
res.release(old_time + 128);
result = 1;
}
else
auto& super_data = *vm::get_super_ptr<decltype(rdata)>(addr);
{
res.release(old_time);
// Full lock (heavyweight)
// TODO: vm::check_addr
vm::writer_lock lock(addr);

if (cmp_rdata(rdata, super_data))
{
mov_rdata(super_data, to_write);
res.release(old_time + 128);
result = 1;
}
else
{
res.release(old_time);
}
}

if (render) render->unpause();
}
else
{
Expand Down
37 changes: 27 additions & 10 deletions rpcs3/Emu/RSX/RSXThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -618,9 +618,7 @@ namespace rsx
// Wait for external pause events
if (external_interrupt_lock)
{
external_interrupt_ack.store(true);

while (external_interrupt_lock) _mm_pause();
wait_pause();
}

// Note a possible rollback address
Expand Down Expand Up @@ -2471,10 +2469,7 @@ namespace rsx
//Pause/cont wrappers for FIFO ctrl. Never call this from rsx thread itself!
void thread::pause()
{
while (external_interrupt_lock.exchange(true)) [[unlikely]]
{
_mm_pause();
}
external_interrupt_lock++;

while (!external_interrupt_ack)
{
Expand All @@ -2483,14 +2478,36 @@ namespace rsx

_mm_pause();
}

external_interrupt_ack.store(false);
}

void thread::unpause()
{
// TODO: Clean this shit up
external_interrupt_lock.store(false);
if (external_interrupt_lock-- == 1)
{
external_interrupt_lock.notify_one();
}
}

void thread::wait_pause()
{
do
{
if (g_cfg.video.multithreaded_rsx)
{
g_dma_manager.sync();
}

external_interrupt_ack.store(true);

while (const u32 old = external_interrupt_lock)
{
external_interrupt_lock.wait(old);
}

external_interrupt_ack.store(false);
}
while (external_interrupt_lock);
}

u32 thread::get_load()
Expand Down
3 changes: 2 additions & 1 deletion rpcs3/Emu/RSX/RSXThread.h
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ namespace rsx
RsxDmaControl* ctrl = nullptr;
rsx_iomap_table iomap_table;
u32 restore_point = 0;
atomic_t<bool> external_interrupt_lock{ false };
atomic_t<u32> external_interrupt_lock{ 0 };
atomic_t<bool> external_interrupt_ack{ false };
void flush_fifo();
void recover_fifo();
Expand Down Expand Up @@ -899,6 +899,7 @@ namespace rsx

void pause();
void unpause();
void wait_pause();

// Get RSX approximate load in %
u32 get_load();
Expand Down
21 changes: 20 additions & 1 deletion rpcs3/Emu/RSX/rsx_methods.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,17 +100,26 @@ namespace rsx
if (Emu.IsStopped())
return;

// Wait for external pause events
if (rsx->external_interrupt_lock)
{
rsx->wait_pause();
continue;
}

if (const auto tdr = static_cast<u64>(g_cfg.video.driver_recovery_timeout))
{
if (Emu.IsPaused())
{
const u64 start0 = get_system_time();

while (Emu.IsPaused())
{
std::this_thread::sleep_for(1ms);
}

// Reset
start = get_system_time();
start += get_system_time() - start0;
}
else
{
Expand Down Expand Up @@ -829,6 +838,8 @@ namespace rsx
const u32 pixel_offset = (method_registers.blit_engine_output_pitch_nv3062() * y) + (x * write_len);
u32 address = get_address(method_registers.blit_engine_output_offset_nv3062() + pixel_offset + (index * write_len), method_registers.blit_engine_output_location_nv3062(), HERE);

//auto res = vm::passive_lock(address, address + write_len);

switch (write_len)
{
case 4:
Expand All @@ -841,6 +852,7 @@ namespace rsx
fmt::throw_exception("Unreachable" HERE);
}

//res->release(0);
rsx->m_graphics_state |= rsx::pipeline_state::fragment_program_dirty;
}
};
Expand Down Expand Up @@ -982,6 +994,9 @@ namespace rsx
const u32 dst_address = get_address(dst_offset, dst_dma, HERE);

const u32 src_line_length = (in_w * in_bpp);

//auto res = vm::passive_lock(dst_address, dst_address + (in_pitch * (in_h - 1) + src_line_length));

if (is_block_transfer && (clip_h == 1 || (in_pitch == out_pitch && src_line_length == in_pitch)))
{
const u32 nb_lines = std::min(clip_h, in_h);
Expand Down Expand Up @@ -1349,6 +1364,8 @@ namespace rsx
}
}

//auto res = vm::passive_lock(write_address, data_length + write_address);

u8 *dst = vm::_ptr<u8>(write_address);
const u8 *src = vm::_ptr<u8>(read_address);

Expand Down Expand Up @@ -1404,6 +1421,8 @@ namespace rsx
}
}
}

//res->release(0);
}
}

Expand Down
1 change: 1 addition & 0 deletions rpcs3/Emu/System.h
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,7 @@ struct cfg_root : cfg::node
cfg::_enum<spu_block_size_type> spu_block_size{this, "SPU Block Size", spu_block_size_type::safe};
cfg::_bool spu_accurate_getllar{this, "Accurate GETLLAR", false};
cfg::_bool spu_accurate_putlluc{this, "Accurate PUTLLUC", false};
cfg::_bool rsx_accurate_res_access{this, "Accurate RSX reservation access", false, true};
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};
Expand Down
2 changes: 2 additions & 0 deletions rpcs3/rpcs3qt/emu_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class emu_settings : public QObject
EnableTSX,
AccurateGETLLAR,
AccuratePUTLLUC,
AccurateRSXAccess,
AccurateXFloat,
SetDAZandFTZ,
SPUBlockSize,
Expand Down Expand Up @@ -274,6 +275,7 @@ public Q_SLOTS:
{ EnableTSX, { "Core", "Enable TSX"}},
{ AccurateGETLLAR, { "Core", "Accurate GETLLAR"}},
{ AccuratePUTLLUC, { "Core", "Accurate PUTLLUC"}},
{ AccurateRSXAccess, { "Core", "Accurate RSX reservation access"}},
{ AccurateXFloat, { "Core", "Accurate xfloat"}},
{ SetDAZandFTZ, { "Core", "Set DAZ and FTZ"}},
{ SPUBlockSize, { "Core", "SPU Block Size"}},
Expand Down
3 changes: 3 additions & 0 deletions rpcs3/rpcs3qt/settings_dialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1583,6 +1583,9 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> guiSettings, std:
xemu_settings->EnhanceCheckBox(ui->accuratePUTLLUC, emu_settings::AccuratePUTLLUC);
SubscribeTooltip(ui->accuratePUTLLUC, tooltips.settings.accurate_putlluc);

xemu_settings->EnhanceCheckBox(ui->accurateRSXAccess, emu_settings::AccurateRSXAccess);
SubscribeTooltip(ui->accurateRSXAccess, tooltips.settings.accurate_rsx_access);

xemu_settings->EnhanceCheckBox(ui->hookStFunc, emu_settings::HookStaticFuncs);
SubscribeTooltip(ui->hookStFunc, tooltips.settings.hook_static_functions);

Expand Down
7 changes: 7 additions & 0 deletions rpcs3/rpcs3qt/settings_dialog.ui
Original file line number Diff line number Diff line change
Expand Up @@ -3101,6 +3101,13 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="accurateRSXAccess">
<property name="text">
<string>Accurate RSX reservation access</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="hookStFunc">
<property name="text">
Expand Down
1 change: 1 addition & 0 deletions rpcs3/rpcs3qt/tooltips.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class Tooltips : public QObject
const QString set_daz_and_ftz = tr("Never use this.");
const QString accurate_getllar = tr("Never use this.");
const QString accurate_putlluc = tr("Never use this.");
const QString accurate_rsx_access = tr("Never use this.");
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 gl_legacy_buffers = tr("Enables use of classic OpenGL buffers which allows capturing tools to work with RPCS3 e.g RenderDoc.\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

0 comments on commit 27b37ef

Please sign in to comment.