From 0d0821e914a2c9ea741c19152813c7277b30bc81 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sat, 9 Dec 2017 13:14:00 +0300 Subject: [PATCH] rsx: Pause FIFO queue when changing ctrl registers --- rpcs3/Emu/Cell/lv2/sys_rsx.cpp | 2 ++ rpcs3/Emu/RSX/RSXThread.cpp | 21 +++++++++++++++++++++ rpcs3/Emu/RSX/RSXThread.h | 5 +++++ 3 files changed, 28 insertions(+) diff --git a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp index 122f03f0e0..a8d17c8703 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp @@ -240,9 +240,11 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6 switch (package_id) { case 0x001: // FIFO + render->pause(); render->ctrl->get = a3; render->ctrl->put = a4; render->internal_get = a3; + render->unpause(); break; case 0x100: // Display mode set diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 2efa9ec853..31bed4dcde 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -483,6 +483,14 @@ namespace rsx //Execute backend-local tasks first do_local_task(); + //Wait for external pause events + if (external_interrupt_lock.load()) + { + external_interrupt_ack.store(true); + while (external_interrupt_lock.load()) _mm_pause(); + } + + //Now load the FIFO ctrl registers ctrl->get.store(internal_get.load()); const u32 put = ctrl->put; @@ -2137,4 +2145,17 @@ namespace rsx { check_zcull_status(false, false); } + + //Pause/cont wrappers for FIFO ctrl. Never call this from rsx thread itself! + void thread::pause() + { + external_interrupt_lock.store(true); + while (!external_interrupt_ack.load()) _mm_pause(); + external_interrupt_ack.store(false); + } + + void thread::unpause() + { + external_interrupt_lock.store(false); + } } diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 6d7076dc08..99fdbf58db 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -233,6 +233,8 @@ namespace rsx public: RsxDmaControl* ctrl = nullptr; atomic_t internal_get{ 0 }; + atomic_t external_interrupt_lock{ false }; + atomic_t external_interrupt_ack{ false }; GcmTileInfo tiles[limits::tiles_count]; GcmZcullInfo zculls[limits::zculls_count]; @@ -477,5 +479,8 @@ namespace rsx u32 ReadIO32(u32 addr); void WriteIO32(u32 addr, u32 value); + + void pause(); + void unpause(); }; }