core, video_core: Fixes to make savestates work

1. Acquire the context before initializing renderer when using async gpu

2. Do not try present when renderer is nullptr
  This has some potential race condition but is also what we do in qt

3. Synchronize before serializing video core (WaitForProcessing)
  For this, the GPU thread is changed to pop commands *after* processing.

4. Avoid waiting on future fences
  Such events can exist in core timing queue when deserializing.
This commit is contained in:
zhupengfei 2020-08-12 23:20:04 +08:00 committed by bunnei
parent 77c8cb23a0
commit 8a31ffaf22
7 changed files with 33 additions and 5 deletions

View File

@ -246,7 +246,7 @@ void EmuWindow_Android::TryPresenting() {
}
}
eglSwapInterval(egl_display, Settings::values.use_vsync_new ? 1 : 0);
if (VideoCore::g_renderer->TryPresent()) {
if (VideoCore::g_renderer && VideoCore::g_renderer->TryPresent()) {
eglSwapBuffers(egl_display, egl_surface);
}
}

View File

@ -13,6 +13,8 @@ GPUBackend::GPUBackend(VideoCore::RendererBase& renderer) : renderer{renderer} {
GPUBackend::~GPUBackend() = default;
void GPUBackend::WaitForProcessing() {}
GPUSerial::GPUSerial(Core::System& system, VideoCore::RendererBase& renderer)
: GPUBackend(renderer), system{system} {}
@ -83,4 +85,8 @@ void GPUParallel::InvalidateRegion(VAddr addr, u64 size) {
gpu_thread.InvalidateRegion(addr, size);
}
void GPUParallel::WaitForProcessing() {
gpu_thread.WaitForProcessing();
}
} // namespace VideoCore

View File

@ -29,6 +29,7 @@ public:
virtual void FlushRegion(VAddr addr, u64 size) = 0;
virtual void FlushAndInvalidateRegion(VAddr addr, u64 size) = 0;
virtual void InvalidateRegion(VAddr addr, u64 size) = 0;
virtual void WaitForProcessing();
protected:
VideoCore::RendererBase& renderer;
@ -65,6 +66,7 @@ public:
void FlushRegion(VAddr addr, u64 size) override;
void FlushAndInvalidateRegion(VAddr addr, u64 size) override;
void InvalidateRegion(VAddr addr, u64 size) override;
void WaitForProcessing() override;
private:
GPUThread::ThreadManager gpu_thread;

View File

@ -32,12 +32,12 @@ static void RunThread(VideoCore::RendererBase& renderer, SynchState& state, Core
Frontend::ScopeAcquireContext acquire_context{renderer.GetRenderWindow()};
CommandDataContainer next;
while (state.is_running) {
state.WaitForCommands();
CommandDataContainer next;
while (state.queue.Pop(next)) {
while (!state.queue.Empty()) {
CommandDataContainer next = state.queue.Front();
auto command = &next.data;
auto fence = next.fence;
if (const auto submit_list = std::get_if<SubmitListCommand>(command)) {
@ -62,6 +62,7 @@ static void RunThread(VideoCore::RendererBase& renderer, SynchState& state, Core
UNREACHABLE();
}
state.signaled_fence = next.fence;
state.queue.Pop();
}
}
}
@ -211,8 +212,15 @@ u64 ThreadManager::PushCommand(CommandData&& command_data) {
return fence;
}
void ThreadManager::WaitForProcessing() {
state.WaitForProcessing();
}
MICROPROFILE_DEFINE(GPU_wait, "GPU", "Wait for the GPU", MP_RGB(128, 128, 192));
void SynchState::WaitForSynchronization(u64 fence) {
if (fence > last_fence) { // We don't want to wait infinitely
return;
}
if (signaled_fence >= fence) {
return;
}

View File

@ -169,9 +169,14 @@ struct SynchState final {
// commands_condition.wait(lock, [this] { return !queue.Empty(); });
}
void WaitForProcessing() {
while (!queue.Empty() && is_running)
;
}
using CommandQueue = Common::SPSCQueue<CommandDataContainer>;
CommandQueue queue;
u64 last_fence{};
std::atomic<u64> last_fence{};
std::atomic<u64> signaled_fence{};
};
@ -195,6 +200,8 @@ public:
void InvalidateRegion(VAddr addr, u64 size);
void WaitForProcessing();
private:
void Synchronize(u64 fence, Settings::GpuTimingMode mode);

View File

@ -1212,6 +1212,10 @@ VideoCore::ResultStatus RendererOpenGL::Init() {
}
#endif
if (Settings::values.use_asynchronous_gpu_emulation) {
render_window.MakeCurrent();
}
const char* gl_version{reinterpret_cast<char const*>(glGetString(GL_VERSION))};
const char* gpu_vendor{reinterpret_cast<char const*>(glGetString(GL_VENDOR))};
const char* gpu_model{reinterpret_cast<char const*>(glGetString(GL_RENDERER))};

View File

@ -104,6 +104,7 @@ u16 GetResolutionScaleFactor() {
template <class Archive>
void serialize(Archive& ar, const unsigned int) {
g_gpu->WaitForProcessing();
ar& Pica::g_state;
}