GPU/HW: Rewrite automatic internal resolution selection

Make it aspect ratio aware, as well as updating when/if the game changes
resolution. Also include the padding area in the OSD/status resolution.
This commit is contained in:
Stenzek 2024-09-20 20:08:01 +10:00
parent e056bcb5ff
commit b5df06a54a
No known key found for this signature in database
8 changed files with 71 additions and 56 deletions

View File

@ -125,9 +125,11 @@ void GPU::UpdateSettings(const Settings& old_settings)
m_console_is_pal = System::IsPALRegion(); m_console_is_pal = System::IsPALRegion();
UpdateCRTCConfig(); UpdateCRTCConfig();
} }
else if (g_settings.display_crop_mode != old_settings.display_crop_mode)
// Crop mode calls this, so recalculate the display area {
UpdateCRTCDisplayParameters(); // Crop mode calls this, so recalculate the display area
UpdateCRTCDisplayParameters();
}
if (g_settings.display_scaling != old_settings.display_scaling || if (g_settings.display_scaling != old_settings.display_scaling ||
g_settings.display_deinterlacing_mode != old_settings.display_deinterlacing_mode || g_settings.display_deinterlacing_mode != old_settings.display_deinterlacing_mode ||
@ -154,16 +156,16 @@ void GPU::CPUClockChanged()
UpdateCRTCConfig(); UpdateCRTCConfig();
} }
u32 GPU::GetResolutionScale() const
{
return 1u;
}
void GPU::UpdateResolutionScale() void GPU::UpdateResolutionScale()
{ {
} }
std::tuple<u32, u32> GPU::GetEffectiveDisplayResolution(bool scaled /* = true */) std::tuple<u32, u32> GPU::GetFullDisplayResolution() const
{
return std::tie(m_crtc_state.display_vram_width, m_crtc_state.display_vram_height);
}
std::tuple<u32, u32> GPU::GetFullDisplayResolution(bool scaled /* = true */)
{ {
return std::tie(m_crtc_state.display_width, m_crtc_state.display_height); return std::tie(m_crtc_state.display_width, m_crtc_state.display_height);
} }
@ -789,6 +791,8 @@ void GPU::UpdateCRTCDisplayParameters()
// won't be broken when displayed. // won't be broken when displayed.
const u8 y_shift = BoolToUInt8(m_GPUSTAT.vertical_interlace && m_GPUSTAT.vertical_resolution); const u8 y_shift = BoolToUInt8(m_GPUSTAT.vertical_interlace && m_GPUSTAT.vertical_resolution);
const u8 height_shift = m_force_progressive_scan ? y_shift : BoolToUInt8(m_GPUSTAT.vertical_interlace); const u8 height_shift = m_force_progressive_scan ? y_shift : BoolToUInt8(m_GPUSTAT.vertical_interlace);
const u16 old_vram_width = m_crtc_state.display_vram_width;
const u16 old_vram_height = m_crtc_state.display_vram_height;
// Determine screen size. // Determine screen size.
cs.display_width = (cs.horizontal_visible_end - cs.horizontal_visible_start) / cs.dot_clock_divider; cs.display_width = (cs.horizontal_visible_end - cs.horizontal_visible_start) / cs.dot_clock_divider;
@ -852,6 +856,9 @@ void GPU::UpdateCRTCDisplayParameters()
std::min(cs.vertical_visible_end, std::max(vertical_display_start, cs.vertical_visible_start))) std::min(cs.vertical_visible_end, std::max(vertical_display_start, cs.vertical_visible_start)))
<< height_shift; << height_shift;
} }
if (cs.display_vram_width != old_vram_width || cs.display_vram_height != old_vram_height)
UpdateResolutionScale();
} }
TickCount GPU::GetPendingCRTCTicks() const TickCount GPU::GetPendingCRTCTicks() const

View File

@ -165,14 +165,14 @@ public:
/// Recompile shaders/recreate framebuffers when needed. /// Recompile shaders/recreate framebuffers when needed.
virtual void UpdateSettings(const Settings& old_settings); virtual void UpdateSettings(const Settings& old_settings);
/// Returns the current resolution scale.
virtual u32 GetResolutionScale() const;
/// Updates the resolution scale when it's set to automatic. /// Updates the resolution scale when it's set to automatic.
virtual void UpdateResolutionScale(); virtual void UpdateResolutionScale();
/// Returns the effective display resolution of the GPU.
virtual std::tuple<u32, u32> GetEffectiveDisplayResolution(bool scaled = true);
/// Returns the full display resolution of the GPU, including padding. /// Returns the full display resolution of the GPU, including padding.
virtual std::tuple<u32, u32> GetFullDisplayResolution(bool scaled = true); std::tuple<u32, u32> GetFullDisplayResolution() const;
float ComputeHorizontalFrequency() const; float ComputeHorizontalFrequency() const;
float ComputeVerticalFrequency() const; float ComputeVerticalFrequency() const;

View File

