diff --git a/src/android/app/src/main/jni/emu_window/emu_window.cpp b/src/android/app/src/main/jni/emu_window/emu_window.cpp index 71a5ff633..118e33e4c 100644 --- a/src/android/app/src/main/jni/emu_window/emu_window.cpp +++ b/src/android/app/src/main/jni/emu_window/emu_window.cpp @@ -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); } } diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index b75157b40..d5423c739 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -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 diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index d239704ba..b47023dc5 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -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; diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index 5cc22433c..fc62e69ae 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp @@ -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(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; } diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h index 27e33d7f8..ade649cdb 100644 --- a/src/video_core/gpu_thread.h +++ b/src/video_core/gpu_thread.h @@ -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; CommandQueue queue; - u64 last_fence{}; + std::atomic last_fence{}; std::atomic signaled_fence{}; }; @@ -195,6 +200,8 @@ public: void InvalidateRegion(VAddr addr, u64 size); + void WaitForProcessing(); + private: void Synchronize(u64 fence, Settings::GpuTimingMode mode); diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index f74fcb7d1..6e59b1f47 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -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(glGetString(GL_VERSION))}; const char* gpu_vendor{reinterpret_cast(glGetString(GL_VENDOR))}; const char* gpu_model{reinterpret_cast(glGetString(GL_RENDERER))}; diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index 2e32953de..e0e234418 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp @@ -104,6 +104,7 @@ u16 GetResolutionScaleFactor() { template void serialize(Archive& ar, const unsigned int) { + g_gpu->WaitForProcessing(); ar& Pica::g_state; }