GPU: Remove duplicate display params fields

And enable postfx when the DAC is turned off.
This commit is contained in:
Stenzek 2024-06-28 15:37:26 +10:00
parent e4cb359625
commit 810ce1ce57
No known key found for this signature in database
6 changed files with 203 additions and 255 deletions

View file

@ -578,7 +578,11 @@ float GPU::ComputeVerticalFrequency() const
float GPU::ComputeDisplayAspectRatio() const float GPU::ComputeDisplayAspectRatio() const
{ {
if (g_settings.display_force_4_3_for_24bit && m_GPUSTAT.display_area_color_depth_24) if (g_settings.debugging.show_vram)
{
return static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT);
}
else if (g_settings.display_force_4_3_for_24bit && m_GPUSTAT.display_area_color_depth_24)
{ {
return 4.0f / 3.0f; return 4.0f / 3.0f;
} }
@ -1916,36 +1920,14 @@ void GPU::SetDisplayTexture(GPUTexture* texture, s32 view_x, s32 view_y, s32 vie
m_display_texture_view_height = view_height; m_display_texture_view_height = view_height;
} }
void GPU::SetDisplayTextureRect(s32 view_x, s32 view_y, s32 view_width, s32 view_height)
{
m_display_texture_view_x = view_x;
m_display_texture_view_y = view_y;
m_display_texture_view_width = view_width;
m_display_texture_view_height = view_height;
}
void GPU::SetDisplayParameters(s32 display_width, s32 display_height, s32 active_left, s32 active_top, s32 active_width,
s32 active_height, float display_aspect_ratio)
{
m_display_width = display_width;
m_display_height = display_height;
m_display_active_left = active_left;
m_display_active_top = active_top;
m_display_active_width = active_width;
m_display_active_height = active_height;
m_display_aspect_ratio = display_aspect_ratio;
}
bool GPU::PresentDisplay() bool GPU::PresentDisplay()
{ {
FlushRender(); FlushRender();
if (!HasDisplayTexture())
return g_gpu_device->BeginPresent(false);
const Common::Rectangle<s32> draw_rect = const Common::Rectangle<s32> draw_rect =
CalculateDrawRect(g_gpu_device->GetWindowWidth(), g_gpu_device->GetWindowHeight()); m_display_texture ? CalculateDrawRect(g_gpu_device->GetWindowWidth(), g_gpu_device->GetWindowHeight()) :
return RenderDisplay(nullptr, draw_rect, true); Common::Rectangle<s32>();
return RenderDisplay(nullptr, draw_rect, !g_settings.debugging.show_vram);
} }
bool GPU::RenderDisplay(GPUTexture* target, const Common::Rectangle<s32>& draw_rect, bool postfx) bool GPU::RenderDisplay(GPUTexture* target, const Common::Rectangle<s32>& draw_rect, bool postfx)
@ -1956,53 +1938,12 @@ bool GPU::RenderDisplay(GPUTexture* target, const Common::Rectangle<s32>& draw_r
if (m_display_texture) if (m_display_texture)
m_display_texture->MakeReadyForSampling(); m_display_texture->MakeReadyForSampling();
bool texture_filter_linear = false;
struct Uniforms
{
float src_rect[4];
float src_size[4];
float clamp_rect[4];
float params[4];
} uniforms;
std::memset(uniforms.params, 0, sizeof(uniforms.params));
switch (g_settings.display_scaling)
{
case DisplayScalingMode::Nearest:
case DisplayScalingMode::NearestInteger:
break;
case DisplayScalingMode::BilinearSmooth:
case DisplayScalingMode::BlinearInteger:
texture_filter_linear = true;
break;
case DisplayScalingMode::BilinearSharp:
{
texture_filter_linear = true;
uniforms.params[0] = std::max(
std::floor(static_cast<float>(draw_rect.GetWidth()) / static_cast<float>(m_display_texture_view_width)), 1.0f);
uniforms.params[1] = std::max(
std::floor(static_cast<float>(draw_rect.GetHeight()) / static_cast<float>(m_display_texture_view_height)),
1.0f);
uniforms.params[2] = 0.5f - 0.5f / uniforms.params[0];
uniforms.params[3] = 0.5f - 0.5f / uniforms.params[1];
}
break;
default:
UnreachableCode();
break;
}
const GPUTexture::Format hdformat = target ? target->GetFormat() : g_gpu_device->GetWindowFormat(); const GPUTexture::Format hdformat = target ? target->GetFormat() : g_gpu_device->GetWindowFormat();
const u32 target_width = target ? target->GetWidth() : g_gpu_device->GetWindowWidth(); const u32 target_width = target ? target->GetWidth() : g_gpu_device->GetWindowWidth();
const u32 target_height = target ? target->GetHeight() : g_gpu_device->GetWindowHeight(); const u32 target_height = target ? target->GetHeight() : g_gpu_device->GetWindowHeight();
const bool really_postfx = const bool really_postfx = (postfx && PostProcessing::IsActive() && !g_gpu_device->GetWindowInfo().IsSurfaceless() &&
(postfx && HasDisplayTexture() && PostProcessing::IsActive() && !g_gpu_device->GetWindowInfo().IsSurfaceless() && hdformat != GPUTexture::Format::Unknown && target_width > 0 && target_height > 0 &&
hdformat != GPUTexture::Format::Unknown && target_width > 0 && target_height > 0 && PostProcessing::CheckTargets(hdformat, target_width, target_height));
PostProcessing::CheckTargets(hdformat, target_width, target_height));
const Common::Rectangle<s32> real_draw_rect = const Common::Rectangle<s32> real_draw_rect =
g_gpu_device->UsesLowerLeftOrigin() ? GPUDevice::FlipToLowerLeft(draw_rect, target_height) : draw_rect; g_gpu_device->UsesLowerLeftOrigin() ? GPUDevice::FlipToLowerLeft(draw_rect, target_height) : draw_rect;
if (really_postfx) if (really_postfx)
@ -2018,50 +1959,94 @@ bool GPU::RenderDisplay(GPUTexture* target, const Common::Rectangle<s32>& draw_r
return false; return false;
} }
if (!HasDisplayTexture()) if (m_display_texture)
return true; {
bool texture_filter_linear = false;
g_gpu_device->SetPipeline(m_display_pipeline.get()); struct Uniforms
g_gpu_device->SetTextureSampler( {
0, m_display_texture, texture_filter_linear ? g_gpu_device->GetLinearSampler() : g_gpu_device->GetNearestSampler()); float src_rect[4];
float src_size[4];
float clamp_rect[4];
float params[4];
} uniforms;
std::memset(uniforms.params, 0, sizeof(uniforms.params));
// For bilinear, clamp to 0.5/SIZE-0.5 to avoid bleeding from the adjacent texels in VRAM. This is because switch (g_settings.display_scaling)
// 1.0 in UV space is not the bottom-right texel, but a mix of the bottom-right and wrapped/next texel. {
const float rcp_width = 1.0f / static_cast<float>(m_display_texture->GetWidth()); case DisplayScalingMode::Nearest:
const float rcp_height = 1.0f / static_cast<float>(m_display_texture->GetHeight()); case DisplayScalingMode::NearestInteger:
uniforms.src_rect[0] = static_cast<float>(m_display_texture_view_x) * rcp_width; break;
uniforms.src_rect[1] = static_cast<float>(m_display_texture_view_y) * rcp_height;
uniforms.src_rect[2] = static_cast<float>(m_display_texture_view_width) * rcp_width;
uniforms.src_rect[3] = static_cast<float>(m_display_texture_view_height) * rcp_height;
uniforms.clamp_rect[0] = (static_cast<float>(m_display_texture_view_x) + 0.5f) * rcp_width;
uniforms.clamp_rect[1] = (static_cast<float>(m_display_texture_view_y) + 0.5f) * rcp_height;
uniforms.clamp_rect[2] =
(static_cast<float>(m_display_texture_view_x + m_display_texture_view_width) - 0.5f) * rcp_width;
uniforms.clamp_rect[3] =
(static_cast<float>(m_display_texture_view_y + m_display_texture_view_height) - 0.5f) * rcp_height;
uniforms.src_size[0] = static_cast<float>(m_display_texture->GetWidth());
uniforms.src_size[1] = static_cast<float>(m_display_texture->GetHeight());
uniforms.src_size[2] = rcp_width;
uniforms.src_size[3] = rcp_height;
g_gpu_device->PushUniformBuffer(&uniforms, sizeof(uniforms));
g_gpu_device->SetViewportAndScissor(real_draw_rect.left, real_draw_rect.top, real_draw_rect.GetWidth(), case DisplayScalingMode::BilinearSmooth:
real_draw_rect.GetHeight()); case DisplayScalingMode::BlinearInteger:
g_gpu_device->Draw(3, 0); texture_filter_linear = true;
break;
case DisplayScalingMode::BilinearSharp:
{
texture_filter_linear = true;
uniforms.params[0] = std::max(
std::floor(static_cast<float>(draw_rect.GetWidth()) / static_cast<float>(m_display_texture_view_width)),
1.0f);
uniforms.params[1] = std::max(
std::floor(static_cast<float>(draw_rect.GetHeight()) / static_cast<float>(m_display_texture_view_height)),
1.0f);
uniforms.params[2] = 0.5f - 0.5f / uniforms.params[0];
uniforms.params[3] = 0.5f - 0.5f / uniforms.params[1];
}
break;
default:
UnreachableCode();
break;
}
g_gpu_device->SetPipeline(m_display_pipeline.get());
g_gpu_device->SetTextureSampler(0, m_display_texture,
texture_filter_linear ? g_gpu_device->GetLinearSampler() :
g_gpu_device->GetNearestSampler());
// For bilinear, clamp to 0.5/SIZE-0.5 to avoid bleeding from the adjacent texels in VRAM. This is because
// 1.0 in UV space is not the bottom-right texel, but a mix of the bottom-right and wrapped/next texel.
const float rcp_width = 1.0f / static_cast<float>(m_display_texture->GetWidth());
const float rcp_height = 1.0f / static_cast<float>(m_display_texture->GetHeight());
uniforms.src_rect[0] = static_cast<float>(m_display_texture_view_x) * rcp_width;
uniforms.src_rect[1] = static_cast<float>(m_display_texture_view_y) * rcp_height;
uniforms.src_rect[2] = static_cast<float>(m_display_texture_view_width) * rcp_width;
uniforms.src_rect[3] = static_cast<float>(m_display_texture_view_height) * rcp_height;
uniforms.clamp_rect[0] = (static_cast<float>(m_display_texture_view_x) + 0.5f) * rcp_width;
uniforms.clamp_rect[1] = (static_cast<float>(m_display_texture_view_y) + 0.5f) * rcp_height;
uniforms.clamp_rect[2] =
(static_cast<float>(m_display_texture_view_x + m_display_texture_view_width) - 0.5f) * rcp_width;
uniforms.clamp_rect[3] =
(static_cast<float>(m_display_texture_view_y + m_display_texture_view_height) - 0.5f) * rcp_height;
uniforms.src_size[0] = static_cast<float>(m_display_texture->GetWidth());
uniforms.src_size[1] = static_cast<float>(m_display_texture->GetHeight());
uniforms.src_size[2] = rcp_width;
uniforms.src_size[3] = rcp_height;
g_gpu_device->PushUniformBuffer(&uniforms, sizeof(uniforms));
g_gpu_device->SetViewportAndScissor(real_draw_rect.left, real_draw_rect.top, real_draw_rect.GetWidth(),
real_draw_rect.GetHeight());
g_gpu_device->Draw(3, 0);
}
if (really_postfx) if (really_postfx)
{ {
DebugAssert(!g_settings.debugging.show_vram);
// "original size" in postfx includes padding. // "original size" in postfx includes padding.
const float upscale_x = const float upscale_x =
static_cast<float>(m_display_texture_view_width) / static_cast<float>(m_display_active_width); static_cast<float>(m_display_texture_view_width) / static_cast<float>(m_crtc_state.display_vram_width);
const float upscale_y = const float upscale_y =
static_cast<float>(m_display_texture_view_height) / static_cast<float>(m_display_active_height); static_cast<float>(m_display_texture_view_height) / static_cast<float>(m_crtc_state.display_vram_height);
const s32 orig_width = static_cast<s32>(std::ceil(m_display_width * upscale_x)); const s32 orig_width = static_cast<s32>(std::ceil(static_cast<float>(m_crtc_state.display_width) * upscale_x));
const s32 orig_height = static_cast<s32>(std::ceil(m_display_height * upscale_y)); const s32 orig_height = static_cast<s32>(std::ceil(static_cast<float>(m_crtc_state.display_height) * upscale_y));
return PostProcessing::Apply(target, real_draw_rect.left, real_draw_rect.top, real_draw_rect.GetWidth(), return PostProcessing::Apply(target, real_draw_rect.left, real_draw_rect.top, real_draw_rect.GetWidth(),
real_draw_rect.GetHeight(), orig_width, orig_height, m_display_width, real_draw_rect.GetHeight(), orig_width, orig_height, m_crtc_state.display_width,
m_display_height); m_crtc_state.display_height);
} }
else else
{ {
@ -2077,17 +2062,20 @@ void GPU::DestroyDeinterlaceTextures()
m_current_deinterlace_buffer = 0; m_current_deinterlace_buffer = 0;
} }
bool GPU::Deinterlace(GPUTexture* src, u32 x, u32 y, u32 width, u32 height, u32 field, u32 line_skip) bool GPU::Deinterlace(u32 field, u32 line_skip)
{ {
GPUTexture* src = m_display_texture;
const u32 x = m_display_texture_view_x;
const u32 y = m_display_texture_view_y;
const u32 width = m_display_texture_view_width;
const u32 height = m_display_texture_view_height;
switch (g_settings.display_deinterlacing_mode) switch (g_settings.display_deinterlacing_mode)
{ {
case DisplayDeinterlacingMode::Disabled: case DisplayDeinterlacingMode::Disabled:
{ {
if (line_skip == 0) if (line_skip == 0)
{
SetDisplayTexture(src, x, y, width, height);
return true; return true;
}
// Still have to extract the field. // Still have to extract the field.
if (!DeinterlaceExtractField(0, src, x, y, width, height, line_skip)) [[unlikely]] if (!DeinterlaceExtractField(0, src, x, y, width, height, line_skip)) [[unlikely]]
@ -2257,8 +2245,12 @@ bool GPU::DeinterlaceSetTargetSize(u32 width, u32 height, bool preserve)
return true; return true;
} }
bool GPU::ApplyChromaSmoothing(GPUTexture* src, u32 x, u32 y, u32 width, u32 height) bool GPU::ApplyChromaSmoothing()
{ {
const u32 x = m_display_texture_view_x;
const u32 y = m_display_texture_view_y;
const u32 width = m_display_texture_view_width;
const u32 height = m_display_texture_view_height;
if (!m_chroma_smoothing_texture || m_chroma_smoothing_texture->GetWidth() != width || if (!m_chroma_smoothing_texture || m_chroma_smoothing_texture->GetWidth() != width ||
m_chroma_smoothing_texture->GetHeight() != height) m_chroma_smoothing_texture->GetHeight() != height)
{ {
@ -2274,11 +2266,11 @@ bool GPU::ApplyChromaSmoothing(GPUTexture* src, u32 x, u32 y, u32 width, u32 hei
GL_SCOPE_FMT("ApplyChromaSmoothing({{{},{}}}, {}x{})", x, y, width, height); GL_SCOPE_FMT("ApplyChromaSmoothing({{{},{}}}, {}x{})", x, y, width, height);
src->MakeReadyForSampling(); m_display_texture->MakeReadyForSampling();
g_gpu_device->InvalidateRenderTarget(m_chroma_smoothing_texture.get()); g_gpu_device->InvalidateRenderTarget(m_chroma_smoothing_texture.get());
g_gpu_device->SetRenderTarget(m_chroma_smoothing_texture.get()); g_gpu_device->SetRenderTarget(m_chroma_smoothing_texture.get());
g_gpu_device->SetPipeline(m_chroma_smoothing_pipeline.get()); g_gpu_device->SetPipeline(m_chroma_smoothing_pipeline.get());
g_gpu_device->SetTextureSampler(0, src, g_gpu_device->GetNearestSampler()); g_gpu_device->SetTextureSampler(0, m_display_texture, g_gpu_device->GetNearestSampler());
const u32 uniforms[] = {x, y, width - 1, height - 1}; const u32 uniforms[] = {x, y, width - 1, height - 1};
g_gpu_device->PushUniformBuffer(uniforms, sizeof(uniforms)); g_gpu_device->PushUniformBuffer(uniforms, sizeof(uniforms));
g_gpu_device->SetViewportAndScissor(0, 0, width, height); g_gpu_device->SetViewportAndScissor(0, 0, width, height);
@ -2289,68 +2281,70 @@ bool GPU::ApplyChromaSmoothing(GPUTexture* src, u32 x, u32 y, u32 width, u32 hei
return true; return true;
} }
Common::Rectangle<float> GPU::CalculateDrawRect(s32 window_width, s32 window_height, float* out_left_padding, Common::Rectangle<s32> GPU::CalculateDrawRect(s32 window_width, s32 window_height,
float* out_top_padding, float* out_scale, float* out_x_scale, bool apply_aspect_ratio /* = true */) const
bool apply_aspect_ratio /* = true */) const
{ {
const bool integer_scale = (g_settings.display_scaling == DisplayScalingMode::NearestInteger || const bool integer_scale = (g_settings.display_scaling == DisplayScalingMode::NearestInteger ||
g_settings.display_scaling == DisplayScalingMode::BlinearInteger); g_settings.display_scaling == DisplayScalingMode::BlinearInteger);
const bool show_vram = g_settings.debugging.show_vram;
const float display_aspect_ratio = ComputeDisplayAspectRatio();
const float window_ratio = static_cast<float>(window_width) / static_cast<float>(window_height); const float window_ratio = static_cast<float>(window_width) / static_cast<float>(window_height);
const float crtc_display_width = static_cast<float>(show_vram ? VRAM_WIDTH : m_crtc_state.display_width);
const float crtc_display_height = static_cast<float>(show_vram ? VRAM_HEIGHT : m_crtc_state.display_height);
const float x_scale = const float x_scale =
apply_aspect_ratio ? apply_aspect_ratio ?
(m_display_aspect_ratio / (static_cast<float>(m_display_width) / static_cast<float>(m_display_height))) : (display_aspect_ratio / (static_cast<float>(crtc_display_width) / static_cast<float>(crtc_display_height))) :
1.0f; 1.0f;
const float display_width = g_settings.display_stretch_vertically ? static_cast<float>(m_display_width) : float display_width = crtc_display_width;
static_cast<float>(m_display_width) * x_scale; float display_height = crtc_display_height;
const float display_height = g_settings.display_stretch_vertically ? static_cast<float>(m_display_height) / x_scale : float active_left = static_cast<float>(show_vram ? 0 : m_crtc_state.display_origin_left);
static_cast<float>(m_display_height); float active_top = static_cast<float>(show_vram ? 0 : m_crtc_state.display_origin_top);
const float active_left = g_settings.display_stretch_vertically ? static_cast<float>(m_display_active_left) : float active_width = static_cast<float>(show_vram ? VRAM_WIDTH : m_crtc_state.display_vram_width);
static_cast<float>(m_display_active_left) * x_scale; float active_height = static_cast<float>(show_vram ? VRAM_HEIGHT : m_crtc_state.display_vram_height);
const float active_top = g_settings.display_stretch_vertically ? static_cast<float>(m_display_active_top) / x_scale : if (!g_settings.display_stretch_vertically)
static_cast<float>(m_display_active_top); {
const float active_width = g_settings.display_stretch_vertically ? display_width *= x_scale;
static_cast<float>(m_display_active_width) : active_left *= x_scale;
static_cast<float>(m_display_active_width) * x_scale; active_width *= x_scale;
const float active_height = g_settings.display_stretch_vertically ? }
static_cast<float>(m_display_active_height) / x_scale : else
static_cast<float>(m_display_active_height); {
if (out_x_scale) display_height /= x_scale;
*out_x_scale = x_scale; active_top /= x_scale;
active_height /= x_scale;
}
// now fit it within the window // now fit it within the window
float scale; float scale;
float left_padding, top_padding;
if ((display_width / display_height) >= window_ratio) if ((display_width / display_height) >= window_ratio)
{ {
// align in middle vertically // align in middle vertically
scale = static_cast<float>(window_width) / display_width; scale = static_cast<float>(window_width) / display_width;
if (integer_scale) if (integer_scale)
{
scale = std::max(std::floor(scale), 1.0f); scale = std::max(std::floor(scale), 1.0f);
left_padding = std::max<float>((static_cast<float>(window_width) - display_width * scale) / 2.0f, 0.0f);
if (out_left_padding)
{
if (integer_scale)
*out_left_padding = std::max<float>((static_cast<float>(window_width) - display_width * scale) / 2.0f, 0.0f);
else
*out_left_padding = 0.0f;
} }
if (out_top_padding) else
{ {
switch (g_settings.display_alignment) left_padding = 0.0f;
{ }
case DisplayAlignment::RightOrBottom:
*out_top_padding = std::max<float>(static_cast<float>(window_height) - (display_height * scale), 0.0f);
break;
case DisplayAlignment::Center: switch (g_settings.display_alignment)
*out_top_padding = {
std::max<float>((static_cast<float>(window_height) - (display_height * scale)) / 2.0f, 0.0f); case DisplayAlignment::RightOrBottom:
break; top_padding = std::max<float>(static_cast<float>(window_height) - (display_height * scale), 0.0f);
break;
case DisplayAlignment::LeftOrTop: case DisplayAlignment::Center:
default: top_padding = std::max<float>((static_cast<float>(window_height) - (display_height * scale)) / 2.0f, 0.0f);
*out_top_padding = 0.0f; break;
break;
} case DisplayAlignment::LeftOrTop:
default:
top_padding = 0.0f;
break;
} }
} }
else else
@ -2358,55 +2352,36 @@ Common::Rectangle<float> GPU::CalculateDrawRect(s32 window_width, s32 window_hei
// align in middle horizontally // align in middle horizontally
scale = static_cast<float>(window_height) / display_height; scale = static_cast<float>(window_height) / display_height;
if (integer_scale) if (integer_scale)
scale = std::max(std::floor(scale), 1.0f);
if (out_left_padding)
{ {
switch (g_settings.display_alignment) scale = std::max(std::floor(scale), 1.0f);
{ top_padding = std::max<float>((static_cast<float>(window_height) - (display_height * scale)) / 2.0f, 0.0f);
case DisplayAlignment::RightOrBottom: }
*out_left_padding = std::max<float>(static_cast<float>(window_width) - (display_width * scale), 0.0f); else
break; {
top_padding = 0.0f;
case DisplayAlignment::Center:
*out_left_padding =
std::max<float>((static_cast<float>(window_width) - (display_width * scale)) / 2.0f, 0.0f);
break;
case DisplayAlignment::LeftOrTop:
default:
*out_left_padding = 0.0f;
break;
}
} }
if (out_top_padding) switch (g_settings.display_alignment)
{ {
if (integer_scale) case DisplayAlignment::RightOrBottom:
*out_top_padding = std::max<float>((static_cast<float>(window_height) - (display_height * scale)) / 2.0f, 0.0f); left_padding = std::max<float>(static_cast<float>(window_width) - (display_width * scale), 0.0f);
else break;
*out_top_padding = 0.0f;
case DisplayAlignment::Center:
left_padding = std::max<float>((static_cast<float>(window_width) - (display_width * scale)) / 2.0f, 0.0f);
break;
case DisplayAlignment::LeftOrTop:
default:
left_padding = 0.0f;
break;
} }
} }
if (out_scale)
*out_scale = scale;
return Common::Rectangle<float>::FromExtents(active_left * scale, active_top * scale, active_width * scale,
active_height * scale);
}
Common::Rectangle<s32> GPU::CalculateDrawRect(s32 window_width, s32 window_height,
bool apply_aspect_ratio /* = true */) const
{
float left_padding, top_padding;
const Common::Rectangle<float> draw_rc =
CalculateDrawRect(window_width, window_height, &left_padding, &top_padding, nullptr, nullptr, apply_aspect_ratio);
// TODO: This should be a float rectangle. But because GL is lame, it only has integer viewports... // TODO: This should be a float rectangle. But because GL is lame, it only has integer viewports...
return Common::Rectangle<s32>::FromExtents( return Common::Rectangle<s32>::FromExtents(
static_cast<s32>(draw_rc.left + left_padding), static_cast<s32>(draw_rc.top + top_padding), static_cast<s32>(active_left * scale + left_padding), static_cast<s32>(active_top * scale + top_padding),
static_cast<s32>(draw_rc.GetWidth()), static_cast<s32>(draw_rc.GetHeight())); static_cast<s32>(active_width * scale), static_cast<s32>(active_height * scale));
} }
bool CompressAndWriteTextureToFile(u32 width, u32 height, std::string filename, FileSystem::ManagedCFilePtr fp, bool CompressAndWriteTextureToFile(u32 width, u32 height, std::string filename, FileSystem::ManagedCFilePtr fp,
@ -2632,7 +2607,7 @@ bool GPU::RenderScreenshotToFile(std::string filename, DisplayScreenshotMode mod
u32 height = g_gpu_device->GetWindowHeight(); u32 height = g_gpu_device->GetWindowHeight();
Common::Rectangle<s32> draw_rect = CalculateDrawRect(width, height); Common::Rectangle<s32> draw_rect = CalculateDrawRect(width, height);
const bool internal_resolution = (mode != DisplayScreenshotMode::ScreenResolution); const bool internal_resolution = (mode != DisplayScreenshotMode::ScreenResolution || g_settings.debugging.show_vram);
if (internal_resolution && m_display_texture_view_width != 0 && m_display_texture_view_height != 0) if (internal_resolution && m_display_texture_view_width != 0 && m_display_texture_view_height != 0)
{ {
if (mode == DisplayScreenshotMode::InternalResolution) if (mode == DisplayScreenshotMode::InternalResolution)

View file

@ -194,7 +194,9 @@ public:
// Returns the video clock frequency. // Returns the video clock frequency.
TickCount GetCRTCFrequency() const; TickCount GetCRTCFrequency() const;
u16 GetCRTCDotClockDivider() const { return m_crtc_state.dot_clock_divider; } ALWAYS_INLINE u16 GetCRTCDotClockDivider() const { return m_crtc_state.dot_clock_divider; }
ALWAYS_INLINE s32 GetCRTCDisplayWidth() const { return m_crtc_state.display_width; }
ALWAYS_INLINE s32 GetCRTCDisplayHeight() const { return m_crtc_state.display_height; }
// Dumps raw VRAM to a file. // Dumps raw VRAM to a file.
bool DumpVRAMToFile(const char* filename); bool DumpVRAMToFile(const char* filename);
@ -202,12 +204,6 @@ public:
// Ensures all buffered vertices are drawn. // Ensures all buffered vertices are drawn.
virtual void FlushRender() = 0; virtual void FlushRender() = 0;
ALWAYS_INLINE const void* GetDisplayTextureHandle() const { return m_display_texture; }
ALWAYS_INLINE s32 GetDisplayWidth() const { return m_display_width; }
ALWAYS_INLINE s32 GetDisplayHeight() const { return m_display_height; }
ALWAYS_INLINE float GetDisplayAspectRatio() const { return m_display_aspect_ratio; }
ALWAYS_INLINE bool HasDisplayTexture() const { return static_cast<bool>(m_display_texture); }
/// Helper function for computing the draw rectangle in a larger window. /// Helper function for computing the draw rectangle in a larger window.
Common::Rectangle<s32> CalculateDrawRect(s32 window_width, s32 window_height, bool apply_aspect_ratio = true) const; Common::Rectangle<s32> CalculateDrawRect(s32 window_width, s32 window_height, bool apply_aspect_ratio = true) const;
@ -607,29 +603,14 @@ protected:
void ClearDisplayTexture(); void ClearDisplayTexture();
void SetDisplayTexture(GPUTexture* texture, s32 view_x, s32 view_y, s32 view_width, s32 view_height); void SetDisplayTexture(GPUTexture* texture, s32 view_x, s32 view_y, s32 view_width, s32 view_height);
void SetDisplayTextureRect(s32 view_x, s32 view_y, s32 view_width, s32 view_height);
void SetDisplayParameters(s32 display_width, s32 display_height, s32 active_left, s32 active_top, s32 active_width,
s32 active_height, float display_aspect_ratio);
Common::Rectangle<float> CalculateDrawRect(s32 window_width, s32 window_height, float* out_left_padding,
float* out_top_padding, float* out_scale, float* out_x_scale,
bool apply_aspect_ratio = true) const;
bool RenderDisplay(GPUTexture* target, const Common::Rectangle<s32>& draw_rect, bool postfx); bool RenderDisplay(GPUTexture* target, const Common::Rectangle<s32>& draw_rect, bool postfx);
bool Deinterlace(GPUTexture* src, u32 x, u32 y, u32 width, u32 height, u32 field, u32 line_skip); bool Deinterlace(u32 field, u32 line_skip);
bool DeinterlaceExtractField(u32 dst_bufidx, GPUTexture* src, u32 x, u32 y, u32 width, u32 height, u32 line_skip); bool DeinterlaceExtractField(u32 dst_bufidx, GPUTexture* src, u32 x, u32 y, u32 width, u32 height, u32 line_skip);
bool DeinterlaceSetTargetSize(u32 width, u32 height, bool preserve); bool DeinterlaceSetTargetSize(u32 width, u32 height, bool preserve);
void DestroyDeinterlaceTextures(); void DestroyDeinterlaceTextures();
bool ApplyChromaSmoothing(GPUTexture* src, u32 x, u32 y, u32 width, u32 height); bool ApplyChromaSmoothing();
s32 m_display_width = 0;
s32 m_display_height = 0;
s32 m_display_active_left = 0;
s32 m_display_active_top = 0;
s32 m_display_active_width = 0;
s32 m_display_active_height = 0;
float m_display_aspect_ratio = 1.0f;
u32 m_current_deinterlace_buffer = 0; u32 m_current_deinterlace_buffer = 0;
std::unique_ptr<GPUPipeline> m_deinterlace_pipeline; std::unique_ptr<GPUPipeline> m_deinterlace_pipeline;

View file

@ -3289,15 +3289,9 @@ void GPU_HW::UpdateDisplay()
SetDisplayTexture(m_vram_texture.get(), 0, 0, m_vram_texture->GetWidth(), m_vram_texture->GetHeight()); SetDisplayTexture(m_vram_texture.get(), 0, 0, m_vram_texture->GetWidth(), m_vram_texture->GetHeight());
} }
SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH, VRAM_HEIGHT,
static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT));
return; return;
} }
SetDisplayParameters(m_crtc_state.display_width, m_crtc_state.display_height, m_crtc_state.display_origin_left,
m_crtc_state.display_origin_top, m_crtc_state.display_vram_width,
m_crtc_state.display_vram_height, ComputeDisplayAspectRatio());
const bool interlaced = IsInterlacedDisplayEnabled(); const bool interlaced = IsInterlacedDisplayEnabled();
const u32 interlaced_field = GetInterlacedDisplayField(); const u32 interlaced_field = GetInterlacedDisplayField();
const u32 resolution_scale = m_GPUSTAT.display_area_color_depth_24 ? 1 : m_resolution_scale; const u32 resolution_scale = m_GPUSTAT.display_area_color_depth_24 ? 1 : m_resolution_scale;
@ -3319,19 +3313,19 @@ void GPU_HW::UpdateDisplay()
(scaled_vram_offset_x + scaled_display_width) <= m_vram_texture->GetWidth() && (scaled_vram_offset_x + scaled_display_width) <= m_vram_texture->GetWidth() &&
(scaled_vram_offset_y + scaled_display_height) <= m_vram_texture->GetHeight()) (scaled_vram_offset_y + scaled_display_height) <= m_vram_texture->GetHeight())
{ {
SetDisplayTexture(m_vram_texture.get(), scaled_vram_offset_x, scaled_vram_offset_y, scaled_display_width,
read_height);
// Fast path if no copies are needed. // Fast path if no copies are needed.
if (interlaced) if (interlaced)
{ {
GL_INS("Deinterlace fast path"); GL_INS("Deinterlace fast path");
drew_anything = true; drew_anything = true;
Deinterlace(m_vram_texture.get(), scaled_vram_offset_x, scaled_vram_offset_y, scaled_display_width, read_height, Deinterlace(interlaced_field, line_skip);
interlaced_field, line_skip);
} }
else else
{ {
GL_INS("Direct display"); GL_INS("Direct display");
SetDisplayTexture(m_vram_texture.get(), scaled_vram_offset_x, scaled_vram_offset_y, scaled_display_width,
scaled_display_height);
} }
} }
else else
@ -3365,28 +3359,26 @@ void GPU_HW::UpdateDisplay()
m_vram_extract_texture->MakeReadyForSampling(); m_vram_extract_texture->MakeReadyForSampling();
drew_anything = true; drew_anything = true;
SetDisplayTexture(m_vram_extract_texture.get(), 0, 0, scaled_display_width, read_height);
if (g_settings.gpu_24bit_chroma_smoothing) if (g_settings.gpu_24bit_chroma_smoothing)
{ {
if (ApplyChromaSmoothing(m_vram_extract_texture.get(), 0, 0, scaled_display_width, read_height)) if (ApplyChromaSmoothing())
{ {
if (interlaced) if (interlaced)
Deinterlace(m_display_texture, 0, 0, scaled_display_width, read_height, interlaced_field, 0); Deinterlace(interlaced_field, 0);
} }
} }
else else
{ {
if (interlaced) if (interlaced)
Deinterlace(m_vram_extract_texture.get(), 0, 0, scaled_display_width, read_height, interlaced_field, 0); Deinterlace(interlaced_field, 0);
else
SetDisplayTexture(m_vram_extract_texture.get(), 0, 0, scaled_display_width, read_height);
} }
} }
if (m_downsample_mode != GPUDownsampleMode::Disabled && !m_GPUSTAT.display_area_color_depth_24) if (m_downsample_mode != GPUDownsampleMode::Disabled && !m_GPUSTAT.display_area_color_depth_24)
{ {
DebugAssert(m_display_texture); DebugAssert(m_display_texture);
DownsampleFramebuffer(m_display_texture, m_display_texture_view_x, m_display_texture_view_y, DownsampleFramebuffer();
m_display_texture_view_width, m_display_texture_view_height);
} }
if (drew_anything) if (drew_anything)
@ -3418,8 +3410,14 @@ void GPU_HW::UpdateDownsamplingLevels()
g_gpu_device->RecycleTexture(std::move(m_downsample_texture)); g_gpu_device->RecycleTexture(std::move(m_downsample_texture));
} }
void GPU_HW::DownsampleFramebuffer(GPUTexture* source, u32 left, u32 top, u32 width, u32 height) void GPU_HW::DownsampleFramebuffer()
{ {
GPUTexture* source = m_display_texture;
const u32 left = m_display_texture_view_x;
const u32 top = m_display_texture_view_y;
const u32 width = m_display_texture_view_width;
const u32 height = m_display_texture_view_height;
if (m_downsample_mode == GPUDownsampleMode::Adaptive) if (m_downsample_mode == GPUDownsampleMode::Adaptive)
DownsampleFramebufferAdaptive(source, left, top, width, height); DownsampleFramebufferAdaptive(source, left, top, width, height);
else else
@ -3453,7 +3451,6 @@ void GPU_HW::DownsampleFramebufferAdaptive(GPUTexture* source, u32 left, u32 top
if (!m_downsample_texture || !level_texture || !weight_texture) if (!m_downsample_texture || !level_texture || !weight_texture)
{ {
ERROR_LOG("Failed to create {}x{} RTs for adaptive downsampling", width, height); ERROR_LOG("Failed to create {}x{} RTs for adaptive downsampling", width, height);
SetDisplayTexture(source, left, top, width, height);
return; return;
} }
@ -3563,7 +3560,6 @@ void GPU_HW::DownsampleFramebufferBoxFilter(GPUTexture* source, u32 left, u32 to
if (!m_downsample_texture) if (!m_downsample_texture)
{ {
ERROR_LOG("Failed to create {}x{} RT for box downsampling", width, height); ERROR_LOG("Failed to create {}x{} RT for box downsampling", width, height);
SetDisplayTexture(source, left, top, width, height);
return; return;
} }

View file

@ -220,7 +220,8 @@ private:
void SetBatchSpriteMode(bool enabled); void SetBatchSpriteMode(bool enabled);
void UpdateDownsamplingLevels(); void UpdateDownsamplingLevels();
void DownsampleFramebuffer(GPUTexture* source, u32 left, u32 top, u32 width, u32 height);
void DownsampleFramebuffer();
void DownsampleFramebufferAdaptive(GPUTexture* source, u32 left, u32 top, u32 width, u32 height); void DownsampleFramebufferAdaptive(GPUTexture* source, u32 left, u32 top, u32 width, u32 height);
void DownsampleFramebufferBoxFilter(GPUTexture* source, u32 left, u32 top, u32 width, u32 height); void DownsampleFramebufferBoxFilter(GPUTexture* source, u32 left, u32 top, u32 width, u32 height);

View file

@ -465,10 +465,6 @@ void GPU_SW::UpdateDisplay()
if (!g_settings.debugging.show_vram) if (!g_settings.debugging.show_vram)
{ {
SetDisplayParameters(m_crtc_state.display_width, m_crtc_state.display_height, m_crtc_state.display_origin_left,
m_crtc_state.display_origin_top, m_crtc_state.display_vram_width,
m_crtc_state.display_vram_height, ComputeDisplayAspectRatio());
if (IsDisplayDisabled()) if (IsDisplayDisabled())
{ {
ClearDisplayTexture(); ClearDisplayTexture();
@ -490,14 +486,15 @@ void GPU_SW::UpdateDisplay()
const u32 line_skip = m_GPUSTAT.vertical_resolution; const u32 line_skip = m_GPUSTAT.vertical_resolution;
if (CopyOut(vram_offset_x, vram_offset_y, skip_x, read_width, read_height, line_skip, is_24bit)) if (CopyOut(vram_offset_x, vram_offset_y, skip_x, read_width, read_height, line_skip, is_24bit))
{ {
SetDisplayTexture(m_upload_texture.get(), 0, 0, read_width, read_height);
if (is_24bit && g_settings.gpu_24bit_chroma_smoothing) if (is_24bit && g_settings.gpu_24bit_chroma_smoothing)
{ {
if (ApplyChromaSmoothing(m_upload_texture.get(), 0, 0, read_width, read_height)) if (ApplyChromaSmoothing())
Deinterlace(m_display_texture, 0, 0, read_width, read_height, field, 0); Deinterlace(field, 0);
} }
else else
{ {
Deinterlace(m_upload_texture.get(), 0, 0, read_width, read_height, field, 0); Deinterlace(field, 0);
} }
} }
} }
@ -505,17 +502,14 @@ void GPU_SW::UpdateDisplay()
{ {
if (CopyOut(vram_offset_x, vram_offset_y, skip_x, read_width, read_height, 0, is_24bit)) if (CopyOut(vram_offset_x, vram_offset_y, skip_x, read_width, read_height, 0, is_24bit))
{ {
SetDisplayTexture(m_upload_texture.get(), 0, 0, read_width, read_height);
if (is_24bit && g_settings.gpu_24bit_chroma_smoothing) if (is_24bit && g_settings.gpu_24bit_chroma_smoothing)
ApplyChromaSmoothing(m_upload_texture.get(), 0, 0, read_width, read_height); ApplyChromaSmoothing();
else
SetDisplayTexture(m_upload_texture.get(), 0, 0, read_width, read_height);
} }
} }
} }
else else
{ {
SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH, VRAM_HEIGHT,
static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT));
if (CopyOut(0, 0, 0, VRAM_WIDTH, VRAM_HEIGHT, 0, false)) if (CopyOut(0, 0, 0, VRAM_WIDTH, VRAM_HEIGHT, 0, false))
SetDisplayTexture(m_upload_texture.get(), 0, 0, VRAM_WIDTH, VRAM_HEIGHT); SetDisplayTexture(m_upload_texture.get(), 0, 0, VRAM_WIDTH, VRAM_HEIGHT);
} }

View file

@ -2661,7 +2661,7 @@ bool System::SaveStateToStream(ByteStream* state, Error* error, u32 screenshot_s
if (screenshot_size > 0) if (screenshot_size > 0)
{ {
// assume this size is the width // assume this size is the width
const float display_aspect_ratio = g_gpu->GetDisplayAspectRatio(); const float display_aspect_ratio = g_gpu->ComputeDisplayAspectRatio();
const u32 screenshot_width = screenshot_size; const u32 screenshot_width = screenshot_size;
const u32 screenshot_height = const u32 screenshot_height =
std::max(1u, static_cast<u32>(static_cast<float>(screenshot_width) / std::max(1u, static_cast<u32>(static_cast<float>(screenshot_width) /
@ -5264,13 +5264,14 @@ void System::RequestDisplaySize(float scale /*= 0.0f*/)
if (scale == 0.0f) if (scale == 0.0f)
scale = g_gpu->IsHardwareRenderer() ? static_cast<float>(g_settings.gpu_resolution_scale) : 1.0f; scale = g_gpu->IsHardwareRenderer() ? static_cast<float>(g_settings.gpu_resolution_scale) : 1.0f;
const float y_scale = (static_cast<float>(g_gpu->GetDisplayWidth()) / static_cast<float>(g_gpu->GetDisplayHeight())) / const float y_scale =
g_gpu->GetDisplayAspectRatio(); (static_cast<float>(g_gpu->GetCRTCDisplayWidth()) / static_cast<float>(g_gpu->GetCRTCDisplayHeight())) /
g_gpu->ComputeDisplayAspectRatio();
const u32 requested_width = const u32 requested_width =
std::max<u32>(static_cast<u32>(std::ceil(static_cast<float>(g_gpu->GetDisplayWidth()) * scale)), 1); std::max<u32>(static_cast<u32>(std::ceil(static_cast<float>(g_gpu->GetCRTCDisplayWidth()) * scale)), 1);
const u32 requested_height = const u32 requested_height =
std::max<u32>(static_cast<u32>(std::ceil(static_cast<float>(g_gpu->GetDisplayHeight()) * y_scale * scale)), 1); std::max<u32>(static_cast<u32>(std::ceil(static_cast<float>(g_gpu->GetCRTCDisplayHeight()) * y_scale * scale)), 1);
Host::RequestResizeHostDisplay(static_cast<s32>(requested_width), static_cast<s32>(requested_height)); Host::RequestResizeHostDisplay(static_cast<s32>(requested_width), static_cast<s32>(requested_height));
} }