HostInterface: Add function to switch between sw/hw rendering

This commit is contained in:
Connor McLaughlin 2020-01-24 14:51:53 +10:00
parent f2231d6669
commit 4a3478b360
11 changed files with 43 additions and 39 deletions

View file

@ -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();

View file

@ -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)
{

View file

@ -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;

View file

@ -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)
{

View file

@ -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;

View file

@ -515,7 +515,6 @@ std::string HostInterface::GetGameListDatabaseFileName() const
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 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<void()>& 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<void()>& 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();

View file

@ -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<void()>& 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.

View file

@ -36,8 +36,8 @@ System::System(HostInterface* host_interface) : m_host_interface(host_interface)
m_spu = std::make_unique<SPU>();
m_mdec = std::make_unique<MDEC>();
m_sio = std::make_unique<SIO>();
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> System::Create(HostInterface* 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 system;
}
bool System::RecreateGPU()
bool System::RecreateGPU(GPURenderer renderer)
{
// save current state
std::unique_ptr<ByteStream> 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()))

View file

@ -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();

View file

@ -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;

View file

@ -99,7 +99,6 @@ private:
void DoSaveState(u32 index);
void DoTogglePause();
void DoFrameStep();
void DoToggleSoftwareRendering();
void DoToggleFullscreen();
void DoModifyInternalResolution(s32 increment);