From b2ca23e9da2ff173986e143dcdb0d2380e162ccc Mon Sep 17 00:00:00 2001 From: Stenzek Date: Tue, 6 Aug 2024 17:38:08 +1000 Subject: [PATCH] GPU: Use full display rect for postfx calculations --- src/core/gpu.cpp | 43 ++++++++++++++++++++++++++----------------- src/core/gpu.h | 15 ++++++++------- src/core/system.cpp | 19 +++++++++++-------- 3 files changed, 45 insertions(+), 32 deletions(-) diff --git a/src/core/gpu.cpp b/src/core/gpu.cpp index fbc1a3047..801651884 100644 --- a/src/core/gpu.cpp +++ b/src/core/gpu.cpp @@ -1095,12 +1095,14 @@ void GPU::UpdateCommandTickEvent() void GPU::ConvertScreenCoordinatesToDisplayCoordinates(float window_x, float window_y, float* display_x, float* display_y) const { - const GSVector4i draw_rc = - CalculateDrawRect(g_gpu_device->GetWindowWidth(), g_gpu_device->GetWindowHeight(), true, true); + GSVector4i display_rc, draw_rc; + CalculateDrawRect(g_gpu_device->GetWindowWidth(), g_gpu_device->GetWindowHeight(), true, true, &display_rc, &draw_rc); // convert coordinates to active display region, then to full display region - const float scaled_display_x = (window_x - static_cast(draw_rc.left)) / static_cast(draw_rc.width()); - const float scaled_display_y = (window_y - static_cast(draw_rc.top)) / static_cast(draw_rc.height()); + const float scaled_display_x = + (window_x - static_cast(display_rc.left)) / static_cast(display_rc.width()); + const float scaled_display_y = + (window_y - static_cast(display_rc.top)) / static_cast(display_rc.height()); // scale back to internal resolution *display_x = scaled_display_x * static_cast(m_crtc_state.display_width); @@ -1941,12 +1943,14 @@ bool GPU::PresentDisplay() { FlushRender(); - const GSVector4i draw_rect = CalculateDrawRect(g_gpu_device->GetWindowWidth(), g_gpu_device->GetWindowHeight(), - !g_settings.debugging.show_vram, true); - return RenderDisplay(nullptr, draw_rect, !g_settings.debugging.show_vram); + GSVector4i display_rect; + GSVector4i draw_rect; + CalculateDrawRect(g_gpu_device->GetWindowWidth(), g_gpu_device->GetWindowHeight(), !g_settings.debugging.show_vram, + true, &display_rect, &draw_rect); + return RenderDisplay(nullptr, display_rect, draw_rect, !g_settings.debugging.show_vram); } -bool GPU::RenderDisplay(GPUTexture* target, const GSVector4i draw_rect, bool postfx) +bool GPU::RenderDisplay(GPUTexture* target, const GSVector4i display_rect, const GSVector4i draw_rect, bool postfx) { GL_SCOPE_FMT("RenderDisplay: {}", draw_rect); @@ -2105,7 +2109,7 @@ bool GPU::RenderDisplay(GPUTexture* target, const GSVector4i draw_rect, bool pos const s32 orig_height = static_cast(std::ceil(static_cast(m_crtc_state.display_height) * upscale_y)); return PostProcessing::DisplayChain.Apply(PostProcessing::DisplayChain.GetInputTexture(), nullptr, target, - real_draw_rect, orig_width, orig_height, m_crtc_state.display_width, + display_rect, orig_width, orig_height, m_crtc_state.display_width, m_crtc_state.display_height); } else @@ -2339,8 +2343,8 @@ bool GPU::ApplyChromaSmoothing() return true; } -GSVector4i GPU::CalculateDrawRect(s32 window_width, s32 window_height, bool apply_rotation, - bool apply_aspect_ratio) const +void GPU::CalculateDrawRect(s32 window_width, s32 window_height, bool apply_rotation, bool apply_aspect_ratio, + GSVector4i* display_rect, GSVector4i* draw_rect) const { const bool integer_scale = (g_settings.display_scaling == DisplayScalingMode::NearestInteger || g_settings.display_scaling == DisplayScalingMode::BilinearInteger); @@ -2450,7 +2454,9 @@ GSVector4i GPU::CalculateDrawRect(s32 window_width, s32 window_height, bool appl const s32 top = static_cast(active_top * scale + top_padding); const s32 right = left + static_cast(active_width * scale); const s32 bottom = top + static_cast(active_height * scale); - return GSVector4i(left, top, right, bottom); + *draw_rect = GSVector4i(left, top, right, bottom); + *display_rect = GSVector4i( + GSVector4(left_padding, top_padding, left_padding + display_width * scale, top_padding + display_height * scale)); } bool CompressAndWriteTextureToFile(u32 width, u32 height, std::string filename, FileSystem::ManagedCFilePtr fp, @@ -2622,8 +2628,9 @@ bool GPU::WriteDisplayTextureToFile(std::string filename, bool compress_on_threa flip_y, std::move(texture_data), texture_data_stride, m_display_texture->GetFormat(), false, compress_on_thread); } -bool GPU::RenderScreenshotToBuffer(u32 width, u32 height, const GSVector4i draw_rect, bool postfx, - std::vector* out_pixels, u32* out_stride, GPUTexture::Format* out_format) +bool GPU::RenderScreenshotToBuffer(u32 width, u32 height, const GSVector4i display_rect, const GSVector4i draw_rect, + bool postfx, std::vector* out_pixels, u32* out_stride, + GPUTexture::Format* out_format) { const GPUTexture::Format hdformat = g_gpu_device->HasSurface() ? g_gpu_device->GetWindowFormat() : GPUTexture::Format::RGBA8; @@ -2636,7 +2643,7 @@ bool GPU::RenderScreenshotToBuffer(u32 width, u32 height, const GSVector4i draw_ g_gpu_device->ClearRenderTarget(render_texture.get(), GPUDevice::DEFAULT_CLEAR_COLOR); // TODO: this should use copy shader instead. - RenderDisplay(render_texture.get(), draw_rect, postfx); + RenderDisplay(render_texture.get(), display_rect, draw_rect, postfx); const u32 stride = Common::AlignUpPow2(GPUTexture::GetPixelSize(hdformat) * width, sizeof(u32)); out_pixels->resize((height * stride) / sizeof(u32)); @@ -2674,7 +2681,8 @@ bool GPU::RenderScreenshotToFile(std::string filename, DisplayScreenshotMode mod { u32 width = g_gpu_device->GetWindowWidth(); u32 height = g_gpu_device->GetWindowHeight(); - GSVector4i draw_rect = CalculateDrawRect(width, height, true, !g_settings.debugging.show_vram); + GSVector4i display_rect, draw_rect; + CalculateDrawRect(width, height, true, !g_settings.debugging.show_vram, &display_rect, &draw_rect); 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) @@ -2727,6 +2735,7 @@ bool GPU::RenderScreenshotToFile(std::string filename, DisplayScreenshotMode mod // Remove padding, it's not part of the framebuffer. draw_rect = GSVector4i(0, 0, static_cast(width), static_cast(height)); + display_rect = draw_rect; } if (width == 0 || height == 0) return false; @@ -2734,7 +2743,7 @@ bool GPU::RenderScreenshotToFile(std::string filename, DisplayScreenshotMode mod std::vector pixels; u32 pixels_stride; GPUTexture::Format pixels_format; - if (!RenderScreenshotToBuffer(width, height, draw_rect, !internal_resolution, &pixels, &pixels_stride, + if (!RenderScreenshotToBuffer(width, height, display_rect, draw_rect, !internal_resolution, &pixels, &pixels_stride, &pixels_format)) { ERROR_LOG("Failed to render {}x{} screenshot", width, height); diff --git a/src/core/gpu.h b/src/core/gpu.h index b15163524..a08ec1b90 100644 --- a/src/core/gpu.h +++ b/src/core/gpu.h @@ -4,8 +4,8 @@ #pragma once #include "gpu_types.h" #include "timers.h" -#include "types.h" #include "timing_event.h" +#include "types.h" #include "util/gpu_texture.h" @@ -207,14 +207,16 @@ public: virtual void FlushRender() = 0; /// Helper function for computing the draw rectangle in a larger window. - GSVector4i CalculateDrawRect(s32 window_width, s32 window_height, bool apply_rotation, bool apply_aspect_ratio) const; + void CalculateDrawRect(s32 window_width, s32 window_height, bool apply_rotation, bool apply_aspect_ratio, + GSVector4i* display_rect, GSVector4i* draw_rect) const; /// Helper function to save current display texture to PNG. bool WriteDisplayTextureToFile(std::string filename, bool compress_on_thread = false); /// Renders the display, optionally with postprocessing to the specified image. - bool RenderScreenshotToBuffer(u32 width, u32 height, const GSVector4i draw_rect, bool postfx, - std::vector* out_pixels, u32* out_stride, GPUTexture::Format* out_format); + bool RenderScreenshotToBuffer(u32 width, u32 height, const GSVector4i display_rect, const GSVector4i draw_rect, + bool postfx, std::vector* out_pixels, u32* out_stride, + GPUTexture::Format* out_format); /// Helper function to save screenshot to PNG. bool RenderScreenshotToFile(std::string filename, DisplayScreenshotMode mode, u8 quality, bool compress_on_thread, @@ -343,8 +345,7 @@ protected: AddCommandTicks(pixels); } - ALWAYS_INLINE_RELEASE void AddDrawRectangleTicks(const GSVector4i clamped_rect, bool textured, - bool semitransparent) + ALWAYS_INLINE_RELEASE void AddDrawRectangleTicks(const GSVector4i clamped_rect, bool textured, bool semitransparent) { u32 drawn_width = clamped_rect.width(); u32 drawn_height = clamped_rect.height(); @@ -591,7 +592,7 @@ protected: void SetDisplayTexture(GPUTexture* texture, GPUTexture* depth_texture, s32 view_x, s32 view_y, s32 view_width, s32 view_height); - bool RenderDisplay(GPUTexture* target, const GSVector4i draw_rect, bool postfx); + bool RenderDisplay(GPUTexture* target, const GSVector4i display_rect, const GSVector4i draw_rect, bool postfx); 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); diff --git a/src/core/system.cpp b/src/core/system.cpp index f7ea10949..a6e1f14c8 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -2869,19 +2869,22 @@ bool System::SaveStateToBuffer(SaveStateBuffer* buffer, Error* error, u32 screen if (screenshot_size > 0) { // assume this size is the width - const float display_aspect_ratio = g_gpu->ComputeDisplayAspectRatio(); - const u32 screenshot_width = screenshot_size; - const u32 screenshot_height = - std::max(1u, static_cast(static_cast(screenshot_width) / - ((display_aspect_ratio > 0.0f) ? display_aspect_ratio : 1.0f))); + GSVector4i screenshot_display_rect, screenshot_draw_rect; + g_gpu->CalculateDrawRect(screenshot_size, screenshot_size, true, true, &screenshot_display_rect, + &screenshot_draw_rect); + + const u32 screenshot_width = static_cast(screenshot_display_rect.width()); + const u32 screenshot_height = static_cast(screenshot_display_rect.height()); + screenshot_draw_rect = screenshot_draw_rect.sub32(screenshot_display_rect.xyxy()); + screenshot_display_rect = screenshot_display_rect.sub32(screenshot_display_rect.xyxy()); VERBOSE_LOG("Saving {}x{} screenshot for state", screenshot_width, screenshot_height); std::vector screenshot_buffer; u32 screenshot_stride; GPUTexture::Format screenshot_format; - if (g_gpu->RenderScreenshotToBuffer(screenshot_width, screenshot_height, - GSVector4i(0, 0, screenshot_width, screenshot_height), false, - &screenshot_buffer, &screenshot_stride, &screenshot_format) && + if (g_gpu->RenderScreenshotToBuffer(screenshot_width, screenshot_height, screenshot_display_rect, + screenshot_draw_rect, false, &screenshot_buffer, &screenshot_stride, + &screenshot_format) && GPUTexture::ConvertTextureDataToRGBA8(screenshot_width, screenshot_height, screenshot_buffer, screenshot_stride, screenshot_format)) {