From 9b7512f7b84351d1e81535aade7e52d54b0dda5d Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Mon, 3 Aug 2020 03:06:03 +1000 Subject: [PATCH] GPU/HW: Implement automatic resolution scale from window size --- src/core/gpu.cpp | 2 ++ src/core/gpu.h | 7 +++-- src/core/gpu_hw.cpp | 35 +++++++++++++++------- src/core/gpu_hw.h | 3 ++ src/duckstation-qt/qthostinterface.cpp | 10 ++++++- src/duckstation-sdl/sdl_host_interface.cpp | 7 +++++ 6 files changed, 51 insertions(+), 13 deletions(-) diff --git a/src/core/gpu.cpp b/src/core/gpu.cpp index 604cb26c2..3e26d7cac 100644 --- a/src/core/gpu.cpp +++ b/src/core/gpu.cpp @@ -57,6 +57,8 @@ void GPU::UpdateSettings() UpdateCRTCDisplayParameters(); } +void GPU::UpdateResolutionScale() {} + void GPU::Reset() { SoftReset(); diff --git a/src/core/gpu.h b/src/core/gpu.h index 62f0a4817..a8572aa36 100644 --- a/src/core/gpu.h +++ b/src/core/gpu.h @@ -154,12 +154,15 @@ public: /// Returns true if a raster scanline or command execution is pending. bool IsCommandCompletionPending() const; - // Synchronizes the CRTC, updating the hblank timer. + /// Synchronizes the CRTC, updating the hblank timer. void SynchronizeCRTC(); - // Recompile shaders/recreate framebuffers when needed. + /// Recompile shaders/recreate framebuffers when needed. virtual void UpdateSettings(); + /// Updates the resolution scale when it's set to automatic. + virtual void UpdateResolutionScale(); + // gpu_hw_d3d11.cpp static std::unique_ptr CreateHardwareD3D11Renderer(); diff --git a/src/core/gpu_hw.cpp b/src/core/gpu_hw.cpp index 564f09343..afb5bad0a 100644 --- a/src/core/gpu_hw.cpp +++ b/src/core/gpu_hw.cpp @@ -7,8 +7,8 @@ #include "pgxp.h" #include "settings.h" #include "system.h" -#include #include +#include #include Log_SetChannel(GPU_HW); @@ -38,18 +38,11 @@ bool GPU_HW::Initialize(HostDisplay* host_display) if (!GPU::Initialize(host_display)) return false; - m_resolution_scale = g_settings.gpu_resolution_scale; + m_resolution_scale = CalculateResolutionScale(); m_render_api = host_display->GetRenderAPI(); m_true_color = g_settings.gpu_true_color; m_scaled_dithering = g_settings.gpu_scaled_dithering; m_texture_filtering = g_settings.gpu_texture_filtering; - if (m_resolution_scale < 1 || m_resolution_scale > m_max_resolution_scale) - { - g_host_interface->AddFormattedOSDMessage(5.0f, "Invalid resolution scale %ux specified. Maximum is %u.", - m_resolution_scale, m_max_resolution_scale); - m_resolution_scale = std::clamp(m_resolution_scale, 1u, m_max_resolution_scale); - } - PrintSettingsToLog(); return true; } @@ -90,13 +83,35 @@ void GPU_HW::UpdateSettings() { GPU::UpdateSettings(); - m_resolution_scale = std::clamp(g_settings.gpu_resolution_scale, 1, m_max_resolution_scale); + m_resolution_scale = CalculateResolutionScale(); m_true_color = g_settings.gpu_true_color; m_scaled_dithering = g_settings.gpu_scaled_dithering; m_texture_filtering = g_settings.gpu_texture_filtering; PrintSettingsToLog(); } +u32 GPU_HW::CalculateResolutionScale() const +{ + if (g_settings.gpu_resolution_scale != 0) + return std::clamp(g_settings.gpu_resolution_scale, 1, m_max_resolution_scale); + + // auto scaling + const s32 height = (m_crtc_state.display_height != 0) ? static_cast(m_crtc_state.display_height) : 480; + const s32 preferred_scale = + static_cast(std::ceil(static_cast(m_host_display->GetWindowHeight()) / height)); + Log_InfoPrintf("Height = %d, preferred scale = %d", height, preferred_scale); + + return static_cast(std::clamp(preferred_scale, 1, m_max_resolution_scale)); +} + +void GPU_HW::UpdateResolutionScale() +{ + GPU::UpdateResolutionScale(); + + if (CalculateResolutionScale() != m_resolution_scale) + UpdateSettings(); +} + void GPU_HW::PrintSettingsToLog() { Log_InfoPrintf("Resolution Scale: %u (%ux%u), maximum %u", m_resolution_scale, VRAM_WIDTH * m_resolution_scale, diff --git a/src/core/gpu_hw.h b/src/core/gpu_hw.h index fdd750402..018342a7d 100644 --- a/src/core/gpu_hw.h +++ b/src/core/gpu_hw.h @@ -35,6 +35,7 @@ public: virtual void Reset() override; virtual bool DoState(StateWrapper& sw) override; virtual void UpdateSettings() override; + virtual void UpdateResolutionScale() override; protected: enum : u32 @@ -167,6 +168,8 @@ protected: virtual void UploadUniformBuffer(const void* uniforms, u32 uniforms_size) = 0; virtual void DrawBatchVertices(BatchRenderMode render_mode, u32 base_vertex, u32 num_vertices) = 0; + u32 CalculateResolutionScale() const; + void SetFullVRAMDirtyRectangle() { m_vram_dirty_rect.Set(0, 0, VRAM_WIDTH, VRAM_HEIGHT); diff --git a/src/duckstation-qt/qthostinterface.cpp b/src/duckstation-qt/qthostinterface.cpp index a4601fa0e..a8cc2d0db 100644 --- a/src/duckstation-qt/qthostinterface.cpp +++ b/src/duckstation-qt/qthostinterface.cpp @@ -425,7 +425,10 @@ void QtHostInterface::onHostDisplayWindowResized(int width, int height) // re-render the display, since otherwise it will be out of date and stretched if paused if (!System::IsShutdown()) + { + g_gpu->UpdateResolutionScale(); renderDisplay(); + } } void QtHostInterface::redrawDisplayWindow() @@ -538,7 +541,12 @@ void QtHostInterface::updateDisplayState() Panic("Failed to make device context current after updating"); connectDisplaySignals(display_widget); - redrawDisplayWindow(); + + if (!System::IsShutdown()) + { + g_gpu->UpdateResolutionScale(); + redrawDisplayWindow(); + } UpdateSpeedLimiterState(); } diff --git a/src/duckstation-sdl/sdl_host_interface.cpp b/src/duckstation-sdl/sdl_host_interface.cpp index ec2b9cd56..9d1d0177d 100644 --- a/src/duckstation-sdl/sdl_host_interface.cpp +++ b/src/duckstation-sdl/sdl_host_interface.cpp @@ -370,6 +370,10 @@ bool SDLHostInterface::SetFullscreen(bool enabled) int window_width, window_height; SDL_GetWindowSize(m_window, &window_width, &window_height); m_display->ResizeRenderWindow(window_width, window_height); + + if (!System::IsShutdown()) + g_gpu->UpdateResolutionScale(); + m_fullscreen = enabled; return true; } @@ -523,6 +527,9 @@ void SDLHostInterface::HandleSDLEvent(const SDL_Event* event) { m_display->ResizeRenderWindow(event->window.data1, event->window.data2); UpdateFramebufferScale(); + + if (!System::IsShutdown()) + g_gpu->UpdateResolutionScale(); } else if (event->window.event == SDL_WINDOWEVENT_MOVED) {