HostDisplay: Add an option to decouple display fps from emulator fps

Makes Android so much faster...
This commit is contained in:
Connor McLaughlin 2020-11-03 15:58:40 +10:00
parent ae1e4b1b8f
commit 2c8a4ff154
10 changed files with 79 additions and 1 deletions

View file

@ -2,6 +2,7 @@
#include "common/file_system.h" #include "common/file_system.h"
#include "common/log.h" #include "common/log.h"
#include "common/string_util.h" #include "common/string_util.h"
#include "common/timer.h"
#include "stb_image.h" #include "stb_image.h"
#include "stb_image_resize.h" #include "stb_image_resize.h"
#include "stb_image_write.h" #include "stb_image_write.h"
@ -14,6 +15,25 @@ HostDisplayTexture::~HostDisplayTexture() = default;
HostDisplay::~HostDisplay() = default; HostDisplay::~HostDisplay() = default;
void HostDisplay::SetDisplayMaxFPS(float max_fps)
{
m_display_frame_interval = (max_fps > 0.0f) ? (1.0f / max_fps) : 0.0f;
}
bool HostDisplay::ShouldSkipDisplayingFrame()
{
if (m_display_frame_interval == 0.0f)
return false;
const u64 now = Common::Timer::GetValue();
const double diff = Common::Timer::ConvertValueToSeconds(now - m_last_frame_displayed_time);
if (diff < m_display_frame_interval)
return true;
m_last_frame_displayed_time = now;
return false;
}
void HostDisplay::SetSoftwareCursor(std::unique_ptr<HostDisplayTexture> texture, float scale /*= 1.0f*/) void HostDisplay::SetSoftwareCursor(std::unique_ptr<HostDisplayTexture> texture, float scale /*= 1.0f*/)
{ {
m_cursor_texture = std::move(texture); m_cursor_texture = std::move(texture);

View file

@ -94,6 +94,9 @@ public:
const s32 GetDisplayTopMargin() const { return m_display_top_margin; } const s32 GetDisplayTopMargin() const { return m_display_top_margin; }
const float GetDisplayAspectRatio() const { return m_display_aspect_ratio; } const float GetDisplayAspectRatio() const { return m_display_aspect_ratio; }
void SetDisplayMaxFPS(float max_fps);
bool ShouldSkipDisplayingFrame();
void ClearDisplayTexture() void ClearDisplayTexture()
{ {
m_display_texture_handle = nullptr; m_display_texture_handle = nullptr;
@ -181,6 +184,8 @@ protected:
WindowInfo m_window_info; WindowInfo m_window_info;
u64 m_last_frame_displayed_time = 0;
s32 m_mouse_position_x = 0; s32 m_mouse_position_x = 0;
s32 m_mouse_position_y = 0; s32 m_mouse_position_y = 0;
@ -191,6 +196,7 @@ protected:
s32 m_display_active_width = 0; s32 m_display_active_width = 0;
s32 m_display_active_height = 0; s32 m_display_active_height = 0;
float m_display_aspect_ratio = 1.0f; float m_display_aspect_ratio = 1.0f;
float m_display_frame_interval = 0.0f;
void* m_display_texture_handle = nullptr; void* m_display_texture_handle = nullptr;
s32 m_display_texture_width = 0; s32 m_display_texture_width = 0;

View file

@ -463,6 +463,7 @@ void HostInterface::SetDefaultSettings(SettingsInterface& si)
si.SetBoolValue("Display", "Fullscreen", false); si.SetBoolValue("Display", "Fullscreen", false);
si.SetBoolValue("Display", "VSync", true); si.SetBoolValue("Display", "VSync", true);
si.SetStringValue("Display", "PostProcessChain", ""); si.SetStringValue("Display", "PostProcessChain", "");
si.SetFloatValue("Display", "MaxFPS", 0.0f);
si.SetBoolValue("CDROM", "ReadThread", true); si.SetBoolValue("CDROM", "ReadThread", true);
si.SetBoolValue("CDROM", "RegionCheck", true); si.SetBoolValue("CDROM", "RegionCheck", true);

View file

@ -177,6 +177,7 @@ void Settings::Load(SettingsInterface& si)
display_show_resolution = si.GetBoolValue("Display", "ShowResolution", false); display_show_resolution = si.GetBoolValue("Display", "ShowResolution", false);
video_sync_enabled = si.GetBoolValue("Display", "VSync", true); video_sync_enabled = si.GetBoolValue("Display", "VSync", true);
display_post_process_chain = si.GetStringValue("Display", "PostProcessChain", ""); display_post_process_chain = si.GetStringValue("Display", "PostProcessChain", "");
display_max_fps = si.GetFloatValue("Display", "MaxFPS", 0.0f);
cdrom_read_thread = si.GetBoolValue("CDROM", "ReadThread", true); cdrom_read_thread = si.GetBoolValue("CDROM", "ReadThread", true);
cdrom_region_check = si.GetBoolValue("CDROM", "RegionCheck", true); cdrom_region_check = si.GetBoolValue("CDROM", "RegionCheck", true);
@ -304,6 +305,7 @@ void Settings::Save(SettingsInterface& si) const
si.DeleteValue("Display", "PostProcessChain"); si.DeleteValue("Display", "PostProcessChain");
else else
si.SetStringValue("Display", "PostProcessChain", display_post_process_chain.c_str()); si.SetStringValue("Display", "PostProcessChain", display_post_process_chain.c_str());
si.SetFloatValue("Display", "MaxFPS", display_max_fps);
si.SetBoolValue("CDROM", "ReadThread", cdrom_read_thread); si.SetBoolValue("CDROM", "ReadThread", cdrom_read_thread);
si.SetBoolValue("CDROM", "RegionCheck", cdrom_region_check); si.SetBoolValue("CDROM", "RegionCheck", cdrom_region_check);

View file

@ -123,6 +123,7 @@ struct Settings
bool display_show_speed = false; bool display_show_speed = false;
bool display_show_resolution = false; bool display_show_resolution = false;
bool video_sync_enabled = true; bool video_sync_enabled = true;
float display_max_fps = 0.0f;
bool cdrom_read_thread = true; bool cdrom_read_thread = true;
bool cdrom_region_check = true; bool cdrom_region_check = true;

View file

@ -105,6 +105,8 @@ AdvancedSettingsWidget::AdvancedSettingsWidget(QtHostInterface* host_interface,
1000, Settings::DEFAULT_GPU_MAX_RUN_AHEAD); 1000, Settings::DEFAULT_GPU_MAX_RUN_AHEAD);
addBooleanTweakOption(m_host_interface, m_ui.tweakOptionTable, tr("Use Debug Host GPU Device"), "GPU", addBooleanTweakOption(m_host_interface, m_ui.tweakOptionTable, tr("Use Debug Host GPU Device"), "GPU",
"UseDebugDevice", false); "UseDebugDevice", false);
addIntRangeTweakOption(m_host_interface, m_ui.tweakOptionTable, tr("Display FPS Limit"), "Display", "MaxFPS", 0, 1000,
0);
} }
AdvancedSettingsWidget::~AdvancedSettingsWidget() = default; AdvancedSettingsWidget::~AdvancedSettingsWidget() = default;
@ -122,4 +124,5 @@ void AdvancedSettingsWidget::onResetToDefaultClicked()
setIntRangeTweakOption(m_ui.tweakOptionTable, 8, static_cast<int>(Settings::DEFAULT_GPU_FIFO_SIZE)); setIntRangeTweakOption(m_ui.tweakOptionTable, 8, static_cast<int>(Settings::DEFAULT_GPU_FIFO_SIZE));
setIntRangeTweakOption(m_ui.tweakOptionTable, 9, static_cast<int>(Settings::DEFAULT_GPU_MAX_RUN_AHEAD)); setIntRangeTweakOption(m_ui.tweakOptionTable, 9, static_cast<int>(Settings::DEFAULT_GPU_MAX_RUN_AHEAD));
setBooleanTweakOption(m_ui.tweakOptionTable, 10, false); setBooleanTweakOption(m_ui.tweakOptionTable, 10, false);
setIntRangeTweakOption(m_ui.tweakOptionTable, 11, 0);
} }