@ -425,13 +425,11 @@ void GPU_HW::UpdateSettings(const Settings& old_settings)
if (m_resolution_scale != resolution_scale) if (m_resolution_scale != resolution_scale)
{ {
Host::AddIconOSDMessage( Host::AddIconOSDMessage("ResolutionScaleChanged", ICON_FA_PAINT_BRUSH,
"ResolutionScaleChanged", ICON_FA_PAINT_BRUSH, fmt::format(TRANSLATE_FS("GPU_HW", "Internal resolution set to {0}x ({1}x{2})."),
fmt::format(TRANSLATE_FS("GPU_HW", "Resolution scale set to {0}x (display {1}x{2}, VRAM {3}x{4})"), resolution_scale, m_crtc_state.display_width * resolution_scale,
resolution_scale, m_crtc_state.display_vram_width * resolution_scale, resolution_scale * m_crtc_state.display_height),
resolution_scale * m_crtc_state.display_vram_height, VRAM_WIDTH * resolution_scale, Host::OSD_INFO_DURATION);
VRAM_HEIGHT * resolution_scale),
Host::OSD_INFO_DURATION);
} }
if (m_multisamples != multisamples || g_settings.gpu_per_sample_shading != old_settings.gpu_per_sample_shading) if (m_multisamples != multisamples || g_settings.gpu_per_sample_shading != old_settings.gpu_per_sample_shading)
@ -635,26 +633,37 @@ void GPU_HW::CheckSettings()
u32 GPU_HW::CalculateResolutionScale() const u32 GPU_HW::CalculateResolutionScale() const
{ {
const u32 max_resolution_scale = GetMaxResolutionScale();
u32 scale; u32 scale;
if (g_settings.gpu_resolution_scale != 0) if (g_settings.gpu_resolution_scale != 0)
{ {
scale = std::clamp<u32>(g_settings.gpu_resolution_scale, 1, max_resolution_scale); scale = g_settings.gpu_resolution_scale;
} }
else else
{ {
// Auto scaling. When the system is starting and all borders crop is enabled, the registers are zero, and // Auto scaling.
// display_height therefore is also zero. Use the default size from the region in this case. if (m_crtc_state.display_width == 0 || m_crtc_state.display_height == 0 || m_crtc_state.display_vram_width == 0 ||
const s32 height = (m_crtc_state.display_height != 0) ? m_crtc_state.display_vram_height == 0 || m_GPUSTAT.display_disable)
static_cast<s32>(m_crtc_state.display_height) : {
(m_console_is_pal ? (PAL_VERTICAL_ACTIVE_END - PAL_VERTICAL_ACTIVE_START) : // When the system is starting and all borders crop is enabled, the registers are zero, and
(NTSC_VERTICAL_ACTIVE_END - NTSC_VERTICAL_ACTIVE_START)); // display_height therefore is also zero. Keep the existing resolution until it updates.
const s32 preferred_scale = scale = m_resolution_scale;
static_cast<s32>(std::ceil(static_cast<float>(g_gpu_device->GetWindowHeight()) / height)); }
VERBOSE_LOG("Height = {}, preferred scale = {}", height, preferred_scale); else
{
GSVector4i display_rect, draw_rect;
CalculateDrawRect(g_gpu_device->GetWindowWidth(), g_gpu_device->GetWindowHeight(), true, true, &display_rect,
&draw_rect);
scale = static_cast<u32>(std::clamp<s32>(preferred_scale, 1, max_resolution_scale)); // We use the draw rect to determine scaling. This way we match the resolution as best we can, regardless of the
// anamorphic aspect ratio.
const s32 draw_width = draw_rect.width();
const s32 draw_height = draw_rect.height();
scale = static_cast<u32>(
std::ceil(std::max(static_cast<float>(draw_width) / static_cast<float>(m_crtc_state.display_vram_width),
static_cast<float>(draw_height) / static_cast<float>(m_crtc_state.display_vram_height))));
VERBOSE_LOG("Draw Size = {}x{}, VRAM Size = {}x{}, Preferred Scale = {}", draw_width, draw_height,
m_crtc_state.display_vram_width, m_crtc_state.display_vram_height, scale);
}
} }
if (g_settings.gpu_downsample_mode == GPUDownsampleMode::Adaptive && scale > 1 && !Common::IsPow2(scale)) if (g_settings.gpu_downsample_mode == GPUDownsampleMode::Adaptive && scale > 1 && !Common::IsPow2(scale))
@ -675,13 +684,16 @@ u32 GPU_HW::CalculateResolutionScale() const
scale = new_scale; scale = new_scale;
} }
return scale; return std::clamp<u32>(scale, 1, GetMaxResolutionScale());
}
u32 GPU_HW::GetResolutionScale() const
{
return m_resolution_scale;
} }
void GPU_HW::UpdateResolutionScale() void GPU_HW::UpdateResolutionScale()
{ {
GPU::UpdateResolutionScale();
if (CalculateResolutionScale() != m_resolution_scale) if (CalculateResolutionScale() != m_resolution_scale)
UpdateSettings(g_settings); UpdateSettings(g_settings);
} }
@ -746,18 +758,6 @@ void GPU_HW::SetTexPageChangedOnOverlap(const GSVector4i update_rect)
} }
} }
std::tuple<u32, u32> GPU_HW::GetEffectiveDisplayResolution(bool scaled /* = true */)
{
const u32 scale = scaled ? m_resolution_scale : 1u;
return std::make_tuple(m_crtc_state.display_vram_width * scale, m_crtc_state.display_vram_height * scale);
}
std::tuple<u32, u32> GPU_HW::GetFullDisplayResolution(bool scaled /* = true */)
{
const u32 scale = scaled ? m_resolution_scale : 1u;
return std::make_tuple(m_crtc_state.display_width * scale, m_crtc_state.display_height * scale);
}
void GPU_HW::PrintSettingsToLog() void GPU_HW::PrintSettingsToLog()
{ {
INFO_LOG("Resolution Scale: {} ({}x{}), maximum {}", m_resolution_scale, VRAM_WIDTH * m_resolution_scale, INFO_LOG("Resolution Scale: {} ({}x{}), maximum {}", m_resolution_scale, VRAM_WIDTH * m_resolution_scale,

View File

@ -65,9 +65,9 @@ public:
void RestoreDeviceContext() override; void RestoreDeviceContext() override;
void UpdateSettings(const Settings& old_settings) override; void UpdateSettings(const Settings& old_settings) override;
void UpdateResolutionScale() override final;
std::tuple<u32, u32> GetEffectiveDisplayResolution(bool scaled = true) override; u32 GetResolutionScale() const override;
std::tuple<u32, u32> GetFullDisplayResolution(bool scaled = true) override; void UpdateResolutionScale() override;
void UpdateDisplay() override; void UpdateDisplay() override;

View File

@ -344,6 +344,7 @@ void Host::UpdateDisplayWindow()
const float f_height = static_cast<float>(g_gpu_device->GetWindowHeight()); const float f_height = static_cast<float>(g_gpu_device->GetWindowHeight());
ImGuiManager::WindowResized(f_width, f_height); ImGuiManager::WindowResized(f_width, f_height);
InputManager::SetDisplayWindowSize(f_width, f_height); InputManager::SetDisplayWindowSize(f_width, f_height);
System::HostDisplayResized();
if (System::IsValid()) if (System::IsValid())
{ {

View File

@ -291,12 +291,12 @@ void ImGuiManager::DrawPerformanceOverlay(float& position_y, float scale, float
if (g_settings.display_show_resolution) if (g_settings.display_show_resolution)
{ {
// TODO: this seems wrong? const u32 resolution_scale = g_gpu->GetResolutionScale();
const auto [effective_width, effective_height] = g_gpu->GetEffectiveDisplayResolution(); const auto [display_width, display_height] = g_gpu->GetFullDisplayResolution();
const bool interlaced = g_gpu->IsInterlacedDisplayEnabled(); const bool interlaced = g_gpu->IsInterlacedDisplayEnabled();
const bool pal = g_gpu->IsInPALMode(); const bool pal = g_gpu->IsInPALMode();
text.format("{}x{} {} {}", effective_width, effective_height, pal ? "PAL" : "NTSC", text.format("{}x{} {} {} [{}x]", display_width * resolution_scale, display_height * resolution_scale,
interlaced ? "Interlaced" : "Progressive"); pal ? "PAL" : "NTSC", interlaced ? "Interlaced" : "Progressive", resolution_scale);
DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255)); DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255));
} }

View File

@ -5718,6 +5718,7 @@ void System::ToggleSoftwareRendering()
Settings::GetRendererDisplayName(new_renderer)), Settings::GetRendererDisplayName(new_renderer)),
Host::OSD_QUICK_DURATION); Host::OSD_QUICK_DURATION);
RecreateGPU(new_renderer); RecreateGPU(new_renderer);
g_gpu->UpdateResolutionScale();
ResetPerformanceCounters(); ResetPerformanceCounters();
} }
@ -5753,6 +5754,7 @@ void System::HostDisplayResized()
if (g_settings.gpu_widescreen_hack && g_settings.display_aspect_ratio == DisplayAspectRatio::MatchWindow) if (g_settings.gpu_widescreen_hack && g_settings.display_aspect_ratio == DisplayAspectRatio::MatchWindow)
GTE::UpdateAspectRatio(); GTE::UpdateAspectRatio();
g_gpu->RestoreDeviceContext();
g_gpu->UpdateResolutionScale(); g_gpu->UpdateResolutionScale();
} }

View File

@ -2005,7 +2005,12 @@ void EmuThread::updatePerformanceCounters()
u32 render_height = 0; u32 render_height = 0;
if (g_gpu) if (g_gpu)
std::tie(render_width, render_height) = g_gpu->GetEffectiveDisplayResolution(); {
const u32 render_scale = g_gpu->GetResolutionScale();
std::tie(render_width, render_height) = g_gpu->GetFullDisplayResolution();
render_width *= render_scale;
render_height *= render_scale;
}
if (render_api != m_last_render_api || hardware_renderer != m_last_hardware_renderer) if (render_api != m_last_render_api || hardware_renderer != m_last_hardware_renderer)
{ {