mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-04-18 20:42:47 +00:00
VideoBackendBase: Do save state logic on the GPU thread
This commit is contained in:
parent
a25a4e0708
commit
b26bb0605b
@ -154,6 +154,10 @@ void AsyncRequests::HandleEvent(const AsyncRequests::Event& e)
|
|||||||
case Event::PERF_QUERY:
|
case Event::PERF_QUERY:
|
||||||
g_perf_query->FlushResults();
|
g_perf_query->FlushResults();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Event::DO_SAVE_STATE:
|
||||||
|
g_video_backend->DoStateGPUThread(*e.do_save_state.p);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "Common/Flag.h"
|
#include "Common/Flag.h"
|
||||||
|
|
||||||
struct EfbPokeData;
|
struct EfbPokeData;
|
||||||
|
class PointerWrap;
|
||||||
|
|
||||||
class AsyncRequests
|
class AsyncRequests
|
||||||
{
|
{
|
||||||
@ -28,6 +29,7 @@ public:
|
|||||||
SWAP_EVENT,
|
SWAP_EVENT,
|
||||||
BBOX_READ,
|
BBOX_READ,
|
||||||
PERF_QUERY,
|
PERF_QUERY,
|
||||||
|
DO_SAVE_STATE,
|
||||||
} type;
|
} type;
|
||||||
u64 time;
|
u64 time;
|
||||||
|
|
||||||
@ -64,6 +66,11 @@ public:
|
|||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
} perf_query;
|
} 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 (((s32*)&bpmem)[bp.address] == bp.newvalue)
|
||||||
{
|
{
|
||||||
if (!(bp.address == BPMEM_TRIGGER_EFB_COPY || bp.address == BPMEM_CLEARBBOX1 ||
|
if (!(bp.address == BPMEM_TRIGGER_EFB_COPY || bp.address == BPMEM_CLEARBBOX1 ||
|
||||||
|
@ -299,14 +299,15 @@ void RunGpuLoop()
|
|||||||
[] {
|
[] {
|
||||||
const SConfig& param = SConfig::GetInstance();
|
const SConfig& param = SConfig::GetInstance();
|
||||||
|
|
||||||
|
// Run events from the CPU thread.
|
||||||
|
AsyncRequests::GetInstance()->PullEvents();
|
||||||
|
|
||||||
// Do nothing while paused
|
// Do nothing while paused
|
||||||
if (!s_emu_running_state.IsSet())
|
if (!s_emu_running_state.IsSet())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (s_use_deterministic_gpu_thread)
|
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.
|
// 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* seen_ptr = s_video_buffer_seen_ptr;
|
||||||
u8* write_ptr = s_video_buffer_write_ptr;
|
u8* write_ptr = s_video_buffer_write_ptr;
|
||||||
@ -321,9 +322,6 @@ void RunGpuLoop()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
CommandProcessor::SCPFifoStruct& fifo = CommandProcessor::fifo;
|
CommandProcessor::SCPFifoStruct& fifo = CommandProcessor::fifo;
|
||||||
|
|
||||||
AsyncRequests::GetInstance()->PullEvents();
|
|
||||||
|
|
||||||
CommandProcessor::SetCPStatusFromGPU();
|
CommandProcessor::SetCPStatusFromGPU();
|
||||||
|
|
||||||
// check if we are able to run this buffer
|
// check if we are able to run this buffer
|
||||||
|
@ -338,9 +338,6 @@ void VertexManagerBase::Flush()
|
|||||||
|
|
||||||
m_is_flushed = true;
|
m_is_flushed = true;
|
||||||
|
|
||||||
// loading a state will invalidate BP, so check for it
|
|
||||||
g_video_backend->CheckInvalidState();
|
|
||||||
|
|
||||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||||
PRIM_LOG("frame%d:\n texgen=%u, numchan=%u, dualtex=%u, ztex=%u, cole=%u, alpe=%u, ze=%u",
|
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,
|
g_ActiveConfig.iSaveTargetId, xfmem.numTexGen.numTexGens, xfmem.numChan.numColorChans,
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
#include "VideoCommon/RenderBase.h"
|
#include "VideoCommon/RenderBase.h"
|
||||||
#include "VideoCommon/TextureCacheBase.h"
|
#include "VideoCommon/TextureCacheBase.h"
|
||||||
#include "VideoCommon/VertexLoaderManager.h"
|
#include "VideoCommon/VertexLoaderManager.h"
|
||||||
|
#include "VideoCommon/VertexManagerBase.h"
|
||||||
#include "VideoCommon/VertexShaderManager.h"
|
#include "VideoCommon/VertexShaderManager.h"
|
||||||
#include "VideoCommon/VideoCommon.h"
|
#include "VideoCommon/VideoCommon.h"
|
||||||
#include "VideoCommon/VideoConfig.h"
|
#include "VideoCommon/VideoConfig.h"
|
||||||
@ -236,8 +237,25 @@ void VideoBackendBase::PopulateBackendInfo()
|
|||||||
g_Config.Refresh();
|
g_Config.Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run from the CPU thread
|
|
||||||
void VideoBackendBase::DoState(PointerWrap& p)
|
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;
|
bool software = false;
|
||||||
p.Do(software);
|
p.Do(software);
|
||||||
@ -254,7 +272,10 @@ void VideoBackendBase::DoState(PointerWrap& p)
|
|||||||
// Refresh state.
|
// Refresh state.
|
||||||
if (p.GetMode() == PointerWrap::MODE_READ)
|
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
|
// Clear all caches that touch RAM
|
||||||
// (? these don't appear to touch any emulation state that gets saved. moved to on load only.)
|
// (? these don't appear to touch any emulation state that gets saved. moved to on load only.)
|
||||||
@ -262,17 +283,6 @@ void VideoBackendBase::DoState(PointerWrap& p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoBackendBase::CheckInvalidState()
|
|
||||||
{
|
|
||||||
if (m_invalid)
|
|
||||||
{
|
|
||||||
m_invalid = false;
|
|
||||||
|
|
||||||
BPReload();
|
|
||||||
g_texture_cache->Invalidate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VideoBackendBase::InitializeShared()
|
void VideoBackendBase::InitializeShared()
|
||||||
{
|
{
|
||||||
memset(&g_main_cp_state, 0, sizeof(g_main_cp_state));
|
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
|
// do not initialize again for the config window
|
||||||
m_initialized = true;
|
m_initialized = true;
|
||||||
|
|
||||||
m_invalid = false;
|
|
||||||
|
|
||||||
CommandProcessor::Init();
|
CommandProcessor::Init();
|
||||||
Fifo::Init();
|
Fifo::Init();
|
||||||
OpcodeDecoder::Init();
|
OpcodeDecoder::Init();
|
||||||
|
@ -63,18 +63,17 @@ public:
|
|||||||
// Called by the UI thread when the graphics config is opened.
|
// Called by the UI thread when the graphics config is opened.
|
||||||
static void PopulateBackendInfo();
|
static void PopulateBackendInfo();
|
||||||
|
|
||||||
// the implementation needs not do synchronization logic, because calls to it are surrounded by
|
// Wrapper function which pushes the event to the GPU thread.
|
||||||
// PauseAndLock now
|
|
||||||
void DoState(PointerWrap& p);
|
void DoState(PointerWrap& p);
|
||||||
|
|
||||||
void CheckInvalidState();
|
// Function which handles the real state load/save logic.
|
||||||
|
void DoStateGPUThread(PointerWrap& p);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void InitializeShared();
|
void InitializeShared();
|
||||||
void ShutdownShared();
|
void ShutdownShared();
|
||||||
|
|
||||||
bool m_initialized = false;
|
bool m_initialized = false;
|
||||||
bool m_invalid = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern std::vector<std::unique_ptr<VideoBackendBase>> g_available_video_backends;
|
extern std::vector<std::unique_ptr<VideoBackendBase>> g_available_video_backends;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user