View file

@ -605,8 +605,10 @@ void CommonHostInterface::UpdateSpeedLimiterState()
!System::IsRunning() || (m_speed_limiter_enabled && g_settings.audio_sync_enabled && !is_non_standard_speed); !System::IsRunning() || (m_speed_limiter_enabled && g_settings.audio_sync_enabled && !is_non_standard_speed);
const bool video_sync_enabled = const bool video_sync_enabled =
!System::IsRunning() || (m_speed_limiter_enabled && g_settings.video_sync_enabled && !is_non_standard_speed); !System::IsRunning() || (m_speed_limiter_enabled && g_settings.video_sync_enabled && !is_non_standard_speed);
const float max_display_fps = m_speed_limiter_enabled ? 0.0f : g_settings.display_max_fps;
Log_InfoPrintf("Syncing to %s%s", audio_sync_enabled ? "audio" : "", Log_InfoPrintf("Syncing to %s%s", audio_sync_enabled ? "audio" : "",
(audio_sync_enabled && video_sync_enabled) ? " and video" : (video_sync_enabled ? "video" : "")); (audio_sync_enabled && video_sync_enabled) ? " and video" : (video_sync_enabled ? "video" : ""));
Log_InfoPrintf("Max display fps: %f", max_display_fps);
if (m_audio_stream) if (m_audio_stream)
{ {
@ -616,7 +618,10 @@ void CommonHostInterface::UpdateSpeedLimiterState()
} }
if (m_display) if (m_display)
{
m_display->SetDisplayMaxFPS(max_display_fps);
m_display->SetVSync(video_sync_enabled); m_display->SetVSync(video_sync_enabled);
}
if (g_settings.increase_timer_resolution) if (g_settings.increase_timer_resolution)
SetTimerResolutionIncreased(m_speed_limiter_enabled); SetTimerResolutionIncreased(m_speed_limiter_enabled);
@ -2077,7 +2082,8 @@ void CommonHostInterface::CheckForSettingsChanges(const Settings& old_settings)
g_settings.audio_sync_enabled != old_settings.audio_sync_enabled || g_settings.audio_sync_enabled != old_settings.audio_sync_enabled ||
g_settings.speed_limiter_enabled != old_settings.speed_limiter_enabled || g_settings.speed_limiter_enabled != old_settings.speed_limiter_enabled ||
g_settings.increase_timer_resolution != old_settings.increase_timer_resolution || g_settings.increase_timer_resolution != old_settings.increase_timer_resolution ||
g_settings.emulation_speed != old_settings.emulation_speed) g_settings.emulation_speed != old_settings.emulation_speed ||
g_settings.display_max_fps != old_settings.display_max_fps)
{ {
UpdateSpeedLimiterState(); UpdateSpeedLimiterState();
} }

