Skip to content
Permalink
Browse files

VideoBackendBase: Do save state logic on the GPU thread

  • Loading branch information...
stenzek committed Jun 29, 2019
1 parent a25a4e0 commit b26bb0605b962456720519b273f171919ebfb65d
@@ -154,6 +154,10 @@ void AsyncRequests::HandleEvent(const AsyncRequests::Event& e)
case Event::PERF_QUERY:
g_perf_query->FlushResults();
break;

case Event::DO_SAVE_STATE:
g_video_backend->DoStateGPUThread(*e.do_save_state.p);
break;
}
}

@@ -13,6 +13,7 @@
#include "Common/Flag.h"

struct EfbPokeData;
class PointerWrap;

class AsyncRequests
{
@@ -28,6 +29,7 @@ class AsyncRequests
SWAP_EVENT,
BBOX_READ,
PERF_QUERY,
DO_SAVE_STATE,
} type;
u64 time;

@@ -64,6 +66,11 @@ class AsyncRequests
struct
{
} perf_query;

struct
{
PointerWrap* p;
} do_save_state;
};
};

@@ -68,9 +68,6 @@ static void BPWritten(const BPCmd& bp)
----------------------------------------------------------------------------------------------------------------
*/

// check for invalid state, else unneeded configuration are built
g_video_backend->CheckInvalidState();

if (((s32*)&bpmem)[bp.address] == bp.newvalue)
{
if (!(bp.address == BPMEM_TRIGGER_EFB_COPY || bp.address == BPMEM_CLEARBBOX1 ||
@@ -299,14 +299,15 @@ void RunGpuLoop()
[] {
const SConfig& param = SConfig::GetInstance();

// Run events from the CPU thread.
AsyncRequests::GetInstance()->PullEvents();

// Do nothing while paused
if (!s_emu_running_state.IsSet())
return;

if (s_use_deterministic_gpu_thread)
{
AsyncRequests::GetInstance()->PullEvents();

// All the fifo/CP stuff is on the CPU. We just need to run the opcode decoder.
u8* seen_ptr = s_video_buffer_seen_ptr;
u8* write_ptr = s_video_buffer_write_ptr;
@@ -321,9 +322,6 @@ void RunGpuLoop()
else
{
CommandProcessor::SCPFifoStruct& fifo = CommandProcessor::fifo;

AsyncRequests::GetInstance()->PullEvents();

CommandProcessor::SetCPStatusFromGPU();

// check if we are able to run this buffer
@@ -338,9 +338,6 @@ void VertexManagerBase::Flush()

m_is_flushed = true;

// loading a state will invalidate BP, so check for it
g_video_backend->CheckInvalidState();

#if defined(_DEBUG) || defined(DEBUGFAST)
PRIM_LOG("frame%d:\n texgen=%u, numchan=%u, dualtex=%u, ztex=%u, cole=%u, alpe=%u, ze=%u",
g_ActiveConfig.iSaveTargetId, xfmem.numTexGen.numTexGens, xfmem.numChan.numColorChans,
@@ -40,6 +40,7 @@
#include "VideoCommon/RenderBase.h"
#include "VideoCommon/TextureCacheBase.h"
#include "VideoCommon/VertexLoaderManager.h"
#include "VideoCommon/VertexManagerBase.h"
#include "VideoCommon/VertexShaderManager.h"
#include "VideoCommon/VideoCommon.h"
#include "VideoCommon/VideoConfig.h"
@@ -236,8 +237,25 @@ void VideoBackendBase::PopulateBackendInfo()
g_Config.Refresh();
}

// Run from the CPU thread
void VideoBackendBase::DoState(PointerWrap& p)
{
if (!SConfig::GetInstance().bCPUThread)
{
DoStateGPUThread(p);
return;
}

AsyncRequests::Event ev = {};
ev.do_save_state.p = &p;
ev.type = AsyncRequests::Event::DO_SAVE_STATE;
AsyncRequests::GetInstance()->PushEvent(ev, true);

// Let the GPU thread sleep after loading the state, so we're not spinning if paused after loading
// a state. The next GP burst will wake it up again.
Fifo::GpuMaySleep();
}

void VideoBackendBase::DoStateGPUThread(PointerWrap& p)
{
bool software = false;
p.Do(software);
@@ -254,25 +272,17 @@ void VideoBackendBase::DoState(PointerWrap& p)
// Refresh state.
if (p.GetMode() == PointerWrap::MODE_READ)
{
m_invalid = true;
// Inform backend of new state from registers.
g_vertex_manager->Flush();
g_texture_cache->Invalidate();
BPReload();

// Clear all caches that touch RAM
// (? these don't appear to touch any emulation state that gets saved. moved to on load only.)
VertexLoaderManager::MarkAllDirty();
}
}

void VideoBackendBase::CheckInvalidState()
{
if (m_invalid)
{
m_invalid = false;

BPReload();
g_texture_cache->Invalidate();
}
}

void VideoBackendBase::InitializeShared()
{
memset(&g_main_cp_state, 0, sizeof(g_main_cp_state));
@@ -282,8 +292,6 @@ void VideoBackendBase::InitializeShared()
// do not initialize again for the config window
m_initialized = true;

m_invalid = false;

CommandProcessor::Init();
Fifo::Init();
OpcodeDecoder::Init();
@@ -63,18 +63,17 @@ class VideoBackendBase
// Called by the UI thread when the graphics config is opened.
static void PopulateBackendInfo();

// the implementation needs not do synchronization logic, because calls to it are surrounded by
// PauseAndLock now
// Wrapper function which pushes the event to the GPU thread.
void DoState(PointerWrap& p);

void CheckInvalidState();
// Function which handles the real state load/save logic.
void DoStateGPUThread(PointerWrap& p);

protected:
void InitializeShared();
void ShutdownShared();

bool m_initialized = false;
bool m_invalid = false;
};

extern std::vector<std::unique_ptr<VideoBackendBase>> g_available_video_backends;

0 comments on commit b26bb06

Please sign in to comment.
You can’t perform that action at this time.