From f7536bbce0030f34670af9139dd1478b251ad7ed Mon Sep 17 00:00:00 2001 From: Eladash Date: Tue, 7 Apr 2020 18:31:19 +0300 Subject: [PATCH] sys_rsx: Fix gcm events spam In realhw the events are only sent if they are masked in driver_info->handlers as well. --- rpcs3/Emu/Cell/lv2/sys_rsx.cpp | 46 +++++++++++++++++++++++----------- rpcs3/Emu/Cell/lv2/sys_rsx.h | 14 ++++++++++- rpcs3/Emu/RSX/RSXThread.cpp | 2 +- 3 files changed, 45 insertions(+), 17 deletions(-) diff --git a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp index 230b52daf9..a4f8aeb769 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp @@ -38,9 +38,19 @@ u64 rsxTimeStamp() return get_timebased_time(); } -void lv2_rsx_config::send_event(u64 data1, u64 data2, u64 data3) const +void lv2_rsx_config::send_event(u64 data1, u64 event_flags, u64 data3) const { - auto error = sys_event_port_send(rsx_event_port, data1, data2, 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 + event_flags &= vm::_ref(driver_info).handlers | 0xffff'ffffull << 32; + + if (!event_flags) + { + // Nothing to do + return; + } + + auto error = sys_event_port_send(rsx_event_port, data1, event_flags, data3); while (error + 0u == CELL_EBUSY) { @@ -70,7 +80,7 @@ void lv2_rsx_config::send_event(u64 data1, u64 data2, u64 data3) const break; } - error = sys_event_port_send(rsx_event_port, data1, data2, data3); + error = sys_event_port_send(rsx_event_port, data1, event_flags, data3); } if (error) @@ -420,6 +430,9 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64 // otherwise it contains a display buffer offset if ((a4 & 0x80000000) != 0) { + // NOTE: There currently seem to only be 2 active heads on PS3 + verify(HERE), a3 < 2; + // last half byte gives buffer, 0xf seems to trigger just last queued u8 idx_check = a4 & 0xf; if (idx_check > 7) @@ -457,14 +470,13 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64 case 0x103: // Display Queue { - driverInfo.head[a3].lastQueuedBufferId = static_cast(a4); - driverInfo.head[a3].flipFlags |= 0x40000000 | (1 << a4); - // NOTE: There currently seem to only be 2 active heads on PS3 verify(HERE), a3 < 2; - const u64 shift_offset = (a3 + 5); - rsx_cfg->send_event(0, (1ull << shift_offset), 0); + driverInfo.head[a3].lastQueuedBufferId = static_cast(a4); + driverInfo.head[a3].flipFlags |= 0x40000000 | (1 << a4); + + rsx_cfg->send_event(0, SYS_RSX_EVENT_QUEUE_BASE << a3, 0); render->on_frame_end(static_cast(a4)); } @@ -513,6 +525,9 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64 return SYS_RSX_CONTEXT_ATTRIBUTE_ERROR; } + // NOTE: There currently seem to only be 2 active heads on PS3 + verify(HERE), a3 < 2; + driverInfo.head[a3].flipFlags.atomic_op([&](be_t& flipStatus) { flipStatus = (flipStatus & static_cast(a4)) | static_cast(a5); @@ -589,6 +604,7 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64 break; case 0xFEC: // hack: flip event notification + // we only ever use head 1 for now driverInfo.head[1].flipFlags |= 0x80000000; driverInfo.head[1].lastFlipTime = rsxTimeStamp(); // should rsxthread set this? @@ -597,23 +613,23 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64 // seems gcmSysWaitLabel uses this offset, so lets set it to 0 every flip vm::_ref(render->label_addr + 0x10) = 0; - //if (a3 == 0) - // rsx_cfg->send_event(0, (1 << 3), 0); - //if (a3 == 1) - rsx_cfg->send_event(0, (1 << 4), 0); + rsx_cfg->send_event(0, SYS_RSX_EVENT_FLIP_BASE << 1, 0); break; case 0xFED: // hack: vblank command { + // NOTE: There currently seem to only be 2 active heads on PS3 + verify(HERE), a3 < 2; + // 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 vm::_ref(render->device_addr + 0x30) = 1; driverInfo.head[a3].vBlankCount++; driverInfo.head[a3].lastSecondVTime = rsxTimeStamp(); - u64 event_flags = (1 << 1); + u64 event_flags = SYS_RSX_EVENT_VBLANK; if (render->enable_second_vhandler) - event_flags |= (1 << 11); // second vhandler + event_flags |= SYS_RSX_EVENT_SECOND_VBLANK_BASE << a3; // second vhandler rsx_cfg->send_event(0, event_flags, 0); break; @@ -624,7 +640,7 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64 // as i think we need custom lv1 interrupts to handle this accurately // this also should probly be set by rsxthread driverInfo.userCmdParam = static_cast(a4); - rsx_cfg->send_event(0, (1 << 7), 0); + rsx_cfg->send_event(0, SYS_RSX_EVENT_USER_CMD, 0); break; default: diff --git a/rpcs3/Emu/Cell/lv2/sys_rsx.h b/rpcs3/Emu/Cell/lv2/sys_rsx.h index 8aaa9b4120..5cb6c5cd12 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rsx.h +++ b/rpcs3/Emu/Cell/lv2/sys_rsx.h @@ -37,7 +37,7 @@ struct RsxDriverInfo be_t unk7; // 0x12B8 be_t unk8; // 0x12BC - be_t handlers; // 0x12C0 -- flags showing which handlers are set + atomic_be_t handlers; // 0x12C0 -- flags showing which handlers are set be_t unk9; // 0x12C4 be_t unk10; // 0x12C8 be_t userCmdParam; // 0x12CC @@ -62,6 +62,18 @@ enum : u64 SYS_RSX_IO_MAP_IS_STRICT = 1ull << 60 }; +// Unofficial event names +enum : u64 +{ + //SYS_RSX_EVENT_GRAPHICS_ERROR = 1 << 0, + SYS_RSX_EVENT_VBLANK = 1 << 1, + SYS_RSX_EVENT_FLIP_BASE = 1 << 3, + SYS_RSX_EVENT_QUEUE_BASE = 1 << 5, + SYS_RSX_EVENT_USER_CMD = 1 << 7, + SYS_RSX_EVENT_SECOND_VBLANK_BASE = 1 << 10, + SYS_RSX_EVENT_UNMAPPED_BASE = 1ull << 32, +}; + struct RsxDmaControl { u8 resv[0x40]; diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index d195817aa5..1d84ef8737 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -2424,7 +2424,7 @@ namespace rsx if (u64 to_unmap = unmap_status[i]) { // Each 64 entries are grouped by a bit - const u64 io_event = 0x100000000ull << i; + const u64 io_event = SYS_RSX_EVENT_UNMAPPED_BASE << i; g_fxo->get()->send_event(0, io_event, to_unmap); } }