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:
parent
77c8cb23a0
commit
8a31ffaf22
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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))};
|
||||
|
@ -104,6 +104,7 @@ u16 GetResolutionScaleFactor() {
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
g_gpu->WaitForProcessing();
|
||||
ar& Pica::g_state;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user