mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2025-01-17 22:25:37 +00:00
HostInterface: Add function to switch between sw/hw rendering
This commit is contained in:
parent
f2231d6669
commit
4a3478b360
|
@ -105,6 +105,8 @@ public:
|
||||||
GPU();
|
GPU();
|
||||||
virtual ~GPU();
|
virtual ~GPU();
|
||||||
|
|
||||||
|
virtual bool IsHardwareRenderer() const = 0;
|
||||||
|
|
||||||
virtual bool Initialize(HostDisplay* host_display, System* system, DMA* dma,
|
virtual bool Initialize(HostDisplay* host_display, System* system, DMA* dma,
|
||||||
InterruptController* interrupt_controller, Timers* timers);
|
InterruptController* interrupt_controller, Timers* timers);
|
||||||
virtual void Reset();
|
virtual void Reset();
|
||||||
|
|
|
@ -15,6 +15,11 @@ GPU_HW::GPU_HW() : GPU()
|
||||||
|
|
||||||
GPU_HW::~GPU_HW() = default;
|
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,
|
bool GPU_HW::Initialize(HostDisplay* host_display, System* system, DMA* dma, InterruptController* interrupt_controller,
|
||||||
Timers* timers)
|
Timers* timers)
|
||||||
{
|
{
|
||||||
|
|
|
@ -29,6 +29,8 @@ public:
|
||||||
GPU_HW();
|
GPU_HW();
|
||||||
virtual ~GPU_HW();
|
virtual ~GPU_HW();
|
||||||
|
|
||||||
|
virtual bool IsHardwareRenderer() const override;
|
||||||
|
|
||||||
virtual bool Initialize(HostDisplay* host_display, System* system, DMA* dma,
|
virtual bool Initialize(HostDisplay* host_display, System* system, DMA* dma,
|
||||||
InterruptController* interrupt_controller, Timers* timers) override;
|
InterruptController* interrupt_controller, Timers* timers) override;
|
||||||
virtual void Reset() override;
|
virtual void Reset() override;
|
||||||
|
|
|
@ -15,6 +15,11 @@ GPU_SW::~GPU_SW()
|
||||||
m_host_display->SetDisplayTexture(nullptr, 0, 0, 0, 0, 0, 0, 1.0f);
|
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,
|
bool GPU_SW::Initialize(HostDisplay* host_display, System* system, DMA* dma, InterruptController* interrupt_controller,
|
||||||
Timers* timers)
|
Timers* timers)
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,6 +12,8 @@ public:
|
||||||
GPU_SW();
|
GPU_SW();
|
||||||
~GPU_SW() override;
|
~GPU_SW() override;
|
||||||
|
|
||||||
|
bool IsHardwareRenderer() const override;
|
||||||
|
|
||||||
bool Initialize(HostDisplay* host_display, System* system, DMA* dma, InterruptController* interrupt_controller,
|
bool Initialize(HostDisplay* host_display, System* system, DMA* dma, InterruptController* interrupt_controller,
|
||||||
Timers* timers) override;
|
Timers* timers) override;
|
||||||
void Reset() override;
|
void Reset() override;
|
||||||
|
|
|
@ -515,7 +515,6 @@ std::string HostInterface::GetGameListDatabaseFileName() const
|
||||||
|
|
||||||
void HostInterface::UpdateSettings(const std::function<void()>& apply_callback)
|
void HostInterface::UpdateSettings(const std::function<void()>& apply_callback)
|
||||||
{
|
{
|
||||||
// TODO: Should we move this to the base class?
|
|
||||||
const GPURenderer old_gpu_renderer = m_settings.gpu_renderer;
|
const GPURenderer old_gpu_renderer = m_settings.gpu_renderer;
|
||||||
const u32 old_gpu_resolution_scale = m_settings.gpu_resolution_scale;
|
const u32 old_gpu_resolution_scale = m_settings.gpu_resolution_scale;
|
||||||
const bool old_gpu_true_color = m_settings.gpu_true_color;
|
const bool old_gpu_true_color = m_settings.gpu_true_color;
|
||||||
|
@ -528,7 +527,6 @@ void HostInterface::UpdateSettings(const std::function<void()>& apply_callback)
|
||||||
|
|
||||||
apply_callback();
|
apply_callback();
|
||||||
|
|
||||||
// TODO: Fast path for hardware->software switches
|
|
||||||
if (m_settings.gpu_renderer != old_gpu_renderer)
|
if (m_settings.gpu_renderer != old_gpu_renderer)
|
||||||
SwitchGPURenderer();
|
SwitchGPURenderer();
|
||||||
|
|
||||||
|
@ -549,6 +547,18 @@ void HostInterface::UpdateSettings(const std::function<void()>& apply_callback)
|
||||||
m_display->SetDisplayLinearFiltering(m_settings.display_linear_filtering);
|
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()
|
void HostInterface::RunFrame()
|
||||||
{
|
{
|
||||||
m_frame_timer.Reset();
|
m_frame_timer.Reset();
|
||||||
|
|
|
@ -104,8 +104,13 @@ protected:
|
||||||
/// Returns the path of the game database cache file.
|
/// Returns the path of the game database cache file.
|
||||||
std::string GetGameListDatabaseFileName() const;
|
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<void()>& apply_callback);
|
void UpdateSettings(const std::function<void()>& apply_callback);
|
||||||
|
|
||||||
|
/// Quick switch between software and hardware rendering.
|
||||||
|
void ToggleSoftwareRendering();
|
||||||
|
|
||||||
void RunFrame();
|
void RunFrame();
|
||||||
|
|
||||||
/// Throttles the system, i.e. sleeps until it's time to execute the next frame.
|
/// Throttles the system, i.e. sleeps until it's time to execute the next frame.
|
||||||
|
|
|
@ -36,8 +36,8 @@ System::System(HostInterface* host_interface) : m_host_interface(host_interface)
|
||||||
m_spu = std::make_unique<SPU>();
|
m_spu = std::make_unique<SPU>();
|
||||||
m_mdec = std::make_unique<MDEC>();
|
m_mdec = std::make_unique<MDEC>();
|
||||||
m_sio = std::make_unique<SIO>();
|
m_sio = std::make_unique<SIO>();
|
||||||
m_region = host_interface->GetSettings().region;
|
m_region = host_interface->m_settings.region;
|
||||||
m_cpu_execution_mode = host_interface->GetSettings().cpu_execution_mode;
|
m_cpu_execution_mode = host_interface->m_settings.cpu_execution_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
System::~System() = default;
|
System::~System() = default;
|
||||||
|
@ -45,13 +45,13 @@ System::~System() = default;
|
||||||
std::unique_ptr<System> System::Create(HostInterface* host_interface)
|
std::unique_ptr<System> System::Create(HostInterface* host_interface)
|
||||||
{
|
{
|
||||||
std::unique_ptr<System> system(new System(host_interface));
|
std::unique_ptr<System> system(new System(host_interface));
|
||||||
if (!system->CreateGPU())
|
if (!system->CreateGPU(host_interface->m_settings.gpu_renderer))
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
return system;
|
return system;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool System::RecreateGPU()
|
bool System::RecreateGPU(GPURenderer renderer)
|
||||||
{
|
{
|
||||||
// save current state
|
// save current state
|
||||||
std::unique_ptr<ByteStream> state_stream = ByteStream_CreateGrowableMemoryStream();
|
std::unique_ptr<ByteStream> state_stream = ByteStream_CreateGrowableMemoryStream();
|
||||||
|
@ -62,7 +62,7 @@ bool System::RecreateGPU()
|
||||||
|
|
||||||
// create new renderer
|
// create new renderer
|
||||||
m_gpu.reset();
|
m_gpu.reset();
|
||||||
if (!CreateGPU())
|
if (!CreateGPU(renderer))
|
||||||
{
|
{
|
||||||
Panic("Failed to recreate GPU");
|
Panic("Failed to recreate GPU");
|
||||||
return false;
|
return false;
|
||||||
|
@ -193,9 +193,9 @@ void System::InitializeComponents()
|
||||||
m_mdec->Initialize(this, m_dma.get());
|
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:
|
case GPURenderer::HardwareOpenGL:
|
||||||
m_gpu = m_host_interface->GetDisplay()->GetRenderAPI() == HostDisplay::RenderAPI::OpenGLES ?
|
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");
|
Log_ErrorPrintf("Failed to initialize GPU, falling back to software");
|
||||||
m_gpu.reset();
|
m_gpu.reset();
|
||||||
m_host_interface->GetSettings().gpu_renderer = GPURenderer::Software;
|
|
||||||
m_gpu = GPU::CreateSoftwareRenderer();
|
m_gpu = GPU::CreateSoftwareRenderer();
|
||||||
if (!m_gpu->Initialize(m_host_interface->GetDisplay(), this, m_dma.get(), m_interrupt_controller.get(),
|
if (!m_gpu->Initialize(m_host_interface->GetDisplay(), this, m_dma.get(), m_interrupt_controller.get(),
|
||||||
m_timers.get()))
|
m_timers.get()))
|
||||||
|
|
|
@ -68,7 +68,7 @@ public:
|
||||||
bool SaveState(ByteStream* state);
|
bool SaveState(ByteStream* state);
|
||||||
|
|
||||||
/// Recreates the GPU component, saving/loading the state so it is preserved. Call when the GPU renderer changes.
|
/// 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.
|
/// Updates GPU settings, without recreating the renderer.
|
||||||
void UpdateGPUSettings();
|
void UpdateGPUSettings();
|
||||||
|
@ -98,7 +98,7 @@ private:
|
||||||
System(HostInterface* host_interface);
|
System(HostInterface* host_interface);
|
||||||
|
|
||||||
bool DoState(StateWrapper& sw);
|
bool DoState(StateWrapper& sw);
|
||||||
bool CreateGPU();
|
bool CreateGPU(GPURenderer renderer);
|
||||||
|
|
||||||
void InitializeComponents();
|
void InitializeComponents();
|
||||||
|
|
||||||
|
|
|
@ -419,7 +419,7 @@ void SDLHostInterface::HandleSDLKeyEvent(const SDL_Event* event)
|
||||||
|
|
||||||
case SDL_SCANCODE_END: {
|
case SDL_SCANCODE_END: {
|
||||||
if (pressed)
|
if (pressed)
|
||||||
DoToggleSoftwareRendering();
|
ToggleSoftwareRendering();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1549,31 +1549,6 @@ void SDLHostInterface::DoFrameStep()
|
||||||
m_paused = false;
|
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()
|
void SDLHostInterface::DoToggleFullscreen()
|
||||||
{
|
{
|
||||||
m_settings.display_fullscreen = !m_settings.display_fullscreen;
|
m_settings.display_fullscreen = !m_settings.display_fullscreen;
|
||||||
|
|
|
@ -99,7 +99,6 @@ private:
|
||||||
void DoSaveState(u32 index);
|
void DoSaveState(u32 index);
|
||||||
void DoTogglePause();
|
void DoTogglePause();
|
||||||
void DoFrameStep();
|
void DoFrameStep();
|
||||||
void DoToggleSoftwareRendering();
|
|
||||||
void DoToggleFullscreen();
|
void DoToggleFullscreen();
|
||||||
void DoModifyInternalResolution(s32 increment);
|
void DoModifyInternalResolution(s32 increment);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue