mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 02:32:36 +01:00
RSX/Savestates: Replace GCM hack with a proper fix
This commit is contained in:
parent
f0c71ae2ae
commit
5f8f9e33f1
@ -1536,14 +1536,14 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe
|
||||
// If we fail due to being busy, wait a bit and try again.
|
||||
while (static_cast<u32>(sending_error) == CELL_EBUSY)
|
||||
{
|
||||
thread_ctrl::wait_for(1000);
|
||||
sending_error = sys_event_port_send(pf_port_id, data1, data2, data3);
|
||||
|
||||
if (cpu->is_stopped())
|
||||
{
|
||||
sending_error = {};
|
||||
break;
|
||||
}
|
||||
|
||||
thread_ctrl::wait_for(1000);
|
||||
sending_error = sys_event_port_send(pf_port_id, data1, data2, data3);
|
||||
}
|
||||
|
||||
if (sending_error)
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "Utilities/JIT.h"
|
||||
#include "Utilities/date_time.h"
|
||||
#include "Emu/Memory/vm.h"
|
||||
@ -1704,7 +1704,7 @@ void spu_thread::serialize_common(utils::serial& ar)
|
||||
, ch_out_mbox.data, ch_out_intr_mbox.data, snr_config, ch_snr1.data, ch_snr2.data, ch_events.raw().all, interrupts_enabled
|
||||
, run_ctrl, exit_status.data, status_npc.raw().status);
|
||||
|
||||
if (GET_SERIALIZATION_VERSION(spu) != 1u)
|
||||
if (GET_SERIALIZATION_VERSION(spu) != 1)
|
||||
{
|
||||
ar(ch_dec_start_timestamp, ch_dec_value, is_dec_frozen);
|
||||
}
|
||||
|
@ -239,7 +239,7 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode)
|
||||
|
||||
const auto queue = idm::withdraw<lv2_obj, lv2_event_queue>(equeue_id, [&](lv2_event_queue& queue) -> CellError
|
||||
{
|
||||
qlock.lock(queue.mutex);
|
||||
qlock = std::unique_lock{queue.mutex};
|
||||
|
||||
if (!mode && !queue.sq.empty())
|
||||
{
|
||||
@ -456,8 +456,14 @@ error_code sys_event_queue_receive(ppu_thread& ppu, u32 equeue_id, vm::ptr<sys_e
|
||||
|
||||
if (is_stopped(state))
|
||||
{
|
||||
extern void signal_gcm_intr_thread_offline(lv2_event_queue&);
|
||||
signal_gcm_intr_thread_offline(*queue);
|
||||
std::lock_guard lock_rsx(queue->mutex);
|
||||
|
||||
if (std::find(queue->sq.begin(), queue->sq.end(), &ppu) == queue->sq.end())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ppu.state += cpu_flag::again;
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -686,7 +692,8 @@ error_code sys_event_port_send(u32 eport_id, u64 data1, u64 data2, u64 data3)
|
||||
{
|
||||
if (port.ret == CELL_EAGAIN)
|
||||
{
|
||||
return CELL_OK;
|
||||
// Not really an error code exposed to games (thread has raised cpu_flag::again)
|
||||
return not_an_error(CELL_EAGAIN);
|
||||
}
|
||||
|
||||
if (port.ret == CELL_EBUSY)
|
||||
|
@ -37,7 +37,7 @@ u64 rsxTimeStamp()
|
||||
return get_timebased_time();
|
||||
}
|
||||
|
||||
void rsx::thread::send_event(u64 data1, u64 event_flags, u64 data3) const
|
||||
bool rsx::thread::send_event(u64 data1, u64 event_flags, u64 data3)
|
||||
{
|
||||
// Filter event bits, send them only if they are masked by gcm
|
||||
// Except the upper 32-bits, they are reserved for unmapped io events and execute unconditionally
|
||||
@ -46,7 +46,7 @@ void rsx::thread::send_event(u64 data1, u64 event_flags, u64 data3) const
|
||||
if (!event_flags)
|
||||
{
|
||||
// Nothing to do
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
auto error = sys_event_port_send(rsx_event_port, data1, event_flags, data3);
|
||||
@ -76,35 +76,19 @@ void rsx::thread::send_event(u64 data1, u64 event_flags, u64 data3) const
|
||||
error = sys_event_port_send(rsx_event_port, data1, event_flags, data3);
|
||||
}
|
||||
|
||||
if (!Emu.IsPaused() && error && error + 0u != CELL_ENOTCONN)
|
||||
if (error + 0u == CELL_EAGAIN)
|
||||
{
|
||||
// Thread has aborted when sending event (VBLANK duplicates are allowed)
|
||||
ensure((unsent_gcm_events.fetch_or(event_flags) & event_flags & ~(SYS_RSX_EVENT_VBLANK | SYS_RSX_EVENT_SECOND_VBLANK_BASE | SYS_RSX_EVENT_SECOND_VBLANK_BASE * 2)) == 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (error && error + 0u != CELL_ENOTCONN)
|
||||
{
|
||||
fmt::throw_exception("rsx::thread::send_event() Failed to send event! (error=%x)", +error);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true on success of receiving the event
|
||||
void signal_gcm_intr_thread_offline(lv2_event_queue& q)
|
||||
{
|
||||
const auto render = rsx::get_current_renderer();
|
||||
const auto cpu = cpu_thread::get_current();
|
||||
|
||||
static shared_mutex s_dummy;
|
||||
|
||||
std::scoped_lock lock_rsx(render ? render->sys_rsx_mtx : s_dummy, q.mutex);
|
||||
|
||||
if (std::find(q.sq.begin(), q.sq.end(), cpu) == q.sq.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
cpu->state += cpu_flag::again;
|
||||
|
||||
if (!vm::check_addr(render->driver_info) || vm::_ref<RsxDriverInfo>(render->driver_info).handler_queue != q.id)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
render->gcm_intr_thread_offline = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
error_code sys_rsx_device_open(cpu_thread& cpu)
|
||||
@ -534,7 +518,10 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
|
||||
driverInfo.head[a3].flipFlags |= 0x40000000 | (1 << a4);
|
||||
|
||||
render->on_frame_end(static_cast<u32>(a4));
|
||||
render->send_event(0, SYS_RSX_EVENT_QUEUE_BASE << a3, 0);
|
||||
if (!render->send_event(0, SYS_RSX_EVENT_QUEUE_BASE << a3, 0))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (g_cfg.video.frame_limit == frame_limit_type::infinite)
|
||||
{
|
||||
@ -780,19 +767,6 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
|
||||
|
||||
case 0xFEC: // hack: flip event notification
|
||||
{
|
||||
reader_lock lock(render->sys_rsx_mtx);
|
||||
|
||||
if (render->gcm_intr_thread_offline)
|
||||
{
|
||||
if (auto cpu = get_current_cpu_thread())
|
||||
{
|
||||
cpu->state += cpu_flag::exit;
|
||||
cpu->state += cpu_flag::again;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// we only ever use head 1 for now
|
||||
driverInfo.head[1].flipFlags |= 0x80000000;
|
||||
driverInfo.head[1].lastFlipTime = rsxTimeStamp(); // should rsxthread set this?
|
||||
@ -817,13 +791,6 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
|
||||
// NOTE: There currently seem to only be 2 active heads on PS3
|
||||
ensure(a3 < 2);
|
||||
|
||||
reader_lock lock(render->sys_rsx_mtx);
|
||||
|
||||
if (render->gcm_intr_thread_offline)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// todo: this is wrong and should be 'second' vblank handler and freq, but since currently everything is reported as being 59.94, this should be fine
|
||||
driverInfo.head[a3].lastSecondVTime.atomic_op([&](be_t<u64>& time)
|
||||
{
|
||||
@ -852,19 +819,6 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
|
||||
|
||||
case 0xFEF: // hack: user command
|
||||
{
|
||||
reader_lock lock(render->sys_rsx_mtx);
|
||||
|
||||
if (render->gcm_intr_thread_offline)
|
||||
{
|
||||
if (auto cpu = get_current_cpu_thread())
|
||||
{
|
||||
cpu->state += cpu_flag::exit;
|
||||
cpu->state += cpu_flag::again;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// 'custom' invalid package id for now
|
||||
// as i think we need custom lv1 interrupts to handle this accurately
|
||||
// this also should probly be set by rsxthread
|
||||
|
@ -453,6 +453,11 @@ namespace rsx
|
||||
ar(device_addr, label_addr, main_mem_size, local_mem_size, rsx_event_port, driver_info);
|
||||
ar(in_begin_end, zcull_stats_enabled, zcull_rendering_enabled, zcull_pixel_cnt_enabled);
|
||||
ar(display_buffers, display_buffers_count, current_display_buffer);
|
||||
|
||||
if (ar.is_writing() || GET_SERIALIZATION_VERSION(rsx) != 1u)
|
||||
{
|
||||
ar(unsent_gcm_events);
|
||||
}
|
||||
}
|
||||
|
||||
thread::thread(utils::serial* _ar)
|
||||
@ -756,6 +761,14 @@ namespace rsx
|
||||
|
||||
vblank_count = 0;
|
||||
|
||||
if (u64 event_flags = unsent_gcm_events.exchange(0))
|
||||
{
|
||||
if (!send_event(0, event_flags, 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
g_fxo->init<named_thread>("VBlank Thread", [this]()
|
||||
{
|
||||
// See sys_timer_usleep for details
|
||||
@ -772,7 +785,7 @@ namespace rsx
|
||||
u64 local_vblank_count = 0;
|
||||
|
||||
// TODO: exit condition
|
||||
while (!is_stopped())
|
||||
while (!is_stopped() && !unsent_gcm_events)
|
||||
{
|
||||
// Get current time
|
||||
const u64 current = get_system_time();
|
||||
@ -3407,6 +3420,13 @@ namespace rsx
|
||||
if (!isHLE)
|
||||
{
|
||||
sys_rsx_context_attribute(0x55555555, 0xFEC, buffer, 0, 0, 0);
|
||||
|
||||
if (unsent_gcm_events)
|
||||
{
|
||||
// TODO: A proper fix
|
||||
return;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -584,9 +584,10 @@ namespace rsx
|
||||
u32 local_mem_size{0};
|
||||
u32 rsx_event_port{0};
|
||||
u32 driver_info{0};
|
||||
bool gcm_intr_thread_offline = false; // Hack for savestates
|
||||
|
||||
void send_event(u64, u64, u64) const;
|
||||
atomic_t<u64> unsent_gcm_events = 0; // Unsent event bits when aborting RSX/VBLANK thread (will be sent on savestate load)
|
||||
|
||||
bool send_event(u64, u64, u64);
|
||||
|
||||
bool m_rtts_dirty = true;
|
||||
std::array<bool, 16> m_textures_dirty;
|
||||
|
@ -67,8 +67,8 @@ u64 g_rtm_tx_limit2 = 0;
|
||||
struct serial_ver_t
|
||||
{
|
||||
bool used = false;
|
||||
u32 current_version = 0;
|
||||
std::set<u32> compatible_versions;
|
||||
s32 current_version = 0;
|
||||
std::set<s32> compatible_versions;
|
||||
};
|
||||
|
||||
static std::array<serial_ver_t, 23> s_serial_versions;
|
||||
@ -83,7 +83,7 @@ static std::array<serial_ver_t, 23> s_serial_versions;
|
||||
::s_serial_versions[identifier].used = true;\
|
||||
}\
|
||||
\
|
||||
extern u32 get_##name##_serialization_version()\
|
||||
extern s32 get_##name##_serialization_version()\
|
||||
{\
|
||||
return ::s_serial_versions[identifier].current_version;\
|
||||
}
|
||||
@ -101,7 +101,7 @@ SERIALIZATION_VER(lv2_config, 9, 1)
|
||||
|
||||
namespace rsx
|
||||
{
|
||||
SERIALIZATION_VER(rsx, 10, 1)
|
||||
SERIALIZATION_VER(rsx, 10, 1, 2)
|
||||
}
|
||||
|
||||
namespace np
|
||||
@ -111,7 +111,7 @@ namespace np
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Compiler bug, lambda function body does seem to inherit used namespace atleast for function decleration
|
||||
SERIALIZATION_VER(rsx, 10, 1)
|
||||
SERIALIZATION_VER(rsx, 10, 1, 2)
|
||||
SERIALIZATION_VER(sceNp, 11, 1)
|
||||
#endif
|
||||
|
||||
|
@ -1118,7 +1118,7 @@ extern bool serialize(utils::serial& ar, T& obj);
|
||||
|
||||
#define GET_SERIALIZATION_VERSION(name) []()\
|
||||
{\
|
||||
extern u32 get_##name##_serialization_version();\
|
||||
extern s32 get_##name##_serialization_version();\
|
||||
return get_##name##_serialization_version();\
|
||||
}()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user