View file

@ -661,6 +661,19 @@ void D3D11HostDisplay::DestroyImGuiContext()
bool D3D11HostDisplay::Render() bool D3D11HostDisplay::Render()
{ {
#ifndef LIBRETRO #ifndef LIBRETRO
if (ShouldSkipDisplayingFrame())
{
#ifdef WITH_IMGUI
if (ImGui::GetCurrentContext())
{
ImGui::Render();
ImGui_ImplDX11_NewFrame();
}
#endif
return false;
}
static constexpr std::array<float, 4> clear_color = {}; static constexpr std::array<float, 4> clear_color = {};
m_context->ClearRenderTargetView(m_swap_chain_rtv.Get(), clear_color.data()); m_context->ClearRenderTargetView(m_swap_chain_rtv.Get(), clear_color.data());
m_context->OMSetRenderTargets(1, m_swap_chain_rtv.GetAddressOf(), nullptr); m_context->OMSetRenderTargets(1, m_swap_chain_rtv.GetAddressOf(), nullptr);

View file

@ -464,6 +464,19 @@ void OpenGLHostDisplay::DestroyResources()
bool OpenGLHostDisplay::Render() bool OpenGLHostDisplay::Render()
{ {
if (ShouldSkipDisplayingFrame())
{
#ifdef WITH_IMGUI
if (ImGui::GetCurrentContext())
{
ImGui::Render();
ImGui_ImplOpenGL3_NewFrame();
}
#endif
return false;
}
glDisable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

View file

@ -539,6 +539,19 @@ bool VulkanHostDisplay::CreateImGuiContext()
bool VulkanHostDisplay::Render() bool VulkanHostDisplay::Render()
{ {
if (ShouldSkipDisplayingFrame())
{
#ifdef WITH_IMGUI
if (ImGui::GetCurrentContext())
{
ImGui::Render();
ImGui_ImplVulkan_NewFrame();
}
#endif
return false;
}
VkResult res = m_swap_chain->AcquireNextImage(); VkResult res = m_swap_chain->AcquireNextImage();
if (res != VK_SUCCESS) if (res != VK_SUCCESS)
{ {