Skip to content

Commit

Permalink
sys_rsx: Fix gcm events spam
Browse files Browse the repository at this point in the history
In realhw the events are only sent if they are masked in driver_info->handlers as well.
  • Loading branch information
elad335 committed Apr 7, 2020
1 parent c4f6281 commit 1c12828
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 20 deletions.
55 changes: 37 additions & 18 deletions rpcs3/Emu/Cell/lv2/sys_rsx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<RsxDriverInfo>(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)
{
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -416,6 +426,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)
Expand Down Expand Up @@ -453,14 +466,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<u32>(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<u32>(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<u32>(a4));
}
Expand Down Expand Up @@ -509,6 +521,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<u32>& flipStatus)
{
flipStatus = (flipStatus & static_cast<u32>(a4)) | static_cast<u32>(a5);
Expand Down Expand Up @@ -585,31 +600,35 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
break;

case 0xFEC: // hack: flip event notification

// NOTE: There currently seem to only be 2 active heads on PS3
// we only ever use head 1 for now
driverInfo.head[1].flipFlags |= 0x80000000;
driverInfo.head[1].lastFlipTime = rsxTimeStamp(); // should rsxthread set this?
driverInfo.head[1].flipBufferId = static_cast<u32>(a3);
verify(HERE), a3 == 1;

driverInfo.head[a3].flipFlags |= 0x80000000;
driverInfo.head[a3].lastFlipTime = rsxTimeStamp(); // should rsxthread set this?
driverInfo.head[a3].flipBufferId = static_cast<u32>(a3);

// seems gcmSysWaitLabel uses this offset, so lets set it to 0 every flip
vm::_ref<u32>(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 << a3, 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<u32>(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;
Expand All @@ -620,7 +639,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<u32>(a4);
rsx_cfg->send_event(0, (1 << 7), 0);
rsx_cfg->send_event(0, SYS_RSX_EVENT_USER_CMD, 0);
break;

default:
Expand Down
14 changes: 13 additions & 1 deletion rpcs3/Emu/Cell/lv2/sys_rsx.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ struct RsxDriverInfo

be_t<u32> unk7; // 0x12B8
be_t<u32> unk8; // 0x12BC
be_t<u32> handlers; // 0x12C0 -- flags showing which handlers are set
atomic_be_t<u32> handlers; // 0x12C0 -- flags showing which handlers are set
be_t<u32> unk9; // 0x12C4
be_t<u32> unk10; // 0x12C8
be_t<u32> userCmdParam; // 0x12CC
Expand All @@ -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];
Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/RSX/RSXThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<lv2_rsx_config>()->send_event(0, io_event, to_unmap);
}
}
Expand Down

0 comments on commit 1c12828

Please sign in to comment.