HostDisplay: Add an option to decouple display fps from emulator fps
Makes Android so much faster...
This commit is contained in:
parent
ae1e4b1b8f
commit
2c8a4ff154
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue