From 31478c6c1b841b9a820742830b136775fafe270f Mon Sep 17 00:00:00 2001
From: ameerj <52414509+ameerj@users.noreply.github.com>
Date: Wed, 6 Oct 2021 01:18:00 -0400
Subject: [PATCH] video_core: Misc resolution scaling related refactoring

---
 src/common/settings.cpp                       |  2 +-
 .../renderer_opengl/gl_rasterizer.cpp         |  4 +--
 .../renderer_opengl/gl_texture_cache.cpp      | 31 +++++++------------
 .../renderer_opengl/gl_texture_cache.h        | 11 ++++---
 .../renderer_vulkan/vk_state_tracker.h        | 10 +++---
 .../renderer_vulkan/vk_texture_cache.cpp      | 31 +++++++++++--------
 .../renderer_vulkan/vk_texture_cache.h        |  7 +++--
 src/video_core/texture_cache/texture_cache.h  |  2 --
 8 files changed, 51 insertions(+), 47 deletions(-)

diff --git a/src/common/settings.cpp b/src/common/settings.cpp
index f0686a7c50..12fdb0f9b6 100644
--- a/src/common/settings.cpp
+++ b/src/common/settings.cpp
@@ -107,7 +107,7 @@ float Volume() {
 }
 
 void UpdateRescalingInfo() {
-    auto setup = values.resolution_setup.GetValue();
+    const auto setup = values.resolution_setup.GetValue();
     auto& info = values.resolution_info;
     switch (setup) {
     case ResolutionSetup::Res1_2X:
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index d94f1e89f3..bb24a06565 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -554,7 +554,7 @@ void RasterizerOpenGL::SyncViewport() {
         }
         glFrontFace(mode);
     }
-    if (dirty_viewport || flags[Dirty::ClipControl]) {
+    if (dirty_viewport || dirty_clip_control) {
         flags[Dirty::ClipControl] = false;
 
         bool flip_y = false;
@@ -925,7 +925,7 @@ void RasterizerOpenGL::SyncScissorTest() {
     const auto& regs = maxwell3d.regs;
 
     const auto& resolution = Settings::values.resolution_info;
-    const auto scale_up = [&](u32 value) -> u32 {
+    const auto scale_up = [resolution](u32 value) -> u32 {
         if (value == 0) {
             return 0U;
         }
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp
index fafee62eec..c68a51ebbe 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp
@@ -405,7 +405,8 @@ ImageBufferMap::~ImageBufferMap() {
 
 TextureCacheRuntime::TextureCacheRuntime(const Device& device_, ProgramManager& program_manager,
                                          StateTracker& state_tracker_)
-    : device{device_}, state_tracker{state_tracker_}, util_shaders(program_manager) {
+    : device{device_}, state_tracker{state_tracker_},
+      util_shaders(program_manager), resolution{Settings::values.resolution_info} {
     static constexpr std::array TARGETS{GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_3D};
     for (size_t i = 0; i < TARGETS.size(); ++i) {
         const GLenum target = TARGETS[i];
@@ -473,7 +474,6 @@ TextureCacheRuntime::TextureCacheRuntime(const Device& device_, ProgramManager&
     set_view(Shader::TextureType::ColorArray2D, null_image_view_2d_array.handle);
     set_view(Shader::TextureType::ColorArrayCube, null_image_cube_array.handle);
 
-    resolution = Settings::values.resolution_info;
     if (resolution.active) {
         for (size_t i = 0; i < rescale_draw_fbos.size(); ++i) {
             rescale_draw_fbos[i].Create();
@@ -681,7 +681,7 @@ Image::Image(TextureCacheRuntime& runtime_, const VideoCommon::ImageInfo& info_,
         gl_type = tuple.type;
     }
     texture = MakeImage(info, gl_internal_format);
-    original_backup = texture.handle;
+    current_texture = texture.handle;
     if (runtime->device.HasDebuggingToolAttached()) {
         const std::string name = VideoCommon::Name(*this);
         glObjectLabel(ImageTarget(info) == GL_TEXTURE_BUFFER ? GL_BUFFER : GL_TEXTURE,
@@ -726,10 +726,6 @@ void Image::UploadMemory(const ImageBufferMap& map,
 void Image::DownloadMemory(ImageBufferMap& map,
                            std::span<const VideoCommon::BufferImageCopy> copies) {
     glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT); // TODO: Move this to its own API
-    const bool is_rescaled = True(flags & ImageFlagBits::Rescaled);
-    if (is_rescaled) {
-        ScaleDown();
-    }
     glBindBuffer(GL_PIXEL_PACK_BUFFER, map.buffer);
     glPixelStorei(GL_PACK_ALIGNMENT, 1);
 
@@ -747,9 +743,6 @@ void Image::DownloadMemory(ImageBufferMap& map,
         }
         CopyImageToBuffer(copy, map.offset);
     }
-    if (is_rescaled) {
-        texture.handle = upscaled_backup.handle;
-    }
 }
 
 GLuint Image::StorageHandle() noexcept {
@@ -775,11 +768,11 @@ GLuint Image::StorageHandle() noexcept {
             return store_view.handle;
         }
         store_view.Create();
-        glTextureView(store_view.handle, ImageTarget(info), texture.handle, GL_RGBA8, 0,
+        glTextureView(store_view.handle, ImageTarget(info), current_texture, GL_RGBA8, 0,
                       info.resources.levels, 0, info.resources.layers);
         return store_view.handle;
     default:
-        return texture.handle;
+        return current_texture;
     }
 }
 
@@ -940,10 +933,10 @@ bool Image::Scale() {
     const u32 original_width = info.size.width;
     const u32 original_height = info.size.height;
 
-    auto dst_info = info;
-    dst_info.size.width = scaled_width;
-    dst_info.size.height = scaled_height;
     if (!upscaled_backup.handle) {
+        auto dst_info = info;
+        dst_info.size.width = scaled_width;
+        dst_info.size.height = scaled_height;
         upscaled_backup = MakeImage(dst_info, gl_internal_format);
     }
     const GLuint read_fbo = runtime->rescale_read_fbos[fbo_index].handle;
@@ -955,14 +948,14 @@ bool Image::Scale() {
             const u32 dst_level_width = std::max(1u, scaled_width >> level);
             const u32 dst_level_height = std::max(1u, scaled_height >> level);
 
-            glNamedFramebufferTextureLayer(read_fbo, attachment, original_backup, level, layer);
+            glNamedFramebufferTextureLayer(read_fbo, attachment, texture.handle, level, layer);
             glNamedFramebufferTextureLayer(draw_fbo, attachment, upscaled_backup.handle, level,
                                            layer);
             glBlitNamedFramebuffer(read_fbo, draw_fbo, 0, 0, src_level_width, src_level_height, 0,
                                    0, dst_level_width, dst_level_height, mask, filter);
         }
     }
-    texture.handle = upscaled_backup.handle;
+    current_texture = upscaled_backup.handle;
     return true;
 }
 
@@ -993,7 +986,7 @@ bool Image::ScaleDown() {
         return false;
     }
     flags &= ~ImageFlagBits::Rescaled;
-    texture.handle = original_backup;
+    current_texture = texture.handle;
     return true;
 }
 
@@ -1010,7 +1003,7 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
     flat_range = info.range;
     set_object_label = device.HasDebuggingToolAttached();
     is_render_target = info.IsRenderTarget();
-    original_texture = image.texture.handle;
+    original_texture = image.Handle();
     num_samples = image.info.num_samples;
     if (!is_render_target) {
         swizzle[0] = info.x_source;
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h
index 61f9b02592..cf7f37a162 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.h
+++ b/src/video_core/renderer_opengl/gl_texture_cache.h
@@ -9,13 +9,16 @@
 
 #include <glad/glad.h>
 
-#include "common/settings.h"
 #include "shader_recompiler/shader_info.h"
 #include "video_core/renderer_opengl/gl_resource_manager.h"
 #include "video_core/renderer_opengl/util_shaders.h"
 #include "video_core/texture_cache/image_view_base.h"
 #include "video_core/texture_cache/texture_cache_base.h"
 
+namespace Settings {
+struct ResolutionScalingInfo;
+}
+
 namespace OpenGL {
 
 class Device;
@@ -155,7 +158,7 @@ private:
 
     std::array<OGLFramebuffer, 3> rescale_draw_fbos;
     std::array<OGLFramebuffer, 3> rescale_read_fbos;
-    Settings::ResolutionScalingInfo resolution;
+    const Settings::ResolutionScalingInfo& resolution;
 };
 
 class Image : public VideoCommon::ImageBase {
@@ -182,7 +185,7 @@ public:
     GLuint StorageHandle() noexcept;
 
     GLuint Handle() const noexcept {
-        return texture.handle;
+        return current_texture;
     }
 
     GLuint GlFormat() const noexcept {
@@ -211,7 +214,7 @@ private:
     GLenum gl_format = GL_NONE;
     GLenum gl_type = GL_NONE;
     TextureCacheRuntime* runtime{};
-    GLuint original_backup{};
+    GLuint current_texture{};
 };
 
 class ImageView : public VideoCommon::ImageViewBase {
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.h b/src/video_core/renderer_vulkan/vk_state_tracker.h
index ac2bbebe0a..40a1498325 100644
--- a/src/video_core/renderer_vulkan/vk_state_tracker.h
+++ b/src/video_core/renderer_vulkan/vk_state_tracker.h
@@ -71,13 +71,15 @@ public:
     }
 
     bool TouchViewports() {
-        return Exchange(Dirty::Viewports, false) ||
-               Exchange(VideoCommon::Dirty::RescaleViewports, false);
+        const bool dirty_viewports = Exchange(Dirty::Viewports, false);
+        const bool rescale_viewports = Exchange(VideoCommon::Dirty::RescaleViewports, false);
+        return dirty_viewports || rescale_viewports;
     }
 
     bool TouchScissors() {
-        return Exchange(Dirty::Scissors, false) ||
-               Exchange(VideoCommon::Dirty::RescaleScissors, false);
+        const bool dirty_scissors = Exchange(Dirty::Scissors, false);
+        const bool rescale_scissors = Exchange(VideoCommon::Dirty::RescaleScissors, false);
+        return dirty_scissors || rescale_scissors;
     }
 
     bool TouchDepthBias() {
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index 4f0bab2743..930c7d5698 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -125,8 +125,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
     }
 }
 
-[[nodiscard]] VkImageCreateInfo MakeImageCreateInfo(const Device& device, const ImageInfo& info,
-                                                    u32 up, u32 down) {
+[[nodiscard]] VkImageCreateInfo MakeImageCreateInfo(const Device& device, const ImageInfo& info) {
     const PixelFormat format = StorageFormat(info.format);
     const auto format_info = MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, false, format);
     VkImageCreateFlags flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
@@ -137,9 +136,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
     if (info.type == ImageType::e3D) {
         flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
     }
-    const auto scale_up = [&](u32 value) { return std::max<u32>((value * up) >> down, 1U); };
     const auto [samples_x, samples_y] = VideoCommon::SamplesLog2(info.num_samples);
-    const bool is_2d = info.type == ImageType::e2D;
     return VkImageCreateInfo{
         .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
         .pNext = nullptr,
@@ -147,8 +144,8 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
         .imageType = ConvertImageType(info.type),
         .format = format_info.format,
         .extent{
-            .width = scale_up(info.size.width) >> samples_x,
-            .height = (is_2d ? scale_up(info.size.height) : info.size.height) >> samples_y,
+            .width = info.size.width >> samples_x,
+            .height = info.size.height >> samples_y,
             .depth = info.size.depth,
         },
         .mipLevels = static_cast<u32>(info.resources.levels),
@@ -163,12 +160,11 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
     };
 }
 
-[[nodiscard]] vk::Image MakeImage(const Device& device, const ImageInfo& info, u32 up = 1,
-                                  u32 down = 0) {
+[[nodiscard]] vk::Image MakeImage(const Device& device, const ImageInfo& info) {
     if (info.type == ImageType::Buffer) {
         return vk::Image{};
     }
-    return device.GetLogical().CreateImage(MakeImageCreateInfo(device, info, up, down));
+    return device.GetLogical().CreateImage(MakeImageCreateInfo(device, info));
 }
 
 [[nodiscard]] VkImageAspectFlags ImageAspectMask(PixelFormat format) {
@@ -860,10 +856,9 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst
         cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
                                0, nullptr, nullptr, read_barriers);
         if (is_resolve) {
-            VkImageResolve resolve_info =
-                MakeImageResolve(dst_region, src_region, dst_layers, src_layers);
             cmdbuf.ResolveImage(src_image, VK_IMAGE_LAYOUT_GENERAL, dst_image,
-                                VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, resolve_info);
+                                VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                                MakeImageResolve(dst_region, src_region, dst_layers, src_layers));
         } else {
             const bool is_linear = filter == Fermi2D::Filter::Bilinear;
             const VkFilter vk_filter = is_linear ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
@@ -1143,7 +1138,17 @@ bool Image::ScaleUp() {
     }
     const auto& device = runtime->device;
     if (!scaled_image) {
-        scaled_image = MakeImage(device, info, resolution.up_scale, resolution.down_shift);
+        const u32 up = resolution.up_scale;
+        const u32 down = resolution.down_shift;
+        const auto scale = [&](u32 value) { return std::max<u32>((value * up) >> down, 1U); };
+
+        const bool is_2d = info.type == ImageType::e2D;
+        const u32 scaled_width = scale(info.size.width);
+        const u32 scaled_height = is_2d ? scale(info.size.height) : info.size.height;
+        auto scaled_info = info;
+        scaled_info.size.width = scaled_width;
+        scaled_info.size.height = scaled_height;
+        scaled_image = MakeImage(device, scaled_info);
         auto& allocator = runtime->memory_allocator;
         scaled_commit = MemoryCommit(allocator.Commit(scaled_image, MemoryUsage::DeviceLocal));
     }
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h
index e5060e3f17..5381343e91 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.h
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.h
@@ -6,7 +6,6 @@
 
 #include <span>
 
-#include "common/settings.h"
 #include "shader_recompiler/shader_info.h"
 #include "video_core/renderer_vulkan/vk_staging_buffer_pool.h"
 #include "video_core/texture_cache/image_view_base.h"
@@ -14,6 +13,10 @@
 #include "video_core/vulkan_common/vulkan_memory_allocator.h"
 #include "video_core/vulkan_common/vulkan_wrapper.h"
 
+namespace Settings {
+struct ResolutionScalingInfo;
+}
+
 namespace Vulkan {
 
 using VideoCommon::ImageId;
@@ -86,7 +89,7 @@ public:
     BlitImageHelper& blit_image_helper;
     ASTCDecoderPass& astc_decoder_pass;
     RenderPassCache& render_pass_cache;
-    Settings::ResolutionScalingInfo resolution;
+    const Settings::ResolutionScalingInfo& resolution;
 };
 
 class Image : public VideoCommon::ImageBase {
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index b708e41b58..630c73005e 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -1726,9 +1726,7 @@ void TextureCache<P>::CopyImage(ImageId dst_id, ImageId src_id, std::vector<Imag
         };
         for (auto& copy : copies) {
             copy.src_offset.x = scale_up(copy.src_offset.x);
-
             copy.dst_offset.x = scale_up(copy.dst_offset.x);
-
             copy.extent.width = scale_up(copy.extent.width);
             if (both_2d) {
                 copy.src_offset.y = scale_up(copy.src_offset.y);