From a3d44b5e1fbd2fbd6eb539cfb67acb1fba260f39 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sat, 22 Sep 2018 10:51:48 +0300 Subject: [PATCH] rsx: Cleanup changes for the flip patch --- rpcs3/Emu/Cell/lv2/sys_rsx.cpp | 60 +++++++++++++++-------------- rpcs3/Emu/Cell/lv2/sys_rsx.h | 5 +-- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 5 ++- rpcs3/Emu/RSX/Overlays/overlays.cpp | 4 +- rpcs3/Emu/RSX/RSXThread.cpp | 27 ++++++------- rpcs3/Emu/RSX/RSXThread.h | 9 +++-- rpcs3/Emu/RSX/VK/VKGSRender.cpp | 6 ++- rpcs3/Emu/RSX/rsx_methods.cpp | 2 + rpcs3/Emu/RSX/rsx_utils.h | 54 +++++++++++++++++++++++++- 9 files changed, 112 insertions(+), 60 deletions(-) diff --git a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp index cb8ff1397b..4a78755643 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "stdafx.h" #include "Emu/Memory/vm.h" #include "Emu/System.h" #include "Emu/Cell/PPUModule.h" @@ -13,7 +13,8 @@ LOG_CHANNEL(sys_rsx); extern u64 get_timebased_time(); -u64 rsxTimeStamp() { +u64 rsxTimeStamp() +{ return get_timebased_time(); } @@ -178,8 +179,8 @@ s32 sys_rsx_context_iomap(u32 context_id, u32 io, u32 ea, u32 size, u64 flags) { sys_rsx.warning("sys_rsx_context_iomap(context_id=0x%x, io=0x%x, ea=0x%x, size=0x%x, flags=0x%llx)", context_id, io, ea, size, flags); - if (!size || io & 0xFFFFF || ea & 0xFFFFF || size & 0xFFFFF - || rsx::get_current_renderer()->main_mem_size < io + size) + if (!size || io & 0xFFFFF || ea & 0xFFFFF || size & 0xFFFFF || + rsx::get_current_renderer()->main_mem_size < io + size) { return CELL_EINVAL; } @@ -323,6 +324,7 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6 if (a3 == 1) sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 6), 0); break; + case 0x104: // Display buffer { u8 id = a3 & 0xFF; @@ -340,11 +342,13 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6 render->display_buffers_count = std::max((u32)id + 1, render->display_buffers_count); } break; + case 0x105: // destroy buffer? break; case 0x106: // ? (Used by cellGcmInitPerfMon) break; + case 0x108: // cellGcmSetSecondVFrequency // a4 == 3, CELL_GCM_DISPLAY_FREQUENCY_59_94HZ // a4 == 2, CELL_GCM_DISPLAY_FREQUENCY_SCANOUT @@ -352,10 +356,12 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6 // Note: Scanout/59_94 is ignored currently as we report refresh rate of 59_94hz as it is, so the difference doesnt matter render->enable_second_vhandler.store(a4 != 4); break; + case 0x10a: // ? Involved in managing flip status through cellGcmResetFlipStatus { if (a3 > 7) return -17; + u32 flipStatus = driverInfo.head[a3].flipFlags; flipStatus = (flipStatus & a4) | a5; driverInfo.head[a3].flipFlags = flipStatus; @@ -417,6 +423,7 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6 case 0x302: // something with zcull break; + case 0x600: // Framebuffer setup break; @@ -429,14 +436,32 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6 case 0x603: // Framebuffer close 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? + driverInfo.head[1].flipBufferId = (u32)a3; + + // seems gcmSysWaitLabel uses this offset, so lets set it to 0 every flip + vm::_ref(render->label_addr + 0x10) = 0; + + //if (a3 == 0) + // sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 3), 0); + //if (a3 == 1) + sys_event_port_send(m_sysrsx->rsx_event_port, 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 driverInfo.head[a3].vBlankCount++; driverInfo.head[a3].lastSecondVTime = rsxTimeStamp(); sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 1), 0); + if (render->enable_second_vhandler) sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 11), 0); // second vhandler + break; + case 0xFEF: // hack: user command // 'custom' invalid package id for now // as i think we need custom lv1 interrupts to handle this accurately @@ -444,6 +469,7 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6 driverInfo.userCmdParam = a4; sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 7), 0); break; + default: return CELL_EINVAL; } @@ -505,28 +531,4 @@ s32 sys_rsx_attribute(u32 packageId, u32 a2, u32 a3, u32 a4, u32 a5) sys_rsx.warning("sys_rsx_attribute(packageId=0x%x, a2=0x%x, a3=0x%x, a4=0x%x, a5=0x%x)", packageId, a2, a3, a4, a5); return CELL_OK; -} - -void sys_rsx_flip_event(u32 buffer) -{ - auto m_sysrsx = fxm::get(); - if (!m_sysrsx) - return; - - auto &driverInfo = vm::_ref(m_sysrsx->driverInfo); - const auto render = rsx::get_current_renderer(); - - // 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 = buffer; - - // seems gcmSysWaitLabel uses this offset, so lets set it to 0 every flip - vm::_ref(render->label_addr + 0x10) = 0; - - //if (a3 == 0) - // sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 3), 0); - //if (a3 == 1) - sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 4), 0); -} +} \ No newline at end of file diff --git a/rpcs3/Emu/Cell/lv2/sys_rsx.h b/rpcs3/Emu/Cell/lv2/sys_rsx.h index c40ced4879..f8eedd5d7c 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rsx.h +++ b/rpcs3/Emu/Cell/lv2/sys_rsx.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once struct RsxDriverInfo { @@ -119,6 +119,3 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6 s32 sys_rsx_device_map(vm::ptr dev_addr, vm::ptr a2, u32 dev_id); s32 sys_rsx_device_unmap(u32 dev_id); s32 sys_rsx_attribute(u32 a1, u32 a2, u32 a3, u32 a4, u32 a5); - -// Custom 'RSX Events', not lv2 syscalls -void sys_rsx_flip_event(u32 buffer); diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 446fa4a3be..b07148cf7f 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -1722,9 +1722,10 @@ void GLGSRender::do_local_task(rsx::FIFO_state state) if (m_overlay_manager) { - if (!in_begin_end && async_flip_requested.test_and_reset(flip_request::native_ui)) + if (!in_begin_end && async_flip_requested & flip_request::native_ui) { - flip((s32)current_display_buffer); + s32 buffer_id = (async_flip_requested & flip_request::emu_requested) ? async_flip_buffer : (s32)current_display_buffer; + flip(buffer_id); } } } diff --git a/rpcs3/Emu/RSX/Overlays/overlays.cpp b/rpcs3/Emu/RSX/Overlays/overlays.cpp index 55325fb2d9..d372b356b9 100644 --- a/rpcs3/Emu/RSX/Overlays/overlays.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlays.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "stdafx.h" #include "overlays.h" #include "../GSRender.h" @@ -35,7 +35,7 @@ namespace rsx const auto now = get_system_time() - 1000000; if ((now - rsxthr->last_flip_time) > min_refresh_duration_us) { - rsxthr->async_flip_requested.test_and_set(rsx::thread::flip_request::native_ui); + rsxthr->async_flip_requested |= rsx::thread::flip_request::native_ui; } } } diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index b7a4e2c0eb..0c4b17a389 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -1356,10 +1356,9 @@ namespace rsx void thread::do_local_task(FIFO_state state) { - if (test(async_flip_requested, flip_request::emu_requested)) + if (async_flip_requested & flip_request::any) { handle_emu_flip(async_flip_buffer); - async_flip_requested.test_and_reset(flip_request::emu_requested); } if (!in_begin_end && state != FIFO_state::lock_wait) @@ -2554,6 +2553,8 @@ namespace rsx void thread::flip(int buffer) { + async_flip_requested.clear(); + if (g_cfg.video.frame_skip_enabled) { m_skip_frame_ctr++; @@ -2811,22 +2812,19 @@ namespace rsx // requested through command buffer if (is_rsxthr) { - // async flip hasnt been handled before next requested...? - if (test(async_flip_requested, flip_request::emu_requested)) - { - handle_emu_flip(async_flip_buffer); - async_flip_requested.test_and_reset(flip_request::emu_requested); - } + // NOTE: The flip will clear any queued flip requests handle_emu_flip(buffer); } else // requested 'manually' through ppu syscall { - // ignore multiple requests until previous happens - if (test(async_flip_requested, flip_request::emu_requested)) + if (async_flip_requested & flip_request::emu_requested) + { + // ignore multiple requests until previous happens return; + } async_flip_buffer = buffer; - async_flip_requested.test_and_set(flip_request::emu_requested); + async_flip_requested |= flip_request::emu_requested; } } @@ -2914,10 +2912,6 @@ namespace rsx int_flip_index++; current_display_buffer = buffer; flip(buffer); - // After each flip PS3 system is executing a routine that changes registers value to some default. - // Some game use this default state (SH3). - if (isHLE) - reset(); last_flip_time = get_system_time() - 1000000; flip_status = CELL_GCM_DISPLAY_FLIP_STATUS_DONE; @@ -2933,7 +2927,8 @@ namespace rsx intr_thread->notify(); } - sys_rsx_flip_event(buffer); + + sys_rsx_context_attribute(0x55555555, 0xFEC, buffer, 0, 0, 0); } diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 1569f373d4..7d0bd185a7 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -323,6 +323,7 @@ namespace rsx u64 timestamp_subvalue = 0; protected: + std::thread::id m_rsx_thread; atomic_t m_rsx_thread_exiting{true}; s32 m_return_addr{-1}, restore_ret_addr{-1}; std::array vertex_push_buffers; @@ -370,13 +371,13 @@ namespace rsx enum class flip_request : u32 { - emu_requested, - native_ui, + emu_requested = 1, + native_ui = 2, - __bitset_enum_max + any = emu_requested | native_ui }; - atomic_t> async_flip_requested{}; + atomic_bitmask_t async_flip_requested{}; u8 async_flip_buffer{ 0 }; GcmTileInfo tiles[limits::tiles_count]; diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 8791ebddc7..1945d83a0c 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -2192,10 +2192,12 @@ void VKGSRender::do_local_task(rsx::FIFO_state state) if (m_overlay_manager) { - if (!in_begin_end && async_flip_requested.test_and_reset(flip_request::native_ui)) + if (!in_begin_end && async_flip_requested & flip_request::native_ui) { + s32 buffer_id = (async_flip_requested & flip_request::emu_requested) ? async_flip_buffer : (s32)current_display_buffer; + flush_command_queue(true); - flip((s32)current_display_buffer); + flip((s32)buffer_id); } } } diff --git a/rpcs3/Emu/RSX/rsx_methods.cpp b/rpcs3/Emu/RSX/rsx_methods.cpp index f8c886b1ba..68109ff387 100644 --- a/rpcs3/Emu/RSX/rsx_methods.cpp +++ b/rpcs3/Emu/RSX/rsx_methods.cpp @@ -1116,6 +1116,8 @@ namespace rsx void flip_command(thread* rsx, u32, u32 arg) { + verify(HERE), rsx->isHLE; + rsx->reset(); rsx->request_emu_flip(arg); } diff --git a/rpcs3/Emu/RSX/rsx_utils.h b/rpcs3/Emu/RSX/rsx_utils.h index 1019d643e9..c21a976a64 100644 --- a/rpcs3/Emu/RSX/rsx_utils.h +++ b/rpcs3/Emu/RSX/rsx_utils.h @@ -784,4 +784,56 @@ namespace rsx } } } -} \ No newline at end of file + + template + class atomic_bitmask_t + { + private: + atomic_t m_data; + + public: + atomic_bitmask_t() { m_data.store(0); }; + ~atomic_bitmask_t() {} + + T load() const + { + return static_cast(m_data.load()); + } + + void store(T value) + { + m_data.store(static_cast(value)); + } + + bool operator & (T mask) const + { + return ((m_data.load() & static_cast(mask)) != 0); + } + + T operator | (T mask) const + { + return static_cast(m_data.load() | static_cast(mask)); + } + + void operator &= (T mask) + { + m_data.fetch_and(static_cast(mask)); + } + + void operator |= (T mask) + { + m_data.fetch_or(static_cast(mask)); + } + + auto clear(T mask) + { + bitmask_type clear_mask = ~(static_cast(mask)); + return m_data.and_fetch(clear_mask); + } + + void clear() + { + m_data.store(0); + } + }; +}