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:
parent
e056bcb5ff
commit
b5df06a54a
|
@ -125,9 +125,11 @@ void GPU::UpdateSettings(const Settings& old_settings)
|
|||
m_console_is_pal = System::IsPALRegion();
|
||||
UpdateCRTCConfig();
|
||||
}
|
||||
|
||||
// Crop mode calls this, so recalculate the display area
|
||||
UpdateCRTCDisplayParameters();
|
||||
else if (g_settings.display_crop_mode != old_settings.display_crop_mode)
|
||||
{
|
||||
// Crop mode calls this, so recalculate the display area
|
||||
UpdateCRTCDisplayParameters();
|
||||
}
|
||||
|
||||
if (g_settings.display_scaling != old_settings.display_scaling ||
|
||||
g_settings.display_deinterlacing_mode != old_settings.display_deinterlacing_mode ||
|
||||
|
@ -154,16 +156,16 @@ void GPU::CPUClockChanged()
|
|||
UpdateCRTCConfig();
|
||||
}
|
||||
|
||||
u32 GPU::GetResolutionScale() const
|
||||
{
|
||||
return 1u;
|
||||
}
|
||||
|
||||
void GPU::UpdateResolutionScale()
|
||||
{
|
||||
}
|
||||
|
||||
std::tuple<u32, u32> GPU::GetEffectiveDisplayResolution(bool scaled /* = true */)
|
||||
{
|
||||
return std::tie(m_crtc_state.display_vram_width, m_crtc_state.display_vram_height);
|
||||
}
|
||||
|
||||
std::tuple<u32, u32> GPU::GetFullDisplayResolution(bool scaled /* = true */)
|
||||
std::tuple<u32, u32> GPU::GetFullDisplayResolution() const
|
||||
{
|
||||
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.
|
||||
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 u16 old_vram_width = m_crtc_state.display_vram_width;
|
||||
const u16 old_vram_height = m_crtc_state.display_vram_height;
|
||||
|
||||
// Determine screen size.
|
||||
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)))
|
||||
<< height_shift;
|
||||
}
|
||||
|
||||
if (cs.display_vram_width != old_vram_width || cs.display_vram_height != old_vram_height)
|
||||
UpdateResolutionScale();
|
||||
}
|
||||
|
||||
TickCount GPU::GetPendingCRTCTicks() const
|
||||
|
|
|
@ -165,14 +165,14 @@ public:
|
|||
/// Recompile shaders/recreate framebuffers when needed.
|
||||
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.
|
||||
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.
|
||||
virtual std::tuple<u32, u32> GetFullDisplayResolution(bool scaled = true);
|
||||
std::tuple<u32, u32> GetFullDisplayResolution() const;
|
||||
|
||||
float ComputeHorizontalFrequency() const;
|
||||
float ComputeVerticalFrequency() const;
|
||||
|
|
|
@ -425,13 +425,11 @@ void GPU_HW::UpdateSettings(const Settings& old_settings)
|
|||
|
||||
if (m_resolution_scale != resolution_scale)
|
||||
{
|
||||
Host::AddIconOSDMessage(
|
||||
"ResolutionScaleChanged", ICON_FA_PAINT_BRUSH,
|
||||
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_vram_width * resolution_scale,
|
||||
resolution_scale * m_crtc_state.display_vram_height, VRAM_WIDTH * resolution_scale,
|
||||
VRAM_HEIGHT * resolution_scale),
|
||||
Host::OSD_INFO_DURATION);
|
||||
Host::AddIconOSDMessage("ResolutionScaleChanged", ICON_FA_PAINT_BRUSH,
|
||||
fmt::format(TRANSLATE_FS("GPU_HW", "Internal resolution set to {0}x ({1}x{2})."),
|
||||
resolution_scale, m_crtc_state.display_width * resolution_scale,
|
||||
resolution_scale * m_crtc_state.display_height),
|
||||
Host::OSD_INFO_DURATION);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
const u32 max_resolution_scale = GetMaxResolutionScale();
|
||||
|
||||
u32 scale;
|
||||
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
|
||||
{
|
||||
// Auto scaling. When the system is starting and all borders crop is enabled, the registers are zero, and
|
||||
// display_height therefore is also zero. Use the default size from the region in this case.
|
||||
const s32 height = (m_crtc_state.display_height != 0) ?
|
||||
static_cast<s32>(m_crtc_state.display_height) :
|
||||
(m_console_is_pal ? (PAL_VERTICAL_ACTIVE_END - PAL_VERTICAL_ACTIVE_START) :
|
||||
(NTSC_VERTICAL_ACTIVE_END - NTSC_VERTICAL_ACTIVE_START));
|
||||
const s32 preferred_scale =
|
||||
static_cast<s32>(std::ceil(static_cast<float>(g_gpu_device->GetWindowHeight()) / height));
|
||||
VERBOSE_LOG("Height = {}, preferred scale = {}", height, preferred_scale);
|
||||
// Auto scaling.
|
||||
if (m_crtc_state.display_width == 0 || m_crtc_state.display_height == 0 || m_crtc_state.display_vram_width == 0 ||
|
||||
m_crtc_state.display_vram_height == 0 || m_GPUSTAT.display_disable)
|
||||
{
|
||||
// When the system is starting and all borders crop is enabled, the registers are zero, and
|
||||
// display_height therefore is also zero. Keep the existing resolution until it updates.
|
||||
scale = m_resolution_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))
|
||||
|
@ -675,13 +684,16 @@ u32 GPU_HW::CalculateResolutionScale() const
|
|||
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()
|
||||
{
|
||||
GPU::UpdateResolutionScale();
|
||||
|
||||
if (CalculateResolutionScale() != m_resolution_scale)
|
||||
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()
|
||||
{
|
||||
INFO_LOG("Resolution Scale: {} ({}x{}), maximum {}", m_resolution_scale, VRAM_WIDTH * m_resolution_scale,
|
||||
|
|
|
@ -65,9 +65,9 @@ public:
|
|||
void RestoreDeviceContext() override;
|
||||
|
||||
void UpdateSettings(const Settings& old_settings) override;
|
||||
void UpdateResolutionScale() override final;
|
||||
std::tuple<u32, u32> GetEffectiveDisplayResolution(bool scaled = true) override;
|
||||
std::tuple<u32, u32> GetFullDisplayResolution(bool scaled = true) override;
|
||||
|
||||
u32 GetResolutionScale() const override;
|
||||
void UpdateResolutionScale() override;
|
||||
|
||||
void UpdateDisplay() override;
|
||||
|
||||
|
|
|
@ -344,6 +344,7 @@ void Host::UpdateDisplayWindow()
|
|||
const float f_height = static_cast<float>(g_gpu_device->GetWindowHeight());
|
||||
ImGuiManager::WindowResized(f_width, f_height);
|
||||
InputManager::SetDisplayWindowSize(f_width, f_height);
|
||||
System::HostDisplayResized();
|
||||
|
||||
if (System::IsValid())
|
||||
{
|
||||
|
|
|
@ -291,12 +291,12 @@ void ImGuiManager::DrawPerformanceOverlay(float& position_y, float scale, float
|
|||
|
||||
if (g_settings.display_show_resolution)
|
||||
{
|
||||
// TODO: this seems wrong?
|
||||
const auto [effective_width, effective_height] = g_gpu->GetEffectiveDisplayResolution();
|
||||
const u32 resolution_scale = g_gpu->GetResolutionScale();
|
||||
const auto [display_width, display_height] = g_gpu->GetFullDisplayResolution();
|
||||
const bool interlaced = g_gpu->IsInterlacedDisplayEnabled();
|
||||
const bool pal = g_gpu->IsInPALMode();
|
||||
text.format("{}x{} {} {}", effective_width, effective_height, pal ? "PAL" : "NTSC",
|
||||
interlaced ? "Interlaced" : "Progressive");
|
||||
text.format("{}x{} {} {} [{}x]", display_width * resolution_scale, display_height * resolution_scale,
|
||||
pal ? "PAL" : "NTSC", interlaced ? "Interlaced" : "Progressive", resolution_scale);
|
||||
DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255));
|
||||
}
|
||||
|
||||
|
|
|
@ -5718,6 +5718,7 @@ void System::ToggleSoftwareRendering()
|
|||
Settings::GetRendererDisplayName(new_renderer)),
|
||||
Host::OSD_QUICK_DURATION);
|
||||
RecreateGPU(new_renderer);
|
||||
g_gpu->UpdateResolutionScale();
|
||||
ResetPerformanceCounters();
|
||||
}
|
||||
|
||||
|
@ -5753,6 +5754,7 @@ void System::HostDisplayResized()
|
|||
if (g_settings.gpu_widescreen_hack && g_settings.display_aspect_ratio == DisplayAspectRatio::MatchWindow)
|
||||
GTE::UpdateAspectRatio();
|
||||
|
||||
g_gpu->RestoreDeviceContext();
|
||||
g_gpu->UpdateResolutionScale();
|
||||
}
|
||||
|
||||
|
|
|
@ -2005,7 +2005,12 @@ void EmuThread::updatePerformanceCounters()
|
|||
u32 render_height = 0;
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue