From 3f48450408476d4b70aa74b3171b9698e02b98ae Mon Sep 17 00:00:00 2001 From: Eladash Date: Tue, 7 Apr 2020 13:18:41 +0300 Subject: [PATCH] sys_rsx: Minor atomicity fixes --- rpcs3/Emu/Cell/lv2/sys_rsx.cpp | 73 +++++++++++++++++++++++++++++----- rpcs3/Emu/Cell/lv2/sys_rsx.h | 7 +++- rpcs3/Emu/RSX/RSXFIFO.cpp | 4 +- rpcs3/Emu/RSX/RSXThread.cpp | 4 +- rpcs3/Emu/RSX/RSXThread.h | 2 +- rpcs3/Emu/RSX/rsx_methods.cpp | 4 +- 6 files changed, 75 insertions(+), 19 deletions(-) diff --git a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp index fbb0ccf211..230b52daf9 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp @@ -38,6 +38,47 @@ u64 rsxTimeStamp() return get_timebased_time(); } +void lv2_rsx_config::send_event(u64 data1, u64 data2, u64 data3) const +{ + auto error = sys_event_port_send(rsx_event_port, data1, data2, data3); + + while (error + 0u == CELL_EBUSY) + { + auto cpu = get_current_cpu_thread(); + + if (cpu && cpu->id_type() != 1) + { + cpu = nullptr; + } + + if (cpu) + { + // Deschedule + lv2_obj::sleep(*cpu, 100); + } + else if (const auto rsx = rsx::get_current_renderer(); rsx->is_current_thread()) + { + rsx->on_semaphore_acquire_wait(); + } + + // Wait a bit before resending event + thread_ctrl::wait_for(100); + + if (cpu && cpu->check_state()) + { + error = 0; + break; + } + + error = sys_event_port_send(rsx_event_port, data1, data2, data3); + } + + if (error) + { + fmt::throw_exception("rsx_event_port_send() Failed to send event! (error=%x)" HERE, +error); + } +} + error_code sys_rsx_device_open() { sys_rsx.todo("sys_rsx_device_open()"); @@ -202,6 +243,8 @@ error_code sys_rsx_context_allocate(vm::ptr context_id, vm::ptr lpar_d sys_event_queue_create(vm::get_addr(&driverInfo.handler_queue), attr, 0, 0x20); sys_event_port_connect_local(rsx_cfg->rsx_event_port, driverInfo.handler_queue); + rsx_cfg->dma_address = vm::cast(*lpar_dma_control, HERE); + const auto render = rsx::get_current_renderer(); render->display_buffers_count = 0; render->current_display_buffer = 0; @@ -350,12 +393,17 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64 switch (package_id) { case 0x001: // FIFO + { render->pause(); + const u64 get = static_cast(a3); + const u64 put = static_cast(a4); + vm::_ref>(rsx_cfg->dma_address + ::offset32(&RsxDmaControl::put)).release(put << 32 | get); render->ctrl->get = static_cast(a3); render->ctrl->put = static_cast(a4); - render->restore_point = static_cast(a3); + render->sync_point_request.release(true); render->unpause(); break; + } case 0x100: // Display mode set break; @@ -416,7 +464,7 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64 verify(HERE), a3 < 2; const u64 shift_offset = (a3 + 5); - sys_event_port_send(rsx_cfg->rsx_event_port, 0, (1ull << shift_offset), 0); + rsx_cfg->send_event(0, (1ull << shift_offset), 0); render->on_frame_end(static_cast(a4)); } @@ -465,9 +513,10 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64 return SYS_RSX_CONTEXT_ATTRIBUTE_ERROR; } - u32 flipStatus = driverInfo.head[a3].flipFlags; - flipStatus = (flipStatus & static_cast(a4)) | static_cast(a5); - driverInfo.head[a3].flipFlags = flipStatus; + driverInfo.head[a3].flipFlags.atomic_op([&](be_t& flipStatus) + { + flipStatus = (flipStatus & static_cast(a4)) | static_cast(a5); + }); } break; @@ -549,29 +598,33 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64 vm::_ref(render->label_addr + 0x10) = 0; //if (a3 == 0) - // sys_event_port_send(rsx_cfg->rsx_event_port, 0, (1 << 3), 0); + // rsx_cfg->send_event(0, (1 << 3), 0); //if (a3 == 1) - sys_event_port_send(rsx_cfg->rsx_event_port, 0, (1 << 4), 0); + rsx_cfg->send_event(0, (1 << 4), 0); break; case 0xFED: // hack: vblank command + { // 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(); - sys_event_port_send(rsx_cfg->rsx_event_port, 0, (1 << 1), 0); + + u64 event_flags = (1 << 1); if (render->enable_second_vhandler) - sys_event_port_send(rsx_cfg->rsx_event_port, 0, (1 << 11), 0); // second vhandler + event_flags |= (1 << 11); // second vhandler + rsx_cfg->send_event(0, event_flags, 0); break; + } case 0xFEF: // hack: user command // '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 driverInfo.userCmdParam = static_cast(a4); - sys_event_port_send(rsx_cfg->rsx_event_port, 0, (1 << 7), 0); + rsx_cfg->send_event(0, (1 << 7), 0); break; default: diff --git a/rpcs3/Emu/Cell/lv2/sys_rsx.h b/rpcs3/Emu/Cell/lv2/sys_rsx.h index 84c4daf7d9..8aaa9b4120 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rsx.h +++ b/rpcs3/Emu/Cell/lv2/sys_rsx.h @@ -22,7 +22,7 @@ struct RsxDriverInfo struct Head { be_t lastFlipTime; // 0x0 last flip time - be_t flipFlags; // 0x8 flags to handle flip/queue + atomic_be_t flipFlags; // 0x8 flags to handle flip/queue be_t offset; // 0xC be_t flipBufferId; // 0x10 be_t lastQueuedBufferId; // 0x14 todo: this is definately not this variable but its 'unused' so im using it for queueId to pass to flip handler @@ -30,7 +30,7 @@ struct RsxDriverInfo be_t unk6; // 0x18 possible low bits of time stamp? used in getlastVBlankTime be_t lastSecondVTime; // 0x20 last time for second vhandler freq be_t unk4; // 0x28 - be_t vBlankCount; // 0x30 + atomic_be_t vBlankCount; // 0x30 be_t unk; // 0x38 possible u32, 'flip field', top/bottom for interlaced be_t unk5; // 0x3C possible high bits of time stamp? used in getlastVBlankTime } head[8]; // size = 0x40, 0x200 @@ -114,6 +114,9 @@ struct lv2_rsx_config u32 context_base{}; u32 device_addr{}; u32 driver_info{}; + u32 dma_address{}; + + void send_event(u64, u64, u64) const; }; // SysCalls diff --git a/rpcs3/Emu/RSX/RSXFIFO.cpp b/rpcs3/Emu/RSX/RSXFIFO.cpp index 1439b54975..4a4a6d6116 100644 --- a/rpcs3/Emu/RSX/RSXFIFO.cpp +++ b/rpcs3/Emu/RSX/RSXFIFO.cpp @@ -431,7 +431,7 @@ namespace rsx if (performance_counters.state == FIFO_state::running) { performance_counters.FIFO_idle_timestamp = get_system_time(); - sync_point_request = true; + sync_point_request.release(true); } performance_counters.state = FIFO_state::spinning; @@ -450,7 +450,7 @@ namespace rsx if (performance_counters.state == FIFO_state::running) { performance_counters.FIFO_idle_timestamp = get_system_time(); - sync_point_request = true; + sync_point_request.release(true); } performance_counters.state = FIFO_state::spinning; diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 7d8b4a1836..d195817aa5 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -615,7 +615,7 @@ namespace rsx { restore_point = ctrl->get; saved_fifo_ret = fifo_ret_addr; - sync_point_request = false; + sync_point_request.release(false); } // Execute backend-local tasks first @@ -2425,7 +2425,7 @@ namespace rsx { // Each 64 entries are grouped by a bit const u64 io_event = 0x100000000ull << i; - sys_event_port_send(g_fxo->get()->rsx_event_port, 0, io_event, to_unmap); + g_fxo->get()->send_event(0, io_event, to_unmap); } } } diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index bb09867911..ece2c93c53 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -725,7 +725,7 @@ namespace rsx bool capture_current_frame = false; public: - bool sync_point_request = false; + atomic_t sync_point_request = false; bool in_begin_end = false; struct desync_fifo_cmd_info diff --git a/rpcs3/Emu/RSX/rsx_methods.cpp b/rpcs3/Emu/RSX/rsx_methods.cpp index fa1f110994..4eae1603bb 100644 --- a/rpcs3/Emu/RSX/rsx_methods.cpp +++ b/rpcs3/Emu/RSX/rsx_methods.cpp @@ -50,7 +50,7 @@ namespace rsx void semaphore_acquire(thread* rsx, u32 /*_reg*/, u32 arg) { - rsx->sync_point_request = true; + rsx->sync_point_request.release(true); const u32 addr = get_address(method_registers.semaphore_offset_406e(), method_registers.semaphore_context_dma_406e(), HERE); const auto& sema = vm::_ref>(addr); @@ -132,7 +132,7 @@ namespace rsx if (const bool is_flip_sema = (offset == 0x10 && ctxt == CELL_GCM_CONTEXT_DMA_SEMAPHORE_R); !is_flip_sema) { - rsx->sync_point_request = true; + rsx->sync_point_request.release(true); } const u32 addr = get_address(offset, ctxt, HERE);