From a4a47392dd754b54a1f3653a2e2a0e8baf275739 Mon Sep 17 00:00:00 2001
From: ptyfyre <254117058+ptyfyre@users.noreply.github.com>
Date: Mon, 6 Apr 2026 11:32:38 +0200
Subject: [PATCH] video_core: Add fractional scaling support
---
.../features/settings/model/IntSetting.kt | 2 +-
src/android/app/src/main/jni/config.cpp | 6 ++
.../app/src/main/res/values/arrays.xml | 40 +++++++++----
.../app/src/main/res/values/strings.xml | 10 ++++
src/citra_libretro/core_settings.cpp | 34 +++++++----
.../emu_window/libretro_window.cpp | 4 +-
src/citra_qt/configuration/config.cpp | 18 ++++++
.../configuration/configure_enhancements.cpp | 38 +++++++++++--
.../configuration/configure_enhancements.ui | 56 ++++++++++++++++++-
src/common/settings.h | 2 +-
src/core/frontend/framebuffer_layout.cpp | 40 ++++++-------
.../rasterizer_cache/framebuffer_base.h | 50 ++++++++++-------
.../rasterizer_cache/rasterizer_cache.h | 10 ++--
.../rasterizer_cache/surface_params.cpp | 6 +-
.../rasterizer_cache/surface_params.h | 15 +++--
src/video_core/renderer_base.cpp | 6 +-
.../renderer_opengl/gl_blit_helper.cpp | 2 +-
.../renderer_opengl/gl_texture_runtime.cpp | 24 ++++----
.../renderer_opengl/gl_texture_runtime.h | 4 +-
.../renderer_opengl/renderer_opengl.cpp | 17 +++---
.../renderer_vulkan/renderer_vulkan.cpp | 16 +++---
.../renderer_vulkan/vk_blit_helper.cpp | 4 +-
.../renderer_vulkan/vk_texture_runtime.cpp | 20 +++----
.../renderer_vulkan/vk_texture_runtime.h | 6 +-
24 files changed, 294 insertions(+), 136 deletions(-)
diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/IntSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/IntSetting.kt
index 2c8cbf2a1..02d6a79ae 100644
--- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/IntSetting.kt
+++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/IntSetting.kt
@@ -18,7 +18,7 @@ enum class IntSetting(
CAMERA_OUTER_LEFT_FLIP(SettingKeys.camera_outer_left_flip(), Settings.SECTION_CAMERA, 0),
CAMERA_OUTER_RIGHT_FLIP(SettingKeys.camera_outer_right_flip(), Settings.SECTION_CAMERA, 0),
GRAPHICS_API(SettingKeys.graphics_api(), Settings.SECTION_RENDERER, 1),
- RESOLUTION_FACTOR(SettingKeys.resolution_factor(), Settings.SECTION_RENDERER, 1),
+ RESOLUTION_FACTOR(SettingKeys.resolution_factor(), Settings.SECTION_RENDERER, 100),
STEREOSCOPIC_3D_MODE(SettingKeys.render_3d(), Settings.SECTION_RENDERER, 2),
STEREOSCOPIC_3D_DEPTH(SettingKeys.factor_3d(), Settings.SECTION_RENDERER, 0),
STEPS_PER_HOUR(SettingKeys.steps_per_hour(), Settings.SECTION_SYSTEM, 0),
diff --git a/src/android/app/src/main/jni/config.cpp b/src/android/app/src/main/jni/config.cpp
index e0fa260c5..83c024934 100644
--- a/src/android/app/src/main/jni/config.cpp
+++ b/src/android/app/src/main/jni/config.cpp
@@ -150,6 +150,12 @@ void Config::ReadValues() {
ReadSetting("Renderer", Settings::values.use_hw_shader);
ReadSetting("Renderer", Settings::values.use_shader_jit);
ReadSetting("Renderer", Settings::values.resolution_factor);
+ {
+ const u32 rf = Settings::values.resolution_factor.GetValue();
+ if (rf >= 1 && rf <= 10) {
+ Settings::values.resolution_factor.SetValue(rf * 100);
+ }
+ }
ReadSetting("Renderer", Settings::values.use_disk_shader_cache);
ReadSetting("Renderer", Settings::values.use_vsync);
ReadSetting("Renderer", Settings::values.texture_filter);
diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml
index 2a08cd546..b694b307d 100644
--- a/src/android/app/src/main/res/values/arrays.xml
+++ b/src/android/app/src/main/res/values/arrays.xml
@@ -374,29 +374,49 @@
- @string/internal_resolution_setting_auto
+ - @string/internal_resolution_setting_0_5x
- @string/internal_resolution_setting_1x
+ - @string/internal_resolution_setting_1_5x
- @string/internal_resolution_setting_2x
+ - @string/internal_resolution_setting_2_5x
- @string/internal_resolution_setting_3x
+ - @string/internal_resolution_setting_3_5x
- @string/internal_resolution_setting_4x
+ - @string/internal_resolution_setting_4_5x
- @string/internal_resolution_setting_5x
+ - @string/internal_resolution_setting_5_5x
- @string/internal_resolution_setting_6x
+ - @string/internal_resolution_setting_6_5x
- @string/internal_resolution_setting_7x
+ - @string/internal_resolution_setting_7_5x
- @string/internal_resolution_setting_8x
+ - @string/internal_resolution_setting_8_5x
- @string/internal_resolution_setting_9x
+ - @string/internal_resolution_setting_9_5x
- @string/internal_resolution_setting_10x
- 0
- - 1
- - 2
- - 3
- - 4
- - 5
- - 6
- - 7
- - 8
- - 9
- - 10
+ - 50
+ - 100
+ - 150
+ - 200
+ - 250
+ - 300
+ - 350
+ - 400
+ - 450
+ - 500
+ - 550
+ - 600
+ - 650
+ - 700
+ - 750
+ - 800
+ - 850
+ - 900
+ - 950
+ - 1000
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml
index 750677fd5..b21c9583e 100644
--- a/src/android/app/src/main/res/values/strings.xml
+++ b/src/android/app/src/main/res/values/strings.xml
@@ -284,15 +284,25 @@
Internal Resolution
Specifies the resolution used to render at. A high resolution will improve visual quality a lot but is also quite heavy on performance and might cause glitches in certain applications.
Auto (Screen Size)
+ 0.5x Native (200x120)
Native (400x240)
+ 1.5x Native (600x360)
2x Native (800x480)
+ 2.5x Native (1000x600)
3x Native (1200x720)
+ 3.5x Native (1400x840)
4x Native (1600x960)
+ 4.5x Native (1800x1080)
5x Native (2000x1200)
+ 5.5x Native (2200x1320)
6x Native (2400x1440)
+ 6.5x Native (2600x1560)
7x Native (2800x1680)
+ 7.5x Native (3000x1800)
8x Native (3200x1920)
+ 8.5x Native (3400x2040)
9x Native (3600x2160)
+ 9.5x Native (3800x2280)
10x Native (4000x2400)
Turning off this setting will significantly reduce emulation performance! For the best experience, it is recommended that you leave this setting enabled.
Warning: Modifying these settings will slow emulation
diff --git a/src/citra_libretro/core_settings.cpp b/src/citra_libretro/core_settings.cpp
index 085f7ac52..f68001f4d 100644
--- a/src/citra_libretro/core_settings.cpp
+++ b/src/citra_libretro/core_settings.cpp
@@ -363,19 +363,29 @@ static constexpr retro_core_option_v2_definition option_definitions[] = {
nullptr,
config::category::graphics,
{
- { "1", "1x (Native 400x240)" },
- { "2", "2x (800x480)" },
- { "3", "3x (1200x720)" },
- { "4", "4x (1600x960)" },
- { "5", "5x (2000x1200)" },
- { "6", "6x (2400x1440)" },
- { "7", "7x (2800x1680)" },
- { "8", "8x (3200x1920)" },
- { "9", "9x (3600x2160)" },
- { "10", "10x (4000x2400)" },
+ { "50", "0.5x (200x120)" },
+ { "100", "1x Native (400x240)" },
+ { "150", "1.5x (600x360)" },
+ { "200", "2x (800x480)" },
+ { "250", "2.5x (1000x600)" },
+ { "300", "3x (1200x720)" },
+ { "350", "3.5x (1400x840)" },
+ { "400", "4x (1600x960)" },
+ { "450", "4.5x (1800x1080)" },
+ { "500", "5x (2000x1200)" },
+ { "550", "5.5x (2200x1320)" },
+ { "600", "6x (2400x1440)" },
+ { "650", "6.5x (2600x1560)" },
+ { "700", "7x (2800x1680)" },
+ { "750", "7.5x (3000x1800)" },
+ { "800", "8x (3200x1920)" },
+ { "850", "8.5x (3400x2040)" },
+ { "900", "9x (3600x2160)" },
+ { "950", "9.5x (3800x2280)" },
+ { "1000", "10x (4000x2400)" },
{ nullptr, nullptr }
},
- "1"
+ "100"
},
{
config::graphics::texture_filter,
@@ -922,7 +932,7 @@ static void ParseGraphicsOptions(void) {
LibRetro::FetchVariable(config::graphics::use_disk_shader_cache, config::enabled) ==
config::enabled;
- auto resolution = LibRetro::FetchVariable(config::graphics::resolution_factor, "1");
+ auto resolution = LibRetro::FetchVariable(config::graphics::resolution_factor, "100");
Settings::values.resolution_factor = std::stoi(resolution);
Settings::values.texture_filter =
diff --git a/src/citra_libretro/emu_window/libretro_window.cpp b/src/citra_libretro/emu_window/libretro_window.cpp
index 8e8532566..a4654fdfc 100644
--- a/src/citra_libretro/emu_window/libretro_window.cpp
+++ b/src/citra_libretro/emu_window/libretro_window.cpp
@@ -239,7 +239,7 @@ LayoutGeometry ComputeLayoutGeometry() {
unsigned baseY;
bool emulated_pointer = true;
- float scaling = Settings::values.resolution_factor.GetValue();
+ float scaling = Settings::values.resolution_factor.GetValue() / 100.0f;
bool swapped = Settings::values.swap_screen.GetValue();
switch (Settings::values.layout_option.GetValue()) {
@@ -264,7 +264,7 @@ LayoutGeometry ComputeLayoutGeometry() {
baseY = Core::kScreenTopHeight;
}
- if (scaling < 4) {
+ if (scaling < 4.0f) {
// Unfortunately, to get this aspect ratio correct (and have non-blurry 1x scaling),
// we have to have a pretty large buffer for the minimum ratio.
baseX *= 4;
diff --git a/src/citra_qt/configuration/config.cpp b/src/citra_qt/configuration/config.cpp
index a5aa9896b..80336812d 100644
--- a/src/citra_qt/configuration/config.cpp
+++ b/src/citra_qt/configuration/config.cpp
@@ -708,6 +708,14 @@ void QtConfig::ReadRendererValues() {
ReadGlobalSetting(Settings::values.use_vsync);
ReadGlobalSetting(Settings::values.use_display_refresh_rate_detection);
ReadGlobalSetting(Settings::values.resolution_factor);
+ {
+ const u32 rf = Settings::values.resolution_factor.GetValue();
+ if (rf >= 1 && rf <= 10) {
+ LOG_WARNING(Frontend, "Migrating old resolution factor value of {} to new value of {}",
+ rf, rf * 100);
+ Settings::values.resolution_factor.SetValue(rf * 100);
+ }
+ }
ReadGlobalSetting(Settings::values.use_integer_scaling);
ReadGlobalSetting(Settings::values.frame_limit);
ReadGlobalSetting(Settings::values.turbo_limit);
@@ -828,6 +836,16 @@ void QtConfig::ReadUIValues() {
ReadBasicSetting(UISettings::values.enable_discord_presence);
#endif
ReadBasicSetting(UISettings::values.screenshot_resolution_factor);
+ {
+ const u16 srf = UISettings::values.screenshot_resolution_factor.GetValue();
+ if (srf >= 1 && srf <= 10) {
+ LOG_WARNING(
+ Frontend,
+ "Migrating old screenshot resolution factor value of {} to new value of {}",
+ srf, srf * 100);
+ UISettings::values.screenshot_resolution_factor.SetValue(srf * 100);
+ }
+ }
ReadUILayoutValues();
ReadUIGameListValues();
diff --git a/src/citra_qt/configuration/configure_enhancements.cpp b/src/citra_qt/configuration/configure_enhancements.cpp
index 62afcbb77..8048c39cd 100644
--- a/src/citra_qt/configuration/configure_enhancements.cpp
+++ b/src/citra_qt/configuration/configure_enhancements.cpp
@@ -2,6 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include
+#include
#include
#include "citra_qt/configuration/configuration_shared.h"
#include "citra_qt/configuration/configure_enhancements.h"
@@ -11,6 +13,19 @@
#include "video_core/renderer_opengl/post_processing_opengl.h"
#endif
+static constexpr std::array RESOLUTION_FACTOR_VALUES = {
+ 0, 50, 100, 150, 200, 250, 300, 350, 400, 450, 500,
+ 550, 600, 650, 700, 750, 800, 850, 900, 950, 1000,
+};
+
+static int ResolutionFactorToIndex(u32 value) {
+ const auto it =
+ std::find(RESOLUTION_FACTOR_VALUES.begin(), RESOLUTION_FACTOR_VALUES.end(), value);
+ return (it != RESOLUTION_FACTOR_VALUES.end())
+ ? static_cast(std::distance(RESOLUTION_FACTOR_VALUES.begin(), it))
+ : 0;
+}
+
ConfigureEnhancements::ConfigureEnhancements(QWidget* parent)
: QWidget(parent), ui(std::make_unique()) {
ui->setupUi(this);
@@ -42,15 +57,20 @@ ConfigureEnhancements::~ConfigureEnhancements() = default;
void ConfigureEnhancements::SetConfiguration() {
if (!Settings::IsConfiguringGlobal()) {
- ConfigurationShared::SetPerGameSetting(ui->resolution_factor_combobox,
- &Settings::values.resolution_factor);
+ if (Settings::values.resolution_factor.UsingGlobal()) {
+ ui->resolution_factor_combobox->setCurrentIndex(ConfigurationShared::USE_GLOBAL_INDEX);
+ } else {
+ ui->resolution_factor_combobox->setCurrentIndex(
+ ResolutionFactorToIndex(Settings::values.resolution_factor.GetValue()) +
+ ConfigurationShared::USE_GLOBAL_OFFSET);
+ }
ConfigurationShared::SetPerGameSetting(ui->texture_filter_combobox,
&Settings::values.texture_filter);
ConfigurationShared::SetHighlight(ui->widget_texture_filter,
!Settings::values.texture_filter.UsingGlobal());
} else {
ui->resolution_factor_combobox->setCurrentIndex(
- Settings::values.resolution_factor.GetValue());
+ ResolutionFactorToIndex(Settings::values.resolution_factor.GetValue()));
ui->texture_filter_combobox->setCurrentIndex(
static_cast(Settings::values.texture_filter.GetValue()));
}
@@ -109,8 +129,13 @@ void ConfigureEnhancements::RetranslateUI() {
}
void ConfigureEnhancements::ApplyConfiguration() {
- ConfigurationShared::ApplyPerGameSetting(&Settings::values.resolution_factor,
- ui->resolution_factor_combobox);
+ ConfigurationShared::ApplyPerGameSetting(
+ &Settings::values.resolution_factor, ui->resolution_factor_combobox, [](s32 index) -> s32 {
+ if (index >= 0 && index < static_cast(RESOLUTION_FACTOR_VALUES.size())) {
+ return static_cast(RESOLUTION_FACTOR_VALUES[index]);
+ }
+ return 0;
+ });
Settings::values.render_3d =
static_cast(ui->render_3d_combobox->currentIndex());
Settings::values.swap_eyes_3d = ui->swap_eyes_3d->isChecked();
@@ -187,7 +212,8 @@ void ConfigureEnhancements::SetupPerGameUI() {
ConfigurationShared::SetColoredComboBox(
ui->resolution_factor_combobox, ui->widget_resolution,
- static_cast(Settings::values.resolution_factor.GetValue(true)));
+ ResolutionFactorToIndex(
+ static_cast(Settings::values.resolution_factor.GetValue(true))));
ConfigurationShared::SetColoredComboBox(
ui->texture_filter_combobox, ui->widget_texture_filter,
diff --git a/src/citra_qt/configuration/configure_enhancements.ui b/src/citra_qt/configuration/configure_enhancements.ui
index dc3c3deaf..27a790a95 100644
--- a/src/citra_qt/configuration/configure_enhancements.ui
+++ b/src/citra_qt/configuration/configure_enhancements.ui
@@ -51,13 +51,23 @@
-
-
-
- Auto (Window Size)
+
+ Auto (Window Size)
+
+
+ -
+
+ 0.5x Native (200x120)
+
+
+ -
+
+ Native (400x240)
-
- Native (400x240)
+ 1.5x Native (600x360)
-
@@ -65,41 +75,81 @@
2x Native (800x480)
+ -
+
+ 2.5x Native (1000x600)
+
+
-
3x Native (1200x720)
+ -
+
+ 3.5x Native (1400x840)
+
+
-
4x Native (1600x960)
+ -
+
+ 4.5x Native (1800x1080)
+
+
-
5x Native (2000x1200)
+ -
+
+ 5.5x Native (2200x1320)
+
+
-
6x Native (2400x1440)
+ -
+
+ 6.5x Native (2600x1560)
+
+
-
7x Native (2800x1680)
+ -
+
+ 7.5x Native (3000x1800)
+
+
-
8x Native (3200x1920)
+ -
+
+ 8.5x Native (3400x2040)
+
+
-
9x Native (3600x2160)
+ -
+
+ 9.5x Native (3800x2280)
+
+
-
10x Native (4000x2400)
diff --git a/src/common/settings.h b/src/common/settings.h
index 90922bcff..059a23ea6 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -529,7 +529,7 @@ struct Values {
SwitchableSetting use_display_refresh_rate_detection{
true, Keys::use_display_refresh_rate_detection};
Setting use_shader_jit{true, Keys::use_shader_jit};
- SwitchableSetting resolution_factor{1, 0, 10, Keys::resolution_factor};
+ SwitchableSetting resolution_factor{100, 0, 1000, Keys::resolution_factor};
SwitchableSetting use_integer_scaling{false, Keys::use_integer_scaling};
SwitchableSetting frame_limit{100, 0, 1000, Keys::frame_limit};
SwitchableSetting turbo_limit{200, 0, 1000, Keys::turbo_limit};
diff --git a/src/core/frontend/framebuffer_layout.cpp b/src/core/frontend/framebuffer_layout.cpp
index 918c1454f..3a36cd57d 100644
--- a/src/core/frontend/framebuffer_layout.cpp
+++ b/src/core/frontend/framebuffer_layout.cpp
@@ -375,7 +375,7 @@ FramebufferLayout CustomFrameLayout(u32 width, u32 height, bool is_swapped, bool
FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondary,
bool is_portrait) {
u32 width, height, gap;
- gap = (int)(Settings::values.screen_gap.GetValue()) * res_scale;
+ gap = (Settings::values.screen_gap.GetValue() * res_scale) / 100;
FramebufferLayout layout;
if (is_portrait) {
@@ -395,18 +395,18 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar
break;
case Settings::PortraitLayoutOption::PortraitTopFullWidth:
- width = Core::kScreenTopWidth * res_scale;
+ width = (Core::kScreenTopWidth * res_scale) / 100;
// clang-format off
- height = (static_cast(Core::kScreenTopHeight + Core::kScreenBottomHeight * 1.25) *
- res_scale) + gap;
+ height = (static_cast(Core::kScreenTopHeight + Core::kScreenBottomHeight * 1.25f) *
+ res_scale) / 100 + gap;
// clang-format on
layout =
PortraitTopFullFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
Settings::values.upright_screen.GetValue());
break;
case Settings::PortraitLayoutOption::PortraitOriginal:
- width = Core::kScreenTopWidth * res_scale;
- height = (Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale;
+ width = (Core::kScreenTopWidth * res_scale) / 100;
+ height = ((Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale) / 100;
layout = PortraitOriginalLayout(width, height, Settings::values.swap_screen.GetValue());
break;
}
@@ -428,11 +428,11 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar
case Settings::LayoutOption::SingleScreen: {
const bool swap_screens = is_secondary || Settings::values.swap_screen.GetValue();
if (swap_screens) {
- width = Core::kScreenBottomWidth * res_scale;
- height = Core::kScreenBottomHeight * res_scale;
+ width = (Core::kScreenBottomWidth * res_scale) / 100;
+ height = (Core::kScreenBottomHeight * res_scale) / 100;
} else {
- width = Core::kScreenTopWidth * res_scale;
- height = Core::kScreenTopHeight * res_scale;
+ width = (Core::kScreenTopWidth * res_scale) / 100;
+ height = (Core::kScreenTopHeight * res_scale) / 100;
}
if (Settings::values.upright_screen.GetValue()) {
std::swap(width, height);
@@ -459,11 +459,11 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar
Settings::values.small_screen_position.GetValue() ==
Settings::SmallScreenPosition::BelowLarge) {
// vertical, so height is sum of heights, width is larger of widths
- width = std::max(largeWidth, smallWidth) * res_scale;
- height = (largeHeight + smallHeight) * res_scale + gap;
+ width = (static_cast(std::max(largeWidth, smallWidth)) * res_scale) / 100;
+ height = ((largeHeight + smallHeight) * res_scale) / 100 + gap;
} else {
- width = (largeWidth + smallWidth) * res_scale + gap;
- height = std::max(largeHeight, smallHeight) * res_scale;
+ width = ((largeWidth + smallWidth) * res_scale) / 100 + gap;
+ height = (static_cast(std::max(largeHeight, smallHeight)) * res_scale) / 100;
}
if (Settings::values.upright_screen.GetValue()) {
@@ -476,8 +476,8 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar
break;
}
case Settings::LayoutOption::SideScreen:
- width = (Core::kScreenTopWidth + Core::kScreenBottomWidth) * res_scale + gap;
- height = Core::kScreenTopHeight * res_scale;
+ width = ((Core::kScreenTopWidth + Core::kScreenBottomWidth) * res_scale) / 100 + gap;
+ height = (Core::kScreenTopHeight * res_scale) / 100;
if (Settings::values.upright_screen.GetValue()) {
std::swap(width, height);
@@ -487,7 +487,7 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar
Settings::SmallScreenPosition::MiddleRight);
break;
case Settings::LayoutOption::HybridScreen:
- height = Core::kScreenTopHeight * res_scale;
+ height = (Core::kScreenTopHeight * res_scale) / 100;
if (Settings::values.swap_screen.GetValue()) {
width = Core::kScreenBottomWidth;
@@ -495,7 +495,7 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar
width = Core::kScreenTopWidth;
}
// 2.25f comes from HybridScreenLayout's scale_factor value.
- width = static_cast((width + (Core::kScreenTopWidth / 2.25f)) * res_scale);
+ width = static_cast((width + (Core::kScreenTopWidth / 2.25f)) * res_scale) / 100;
if (Settings::values.upright_screen.GetValue()) {
std::swap(width, height);
@@ -506,8 +506,8 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar
break;
case Settings::LayoutOption::Default:
default:
- width = Core::kScreenTopWidth * res_scale;
- height = (Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale + gap;
+ width = (Core::kScreenTopWidth * res_scale) / 100;
+ height = ((Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale) / 100 + gap;
if (Settings::values.upright_screen.GetValue()) {
std::swap(width, height);
diff --git a/src/video_core/rasterizer_cache/framebuffer_base.h b/src/video_core/rasterizer_cache/framebuffer_base.h
index 2f2545849..70cdd2474 100644
--- a/src/video_core/rasterizer_cache/framebuffer_base.h
+++ b/src/video_core/rasterizer_cache/framebuffer_base.h
@@ -69,7 +69,7 @@ public:
Common::Rectangle surfaces_rect)
: res_cache{res_cache_}, fb{fb_} {
const u32 res_scale = fb->Scale();
- const u32 height = surfaces_rect.GetHeight() / res_scale;
+ const u32 height = (surfaces_rect.GetHeight() * 100) / res_scale;
// Determine the draw rectangle (render area + scissor)
Common::Rectangle viewport_rect = regs.GetViewportRect();
@@ -77,45 +77,53 @@ public:
viewport_rect = viewport_rect.VerticalMirror(height);
}
- draw_rect.left =
- std::clamp(static_cast(surfaces_rect.left) + viewport_rect.left * res_scale,
- surfaces_rect.left, surfaces_rect.right);
- draw_rect.top =
- std::clamp(static_cast(surfaces_rect.bottom) + viewport_rect.top * res_scale,
- surfaces_rect.bottom, surfaces_rect.top);
- draw_rect.right =
- std::clamp(static_cast(surfaces_rect.left) + viewport_rect.right * res_scale,
- surfaces_rect.left, surfaces_rect.right);
+ draw_rect.left = std::clamp(static_cast(surfaces_rect.left) +
+ (viewport_rect.left * res_scale) / 100,
+ surfaces_rect.left, surfaces_rect.right);
+ draw_rect.top = std::clamp(static_cast(surfaces_rect.bottom) +
+ (viewport_rect.top * res_scale) / 100,
+ surfaces_rect.bottom, surfaces_rect.top);
+ draw_rect.right = std::clamp(static_cast(surfaces_rect.left) +
+ (viewport_rect.right * res_scale) / 100,
+ surfaces_rect.left, surfaces_rect.right);
draw_rect.bottom = std::clamp(static_cast(surfaces_rect.bottom) +
- viewport_rect.bottom * res_scale,
+ (viewport_rect.bottom * res_scale) / 100,
surfaces_rect.bottom, surfaces_rect.top);
// Update viewport
- viewport.x = static_cast(surfaces_rect.left) + viewport_rect.left * res_scale;
- viewport.y = static_cast(surfaces_rect.bottom) + viewport_rect.bottom * res_scale;
- viewport.width = static_cast(viewport_rect.GetWidth() * res_scale);
- viewport.height = static_cast(viewport_rect.GetHeight() * res_scale);
+ viewport.x = static_cast(surfaces_rect.left) + (viewport_rect.left * res_scale) / 100;
+ viewport.y =
+ static_cast(surfaces_rect.bottom) + (viewport_rect.bottom * res_scale) / 100;
+ viewport.width = static_cast((viewport_rect.GetWidth() * res_scale) / 100);
+ viewport.height = static_cast((viewport_rect.GetHeight() * res_scale) / 100);
// Scissor checks are window-, not viewport-relative, which means that if the cached texture
// sub-rect changes, the scissor bounds also need to be updated.
- scissor_rect.left = static_cast(surfaces_rect.left + regs.scissor_test.x1 * res_scale);
+ scissor_rect.left =
+ static_cast(surfaces_rect.left + (regs.scissor_test.x1 * res_scale) / 100);
scissor_rect.bottom =
- static_cast(surfaces_rect.bottom + regs.scissor_test.y1 * res_scale);
+ static_cast(surfaces_rect.bottom + (regs.scissor_test.y1 * res_scale) / 100);
// x2, y2 have +1 added to cover the entire pixel area, otherwise you might get cracks when
// scaling or doing multisampling.
scissor_rect.right =
- static_cast(surfaces_rect.left + (regs.scissor_test.x2 + 1) * res_scale);
+ static_cast(surfaces_rect.left + ((regs.scissor_test.x2 + 1) * res_scale) / 100);
scissor_rect.top =
- static_cast(surfaces_rect.bottom + (regs.scissor_test.y2 + 1) * res_scale);
+ static_cast(surfaces_rect.bottom + ((regs.scissor_test.y2 + 1) * res_scale) / 100);
if (flip_rect) {
- scissor_rect = scissor_rect.VerticalMirror(height);
+ scissor_rect = scissor_rect.VerticalMirror(surfaces_rect.GetHeight());
}
}
~FramebufferHelper() {
- const Common::Rectangle draw_rect_unscaled{draw_rect / fb->Scale()};
+ const u32 scale = fb->Scale();
+ const Common::Rectangle draw_rect_unscaled{
+ (draw_rect.left * 100) / scale,
+ (draw_rect.top * 100) / scale,
+ (draw_rect.right * 100) / scale,
+ (draw_rect.bottom * 100) / scale,
+ };
const auto invalidate = [&](SurfaceId surface_id, u32 level) {
const auto& surface = res_cache->GetSurface(surface_id);
const SurfaceInterval interval = surface.GetSubRectInterval(draw_rect_unscaled, level);
diff --git a/src/video_core/rasterizer_cache/rasterizer_cache.h b/src/video_core/rasterizer_cache/rasterizer_cache.h
index 09d936020..69d82a944 100644
--- a/src/video_core/rasterizer_cache/rasterizer_cache.h
+++ b/src/video_core/rasterizer_cache/rasterizer_cache.h
@@ -213,7 +213,7 @@ bool RasterizerCache::AccelerateTextureCopy(const Pica::DisplayTransferConfig
const SurfaceParams src_info = slot_surfaces[src_surface_id];
if (output_gap != 0 &&
- (output_width != src_info.BytesInPixels(src_rect.GetWidth() / src_info.res_scale) *
+ (output_width != src_info.BytesInPixels((src_rect.GetWidth() * 100) / src_info.res_scale) *
(src_info.is_tiled ? 8 : 1) ||
output_gap % src_info.BytesInPixels(src_info.is_tiled ? 64 : 1) != 0)) {
return false;
@@ -221,10 +221,10 @@ bool RasterizerCache::AccelerateTextureCopy(const Pica::DisplayTransferConfig
SurfaceParams dst_params = src_info;
dst_params.addr = config.GetPhysicalOutputAddress();
- dst_params.width = src_rect.GetWidth() / src_info.res_scale;
+ dst_params.width = (src_rect.GetWidth() * 100) / src_info.res_scale;
dst_params.stride =
dst_params.width + src_info.PixelsInBytes(src_info.is_tiled ? output_gap / 8 : output_gap);
- dst_params.height = src_rect.GetHeight() / src_info.res_scale;
+ dst_params.height = (src_rect.GetHeight() * 100) / src_info.res_scale;
dst_params.res_scale = src_info.res_scale;
dst_params.UpdateParams();
@@ -559,7 +559,7 @@ SurfaceId RasterizerCache::GetTextureSurface(const Pica::Texture::TextureInfo
params.levels = max_level + 1;
params.is_tiled = true;
params.pixel_format = PixelFormatFromTextureFormat(info.format);
- params.res_scale = filter != Settings::TextureFilter::NoFilter ? resolution_scale_factor : 1;
+ params.res_scale = filter != Settings::TextureFilter::NoFilter ? resolution_scale_factor : 100;
params.UpdateParams();
const u32 min_width = info.width >> max_level;
@@ -616,7 +616,7 @@ typename T::Surface& RasterizerCache::GetTextureCube(const TextureCubeConfig&
};
info.SetDefaultStride();
- u32 res_scale = 1;
+ u32 res_scale = 100;
for (u32 i = 0; i < addresses.size(); i++) {
if (!addresses[i]) {
continue;
diff --git a/src/video_core/rasterizer_cache/surface_params.cpp b/src/video_core/rasterizer_cache/surface_params.cpp
index 74ae8205c..1510c091c 100644
--- a/src/video_core/rasterizer_cache/surface_params.cpp
+++ b/src/video_core/rasterizer_cache/surface_params.cpp
@@ -1,4 +1,4 @@
-// Copyright 2022 Citra Emulator Project
+// Copyright Citra Emulator Project / Azahar Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
@@ -98,7 +98,9 @@ Common::Rectangle SurfaceParams::GetSubRect(const SurfaceParams& sub_surfac
}
Common::Rectangle SurfaceParams::GetScaledSubRect(const SurfaceParams& sub_surface) const {
- return GetSubRect(sub_surface) * res_scale;
+ auto rect = GetSubRect(sub_surface);
+ return {(rect.left * res_scale) / 100, (rect.top * res_scale) / 100,
+ (rect.right * res_scale) / 100, (rect.bottom * res_scale) / 100};
}
SurfaceParams SurfaceParams::FromInterval(SurfaceInterval interval) const {
diff --git a/src/video_core/rasterizer_cache/surface_params.h b/src/video_core/rasterizer_cache/surface_params.h
index 23e4db7e2..d97c329ec 100644
--- a/src/video_core/rasterizer_cache/surface_params.h
+++ b/src/video_core/rasterizer_cache/surface_params.h
@@ -1,4 +1,4 @@
-// Copyright 2022 Citra Emulator Project
+// Copyright Citra Emulator Project / Azahar Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
@@ -64,11 +64,18 @@ public:
}
[[nodiscard]] u32 GetScaledWidth() const noexcept {
- return width * res_scale;
+ return (width * res_scale) / 100;
}
[[nodiscard]] u32 GetScaledHeight() const noexcept {
- return height * res_scale;
+ return (height * res_scale) / 100;
+ }
+
+ /// Returns the scaled version of an unscaled rectangle using the 100-based res_scale
+ [[nodiscard]] Common::Rectangle ScaleRect(
+ const Common::Rectangle& rect) const noexcept {
+ return {(rect.left * res_scale) / 100, (rect.top * res_scale) / 100,
+ (rect.right * res_scale) / 100, (rect.bottom * res_scale) / 100};
}
[[nodiscard]] Common::Rectangle GetRect(u32 level = 0) const noexcept {
@@ -103,7 +110,7 @@ public:
u32 height = 0;
u32 stride = 0;
u32 levels = 1;
- u32 res_scale = 1;
+ u32 res_scale = 100;
bool is_tiled = false;
TextureType texture_type = TextureType::Texture2D;
diff --git a/src/video_core/renderer_base.cpp b/src/video_core/renderer_base.cpp
index e78ab9c91..af0b383be 100644
--- a/src/video_core/renderer_base.cpp
+++ b/src/video_core/renderer_base.cpp
@@ -20,13 +20,13 @@ RendererBase::~RendererBase() = default;
u32 RendererBase::GetResolutionScaleFactor() {
const auto graphics_api = Settings::values.graphics_api.GetValue();
if (graphics_api == Settings::GraphicsAPI::Software) {
- // Software renderer always render at native resolution
- return 1;
+ // Software renderer always renders at native resolution
+ return 100;
}
const u32 scale_factor = Settings::values.resolution_factor.GetValue();
return scale_factor != 0 ? scale_factor
- : render_window.GetFramebufferLayout().GetScalingRatio();
+ : render_window.GetFramebufferLayout().GetScalingRatio() * 100;
}
void RendererBase::UpdateCurrentFramebufferLayout(bool is_portrait_mode) {
diff --git a/src/video_core/renderer_opengl/gl_blit_helper.cpp b/src/video_core/renderer_opengl/gl_blit_helper.cpp
index 30a502316..5238eda89 100644
--- a/src/video_core/renderer_opengl/gl_blit_helper.cpp
+++ b/src/video_core/renderer_opengl/gl_blit_helper.cpp
@@ -265,7 +265,7 @@ void BlitHelper::FilterXbrz(Surface& surface, const VideoCore::TextureBlit& blit
const OpenGLState prev_state = OpenGLState::GetCurState();
SCOPE_EXIT({ prev_state.Apply(); });
state.texture_units[0].texture_2d = surface.Handle(0);
- glProgramUniform1f(xbrz_program.handle, 2, static_cast(surface.res_scale));
+ glProgramUniform1f(xbrz_program.handle, 2, static_cast(surface.res_scale) / 100.0f);
SetParams(xbrz_program, surface.RealExtent(false), blit.src_rect);
Draw(xbrz_program, surface.Handle(), draw_fbo.handle, blit.dst_level, blit.dst_rect);
}
diff --git a/src/video_core/renderer_opengl/gl_texture_runtime.cpp b/src/video_core/renderer_opengl/gl_texture_runtime.cpp
index f93b033ed..31a301e8e 100644
--- a/src/video_core/renderer_opengl/gl_texture_runtime.cpp
+++ b/src/video_core/renderer_opengl/gl_texture_runtime.cpp
@@ -1,4 +1,4 @@
-// Copyright 2023 Citra Emulator Project
+// Copyright Citra Emulator Project / Azahar Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
@@ -328,7 +328,7 @@ Surface::Surface(TextureRuntime& runtime_, const VideoCore::SurfaceParams& param
texture_type == VideoCore::TextureType::CubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
textures[0] = MakeHandle(target, width, height, levels, tuple, DebugName(false));
- if (res_scale != 1) {
+ if (res_scale != 100) {
textures[1] = MakeHandle(target, GetScaledWidth(), GetScaledHeight(), levels, tuple,
DebugName(true, false));
}
@@ -349,7 +349,7 @@ Surface::Surface(TextureRuntime& runtime, const VideoCore::SurfaceBase& surface,
material = mat;
textures[0] = MakeHandle(target, mat->width, mat->height, levels, tuple, DebugName(false));
- if (res_scale != 1) {
+ if (res_scale != 100) {
textures[1] = MakeHandle(target, mat->width, mat->height, levels, DEFAULT_TUPLE,
DebugName(true, true));
}
@@ -406,9 +406,9 @@ void Surface::Upload(const VideoCore::BufferTextureCopy& upload,
.src_level = upload.texture_level,
.dst_level = upload.texture_level,
.src_rect = upload.texture_rect,
- .dst_rect = upload.texture_rect * res_scale,
+ .dst_rect = ScaleRect(upload.texture_rect),
};
- if (res_scale != 1 && !runtime->blit_helper.Filter(*this, blit)) {
+ if (res_scale != 100 && !runtime->blit_helper.Filter(*this, blit)) {
BlitScale(blit, true);
}
}
@@ -440,7 +440,7 @@ void Surface::UploadCustom(const VideoCore::Material* material, u32 level) {
.src_rect = filter_rect,
.dst_rect = filter_rect,
};
- if (res_scale != 1 && !runtime->blit_helper.Filter(*this, blit)) {
+ if (res_scale != 100 && !runtime->blit_helper.Filter(*this, blit)) {
BlitScale(blit, true);
}
for (u32 i = 1; i < VideoCore::MAX_MAPS; i++) {
@@ -463,11 +463,11 @@ void Surface::Download(const VideoCore::BufferTextureCopy& download,
glPixelStorei(GL_UNPACK_ROW_LENGTH, unscaled_width);
// Scale down upscaled data before downloading it
- if (res_scale != 1) {
+ if (res_scale != 100) {
const VideoCore::TextureBlit blit = {
.src_level = download.texture_level,
.dst_level = download.texture_level,
- .src_rect = download.texture_rect * res_scale,
+ .src_rect = ScaleRect(download.texture_rect),
.dst_rect = download.texture_rect,
};
BlitScale(blit, false);
@@ -554,7 +554,7 @@ void Surface::Attach(GLenum target, u32 level, u32 layer, bool scaled) {
}
void Surface::ScaleUp(u32 new_scale) {
- if (res_scale == new_scale || new_scale == 1) {
+ if (res_scale == new_scale || new_scale == 100) {
return;
}
@@ -603,7 +603,7 @@ void Surface::BlitScale(const VideoCore::TextureBlit& blit, bool up_scale) {
Framebuffer::Framebuffer(TextureRuntime& runtime, const VideoCore::FramebufferParams& params,
const Surface* color, const Surface* depth)
: VideoCore::FramebufferParams{params},
- res_scale{color ? color->res_scale : (depth ? depth->res_scale : 1u)} {
+ res_scale{color ? color->res_scale : (depth ? depth->res_scale : 100u)} {
if (shadow_rendering && !color) {
return;
@@ -624,9 +624,9 @@ Framebuffer::Framebuffer(TextureRuntime& runtime, const VideoCore::FramebufferPa
if (shadow_rendering) {
glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH,
- color->width * res_scale);
+ (color->width * res_scale) / 100);
glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT,
- color->height * res_scale);
+ (color->height * res_scale) / 100);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0,
0);
diff --git a/src/video_core/renderer_opengl/gl_texture_runtime.h b/src/video_core/renderer_opengl/gl_texture_runtime.h
index 5fe7300a7..bbed4433d 100644
--- a/src/video_core/renderer_opengl/gl_texture_runtime.h
+++ b/src/video_core/renderer_opengl/gl_texture_runtime.h
@@ -1,4 +1,4 @@
-// Copyright 2023 Citra Emulator Project
+// Copyright Citra Emulator Project / Azahar Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
@@ -182,7 +182,7 @@ public:
}
private:
- u32 res_scale{1};
+ u32 res_scale{100};
std::array attachments{};
OGLFramebuffer framebuffer;
};
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index c8cb6c000..f4b024e31 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -556,10 +556,11 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float x, fl
const u32 scale_factor = GetResolutionScaleFactor();
const GLuint sampler = samplers[Settings::values.filter_mode.GetValue()].handle;
- glUniform4f(uniform_i_resolution, static_cast(screen_info.texture.width * scale_factor),
- static_cast(screen_info.texture.height * scale_factor),
- 1.0f / static_cast(screen_info.texture.width * scale_factor),
- 1.0f / static_cast(screen_info.texture.height * scale_factor));
+ glUniform4f(uniform_i_resolution,
+ static_cast((screen_info.texture.width * scale_factor) / 100.0f),
+ static_cast((screen_info.texture.height * scale_factor) / 100.0f),
+ 100.0f / static_cast(screen_info.texture.width * scale_factor),
+ 100.0f / static_cast(screen_info.texture.height * scale_factor));
glUniform4f(uniform_o_resolution, h, w, 1.0f / h, 1.0f / w);
state.texture_units[0].texture_2d = screen_info.display_texture;
state.texture_units[0].sampler = sampler;
@@ -627,10 +628,10 @@ void RendererOpenGL::DrawSingleScreenStereo(const ScreenInfo& screen_info_l,
const u32 scale_factor = GetResolutionScaleFactor();
const GLuint sampler = samplers[Settings::values.filter_mode.GetValue()].handle;
glUniform4f(uniform_i_resolution,
- static_cast(screen_info_l.texture.width * scale_factor),
- static_cast(screen_info_l.texture.height * scale_factor),
- 1.0f / static_cast(screen_info_l.texture.width * scale_factor),
- 1.0f / static_cast(screen_info_l.texture.height * scale_factor));
+ static_cast((screen_info_l.texture.width * scale_factor) / 100.0f),
+ static_cast((screen_info_l.texture.height * scale_factor) / 100.0f),
+ 100.0f / static_cast(screen_info_l.texture.width * scale_factor),
+ 100.0f / static_cast(screen_info_l.texture.height * scale_factor));
glUniform4f(uniform_o_resolution, h, w, 1.0f / h, 1.0f / w);
state.texture_units[0].texture_2d = screen_info_l.display_texture;
state.texture_units[1].texture_2d = screen_info_r.display_texture;
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
index 0a25c2036..53ae1461b 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
@@ -783,10 +783,10 @@ void RendererVulkan::DrawSingleScreen(u32 screen_id, float x, float y, float w,
const u32 scale_factor = GetResolutionScaleFactor();
draw_info.i_resolution =
- Common::MakeVec(static_cast(screen_info.texture.width * scale_factor),
- static_cast(screen_info.texture.height * scale_factor),
- 1.0f / static_cast(screen_info.texture.width * scale_factor),
- 1.0f / static_cast(screen_info.texture.height * scale_factor));
+ Common::MakeVec(static_cast((screen_info.texture.width * scale_factor) / 100.0f),
+ static_cast((screen_info.texture.height * scale_factor) / 100.0f),
+ 100.0f / static_cast(screen_info.texture.width * scale_factor),
+ 100.0f / static_cast(screen_info.texture.height * scale_factor));
draw_info.o_resolution = Common::MakeVec(h, w, 1.0f / h, 1.0f / w);
draw_info.screen_id_l = screen_id;
@@ -855,10 +855,10 @@ void RendererVulkan::DrawSingleScreenStereo(u32 screen_id_l, u32 screen_id_r, fl
const u32 scale_factor = GetResolutionScaleFactor();
draw_info.i_resolution =
- Common::MakeVec(static_cast(screen_info_l.texture.width * scale_factor),
- static_cast(screen_info_l.texture.height * scale_factor),
- 1.0f / static_cast(screen_info_l.texture.width * scale_factor),
- 1.0f / static_cast(screen_info_l.texture.height * scale_factor));
+ Common::MakeVec(static_cast((screen_info_l.texture.width * scale_factor) / 100.0f),
+ static_cast((screen_info_l.texture.height * scale_factor) / 100.0f),
+ 100.0f / static_cast(screen_info_l.texture.width * scale_factor),
+ 100.0f / static_cast(screen_info_l.texture.height * scale_factor));
draw_info.o_resolution = Common::MakeVec(h, w, 1.0f / h, 1.0f / w);
draw_info.screen_id_l = screen_id_l;
draw_info.screen_id_r = screen_id_r;
diff --git a/src/video_core/renderer_vulkan/vk_blit_helper.cpp b/src/video_core/renderer_vulkan/vk_blit_helper.cpp
index 9982948b3..3c24c0238 100644
--- a/src/video_core/renderer_vulkan/vk_blit_helper.cpp
+++ b/src/video_core/renderer_vulkan/vk_blit_helper.cpp
@@ -759,7 +759,7 @@ void BlitHelper::FilterPass(Surface& surface, vk::Pipeline pipeline, vk::Pipelin
},
};
renderpass_cache.BeginRendering(render_pass);
- const float src_scale = static_cast(surface.GetResScale());
+ const float src_scale = static_cast(surface.GetResScale()) / 100.0f;
// Calculate normalized texture coordinates like OpenGL does
const auto src_extent = surface.RealExtent(false); // Get unscaled texture extent
const float tex_scale_x =
@@ -845,7 +845,7 @@ void BlitHelper::FilterPassThreeTextures(Surface& surface, vk::Pipeline pipeline
};
renderpass_cache.BeginRendering(render_pass);
- const float src_scale = static_cast(surface.GetResScale());
+ const float src_scale = static_cast(surface.GetResScale()) / 100.0f;
// Calculate normalized texture coordinates like OpenGL does
const auto src_extent = surface.RealExtent(false); // Get unscaled texture extent
const float tex_scale_x =
diff --git a/src/video_core/renderer_vulkan/vk_texture_runtime.cpp b/src/video_core/renderer_vulkan/vk_texture_runtime.cpp
index 52b7c6392..c916ad863 100644
--- a/src/video_core/renderer_vulkan/vk_texture_runtime.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_runtime.cpp
@@ -766,14 +766,14 @@ Surface::Surface(TextureRuntime& runtime_, const VideoCore::SurfaceParams& param
traits.aspect, need_format_list, DebugName(false));
raw_images[num_images++] = handles[Type::Base].image;
- if (res_scale != 1) {
+ if (res_scale != 100) {
handles[Type::Scaled].Create(GetScaledWidth(), GetScaledHeight(), levels, texture_type,
format, usage, flags, traits.aspect, need_format_list,
DebugName(true));
raw_images[num_images++] = handles[Type::Scaled].image;
}
- current = res_scale != 1 ? Type::Scaled : Type::Base;
+ current = res_scale != 100 ? Type::Scaled : Type::Base;
runtime.renderpass_cache.EndRendering();
scheduler.Record([raw_images, num_images, aspect = traits.aspect](vk::CommandBuffer cmdbuf) {
@@ -810,7 +810,7 @@ Surface::Surface(TextureRuntime& runtime_, const VideoCore::SurfaceBase& surface
flags, traits.aspect, false, debug_name);
raw_images[num_images++] = handles[Type::Base].image;
- if (res_scale != 1) {
+ if (res_scale != 100) {
handles[Type::Scaled].Create(mat->width, mat->height, levels, texture_type,
vk::Format::eR8G8B8A8Unorm, traits.usage, flags, traits.aspect,
false, debug_name);
@@ -822,7 +822,7 @@ Surface::Surface(TextureRuntime& runtime_, const VideoCore::SurfaceBase& surface
raw_images[num_images++] = handles[Type::Custom].image;
}
- current = res_scale != 1 ? Type::Scaled : Type::Base;
+ current = res_scale != 100 ? Type::Scaled : Type::Base;
runtime.renderpass_cache.EndRendering();
scheduler.Record([raw_images, num_images, aspect = traits.aspect](vk::CommandBuffer cmdbuf) {
@@ -910,14 +910,14 @@ void Surface::Upload(const VideoCore::BufferTextureCopy& upload,
runtime.upload_buffer.Commit(staging.size);
- if (res_scale != 1) {
+ if (res_scale != 100) {
ASSERT_MSG(handles[Type::Scaled], "Scaled allocation missing during upload");
const VideoCore::TextureBlit blit = {
.src_level = upload.texture_level,
.dst_level = upload.texture_level,
.src_rect = upload.texture_rect,
- .dst_rect = upload.texture_rect * res_scale,
+ .dst_rect = ScaleRect(upload.texture_rect),
};
if ((type != SurfaceType::Color && type != SurfaceType::Texture) ||
!runtime.blit_helper.Filter(*this, blit)) {
@@ -1013,11 +1013,11 @@ void Surface::Download(const VideoCore::BufferTextureCopy& download,
return;
}
- if (res_scale != 1) {
+ if (res_scale != 100) {
const VideoCore::TextureBlit blit = {
.src_level = download.texture_level,
.dst_level = download.texture_level,
- .src_rect = download.texture_rect * res_scale,
+ .src_rect = ScaleRect(download.texture_rect),
.dst_rect = download.texture_rect,
};
@@ -1086,7 +1086,7 @@ void Surface::Download(const VideoCore::BufferTextureCopy& download,
}
void Surface::ScaleUp(u32 new_scale) {
- if (res_scale == new_scale || new_scale == 1) {
+ if (res_scale == new_scale || new_scale == 100) {
return;
}
@@ -1437,7 +1437,7 @@ void Surface::BlitScale(const VideoCore::TextureBlit& blit, bool up_scale) {
Framebuffer::Framebuffer(TextureRuntime& runtime, const VideoCore::FramebufferParams& params,
Surface* color, Surface* depth)
: VideoCore::FramebufferParams{params}, instance{runtime.GetInstance()},
- res_scale{color ? color->res_scale : (depth ? depth->res_scale : 1u)} {
+ res_scale{color ? color->res_scale : (depth ? depth->res_scale : 100u)} {
auto& renderpass_cache = runtime.GetRenderpassCache();
if (shadow_rendering && !color) {
return;
diff --git a/src/video_core/renderer_vulkan/vk_texture_runtime.h b/src/video_core/renderer_vulkan/vk_texture_runtime.h
index 17ac89c91..1d39e1fd9 100644
--- a/src/video_core/renderer_vulkan/vk_texture_runtime.h
+++ b/src/video_core/renderer_vulkan/vk_texture_runtime.h
@@ -305,7 +305,7 @@ public:
formats(std::exchange(
other.formats, {VideoCore::PixelFormat::Invalid, VideoCore::PixelFormat::Invalid})),
width(std::exchange(other.width, 0)), height(std::exchange(other.height, 0)),
- res_scale(std::exchange(other.res_scale, 1)) {}
+ res_scale(std::exchange(other.res_scale, 100)) {}
Framebuffer& operator=(Framebuffer&& other) noexcept {
VideoCore::FramebufferParams::operator=(std::move(other));
@@ -319,7 +319,7 @@ public:
{VideoCore::PixelFormat::Invalid, VideoCore::PixelFormat::Invalid});
width = std::exchange(other.width, 0);
height = std::exchange(other.height, 0);
- res_scale = std::exchange(other.res_scale, 1);
+ res_scale = std::exchange(other.res_scale, 100);
return *this;
}
@@ -364,7 +364,7 @@ private:
VideoCore::PixelFormat::Invalid};
u32 width{};
u32 height{};
- u32 res_scale{1};
+ u32 res_scale{100};
};
class Sampler {