From 4a3478b360909e1d0b27f35959d024b1dc67fa0a Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Fri, 24 Jan 2020 14:51:53 +1000 Subject: [PATCH] HostInterface: Add function to switch between sw/hw rendering --- src/core/gpu.h | 2 ++ src/core/gpu_hw.cpp | 5 +++++ src/core/gpu_hw.h | 2 ++ src/core/gpu_sw.cpp | 5 +++++ src/core/gpu_sw.h | 2 ++ src/core/host_interface.cpp | 14 +++++++++++-- src/core/host_interface.h | 5 +++++ src/core/system.cpp | 15 +++++++------- src/core/system.h | 4 ++-- src/duckstation/sdl_host_interface.cpp | 27 +------------------------- src/duckstation/sdl_host_interface.h | 1 - 11 files changed, 43 insertions(+), 39 deletions(-) diff --git a/src/core/gpu.h b/src/core/gpu.h index 9806ec148..da98dea36 100644 --- a/src/core/gpu.h +++ b/src/core/gpu.h @@ -105,6 +105,8 @@ public: GPU(); virtual ~GPU(); + virtual bool IsHardwareRenderer() const = 0; + virtual bool Initialize(HostDisplay* host_display, System* system, DMA* dma, InterruptController* interrupt_controller, Timers* timers); virtual void Reset(); diff --git a/src/core/gpu_hw.cpp b/src/core/gpu_hw.cpp index 1bf72cde6..9227b14b7 100644 --- a/src/core/gpu_hw.cpp +++ b/src/core/gpu_hw.cpp @@ -15,6 +15,11 @@ GPU_HW::GPU_HW() : GPU() GPU_HW::~GPU_HW() = default; +bool GPU_HW::IsHardwareRenderer() const +{ + return true; +} + bool GPU_HW::Initialize(HostDisplay* host_display, System* system, DMA* dma, InterruptController* interrupt_controller, Timers* timers) { diff --git a/src/core/gpu_hw.h b/src/core/gpu_hw.h index bdee9ce3b..690b65dfb 100644 --- a/src/core/gpu_hw.h +++ b/src/core/gpu_hw.h @@ -29,6 +29,8 @@ public: GPU_HW(); virtual ~GPU_HW(); + virtual bool IsHardwareRenderer() const override; + virtual bool Initialize(HostDisplay* host_display, System* system, DMA* dma, InterruptController* interrupt_controller, Timers* timers) override; virtual void Reset() override; diff --git a/src/core/gpu_sw.cpp b/src/core/gpu_sw.cpp index 231ea5691..a8e6559e7 100644 --- a/src/core/gpu_sw.cpp +++ b/src/core/gpu_sw.cpp @@ -15,6 +15,11 @@ GPU_SW::~GPU_SW() m_host_display->SetDisplayTexture(nullptr, 0, 0, 0, 0, 0, 0, 1.0f); } +bool GPU_SW::IsHardwareRenderer() const +{ + return false; +} + bool GPU_SW::Initialize(HostDisplay* host_display, System* system, DMA* dma, InterruptController* interrupt_controller, Timers* timers) { diff --git a/src/core/gpu_sw.h b/src/core/gpu_sw.h index 358d19562..098cd648f 100644 --- a/src/core/gpu_sw.h +++ b/src/core/gpu_sw.h @@ -12,6 +12,8 @@ public: GPU_SW(); ~GPU_SW() override; + bool IsHardwareRenderer() const override; + bool Initialize(HostDisplay* host_display, System* system, DMA* dma, InterruptController* interrupt_controller, Timers* timers) override; void Reset() override; diff --git a/src/core/host_interface.cpp b/src/core/host_interface.cpp index d0716369f..b10e1f981 100644 --- a/src/core/host_interface.cpp +++ b/src/core/host_interface.cpp @@ -515,7 +515,6 @@ std::string HostInterface::GetGameListDatabaseFileName() const void HostInterface::UpdateSettings(const std::function& apply_callback) { - // TODO: Should we move this to the base class? const GPURenderer old_gpu_renderer = m_settings.gpu_renderer; const u32 old_gpu_resolution_scale = m_settings.gpu_resolution_scale; const bool old_gpu_true_color = m_settings.gpu_true_color; @@ -528,7 +527,6 @@ void HostInterface::UpdateSettings(const std::function& apply_callback) apply_callback(); - // TODO: Fast path for hardware->software switches if (m_settings.gpu_renderer != old_gpu_renderer) SwitchGPURenderer(); @@ -549,6 +547,18 @@ void HostInterface::UpdateSettings(const std::function& apply_callback) m_display->SetDisplayLinearFiltering(m_settings.display_linear_filtering); } +void HostInterface::ToggleSoftwareRendering() +{ + if (!m_system || m_settings.gpu_renderer == GPURenderer::Software) + return; + + const GPURenderer new_renderer = + m_system->GetGPU()->IsHardwareRenderer() ? GPURenderer::Software : m_settings.gpu_renderer; + + AddFormattedOSDMessage(2.0f, "Switching to %s renderer...", Settings::GetRendererDisplayName(new_renderer)); + m_system->RecreateGPU(new_renderer); +} + void HostInterface::RunFrame() { m_frame_timer.Reset(); diff --git a/src/core/host_interface.h b/src/core/host_interface.h index facdf7397..7d42066b1 100644 --- a/src/core/host_interface.h +++ b/src/core/host_interface.h @@ -104,8 +104,13 @@ protected: /// Returns the path of the game database cache file. std::string GetGameListDatabaseFileName() const; + /// Applies new settings, updating internal state as needed. apply_callback should call m_settings.Load() after + /// locking any required mutexes. void UpdateSettings(const std::function& apply_callback); + /// Quick switch between software and hardware rendering. + void ToggleSoftwareRendering(); + void RunFrame(); /// Throttles the system, i.e. sleeps until it's time to execute the next frame. diff --git a/src/core/system.cpp b/src/core/system.cpp index 869ec1883..eb769c25d 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -36,8 +36,8 @@ System::System(HostInterface* host_interface) : m_host_interface(host_interface) m_spu = std::make_unique(); m_mdec = std::make_unique(); m_sio = std::make_unique(); - m_region = host_interface->GetSettings().region; - m_cpu_execution_mode = host_interface->GetSettings().cpu_execution_mode; + m_region = host_interface->m_settings.region; + m_cpu_execution_mode = host_interface->m_settings.cpu_execution_mode; } System::~System() = default; @@ -45,13 +45,13 @@ System::~System() = default; std::unique_ptr System::Create(HostInterface* host_interface) { std::unique_ptr system(new System(host_interface)); - if (!system->CreateGPU()) + if (!system->CreateGPU(host_interface->m_settings.gpu_renderer)) return {}; return system; } -bool System::RecreateGPU() +bool System::RecreateGPU(GPURenderer renderer) { // save current state std::unique_ptr state_stream = ByteStream_CreateGrowableMemoryStream(); @@ -62,7 +62,7 @@ bool System::RecreateGPU() // create new renderer m_gpu.reset(); - if (!CreateGPU()) + if (!CreateGPU(renderer)) { Panic("Failed to recreate GPU"); return false; @@ -193,9 +193,9 @@ void System::InitializeComponents() m_mdec->Initialize(this, m_dma.get()); } -bool System::CreateGPU() +bool System::CreateGPU(GPURenderer renderer) { - switch (m_host_interface->GetSettings().gpu_renderer) + switch (renderer) { case GPURenderer::HardwareOpenGL: m_gpu = m_host_interface->GetDisplay()->GetRenderAPI() == HostDisplay::RenderAPI::OpenGLES ? @@ -220,7 +220,6 @@ bool System::CreateGPU() { Log_ErrorPrintf("Failed to initialize GPU, falling back to software"); m_gpu.reset(); - m_host_interface->GetSettings().gpu_renderer = GPURenderer::Software; m_gpu = GPU::CreateSoftwareRenderer(); if (!m_gpu->Initialize(m_host_interface->GetDisplay(), this, m_dma.get(), m_interrupt_controller.get(), m_timers.get())) diff --git a/src/core/system.h b/src/core/system.h index 8aaf7b12c..7809f049c 100644 --- a/src/core/system.h +++ b/src/core/system.h @@ -68,7 +68,7 @@ public: bool SaveState(ByteStream* state); /// Recreates the GPU component, saving/loading the state so it is preserved. Call when the GPU renderer changes. - bool RecreateGPU(); + bool RecreateGPU(GPURenderer renderer); /// Updates GPU settings, without recreating the renderer. void UpdateGPUSettings(); @@ -98,7 +98,7 @@ private: System(HostInterface* host_interface); bool DoState(StateWrapper& sw); - bool CreateGPU(); + bool CreateGPU(GPURenderer renderer); void InitializeComponents(); diff --git a/src/duckstation/sdl_host_interface.cpp b/src/duckstation/sdl_host_interface.cpp index 7674ba552..654a7e976 100644 --- a/src/duckstation/sdl_host_interface.cpp +++ b/src/duckstation/sdl_host_interface.cpp @@ -419,7 +419,7 @@ void SDLHostInterface::HandleSDLKeyEvent(const SDL_Event* event) case SDL_SCANCODE_END: { if (pressed) - DoToggleSoftwareRendering(); + ToggleSoftwareRendering(); } break; @@ -1549,31 +1549,6 @@ void SDLHostInterface::DoFrameStep() m_paused = false; } -void SDLHostInterface::DoToggleSoftwareRendering() -{ - if (!m_system) - return; - - if (m_settings.gpu_renderer != GPURenderer::Software) - { - m_settings.gpu_renderer = GPURenderer::Software; - AddOSDMessage("Switched to software GPU renderer."); - } - else - { -#ifdef WIN32 - m_settings.gpu_renderer = m_display->GetRenderAPI() == HostDisplay::RenderAPI::D3D11 ? GPURenderer::HardwareD3D11 : - GPURenderer::HardwareOpenGL; -#else - m_settings.gpu_renderer = GPURenderer::HardwareOpenGL; -#endif - - AddOSDMessage("Switched to hardware GPU renderer."); - } - - m_system->RecreateGPU(); -} - void SDLHostInterface::DoToggleFullscreen() { m_settings.display_fullscreen = !m_settings.display_fullscreen; diff --git a/src/duckstation/sdl_host_interface.h b/src/duckstation/sdl_host_interface.h index 592d27f0b..257657a90 100644 --- a/src/duckstation/sdl_host_interface.h +++ b/src/duckstation/sdl_host_interface.h @@ -99,7 +99,6 @@ private: void DoSaveState(u32 index); void DoTogglePause(); void DoFrameStep(); - void DoToggleSoftwareRendering(); void DoToggleFullscreen(); void DoModifyInternalResolution(s32 increment);