mirror of https://github.com/PCSX2/pcsx2.git
MTGS: Support 'running idle', i.e. redisplaying the current frame
This commit is contained in:
parent
be3f120548
commit
d466184a02
|
@ -26,6 +26,30 @@
|
|||
// Semaphore Implementations
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
bool Threading::WorkSema::CheckForWork()
|
||||
{
|
||||
s32 value = m_state.load(std::memory_order_relaxed);
|
||||
pxAssert(!IsDead(value));
|
||||
|
||||
// we want to switch to the running state, but preserve the waiting empty bit for RUNNING_N -> RUNNING_0
|
||||
// otherwise, we clear the waiting flag (since we're notifying the waiter that we're empty below)
|
||||
while (!m_state.compare_exchange_weak(value,
|
||||
IsReadyForSleep(value) ? STATE_RUNNING_0 : (value & STATE_FLAG_WAITING_EMPTY),
|
||||
std::memory_order_acq_rel, std::memory_order_relaxed))
|
||||
{
|
||||
}
|
||||
|
||||
// if we're not empty, we have work to do
|
||||
if (!IsReadyForSleep(value))
|
||||
return true;
|
||||
|
||||
// this means we're empty, so notify any waiters
|
||||
if (value & STATE_FLAG_WAITING_EMPTY)
|
||||
m_empty_sema.Post();
|
||||
|
||||
// no work to do
|
||||
return false;
|
||||
}
|
||||
|
||||
void Threading::WorkSema::WaitForWork()
|
||||
{
|
||||
|
|
|
@ -211,6 +211,8 @@ namespace Threading
|
|||
m_sema.Post();
|
||||
}
|
||||
|
||||
/// Checks if there's any work in the queue
|
||||
bool CheckForWork();
|
||||
/// Wait for work to be added to the queue
|
||||
void WaitForWork();
|
||||
/// Wait for work to be added to the queue, spinning for a bit before sleeping the thread
|
||||
|
|
|
@ -367,6 +367,7 @@ public:
|
|||
Threading::ThreadHandle m_thread_handle;
|
||||
std::atomic_bool m_open_flag{false};
|
||||
std::atomic_bool m_shutdown_flag{false};
|
||||
std::atomic_bool m_run_idle_flag{false};
|
||||
Threading::KernelSemaphore m_open_or_close_done;
|
||||
|
||||
public:
|
||||
|
@ -416,6 +417,7 @@ public:
|
|||
void SetSoftwareRendering(bool software, bool display_message = true);
|
||||
void ToggleSoftwareRendering();
|
||||
bool SaveMemorySnapshot(u32 width, u32 height, std::vector<u32>* pixels);
|
||||
void SetRunIdle(bool enabled);
|
||||
|
||||
protected:
|
||||
bool TryOpenGS();
|
||||
|
|
|
@ -79,4 +79,4 @@ public:
|
|||
#endif
|
||||
};
|
||||
|
||||
extern std::unique_ptr<GSRenderer> g_gs_renderer;
|
||||
extern std::unique_ptr<GSRenderer> g_gs_renderer;
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
|
||||
#ifndef PCSX2_CORE
|
||||
#include "gui/Dialogs/ModalPopups.h"
|
||||
#else
|
||||
#include "VMManager.h"
|
||||
#endif
|
||||
|
||||
// Uncomment this to enable profiling of the GS RingBufferCopy function.
|
||||
|
@ -296,9 +298,23 @@ void SysMtgsThread::MainLoop()
|
|||
// is very optimized (only 1 instruction test in most cases), so no point in trying
|
||||
// to avoid it.
|
||||
|
||||
#ifdef PCSX2_CORE
|
||||
if (m_run_idle_flag.load(std::memory_order_acquire) && VMManager::GetState() != VMState::Running)
|
||||
{
|
||||
if (!m_sem_event.CheckForWork())
|
||||
GSPresentCurrentFrame();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtvu_lock.unlock();
|
||||
m_sem_event.WaitForWork();
|
||||
mtvu_lock.lock();
|
||||
}
|
||||
#else
|
||||
mtvu_lock.unlock();
|
||||
m_sem_event.WaitForWork();
|
||||
mtvu_lock.lock();
|
||||
#endif
|
||||
|
||||
if (!m_open_flag.load(std::memory_order_acquire))
|
||||
break;
|
||||
|
@ -1005,3 +1021,9 @@ void SysMtgsThread::PresentCurrentFrame()
|
|||
{
|
||||
GSPresentCurrentFrame();
|
||||
}
|
||||
|
||||
void SysMtgsThread::SetRunIdle(bool enabled)
|
||||
{
|
||||
// NOTE: Should only be called on the GS thread.
|
||||
m_run_idle_flag.store(enabled, std::memory_order_release);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue