From f9053527a9657ae748ab6b63d1fec0917c545e22 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Fri, 26 Jan 2018 12:44:23 +1000 Subject: [PATCH 1/5] Core: Don't spawn an extra thread in single-core mode We don't need a message pump thread for the video backend, as the window is created on the UI thread, not the "idle" emu thread. --- Source/Core/Core/Core.cpp | 36 ++++++------------------------------ 1 file changed, 6 insertions(+), 30 deletions(-) diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index 5f740c489f..b1fdd8261a 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -421,12 +421,6 @@ static void FifoPlayerThread(const std::optional& savestate_path, { s_is_started = true; Host_Message(WM_USER_STOP); - while (CPU::GetState() != CPU::State::PowerDown) - { - if (!_CoreParameter.bCPUThread) - g_video_backend->PeekMessages(); - std::this_thread::sleep_for(std::chrono::milliseconds(20)); - } s_is_started = false; } @@ -610,41 +604,23 @@ static void EmuThread(std::unique_ptr boot) // We have now exited the Video Loop INFO_LOG(CONSOLE, "%s", StopMessage(false, "Video Loop Ended").c_str()); + + // Join with the CPU thread. + s_cpu_thread.join(); + INFO_LOG(CONSOLE, "%s", StopMessage(true, "CPU thread stopped.").c_str()); } else // SingleCore mode { - // The spawned CPU Thread also does the graphics. - // The EmuThread is thus an idle thread, which sleeps while - // waiting for the program to terminate. Without this extra - // thread, the video backend window hangs in single core mode - // because no one is pumping messages. - Common::SetCurrentThreadName("Emuthread - Idle"); - - // Spawn the CPU+GPU thread - s_cpu_thread = std::thread(cpuThreadFunc, savestate_path, delete_savestate); - - while (CPU::GetState() != CPU::State::PowerDown) - { - g_video_backend->PeekMessages(); - Common::SleepCurrentThread(20); - } + // Become the CPU thread + cpuThreadFunc(savestate_path, delete_savestate); } - INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping Emu thread ...").c_str()); - - // Wait for s_cpu_thread to exit - INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping CPU-GPU thread ...").c_str()); - #ifdef USE_GDBSTUB INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping GDB ...").c_str()); gdb_deinit(); INFO_LOG(CONSOLE, "%s", StopMessage(true, "GDB stopped.").c_str()); #endif - s_cpu_thread.join(); - - INFO_LOG(CONSOLE, "%s", StopMessage(true, "CPU thread stopped.").c_str()); - if (core_parameter.bCPUThread) g_video_backend->Video_CleanupShared(); From 04027a7da774bfcafeff0b8565417e43e5e3c198 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Fri, 26 Jan 2018 14:41:57 +1000 Subject: [PATCH 2/5] Core: Improve ordering of boot - Smplification of graphics backend startup/shutdown. - Don't send complete message until CPU is ready to execute. - Remove redundant stop message. - Remove OSD message with backend name. --- Source/Core/Core/Core.cpp | 94 ++++++++------------------ Source/Core/DolphinNoGUI/MainNoGUI.cpp | 3 +- 2 files changed, 31 insertions(+), 66 deletions(-) diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index b1fdd8261a..61ab1f9062 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -241,7 +241,6 @@ bool Init(std::unique_ptr boot) // Start the emu thread s_emu_thread = std::thread(EmuThread, std::move(boot)); - return true; } @@ -311,9 +310,13 @@ void UndeclareAsCPUThread() // For the CPU Thread only. static void CPUSetInitialExecutionState() { - QueueHostJob([] { + // The CPU starts in stepping state, and will wait until a new state is set before executing. + // SetState must be called on the host thread, so we defer it for later. + QueueHostJob([]() { SetState(SConfig::GetInstance().bBootToPause ? State::Paused : State::Running); + Host_UpdateDisasmDialog(); Host_UpdateMainFrame(); + Host_Message(WM_USER_CREATE); }); } @@ -323,17 +326,10 @@ static void CpuThread(const std::optional& savestate_path, bool del DeclareAsCPUThread(); const SConfig& _CoreParameter = SConfig::GetInstance(); - if (_CoreParameter.bCPUThread) - { Common::SetCurrentThreadName("CPU thread"); - } else - { Common::SetCurrentThreadName("CPU-GPU thread"); - g_video_backend->Video_Prepare(); - Host_Message(WM_USER_CREATE); - } // This needs to be delayed until after the video backend is ready. DolphinAnalytics::Instance()->ReportGameStart(); @@ -341,6 +337,17 @@ static void CpuThread(const std::optional& savestate_path, bool del if (_CoreParameter.bFastmem) EMM::InstallExceptionHandler(); // Let's run under memory watch +#ifdef USE_MEMORYWATCHER + MemoryWatcher::Init(); +#endif + + if (savestate_path) + { + ::State::LoadAs(*savestate_path); + if (delete_savestate) + File::Delete(*savestate_path); + } + s_is_started = true; CPUSetInitialExecutionState(); @@ -361,25 +368,11 @@ static void CpuThread(const std::optional& savestate_path, bool del } #endif -#ifdef USE_MEMORYWATCHER - MemoryWatcher::Init(); -#endif - - if (savestate_path) - { - ::State::LoadAs(*savestate_path); - if (delete_savestate) - File::Delete(*savestate_path); - } - // Enter CPU run loop. When we leave it - we are done. CPU::Run(); s_is_started = false; - if (!_CoreParameter.bCPUThread) - g_video_backend->Video_CleanupShared(); - if (_CoreParameter.bFastmem) EMM::UninstallExceptionHandler(); } @@ -388,18 +381,12 @@ static void FifoPlayerThread(const std::optional& savestate_path, bool delete_savestate) { DeclareAsCPUThread(); - const SConfig& _CoreParameter = SConfig::GetInstance(); + const SConfig& _CoreParameter = SConfig::GetInstance(); if (_CoreParameter.bCPUThread) - { Common::SetCurrentThreadName("FIFO player thread"); - } else - { - g_video_backend->Video_Prepare(); - Host_Message(WM_USER_CREATE); Common::SetCurrentThreadName("FIFO-GPU thread"); - } // Enter CPU run loop. When we leave it - we are done. if (auto cpu_core = FifoPlayer::GetInstance().GetCPUCore()) @@ -412,20 +399,15 @@ static void FifoPlayerThread(const std::optional& savestate_path, s_is_started = false; PowerPC::InjectExternalCPUCore(nullptr); + FifoPlayer::GetInstance().Close(); } - FifoPlayer::GetInstance().Close(); - - // If we did not enter the CPU Run Loop above then run a fake one instead. - // We need to be IsRunningAndStarted() for DolphinWX to stop us. - if (CPU::GetState() != CPU::State::PowerDown) + else { - s_is_started = true; - Host_Message(WM_USER_STOP); - s_is_started = false; + // FIFO log does not contain any frames, cannot continue. + PanicAlert("FIFO file is invalid, cannot playback."); + FifoPlayer::GetInstance().Close(); + return; } - - if (!_CoreParameter.bCPUThread) - g_video_backend->Video_CleanupShared(); } // Initialize and create emulation thread @@ -449,9 +431,6 @@ static void EmuThread(std::unique_ptr boot) INFO_LOG(CONSOLE, "Stop\t\t---- Shutdown complete ----"); }}; - // Prevent the UI from getting stuck whenever an error occurs. - Common::ScopeGuard stop_message_guard{[] { Host_Message(WM_USER_STOP); }}; - Common::SetCurrentThreadName("Emuthread - Starting"); // For a time this acts as the CPU thread... @@ -485,9 +464,11 @@ static void EmuThread(std::unique_ptr boot) PanicAlert("Failed to initialize video backend!"); return; } - Common::ScopeGuard video_guard{[] { g_video_backend->Shutdown(); }}; - - OSD::AddMessage("Dolphin " + g_video_backend->GetName() + " Video Backend.", 5000); + g_video_backend->Video_Prepare(); + Common::ScopeGuard video_guard{[] { + g_video_backend->Video_Cleanup(); + g_video_backend->Shutdown(); + }}; if (cpu_info.HTT) SConfig::GetInstance().bDSPThread = cpu_info.num_cores > 4; @@ -568,9 +549,6 @@ static void EmuThread(std::unique_ptr boot) // This adds the SyncGPU handler to CoreTiming, so now CoreTiming::Advance might block. Fifo::Prepare(); - // Thread is no longer acting as CPU Thread - UndeclareAsCPUThread(); - // Setup our core, but can't use dynarec if we are compare server if (core_parameter.iCPUCore != PowerPC::CORE_INTERPRETER && (!core_parameter.bRunCompareServer || core_parameter.bRunCompareClient)) @@ -582,21 +560,15 @@ static void EmuThread(std::unique_ptr boot) PowerPC::SetMode(PowerPC::CoreMode::Interpreter); } - // Update the window again because all stuff is initialized - Host_UpdateDisasmDialog(); - Host_UpdateMainFrame(); - // ENTER THE VIDEO THREAD LOOP if (core_parameter.bCPUThread) { // This thread, after creating the EmuWindow, spawns a CPU // thread, and then takes over and becomes the video thread Common::SetCurrentThreadName("Video thread"); + UndeclareAsCPUThread(); - g_video_backend->Video_Prepare(); - Host_Message(WM_USER_CREATE); - - // Spawn the CPU thread + // Spawn the CPU thread. The CPU thread will signal the event that boot is complete. s_cpu_thread = std::thread(cpuThreadFunc, savestate_path, delete_savestate); // become the GPU thread @@ -620,12 +592,6 @@ static void EmuThread(std::unique_ptr boot) gdb_deinit(); INFO_LOG(CONSOLE, "%s", StopMessage(true, "GDB stopped.").c_str()); #endif - - if (core_parameter.bCPUThread) - g_video_backend->Video_CleanupShared(); - - // If we shut down normally, the stop message does not need to be triggered. - stop_message_guard.Dismiss(); } // Set or get the running state diff --git a/Source/Core/DolphinNoGUI/MainNoGUI.cpp b/Source/Core/DolphinNoGUI/MainNoGUI.cpp index 9582facf2d..574ebc07ba 100644 --- a/Source/Core/DolphinNoGUI/MainNoGUI.cpp +++ b/Source/Core/DolphinNoGUI/MainNoGUI.cpp @@ -83,10 +83,9 @@ static Common::Event updateMainFrameEvent; void Host_Message(int Id) { if (Id == WM_USER_STOP) - { s_running.Clear(); + if (Id == WM_USER_JOB_DISPATCH || Id == WM_USER_STOP) updateMainFrameEvent.Set(); - } } static void* s_window_handle = nullptr; From d96e8c9d76389411e4b17f0b7b5c4fdb0f0977f8 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Fri, 26 Jan 2018 15:09:07 +1000 Subject: [PATCH 3/5] VideoBackends: Combine Initialize/Prepare and Cleanup/Shutdown methods Also allows the work previously done in Prepare to return a failure status. --- Source/Core/Core/Core.cpp | 6 +-- Source/Core/VideoBackends/D3D/VideoBackend.h | 5 -- Source/Core/VideoBackends/D3D/main.cpp | 25 ++++------ .../Core/VideoBackends/Null/NullBackend.cpp | 18 +++---- Source/Core/VideoBackends/Null/VideoBackend.h | 3 -- Source/Core/VideoBackends/OGL/Render.cpp | 1 + Source/Core/VideoBackends/OGL/Render.h | 2 +- Source/Core/VideoBackends/OGL/VideoBackend.h | 3 -- Source/Core/VideoBackends/OGL/main.cpp | 30 +++--------- .../VideoBackends/Software/SWRenderer.cpp | 9 ---- .../Core/VideoBackends/Software/SWRenderer.h | 3 -- Source/Core/VideoBackends/Software/SWmain.cpp | 47 +++++++------------ .../VideoBackends/Software/VideoBackend.h | 3 -- .../Core/VideoBackends/Vulkan/ShaderCache.cpp | 3 ++ .../Core/VideoBackends/Vulkan/VideoBackend.h | 3 -- Source/Core/VideoBackends/Vulkan/main.cpp | 27 ++--------- Source/Core/VideoCommon/MainBase.cpp | 15 +----- Source/Core/VideoCommon/RenderBase.cpp | 7 +++ Source/Core/VideoCommon/RenderBase.h | 3 +- Source/Core/VideoCommon/VideoBackendBase.h | 5 -- 20 files changed, 58 insertions(+), 160 deletions(-) diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index 61ab1f9062..4c8433e7dd 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -464,11 +464,7 @@ static void EmuThread(std::unique_ptr boot) PanicAlert("Failed to initialize video backend!"); return; } - g_video_backend->Video_Prepare(); - Common::ScopeGuard video_guard{[] { - g_video_backend->Video_Cleanup(); - g_video_backend->Shutdown(); - }}; + Common::ScopeGuard video_guard{[] { g_video_backend->Shutdown(); }}; if (cpu_info.HTT) SConfig::GetInstance().bDSPThread = cpu_info.num_cores > 4; diff --git a/Source/Core/VideoBackends/D3D/VideoBackend.h b/Source/Core/VideoBackends/D3D/VideoBackend.h index 81aa79417b..97870ffdea 100644 --- a/Source/Core/VideoBackends/D3D/VideoBackend.h +++ b/Source/Core/VideoBackends/D3D/VideoBackend.h @@ -17,13 +17,8 @@ class VideoBackend : public VideoBackendBase std::string GetName() const override; std::string GetDisplayName() const override; - void Video_Prepare() override; - void Video_Cleanup() override; - void InitBackendInfo() override; unsigned int PeekMessages() override; - - void* m_window_handle; }; } diff --git a/Source/Core/VideoBackends/D3D/main.cpp b/Source/Core/VideoBackends/D3D/main.cpp index 26a8c4dcfd..3f9529d318 100644 --- a/Source/Core/VideoBackends/D3D/main.cpp +++ b/Source/Core/VideoBackends/D3D/main.cpp @@ -145,32 +145,30 @@ bool VideoBackend::Initialize(void* window_handle) InitBackendInfo(); InitializeShared(); - m_window_handle = window_handle; - - return true; -} - -void VideoBackend::Video_Prepare() -{ - if (FAILED(D3D::Create(reinterpret_cast(m_window_handle)))) + if (FAILED(D3D::Create(reinterpret_cast(window_handle)))) + { PanicAlert("Failed to create D3D device."); + return false; + } - // internal interfaces g_renderer = std::make_unique(); g_texture_cache = std::make_unique(); g_vertex_manager = std::make_unique(); g_perf_query = std::make_unique(); + VertexShaderCache::Init(); PixelShaderCache::Init(); GeometryShaderCache::Init(); VertexShaderCache::WaitForBackgroundCompilesToComplete(); D3D::InitUtils(); BBox::Init(); + return true; } void VideoBackend::Shutdown() { - // TODO: should be in Video_Cleanup + g_renderer->Shutdown(); + D3D::ShutdownUtils(); PixelShaderCache::Shutdown(); VertexShaderCache::Shutdown(); @@ -182,13 +180,8 @@ void VideoBackend::Shutdown() g_texture_cache.reset(); g_renderer.reset(); - D3D::Close(); - ShutdownShared(); -} -void VideoBackend::Video_Cleanup() -{ - CleanupShared(); + D3D::Close(); } } diff --git a/Source/Core/VideoBackends/Null/NullBackend.cpp b/Source/Core/VideoBackends/Null/NullBackend.cpp index 4ea460e440..c687c8f2df 100644 --- a/Source/Core/VideoBackends/Null/NullBackend.cpp +++ b/Source/Core/VideoBackends/Null/NullBackend.cpp @@ -58,38 +58,32 @@ bool VideoBackend::Initialize(void* window_handle) InitializeShared(); InitBackendInfo(); - return true; -} - -// This is called after Initialize() from the Core -// Run from the graphics thread -void VideoBackend::Video_Prepare() -{ g_renderer = std::make_unique(); g_vertex_manager = std::make_unique(); g_perf_query = std::make_unique(); g_framebuffer_manager = std::make_unique(); g_texture_cache = std::make_unique(); + VertexShaderCache::s_instance = std::make_unique(); GeometryShaderCache::s_instance = std::make_unique(); PixelShaderCache::s_instance = std::make_unique(); + return true; } void VideoBackend::Shutdown() { - ShutdownShared(); -} + g_renderer->Shutdown(); -void VideoBackend::Video_Cleanup() -{ - CleanupShared(); PixelShaderCache::s_instance.reset(); VertexShaderCache::s_instance.reset(); GeometryShaderCache::s_instance.reset(); + g_texture_cache.reset(); g_perf_query.reset(); g_vertex_manager.reset(); g_framebuffer_manager.reset(); g_renderer.reset(); + + ShutdownShared(); } } diff --git a/Source/Core/VideoBackends/Null/VideoBackend.h b/Source/Core/VideoBackends/Null/VideoBackend.h index 5581d8511a..bb7da23c8d 100644 --- a/Source/Core/VideoBackends/Null/VideoBackend.h +++ b/Source/Core/VideoBackends/Null/VideoBackend.h @@ -15,9 +15,6 @@ class VideoBackend : public VideoBackendBase std::string GetName() const override { return "Null"; } std::string GetDisplayName() const override { return "Null"; } - void Video_Prepare() override; - void Video_Cleanup() override; - void InitBackendInfo() override; unsigned int PeekMessages() override { return 0; } diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index d3cfa4136d..3408d6099c 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -809,6 +809,7 @@ Renderer::~Renderer() = default; void Renderer::Shutdown() { + ::Renderer::Shutdown(); g_framebuffer_manager.reset(); UpdateActiveConfig(); diff --git a/Source/Core/VideoBackends/OGL/Render.h b/Source/Core/VideoBackends/OGL/Render.h index 797e1e0e98..993057b2d9 100644 --- a/Source/Core/VideoBackends/OGL/Render.h +++ b/Source/Core/VideoBackends/OGL/Render.h @@ -84,7 +84,7 @@ public: ~Renderer() override; void Init(); - void Shutdown(); + void Shutdown() override; std::unique_ptr CreateTexture(const TextureConfig& config) override; std::unique_ptr diff --git a/Source/Core/VideoBackends/OGL/VideoBackend.h b/Source/Core/VideoBackends/OGL/VideoBackend.h index c78c94c4c1..a42fc3cce6 100644 --- a/Source/Core/VideoBackends/OGL/VideoBackend.h +++ b/Source/Core/VideoBackends/OGL/VideoBackend.h @@ -17,9 +17,6 @@ class VideoBackend : public VideoBackendBase std::string GetName() const override; std::string GetDisplayName() const override; - void Video_Prepare() override; - void Video_Cleanup() override; - void InitBackendInfo() override; unsigned int PeekMessages() override; diff --git a/Source/Core/VideoBackends/OGL/main.cpp b/Source/Core/VideoBackends/OGL/main.cpp index 3b07eb96a7..64aea5f2c5 100644 --- a/Source/Core/VideoBackends/OGL/main.cpp +++ b/Source/Core/VideoBackends/OGL/main.cpp @@ -172,23 +172,11 @@ bool VideoBackend::Initialize(void* window_handle) if (!GLInterface->Create(window_handle, g_ActiveConfig.stereo_mode == StereoMode::QuadBuffer)) return false; - return true; -} - -// This is called after Initialize() from the Core -// Run from the graphics thread -void VideoBackend::Video_Prepare() -{ GLInterface->MakeCurrent(); if (!InitializeGLExtensions() || !FillBackendInfo()) - { - // TODO: Handle this better. We'll likely end up crashing anyway, but this method doesn't - // return anything, so we can't inform the caller that startup failed. - return; - } + return false; g_renderer = std::make_unique(); - g_vertex_manager = std::make_unique(); g_perf_query = GetPerfQuery(); ProgramShaderCache::Init(); @@ -197,21 +185,12 @@ void VideoBackend::Video_Prepare() static_cast(g_renderer.get())->Init(); TextureConverter::Init(); BoundingBox::Init(g_renderer->GetTargetWidth(), g_renderer->GetTargetHeight()); + return true; } void VideoBackend::Shutdown() { - GLInterface->Shutdown(); - GLInterface.reset(); - ShutdownShared(); -} - -void VideoBackend::Video_Cleanup() -{ - // The following calls are NOT Thread Safe - // And need to be called from the video thread - CleanupShared(); - static_cast(g_renderer.get())->Shutdown(); + g_renderer->Shutdown(); BoundingBox::Shutdown(); TextureConverter::Shutdown(); g_sampler_cache.reset(); @@ -221,5 +200,8 @@ void VideoBackend::Video_Cleanup() g_vertex_manager.reset(); g_renderer.reset(); GLInterface->ClearCurrent(); + GLInterface->Shutdown(); + GLInterface.reset(); + ShutdownShared(); } } diff --git a/Source/Core/VideoBackends/Software/SWRenderer.cpp b/Source/Core/VideoBackends/Software/SWRenderer.cpp index 4b84655002..28bd57557e 100644 --- a/Source/Core/VideoBackends/Software/SWRenderer.cpp +++ b/Source/Core/VideoBackends/Software/SWRenderer.cpp @@ -26,15 +26,6 @@ SWRenderer::SWRenderer() { } -void SWRenderer::Init() -{ -} - -void SWRenderer::Shutdown() -{ - UpdateActiveConfig(); -} - std::unique_ptr SWRenderer::CreateTexture(const TextureConfig& config) { return std::make_unique(config); diff --git a/Source/Core/VideoBackends/Software/SWRenderer.h b/Source/Core/VideoBackends/Software/SWRenderer.h index 312acd1991..ecab73cccc 100644 --- a/Source/Core/VideoBackends/Software/SWRenderer.h +++ b/Source/Core/VideoBackends/Software/SWRenderer.h @@ -13,9 +13,6 @@ class SWRenderer : public Renderer public: SWRenderer(); - static void Init(); - static void Shutdown(); - std::unique_ptr CreateTexture(const TextureConfig& config) override; std::unique_ptr CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override; diff --git a/Source/Core/VideoBackends/Software/SWmain.cpp b/Source/Core/VideoBackends/Software/SWmain.cpp index 115f9a9509..a79540891f 100644 --- a/Source/Core/VideoBackends/Software/SWmain.cpp +++ b/Source/Core/VideoBackends/Software/SWmain.cpp @@ -88,38 +88,8 @@ bool VideoSoftware::Initialize(void* window_handle) Clipper::Init(); Rasterizer::Init(); - SWRenderer::Init(); DebugUtil::Init(); - return true; -} - -void VideoSoftware::Shutdown() -{ - SWOGLWindow::Shutdown(); - - ShutdownShared(); -} - -void VideoSoftware::Video_Cleanup() -{ - CleanupShared(); - - SWRenderer::Shutdown(); - DebugUtil::Shutdown(); - // The following calls are NOT Thread Safe - // And need to be called from the video thread - SWRenderer::Shutdown(); - g_framebuffer_manager.reset(); - g_texture_cache.reset(); - g_perf_query.reset(); - g_vertex_manager.reset(); - g_renderer.reset(); -} - -// This is called after Video_Initialize() from the Core -void VideoSoftware::Video_Prepare() -{ GLInterface->MakeCurrent(); SWOGLWindow::s_instance->Prepare(); @@ -127,7 +97,22 @@ void VideoSoftware::Video_Prepare() g_vertex_manager = std::make_unique(); g_perf_query = std::make_unique(); g_texture_cache = std::make_unique(); - SWRenderer::Init(); + return true; +} + +void VideoSoftware::Shutdown() +{ + if (g_renderer) + g_renderer->Shutdown(); + + DebugUtil::Shutdown(); + SWOGLWindow::Shutdown(); + g_framebuffer_manager.reset(); + g_texture_cache.reset(); + g_perf_query.reset(); + g_vertex_manager.reset(); + g_renderer.reset(); + ShutdownShared(); } unsigned int VideoSoftware::PeekMessages() diff --git a/Source/Core/VideoBackends/Software/VideoBackend.h b/Source/Core/VideoBackends/Software/VideoBackend.h index fbc2cbd20d..0221aba9c7 100644 --- a/Source/Core/VideoBackends/Software/VideoBackend.h +++ b/Source/Core/VideoBackends/Software/VideoBackend.h @@ -17,9 +17,6 @@ class VideoSoftware : public VideoBackendBase std::string GetName() const override; std::string GetDisplayName() const override; - void Video_Prepare() override; - void Video_Cleanup() override; - void InitBackendInfo() override; unsigned int PeekMessages() override; diff --git a/Source/Core/VideoBackends/Vulkan/ShaderCache.cpp b/Source/Core/VideoBackends/Vulkan/ShaderCache.cpp index 2c69267dfc..9f77958b0f 100644 --- a/Source/Core/VideoBackends/Vulkan/ShaderCache.cpp +++ b/Source/Core/VideoBackends/Vulkan/ShaderCache.cpp @@ -76,6 +76,9 @@ void ShaderCache::Shutdown() m_async_shader_compiler->StopWorkerThreads(); m_async_shader_compiler->RetrieveWorkItems(); } + + if (g_ActiveConfig.bShaderCache && m_pipeline_cache != VK_NULL_HANDLE) + SavePipelineCache(); } static bool IsStripPrimitiveTopology(VkPrimitiveTopology topology) diff --git a/Source/Core/VideoBackends/Vulkan/VideoBackend.h b/Source/Core/VideoBackends/Vulkan/VideoBackend.h index 4a32ae076b..b38ec28131 100644 --- a/Source/Core/VideoBackends/Vulkan/VideoBackend.h +++ b/Source/Core/VideoBackends/Vulkan/VideoBackend.h @@ -16,9 +16,6 @@ public: std::string GetName() const override { return "Vulkan"; } std::string GetDisplayName() const override { return "Vulkan (experimental)"; } - void Video_Prepare() override; - void Video_Cleanup() override; - void InitBackendInfo() override; unsigned int PeekMessages() override { return 0; } diff --git a/Source/Core/VideoBackends/Vulkan/main.cpp b/Source/Core/VideoBackends/Vulkan/main.cpp index 63b7921442..d8a725845a 100644 --- a/Source/Core/VideoBackends/Vulkan/main.cpp +++ b/Source/Core/VideoBackends/Vulkan/main.cpp @@ -245,22 +245,16 @@ bool VideoBackend::Initialize(void* window_handle) if (g_ActiveConfig.CanPrecompileUberShaders()) g_shader_cache->PrecompileUberShaders(); + // Display the name so the user knows which device was actually created. + INFO_LOG(VIDEO, "Vulkan Device: %s", g_vulkan_context->GetDeviceProperties().deviceName); return true; } -// This is called after Initialize() from the Core -// Run from the graphics thread -void VideoBackend::Video_Prepare() -{ - // Display the name so the user knows which device was actually created - OSD::AddMessage(StringFromFormat("Using physical adapter %s", - g_vulkan_context->GetDeviceProperties().deviceName) - .c_str(), - 5000); -} - void VideoBackend::Shutdown() { + if (g_renderer) + g_renderer->Shutdown(); + if (g_command_buffer_mgr) g_command_buffer_mgr->WaitForGPUIdle(); @@ -279,15 +273,4 @@ void VideoBackend::Shutdown() ShutdownShared(); UnloadVulkanLibrary(); } - -void VideoBackend::Video_Cleanup() -{ - g_command_buffer_mgr->WaitForGPUIdle(); - - // Save all cached pipelines out to disk for next time. - if (g_ActiveConfig.bShaderCache) - g_shader_cache->SavePipelineCache(); - - CleanupShared(); -} } diff --git a/Source/Core/VideoCommon/MainBase.cpp b/Source/Core/VideoCommon/MainBase.cpp index 4dfb97f84a..fcad23ccbf 100644 --- a/Source/Core/VideoCommon/MainBase.cpp +++ b/Source/Core/VideoCommon/MainBase.cpp @@ -45,15 +45,6 @@ void VideoBackendBase::Video_ExitLoop() s_FifoShuttingDown.Set(); } -void VideoBackendBase::Video_CleanupShared() -{ - // First stop any framedumping, which might need to dump the last xfb frame. This process - // can require additional graphics sub-systems so it needs to be done first - g_renderer->ShutdownFrameDumping(); - - Video_Cleanup(); -} - // Run from the CPU thread (from VideoInterface.cpp) void VideoBackendBase::Video_BeginField(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, u64 ticks) @@ -211,12 +202,8 @@ void VideoBackendBase::ShutdownShared() m_initialized = false; - Fifo::Shutdown(); -} - -void VideoBackendBase::CleanupShared() -{ VertexLoaderManager::Clear(); + Fifo::Shutdown(); } // Run from the CPU thread diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index 410330709f..9e56d20f29 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -101,6 +101,13 @@ Renderer::Renderer(int backbuffer_width, int backbuffer_height) Renderer::~Renderer() = default; +void Renderer::Shutdown() +{ + // First stop any framedumping, which might need to dump the last xfb frame. This process + // can require additional graphics sub-systems so it needs to be done first + ShutdownFrameDumping(); +} + void Renderer::RenderToXFB(u32 xfbAddr, const EFBRectangle& sourceRc, u32 fbStride, u32 fbHeight, float Gamma) { diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index 819d6aae88..423707166b 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -154,7 +154,7 @@ public: virtual void ChangeSurface(void* new_surface_handle) {} bool UseVertexDepthRange() const; - void ShutdownFrameDumping(); + virtual void Shutdown(); protected: std::tuple CalculateTargetScale(int x, int y) const; @@ -243,6 +243,7 @@ private: std::string GetFrameDumpNextImageFileName() const; bool StartFrameDumpToImage(const FrameDumpConfig& config); void DumpFrameToImage(const FrameDumpConfig& config); + void ShutdownFrameDumping(); bool IsFrameDumping(); diff --git a/Source/Core/VideoCommon/VideoBackendBase.h b/Source/Core/VideoCommon/VideoBackendBase.h index b7d6e1faa8..060c52916a 100644 --- a/Source/Core/VideoCommon/VideoBackendBase.h +++ b/Source/Core/VideoCommon/VideoBackendBase.h @@ -45,12 +45,8 @@ public: void ShowConfig(void*); virtual void InitBackendInfo() = 0; - virtual void Video_Prepare() = 0; void Video_ExitLoop(); - void Video_CleanupShared(); // called from gl/d3d thread - virtual void Video_Cleanup() = 0; - void Video_BeginField(u32, u32, u32, u32, u64); u32 Video_AccessEFB(EFBAccessType, u32, u32, u32); @@ -70,7 +66,6 @@ public: protected: void InitializeShared(); void ShutdownShared(); - void CleanupShared(); bool m_initialized = false; bool m_invalid = false; From c790077c139dad43586a87d8080b4b9107167930 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Fri, 26 Jan 2018 15:12:26 +1000 Subject: [PATCH 4/5] VideoBackend: Remove PeekMessages method The video thread and backend no longer create any windows, therefore there will never be any messages dispatched to their thread. --- Source/Core/VideoBackends/D3D/VideoBackend.h | 2 -- Source/Core/VideoBackends/D3D/main.cpp | 13 ------------- Source/Core/VideoBackends/Null/VideoBackend.h | 2 -- Source/Core/VideoBackends/OGL/VideoBackend.h | 2 -- Source/Core/VideoBackends/OGL/main.cpp | 6 ------ Source/Core/VideoBackends/Software/SWmain.cpp | 5 ----- Source/Core/VideoBackends/Software/VideoBackend.h | 2 -- Source/Core/VideoBackends/Vulkan/VideoBackend.h | 2 -- Source/Core/VideoCommon/Fifo.cpp | 2 -- Source/Core/VideoCommon/VideoBackendBase.h | 2 -- 10 files changed, 38 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/VideoBackend.h b/Source/Core/VideoBackends/D3D/VideoBackend.h index 97870ffdea..59bd8d9b73 100644 --- a/Source/Core/VideoBackends/D3D/VideoBackend.h +++ b/Source/Core/VideoBackends/D3D/VideoBackend.h @@ -18,7 +18,5 @@ class VideoBackend : public VideoBackendBase std::string GetDisplayName() const override; void InitBackendInfo() override; - - unsigned int PeekMessages() override; }; } diff --git a/Source/Core/VideoBackends/D3D/main.cpp b/Source/Core/VideoBackends/D3D/main.cpp index 3f9529d318..6d689573b9 100644 --- a/Source/Core/VideoBackends/D3D/main.cpp +++ b/Source/Core/VideoBackends/D3D/main.cpp @@ -26,19 +26,6 @@ namespace DX11 { -unsigned int VideoBackend::PeekMessages() -{ - MSG msg; - while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) - { - if (msg.message == WM_QUIT) - return FALSE; - TranslateMessage(&msg); - DispatchMessage(&msg); - } - return TRUE; -} - std::string VideoBackend::GetName() const { return "D3D"; diff --git a/Source/Core/VideoBackends/Null/VideoBackend.h b/Source/Core/VideoBackends/Null/VideoBackend.h index bb7da23c8d..eb1d419775 100644 --- a/Source/Core/VideoBackends/Null/VideoBackend.h +++ b/Source/Core/VideoBackends/Null/VideoBackend.h @@ -16,7 +16,5 @@ class VideoBackend : public VideoBackendBase std::string GetName() const override { return "Null"; } std::string GetDisplayName() const override { return "Null"; } void InitBackendInfo() override; - - unsigned int PeekMessages() override { return 0; } }; } diff --git a/Source/Core/VideoBackends/OGL/VideoBackend.h b/Source/Core/VideoBackends/OGL/VideoBackend.h index a42fc3cce6..1bb4cb3af1 100644 --- a/Source/Core/VideoBackends/OGL/VideoBackend.h +++ b/Source/Core/VideoBackends/OGL/VideoBackend.h @@ -19,8 +19,6 @@ class VideoBackend : public VideoBackendBase void InitBackendInfo() override; - unsigned int PeekMessages() override; - private: bool InitializeGLExtensions(); bool FillBackendInfo(); diff --git a/Source/Core/VideoBackends/OGL/main.cpp b/Source/Core/VideoBackends/OGL/main.cpp index 64aea5f2c5..acabd3d530 100644 --- a/Source/Core/VideoBackends/OGL/main.cpp +++ b/Source/Core/VideoBackends/OGL/main.cpp @@ -58,12 +58,6 @@ Make AA apply instantly during gameplay if possible namespace OGL { -// Draw messages on top of the screen -unsigned int VideoBackend::PeekMessages() -{ - return GLInterface->PeekMessages(); -} - std::string VideoBackend::GetName() const { return "OGL"; diff --git a/Source/Core/VideoBackends/Software/SWmain.cpp b/Source/Core/VideoBackends/Software/SWmain.cpp index a79540891f..37d626c854 100644 --- a/Source/Core/VideoBackends/Software/SWmain.cpp +++ b/Source/Core/VideoBackends/Software/SWmain.cpp @@ -114,9 +114,4 @@ void VideoSoftware::Shutdown() g_renderer.reset(); ShutdownShared(); } - -unsigned int VideoSoftware::PeekMessages() -{ - return SWOGLWindow::s_instance->PeekMessages(); -} } diff --git a/Source/Core/VideoBackends/Software/VideoBackend.h b/Source/Core/VideoBackends/Software/VideoBackend.h index 0221aba9c7..f618ea44ab 100644 --- a/Source/Core/VideoBackends/Software/VideoBackend.h +++ b/Source/Core/VideoBackends/Software/VideoBackend.h @@ -18,7 +18,5 @@ class VideoSoftware : public VideoBackendBase std::string GetDisplayName() const override; void InitBackendInfo() override; - - unsigned int PeekMessages() override; }; } diff --git a/Source/Core/VideoBackends/Vulkan/VideoBackend.h b/Source/Core/VideoBackends/Vulkan/VideoBackend.h index b38ec28131..c511013394 100644 --- a/Source/Core/VideoBackends/Vulkan/VideoBackend.h +++ b/Source/Core/VideoBackends/Vulkan/VideoBackend.h @@ -17,7 +17,5 @@ public: std::string GetName() const override { return "Vulkan"; } std::string GetDisplayName() const override { return "Vulkan (experimental)"; } void InitBackendInfo() override; - - unsigned int PeekMessages() override { return 0; } }; } diff --git a/Source/Core/VideoCommon/Fifo.cpp b/Source/Core/VideoCommon/Fifo.cpp index abf2d78f0c..7b6a412c2c 100644 --- a/Source/Core/VideoCommon/Fifo.cpp +++ b/Source/Core/VideoCommon/Fifo.cpp @@ -299,8 +299,6 @@ void RunGpuLoop() [] { const SConfig& param = SConfig::GetInstance(); - g_video_backend->PeekMessages(); - // Do nothing while paused if (!s_emu_running_state.IsSet()) return; diff --git a/Source/Core/VideoCommon/VideoBackendBase.h b/Source/Core/VideoCommon/VideoBackendBase.h index 060c52916a..b3c7cbe49d 100644 --- a/Source/Core/VideoCommon/VideoBackendBase.h +++ b/Source/Core/VideoCommon/VideoBackendBase.h @@ -35,8 +35,6 @@ class VideoBackendBase { public: virtual ~VideoBackendBase() {} - virtual unsigned int PeekMessages() = 0; - virtual bool Initialize(void* window_handle) = 0; virtual void Shutdown() = 0; From 505d30be3d922f2fba7abe6fd9880f3c8e66767a Mon Sep 17 00:00:00 2001 From: Stenzek Date: Fri, 26 Jan 2018 15:15:35 +1000 Subject: [PATCH 5/5] DolphinWX: Move fullscreen switch to after startup is complete This means that any error messages won't be hidden by the fullscreen window. --- Source/Core/DolphinWX/Frame.cpp | 2 ++ Source/Core/DolphinWX/FrameTools.cpp | 6 +----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index c9745efb33..26fb66b958 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -761,6 +761,8 @@ void CFrame::OnHostMessage(wxCommandEvent& event) case WM_USER_CREATE: if (SConfig::GetInstance().bHideCursor) m_render_parent->SetCursor(wxCURSOR_BLANK); + if (SConfig::GetInstance().bFullscreen) + DoFullscreen(true); break; case IDM_PANIC: diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp index 28bce659e3..7f35afbc5f 100644 --- a/Source/Core/DolphinWX/FrameTools.cpp +++ b/Source/Core/DolphinWX/FrameTools.cpp @@ -717,6 +717,7 @@ void CFrame::StartGame(std::unique_ptr boot) m_render_parent = new wxPanel(m_render_frame, IDM_MPANEL, wxDefaultPosition, wxDefaultSize, 0); #endif m_render_frame->Show(); + m_render_frame->Raise(); } #if defined(__APPLE__) @@ -724,15 +725,10 @@ void CFrame::StartGame(std::unique_ptr boot) #endif wxBusyCursor hourglass; - - DoFullscreen(SConfig::GetInstance().bFullscreen); - SetDebuggerStartupParameters(); if (!BootManager::BootCore(std::move(boot))) { - DoFullscreen(false); - // Destroy the renderer frame when not rendering to main if (!SConfig::GetInstance().bRenderToMain) m_render_frame->Destroy();