From 7a957d501fabc7ae666e2d6281d41090cc0bab04 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sun, 18 Jul 2021 18:40:14 +0200 Subject: VideoCore: Initial Setup for the Resolution Scaler. --- src/common/settings.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/common/settings.cpp') diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 9dd5e3efbc..8c6be2c849 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -47,6 +47,7 @@ void LogSettings() { log_setting("System_TimeZoneIndex", values.time_zone_index.GetValue()); log_setting("Core_UseMultiCore", values.use_multi_core.GetValue()); log_setting("CPU_Accuracy", values.cpu_accuracy.GetValue()); + log_setting("Renderer_UseResolutionScaling", values.resolution_setup.GetValue()); log_setting("Renderer_UseResolutionFactor", values.resolution_factor.GetValue()); log_setting("Renderer_UseSpeedLimit", values.use_speed_limit.GetValue()); log_setting("Renderer_SpeedLimit", values.speed_limit.GetValue()); -- cgit v1.2.3 From b9a9b8d7685711b4618582e98b17c123113ece0a Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sun, 18 Jul 2021 20:33:20 +0200 Subject: Settings: Add resolution scaling to settings. --- src/common/settings.cpp | 51 +++++++++++++++++++++ src/common/settings.h | 13 ++++-- src/yuzu/configuration/config.cpp | 5 +++ src/yuzu/configuration/config.h | 1 + src/yuzu/configuration/configure_graphics.cpp | 26 ++++++++++- src/yuzu/configuration/configure_graphics.ui | 64 +++++++++++++++++++++++++++ 6 files changed, 155 insertions(+), 5 deletions(-) (limited to 'src/common/settings.cpp') diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 8c6be2c849..dd3a3d4565 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -106,6 +106,57 @@ float Volume() { return values.volume.GetValue() / 100.0f; } +void UpdateRescalingInfo() { + auto setup = values.resolution_setup.GetValue(); + auto& info = values.resolution_info; + switch (setup) { + case ResolutionSetup::Res1_2X: { + info.up_scale = 1; + info.down_shift = 1; + break; + } + case ResolutionSetup::Res3_4X: { + info.up_scale = 3; + info.down_shift = 2; + break; + } + case ResolutionSetup::Res1X: { + info.up_scale = 1; + info.down_shift = 0; + break; + } + case ResolutionSetup::Res3_2X: { + info.up_scale = 3; + info.down_shift = 1; + break; + } + case ResolutionSetup::Res2X: { + info.up_scale = 2; + info.down_shift = 0; + break; + } + case ResolutionSetup::Res3X: { + info.up_scale = 3; + info.down_shift = 0; + break; + } + case ResolutionSetup::Res4X: { + info.up_scale = 4; + info.down_shift = 0; + break; + } + default: { + UNREACHABLE(); + info.up_scale = 1; + info.down_shift = 0; + } + } + info.up_factor = static_cast(info.up_scale) / (1U << info.down_shift); + info.down_factor = static_cast(1U << info.down_shift) / info.up_scale; + info.size_up = info.up_scale * info.up_scale; + info.size_shift = info.down_shift * 2; +} + void RestoreGlobalState(bool is_powered_on) { // If a game is running, DO NOT restore the global settings state if (is_powered_on) { diff --git a/src/common/settings.h b/src/common/settings.h index 08f3da0558..f4df2fc95d 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -56,16 +56,19 @@ enum class ResolutionSetup : u32 { Res1_2X = 0, Res3_4X = 1, Res1X = 2, - Res3_2K = 3, + Res3_2X = 3, Res2X = 4, Res3X = 5, + Res4X = 6, }; struct ResolutionScalingInfo { - u32 up_scale{2}; + u32 up_scale{1}; u32 down_shift{0}; - f32 up_factor{2.0f}; - f32 down_factor{0.5f}; + f32 up_factor{1.0f}; + f32 down_factor{1.0f}; + u32 size_up{1}; + u32 size_shift{0}; }; /** The BasicSetting class is a simple resource manager. It defines a label and default value @@ -613,6 +616,8 @@ std::string GetTimeZoneString(); void LogSettings(); +void UpdateRescalingInfo(); + // Restore the global state of all applicable settings in the Values struct void RestoreGlobalState(bool is_powered_on); diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index faea5dda11..7ddc40b009 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -824,6 +824,7 @@ void Config::ReadRendererValues() { ReadGlobalSetting(Settings::values.vulkan_device); ReadGlobalSetting(Settings::values.fullscreen_mode); ReadGlobalSetting(Settings::values.aspect_ratio); + ReadGlobalSetting(Settings::values.resolution_setup); ReadGlobalSetting(Settings::values.max_anisotropy); ReadGlobalSetting(Settings::values.use_speed_limit); ReadGlobalSetting(Settings::values.speed_limit); @@ -1364,6 +1365,10 @@ void Config::SaveRendererValues() { static_cast(Settings::values.fullscreen_mode.GetDefault()), Settings::values.fullscreen_mode.UsingGlobal()); WriteGlobalSetting(Settings::values.aspect_ratio); + WriteSetting(QString::fromStdString(Settings::values.resolution_setup.GetLabel()), + static_cast(Settings::values.resolution_setup.GetValue(global)), + static_cast(Settings::values.resolution_setup.GetDefault()), + Settings::values.resolution_setup.UsingGlobal()); WriteGlobalSetting(Settings::values.max_anisotropy); WriteGlobalSetting(Settings::values.use_speed_limit); WriteGlobalSetting(Settings::values.speed_limit); diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index a7f4a67209..fbb91d3125 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h @@ -189,5 +189,6 @@ Q_DECLARE_METATYPE(Settings::CPUAccuracy); Q_DECLARE_METATYPE(Settings::GPUAccuracy); Q_DECLARE_METATYPE(Settings::FullscreenMode); Q_DECLARE_METATYPE(Settings::NvdecEmulation); +Q_DECLARE_METATYPE(Settings::ResolutionSetup); Q_DECLARE_METATYPE(Settings::RendererBackend); Q_DECLARE_METATYPE(Settings::ShaderBackend); diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index 8e20cc6f30..4f08ae3e07 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -102,6 +102,8 @@ void ConfigureGraphics::SetConfiguration() { ui->nvdec_emulation->setCurrentIndex( static_cast(Settings::values.nvdec_emulation.GetValue())); ui->aspect_ratio_combobox->setCurrentIndex(Settings::values.aspect_ratio.GetValue()); + ui->resolution_combobox->setCurrentIndex( + static_cast(Settings::values.resolution_setup.GetValue())); } else { ConfigurationShared::SetPerGameSetting(ui->api, &Settings::values.renderer_backend); ConfigurationShared::SetHighlight(ui->api_widget, @@ -122,6 +124,11 @@ void ConfigureGraphics::SetConfiguration() { ConfigurationShared::SetHighlight(ui->ar_label, !Settings::values.aspect_ratio.UsingGlobal()); + ConfigurationShared::SetPerGameSetting(ui->resolution_combobox, + &Settings::values.resolution_setup); + ConfigurationShared::SetHighlight(ui->resolution_label, + !Settings::values.resolution_setup.UsingGlobal()); + ui->bg_combobox->setCurrentIndex(Settings::values.bg_red.UsingGlobal() ? 0 : 1); ui->bg_button->setEnabled(!Settings::values.bg_red.UsingGlobal()); ConfigurationShared::SetHighlight(ui->bg_layout, !Settings::values.bg_red.UsingGlobal()); @@ -133,11 +140,14 @@ void ConfigureGraphics::SetConfiguration() { } void ConfigureGraphics::ApplyConfiguration() { + const auto resolution_setup = static_cast( + ui->resolution_combobox->currentIndex() - + ((Settings::IsConfiguringGlobal()) ? 0 : ConfigurationShared::USE_GLOBAL_OFFSET)); + ConfigurationShared::ApplyPerGameSetting(&Settings::values.fullscreen_mode, ui->fullscreen_mode_combobox); ConfigurationShared::ApplyPerGameSetting(&Settings::values.aspect_ratio, ui->aspect_ratio_combobox); - ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_disk_shader_cache, ui->use_disk_shader_cache, use_disk_shader_cache); ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_gpu_emulation, @@ -165,7 +175,16 @@ void ConfigureGraphics::ApplyConfiguration() { Settings::values.bg_green.SetValue(static_cast(bg_color.green())); Settings::values.bg_blue.SetValue(static_cast(bg_color.blue())); } + if (Settings::values.resolution_setup.UsingGlobal()) { + Settings::values.resolution_setup.SetValue(resolution_setup); + } } else { + if (ui->resolution_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { + Settings::values.resolution_setup.SetGlobal(true); + } else { + Settings::values.resolution_setup.SetGlobal(false); + Settings::values.resolution_setup.SetValue(resolution_setup); + } if (ui->api->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { Settings::values.renderer_backend.SetGlobal(true); Settings::values.shader_backend.SetGlobal(true); @@ -207,6 +226,7 @@ void ConfigureGraphics::ApplyConfiguration() { Settings::values.bg_blue.SetValue(static_cast(bg_color.blue())); } } + Settings::UpdateRescalingInfo(); } void ConfigureGraphics::changeEvent(QEvent* event) { @@ -312,6 +332,7 @@ void ConfigureGraphics::SetupPerGameUI() { ui->device->setEnabled(Settings::values.renderer_backend.UsingGlobal()); ui->fullscreen_mode_combobox->setEnabled(Settings::values.fullscreen_mode.UsingGlobal()); ui->aspect_ratio_combobox->setEnabled(Settings::values.aspect_ratio.UsingGlobal()); + ui->resolution_combobox->setEnabled(Settings::values.resolution_setup.UsingGlobal()); ui->use_asynchronous_gpu_emulation->setEnabled( Settings::values.use_asynchronous_gpu_emulation.UsingGlobal()); ui->nvdec_emulation->setEnabled(Settings::values.nvdec_emulation.UsingGlobal()); @@ -340,6 +361,9 @@ void ConfigureGraphics::SetupPerGameUI() { ConfigurationShared::SetColoredComboBox( ui->fullscreen_mode_combobox, ui->fullscreen_mode_label, static_cast(Settings::values.fullscreen_mode.GetValue(true))); + ConfigurationShared::SetColoredComboBox( + ui->resolution_combobox, ui->resolution_label, + static_cast(Settings::values.resolution_setup.GetValue(true))); ConfigurationShared::InsertGlobalItem( ui->api, static_cast(Settings::values.renderer_backend.GetValue(true))); ConfigurationShared::InsertGlobalItem( diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui index beae74344e..1b6ac3cbba 100644 --- a/src/yuzu/configuration/configure_graphics.ui +++ b/src/yuzu/configuration/configure_graphics.ui @@ -309,6 +309,70 @@ + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Resolution: + + + + + + + + 0.5X (360p/540p) + + + + + 0.75X (540p/810p) + + + + + 1X (720p/1080p) + + + + + 1.5X (1080p/1620p) + + + + + 2X (1440p/2160[4K]p) + + + + + 3X (2160p[4K]/3240p[6K]) + + + + + 4X (2880p/4320p[8K]) + + + + + + + -- cgit v1.2.3 From fcae5dab7b262ae41b14eb566e52b95158b643ad Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 20 Jul 2021 18:29:52 +0200 Subject: Settings: eliminate rescaling_factor. --- src/common/settings.cpp | 2 +- src/common/settings.h | 2 +- src/core/hle/service/am/am.cpp | 12 ++++-------- src/core/hle/service/vi/vi.cpp | 27 ++++++++------------------- src/core/telemetry_session.cpp | 2 -- src/video_core/video_core.cpp | 9 ++++----- src/video_core/video_core.h | 2 +- 7 files changed, 19 insertions(+), 37 deletions(-) (limited to 'src/common/settings.cpp') diff --git a/src/common/settings.cpp b/src/common/settings.cpp index dd3a3d4565..6f3acee795 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -48,7 +48,6 @@ void LogSettings() { log_setting("Core_UseMultiCore", values.use_multi_core.GetValue()); log_setting("CPU_Accuracy", values.cpu_accuracy.GetValue()); log_setting("Renderer_UseResolutionScaling", values.resolution_setup.GetValue()); - log_setting("Renderer_UseResolutionFactor", values.resolution_factor.GetValue()); log_setting("Renderer_UseSpeedLimit", values.use_speed_limit.GetValue()); log_setting("Renderer_SpeedLimit", values.speed_limit.GetValue()); log_setting("Renderer_UseDiskShaderCache", values.use_disk_shader_cache.GetValue()); @@ -155,6 +154,7 @@ void UpdateRescalingInfo() { info.down_factor = static_cast(1U << info.down_shift) / info.up_scale; info.size_up = info.up_scale * info.up_scale; info.size_shift = info.down_shift * 2; + info.active = info.up_scale != 1 || info.down_shift != 0; } void RestoreGlobalState(bool is_powered_on) { diff --git a/src/common/settings.h b/src/common/settings.h index f4df2fc95d..2b11984b45 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -69,6 +69,7 @@ struct ResolutionScalingInfo { f32 down_factor{1.0f}; u32 size_up{1}; u32 size_shift{0}; + bool active{}; }; /** The BasicSetting class is a simple resource manager. It defines a label and default value @@ -472,7 +473,6 @@ struct Values { ResolutionScalingInfo resolution_info{}; Setting resolution_setup{ResolutionSetup::Res1X, "resolution_setup"}; - Setting resolution_factor{1, "resolution_factor"}; // *nix platforms may have issues with the borderless windowed fullscreen mode. // Default to exclusive fullscreen on these platforms for now. RangedSetting fullscreen_mode{ diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 50c2ace936..aee8d4f933 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -797,15 +797,11 @@ void ICommonStateGetter::GetDefaultDisplayResolution(Kernel::HLERequestContext& rb.Push(ResultSuccess); if (Settings::values.use_docked_mode.GetValue()) { - rb.Push(static_cast(Service::VI::DisplayResolution::DockedWidth) * - static_cast(Settings::values.resolution_factor.GetValue())); - rb.Push(static_cast(Service::VI::DisplayResolution::DockedHeight) * - static_cast(Settings::values.resolution_factor.GetValue())); + rb.Push(static_cast(Service::VI::DisplayResolution::DockedWidth)); + rb.Push(static_cast(Service::VI::DisplayResolution::DockedHeight)); } else { - rb.Push(static_cast(Service::VI::DisplayResolution::UndockedWidth) * - static_cast(Settings::values.resolution_factor.GetValue())); - rb.Push(static_cast(Service::VI::DisplayResolution::UndockedHeight) * - static_cast(Settings::values.resolution_factor.GetValue())); + rb.Push(static_cast(Service::VI::DisplayResolution::UndockedWidth)); + rb.Push(static_cast(Service::VI::DisplayResolution::UndockedHeight)); } } diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 63d5242c4e..75ee3e5e49 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -541,11 +541,8 @@ private: switch (transaction) { case TransactionId::Connect: { IGBPConnectRequestParcel request{ctx.ReadBuffer()}; - IGBPConnectResponseParcel response{ - static_cast(static_cast(DisplayResolution::UndockedWidth) * - Settings::values.resolution_factor.GetValue()), - static_cast(static_cast(DisplayResolution::UndockedHeight) * - Settings::values.resolution_factor.GetValue())}; + IGBPConnectResponseParcel response{static_cast(DisplayResolution::UndockedWidth), + static_cast(DisplayResolution::UndockedHeight)}; buffer_queue.Connect(); @@ -775,15 +772,11 @@ private: rb.Push(ResultSuccess); if (Settings::values.use_docked_mode.GetValue()) { - rb.Push(static_cast(Service::VI::DisplayResolution::DockedWidth) * - static_cast(Settings::values.resolution_factor.GetValue())); - rb.Push(static_cast(Service::VI::DisplayResolution::DockedHeight) * - static_cast(Settings::values.resolution_factor.GetValue())); + rb.Push(static_cast(Service::VI::DisplayResolution::DockedWidth)); + rb.Push(static_cast(Service::VI::DisplayResolution::DockedHeight)); } else { - rb.Push(static_cast(Service::VI::DisplayResolution::UndockedWidth) * - static_cast(Settings::values.resolution_factor.GetValue())); - rb.Push(static_cast(Service::VI::DisplayResolution::UndockedHeight) * - static_cast(Settings::values.resolution_factor.GetValue())); + rb.Push(static_cast(Service::VI::DisplayResolution::UndockedWidth)); + rb.Push(static_cast(Service::VI::DisplayResolution::UndockedHeight)); } rb.PushRaw(60.0f); // This wouldn't seem to be correct for 30 fps games. @@ -1063,10 +1056,8 @@ private: // This only returns the fixed values of 1280x720 and makes no distinguishing // between docked and undocked dimensions. We take the liberty of applying // the resolution scaling factor here. - rb.Push(static_cast(DisplayResolution::UndockedWidth) * - static_cast(Settings::values.resolution_factor.GetValue())); - rb.Push(static_cast(DisplayResolution::UndockedHeight) * - static_cast(Settings::values.resolution_factor.GetValue())); + rb.Push(static_cast(DisplayResolution::UndockedWidth)); + rb.Push(static_cast(DisplayResolution::UndockedHeight)); } void SetLayerScalingMode(Kernel::HLERequestContext& ctx) { @@ -1099,8 +1090,6 @@ private: LOG_WARNING(Service_VI, "(STUBBED) called"); DisplayInfo display_info; - display_info.width *= static_cast(Settings::values.resolution_factor.GetValue()); - display_info.height *= static_cast(Settings::values.resolution_factor.GetValue()); ctx.WriteBuffer(&display_info, sizeof(DisplayInfo)); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp index 191475f71c..654db0b524 100644 --- a/src/core/telemetry_session.cpp +++ b/src/core/telemetry_session.cpp @@ -229,8 +229,6 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader, AddField(field_type, "Core_UseMultiCore", Settings::values.use_multi_core.GetValue()); AddField(field_type, "Renderer_Backend", TranslateRenderer(Settings::values.renderer_backend.GetValue())); - AddField(field_type, "Renderer_ResolutionFactor", - Settings::values.resolution_factor.GetValue()); AddField(field_type, "Renderer_UseSpeedLimit", Settings::values.use_speed_limit.GetValue()); AddField(field_type, "Renderer_SpeedLimit", Settings::values.speed_limit.GetValue()); AddField(field_type, "Renderer_UseDiskShaderCache", diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index cae543a511..508173db3a 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp @@ -53,11 +53,10 @@ std::unique_ptr CreateGPU(Core::Frontend::EmuWindow& emu_window, Cor } } -u16 GetResolutionScaleFactor(const RendererBase& renderer) { - return static_cast( - Settings::values.resolution_factor.GetValue() != 0 - ? Settings::values.resolution_factor.GetValue() - : renderer.GetRenderWindow().GetFramebufferLayout().GetScalingRatio()); +float GetResolutionScaleFactor(const RendererBase& renderer) { + return Settings::values.resolution_info.active + ? Settings::values.resolution_info.up_factor + : renderer.GetRenderWindow().GetFramebufferLayout().GetScalingRatio(); } } // namespace VideoCore diff --git a/src/video_core/video_core.h b/src/video_core/video_core.h index f5c27125d7..f86877e862 100644 --- a/src/video_core/video_core.h +++ b/src/video_core/video_core.h @@ -25,6 +25,6 @@ class RendererBase; /// Creates an emulated GPU instance using the given system context. std::unique_ptr CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system); -u16 GetResolutionScaleFactor(const RendererBase& renderer); +float GetResolutionScaleFactor(const RendererBase& renderer); } // namespace VideoCore -- cgit v1.2.3 From 1b78ba7247263fd1c7f9a8ad77dad1c068b6e769 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 25 Jul 2021 21:20:12 -0300 Subject: common/settings: Remove unused scaling options --- src/common/settings.cpp | 23 +++++++---------------- src/common/settings.h | 2 -- 2 files changed, 7 insertions(+), 18 deletions(-) (limited to 'src/common/settings.cpp') diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 6f3acee795..4b7fa4b822 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -109,51 +109,42 @@ void UpdateRescalingInfo() { auto setup = values.resolution_setup.GetValue(); auto& info = values.resolution_info; switch (setup) { - case ResolutionSetup::Res1_2X: { + case ResolutionSetup::Res1_2X: info.up_scale = 1; info.down_shift = 1; break; - } - case ResolutionSetup::Res3_4X: { + case ResolutionSetup::Res3_4X: info.up_scale = 3; info.down_shift = 2; break; - } - case ResolutionSetup::Res1X: { + case ResolutionSetup::Res1X: info.up_scale = 1; info.down_shift = 0; break; - } case ResolutionSetup::Res3_2X: { info.up_scale = 3; info.down_shift = 1; break; } - case ResolutionSetup::Res2X: { + case ResolutionSetup::Res2X: info.up_scale = 2; info.down_shift = 0; break; - } - case ResolutionSetup::Res3X: { + case ResolutionSetup::Res3X: info.up_scale = 3; info.down_shift = 0; break; - } - case ResolutionSetup::Res4X: { + case ResolutionSetup::Res4X: info.up_scale = 4; info.down_shift = 0; break; - } - default: { + default: UNREACHABLE(); info.up_scale = 1; info.down_shift = 0; } - } info.up_factor = static_cast(info.up_scale) / (1U << info.down_shift); info.down_factor = static_cast(1U << info.down_shift) / info.up_scale; - info.size_up = info.up_scale * info.up_scale; - info.size_shift = info.down_shift * 2; info.active = info.up_scale != 1 || info.down_shift != 0; } diff --git a/src/common/settings.h b/src/common/settings.h index 2b11984b45..ca88c086b6 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -67,8 +67,6 @@ struct ResolutionScalingInfo { u32 down_shift{0}; f32 up_factor{1.0f}; f32 down_factor{1.0f}; - u32 size_up{1}; - u32 size_shift{0}; bool active{}; }; -- cgit v1.2.3 From bca25d2a0f4a04ba5daee3b75ff554ee01ba13bc Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 17 Aug 2021 00:12:52 +0200 Subject: Renderer: Implement Bicubic and ScaleForce filters. --- src/common/settings.cpp | 10 +- src/common/settings.h | 17 ++- src/video_core/host_shaders/CMakeLists.txt | 4 + .../host_shaders/opengl_present_bicubic.frag | 56 +++++++++ .../host_shaders/opengl_present_scaleforce.frag | 135 ++++++++++++++++++++ .../host_shaders/vulkan_present_bicubic.frag | 56 +++++++++ .../host_shaders/vulkan_present_scaleforce.frag | 137 +++++++++++++++++++++ src/video_core/renderer_opengl/renderer_opengl.cpp | 27 +++- src/video_core/renderer_opengl/renderer_opengl.h | 4 +- src/video_core/renderer_vulkan/vk_blit_screen.cpp | 123 ++++++++++++++++-- src/video_core/renderer_vulkan/vk_blit_screen.h | 8 +- src/yuzu/configuration/config.cpp | 5 + src/yuzu/configuration/config.h | 1 + src/yuzu/configuration/configure_graphics.cpp | 25 ++++ src/yuzu/configuration/configure_graphics.ui | 46 ++++++- 15 files changed, 620 insertions(+), 34 deletions(-) create mode 100644 src/video_core/host_shaders/opengl_present_bicubic.frag create mode 100644 src/video_core/host_shaders/opengl_present_scaleforce.frag create mode 100644 src/video_core/host_shaders/vulkan_present_bicubic.frag create mode 100644 src/video_core/host_shaders/vulkan_present_scaleforce.frag (limited to 'src/common/settings.cpp') diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 4b7fa4b822..f0686a7c50 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -48,6 +48,7 @@ void LogSettings() { log_setting("Core_UseMultiCore", values.use_multi_core.GetValue()); log_setting("CPU_Accuracy", values.cpu_accuracy.GetValue()); log_setting("Renderer_UseResolutionScaling", values.resolution_setup.GetValue()); + log_setting("Renderer_ScalingFilter", values.scaling_filter.GetValue()); log_setting("Renderer_UseSpeedLimit", values.use_speed_limit.GetValue()); log_setting("Renderer_SpeedLimit", values.speed_limit.GetValue()); log_setting("Renderer_UseDiskShaderCache", values.use_disk_shader_cache.GetValue()); @@ -113,19 +114,10 @@ void UpdateRescalingInfo() { info.up_scale = 1; info.down_shift = 1; break; - case ResolutionSetup::Res3_4X: - info.up_scale = 3; - info.down_shift = 2; - break; case ResolutionSetup::Res1X: info.up_scale = 1; info.down_shift = 0; break; - case ResolutionSetup::Res3_2X: { - info.up_scale = 3; - info.down_shift = 1; - break; - } case ResolutionSetup::Res2X: info.up_scale = 2; info.down_shift = 0; diff --git a/src/common/settings.h b/src/common/settings.h index ca88c086b6..f629c7c561 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -54,12 +54,16 @@ enum class NvdecEmulation : u32 { enum class ResolutionSetup : u32 { Res1_2X = 0, - Res3_4X = 1, - Res1X = 2, - Res3_2X = 3, - Res2X = 4, - Res3X = 5, - Res4X = 6, + Res1X = 1, + Res2X = 2, + Res3X = 3, + Res4X = 4, +}; + +enum class ScalingFilter : u32 { + Bilinear = 0, + Bicubic = 1, + ScaleForce = 2, }; struct ResolutionScalingInfo { @@ -471,6 +475,7 @@ struct Values { ResolutionScalingInfo resolution_info{}; Setting resolution_setup{ResolutionSetup::Res1X, "resolution_setup"}; + Setting scaling_filter{ScalingFilter::Bilinear, "scaling_filter"}; // *nix platforms may have issues with the borderless windowed fullscreen mode. // Default to exclusive fullscreen on these platforms for now. RangedSetting fullscreen_mode{ diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index 20d748c12d..835b379447 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt @@ -6,11 +6,15 @@ set(SHADER_FILES convert_float_to_depth.frag full_screen_triangle.vert opengl_copy_bc4.comp + opengl_present_scaleforce.frag + opengl_present_bicubic.frag opengl_present.frag opengl_present.vert pitch_unswizzle.comp vulkan_blit_color_float.frag vulkan_blit_depth_stencil.frag + vulkan_present_bicubic.frag + vulkan_present_scaleforce.frag vulkan_present.frag vulkan_present.vert vulkan_quad_indexed.comp diff --git a/src/video_core/host_shaders/opengl_present_bicubic.frag b/src/video_core/host_shaders/opengl_present_bicubic.frag new file mode 100644 index 0000000000..17772095ae --- /dev/null +++ b/src/video_core/host_shaders/opengl_present_bicubic.frag @@ -0,0 +1,56 @@ +// Copyright 2019 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#version 460 core + +layout (location = 0) in vec2 frag_tex_coord; + +layout (location = 0) out vec4 color; + +layout (binding = 1) uniform sampler2D color_texture; + +vec4 cubic(float v) { + vec4 n = vec4(1.0, 2.0, 3.0, 4.0) - v; + vec4 s = n * n * n; + float x = s.x; + float y = s.y - 4.0 * s.x; + float z = s.z - 4.0 * s.y + 6.0 * s.x; + float w = 6.0 - x - y - z; + return vec4(x, y, z, w) * (1.0 / 6.0); +} + +vec4 textureBicubic( sampler2D textureSampler, vec2 texCoords ) { + + vec2 texSize = textureSize(textureSampler, 0); + vec2 invTexSize = 1.0 / texSize; + + texCoords = texCoords * texSize - 0.5; + + vec2 fxy = fract(texCoords); + texCoords -= fxy; + + vec4 xcubic = cubic(fxy.x); + vec4 ycubic = cubic(fxy.y); + + vec4 c = texCoords.xxyy + vec2(-0.5, +1.5).xyxy; + + vec4 s = vec4(xcubic.xz + xcubic.yw, ycubic.xz + ycubic.yw); + vec4 offset = c + vec4(xcubic.yw, ycubic.yw) / s; + + offset *= invTexSize.xxyy; + + vec4 sample0 = texture(textureSampler, offset.xz); + vec4 sample1 = texture(textureSampler, offset.yz); + vec4 sample2 = texture(textureSampler, offset.xw); + vec4 sample3 = texture(textureSampler, offset.yw); + + float sx = s.x / (s.x + s.y); + float sy = s.z / (s.z + s.w); + + return mix(mix(sample3, sample2, sx), mix(sample1, sample0, sx), sy); +} + +void main() { + color = vec4(textureBicubic(color_texture, frag_tex_coord).rgb, 1.0f); +} diff --git a/src/video_core/host_shaders/opengl_present_scaleforce.frag b/src/video_core/host_shaders/opengl_present_scaleforce.frag new file mode 100644 index 0000000000..0153f62c07 --- /dev/null +++ b/src/video_core/host_shaders/opengl_present_scaleforce.frag @@ -0,0 +1,135 @@ +// from https://github.com/BreadFish64/ScaleFish/tree/master/scale_force + +// MIT License +// +// Copyright (c) 2020 BreadFish64 +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +precision mediump float; + +layout (location = 0) in vec2 tex_coord; + +layout (location = 0) out vec4 frag_color; + +layout (binding = 1) uniform sampler2D input_texture; + +vec2 tex_size; +vec2 inv_tex_size; + +vec4 cubic(float v) { + vec3 n = vec3(1.0, 2.0, 3.0) - v; + vec3 s = n * n * n; + float x = s.x; + float y = s.y - 4.0 * s.x; + float z = s.z - 4.0 * s.y + 6.0 * s.x; + float w = 6.0 - x - y - z; + return vec4(x, y, z, w) / 6.0; +} + +// Bicubic interpolation +vec4 textureBicubic(vec2 tex_coords) { + tex_coords = tex_coords * tex_size - 0.5; + + vec2 fxy = modf(tex_coords, tex_coords); + + vec4 xcubic = cubic(fxy.x); + vec4 ycubic = cubic(fxy.y); + + vec4 c = tex_coords.xxyy + vec2(-0.5, +1.5).xyxy; + + vec4 s = vec4(xcubic.xz + xcubic.yw, ycubic.xz + ycubic.yw); + vec4 offset = c + vec4(xcubic.yw, ycubic.yw) / s; + + offset *= inv_tex_size.xxyy; + + vec4 sample0 = textureLod(input_texture, offset.xz, 0.0); + vec4 sample1 = textureLod(input_texture, offset.yz, 0.0); + vec4 sample2 = textureLod(input_texture, offset.xw, 0.0); + vec4 sample3 = textureLod(input_texture, offset.yw, 0.0); + + float sx = s.x / (s.x + s.y); + float sy = s.z / (s.z + s.w); + + return mix(mix(sample3, sample2, sx), mix(sample1, sample0, sx), sy); +} + +mat4x3 center_matrix; +vec4 center_alpha; + +// Finds the distance between four colors and cc in YCbCr space +vec4 ColorDist(vec4 A, vec4 B, vec4 C, vec4 D) { + // https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.2020_conversion + const vec3 K = vec3(0.2627, 0.6780, 0.0593); + const float LUMINANCE_WEIGHT = .6; + const mat3 YCBCR_MATRIX = + mat3(K * LUMINANCE_WEIGHT, -.5 * K.r / (1.0 - K.b), -.5 * K.g / (1.0 - K.b), .5, .5, + -.5 * K.g / (1.0 - K.r), -.5 * K.b / (1.0 - K.r)); + + mat4x3 colors = mat4x3(A.rgb, B.rgb, C.rgb, D.rgb) - center_matrix; + mat4x3 YCbCr = YCBCR_MATRIX * colors; + vec4 color_dist = vec3(1.0) * YCbCr; + color_dist *= color_dist; + vec4 alpha = vec4(A.a, B.a, C.a, D.a); + + return sqrt((color_dist + abs(center_alpha - alpha)) * alpha * center_alpha); +} + +void main() { + vec4 bl = textureLodOffset(input_texture, tex_coord, 0.0, ivec2(-1, -1)); + vec4 bc = textureLodOffset(input_texture, tex_coord, 0.0, ivec2(0, -1)); + vec4 br = textureLodOffset(input_texture, tex_coord, 0.0, ivec2(1, -1)); + vec4 cl = textureLodOffset(input_texture, tex_coord, 0.0, ivec2(-1, 0)); + vec4 cc = textureLod(input_texture, tex_coord, 0.0); + vec4 cr = textureLodOffset(input_texture, tex_coord, 0.0, ivec2(1, 0)); + vec4 tl = textureLodOffset(input_texture, tex_coord, 0.0, ivec2(-1, 1)); + vec4 tc = textureLodOffset(input_texture, tex_coord, 0.0, ivec2(0, 1)); + vec4 tr = textureLodOffset(input_texture, tex_coord, 0.0, ivec2(1, 1)); + + + tex_size = vec2(textureSize(input_texture, 0)); + inv_tex_size = 1.0 / tex_size; + center_matrix = mat4x3(cc.rgb, cc.rgb, cc.rgb, cc.rgb); + center_alpha = cc.aaaa; + + vec4 offset_tl = ColorDist(tl, tc, tr, cr); + vec4 offset_br = ColorDist(br, bc, bl, cl); + + // Calculate how different cc is from the texels around it + float total_dist = dot(offset_tl + offset_br, vec4(1.0)); + + // Add together all the distances with direction taken into account + vec4 tmp = offset_tl - offset_br; + vec2 total_offset = tmp.wy + tmp.zz + vec2(-tmp.x, tmp.x); + + if (total_dist == 0.0) { + // Doing bicubic filtering just past the edges where the offset is 0 causes black floaters + // and it doesn't really matter which filter is used when the colors aren't changing. + frag_color = vec4(cc.rgb, 1.0f); + } else { + // When the image has thin points, they tend to split apart. + // This is because the texels all around are different + // and total_offset reaches into clear areas. + // This works pretty well to keep the offset in bounds for these cases. + float clamp_val = length(total_offset) / total_dist; + vec2 final_offset = clamp(total_offset, -clamp_val, clamp_val) * inv_tex_size; + + frag_color = vec4(textureBicubic(tex_coord - final_offset).rgb, 1.0f); + } +} diff --git a/src/video_core/host_shaders/vulkan_present_bicubic.frag b/src/video_core/host_shaders/vulkan_present_bicubic.frag new file mode 100644 index 0000000000..17772095ae --- /dev/null +++ b/src/video_core/host_shaders/vulkan_present_bicubic.frag @@ -0,0 +1,56 @@ +// Copyright 2019 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#version 460 core + +layout (location = 0) in vec2 frag_tex_coord; + +layout (location = 0) out vec4 color; + +layout (binding = 1) uniform sampler2D color_texture; + +vec4 cubic(float v) { + vec4 n = vec4(1.0, 2.0, 3.0, 4.0) - v; + vec4 s = n * n * n; + float x = s.x; + float y = s.y - 4.0 * s.x; + float z = s.z - 4.0 * s.y + 6.0 * s.x; + float w = 6.0 - x - y - z; + return vec4(x, y, z, w) * (1.0 / 6.0); +} + +vec4 textureBicubic( sampler2D textureSampler, vec2 texCoords ) { + + vec2 texSize = textureSize(textureSampler, 0); + vec2 invTexSize = 1.0 / texSize; + + texCoords = texCoords * texSize - 0.5; + + vec2 fxy = fract(texCoords); + texCoords -= fxy; + + vec4 xcubic = cubic(fxy.x); + vec4 ycubic = cubic(fxy.y); + + vec4 c = texCoords.xxyy + vec2(-0.5, +1.5).xyxy; + + vec4 s = vec4(xcubic.xz + xcubic.yw, ycubic.xz + ycubic.yw); + vec4 offset = c + vec4(xcubic.yw, ycubic.yw) / s; + + offset *= invTexSize.xxyy; + + vec4 sample0 = texture(textureSampler, offset.xz); + vec4 sample1 = texture(textureSampler, offset.yz); + vec4 sample2 = texture(textureSampler, offset.xw); + vec4 sample3 = texture(textureSampler, offset.yw); + + float sx = s.x / (s.x + s.y); + float sy = s.z / (s.z + s.w); + + return mix(mix(sample3, sample2, sx), mix(sample1, sample0, sx), sy); +} + +void main() { + color = vec4(textureBicubic(color_texture, frag_tex_coord).rgb, 1.0f); +} diff --git a/src/video_core/host_shaders/vulkan_present_scaleforce.frag b/src/video_core/host_shaders/vulkan_present_scaleforce.frag new file mode 100644 index 0000000000..801c8eae96 --- /dev/null +++ b/src/video_core/host_shaders/vulkan_present_scaleforce.frag @@ -0,0 +1,137 @@ +#version 320 es + +// from https://github.com/BreadFish64/ScaleFish/tree/master/scale_force + +// MIT License +// +// Copyright (c) 2020 BreadFish64 +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +precision mediump float; + +layout (location = 0) in vec2 tex_coord; + +layout (location = 0) out vec4 frag_color; + +layout (binding = 1) uniform sampler2D input_texture; + +vec2 tex_size; +vec2 inv_tex_size; + +vec4 cubic(float v) { + vec3 n = vec3(1.0, 2.0, 3.0) - v; + vec3 s = n * n * n; + float x = s.x; + float y = s.y - 4.0 * s.x; + float z = s.z - 4.0 * s.y + 6.0 * s.x; + float w = 6.0 - x - y - z; + return vec4(x, y, z, w) / 6.0; +} + +// Bicubic interpolation +vec4 textureBicubic(vec2 tex_coords) { + tex_coords = tex_coords * tex_size - 0.5; + + vec2 fxy = modf(tex_coords, tex_coords); + + vec4 xcubic = cubic(fxy.x); + vec4 ycubic = cubic(fxy.y); + + vec4 c = tex_coords.xxyy + vec2(-0.5, +1.5).xyxy; + + vec4 s = vec4(xcubic.xz + xcubic.yw, ycubic.xz + ycubic.yw); + vec4 offset = c + vec4(xcubic.yw, ycubic.yw) / s; + + offset *= inv_tex_size.xxyy; + + vec4 sample0 = textureLod(input_texture, offset.xz, 0.0); + vec4 sample1 = textureLod(input_texture, offset.yz, 0.0); + vec4 sample2 = textureLod(input_texture, offset.xw, 0.0); + vec4 sample3 = textureLod(input_texture, offset.yw, 0.0); + + float sx = s.x / (s.x + s.y); + float sy = s.z / (s.z + s.w); + + return mix(mix(sample3, sample2, sx), mix(sample1, sample0, sx), sy); +} + +mat4x3 center_matrix; +vec4 center_alpha; + +// Finds the distance between four colors and cc in YCbCr space +vec4 ColorDist(vec4 A, vec4 B, vec4 C, vec4 D) { + // https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.2020_conversion + const vec3 K = vec3(0.2627, 0.6780, 0.0593); + const float LUMINANCE_WEIGHT = .6; + const mat3 YCBCR_MATRIX = + mat3(K * LUMINANCE_WEIGHT, -.5 * K.r / (1.0 - K.b), -.5 * K.g / (1.0 - K.b), .5, .5, + -.5 * K.g / (1.0 - K.r), -.5 * K.b / (1.0 - K.r)); + + mat4x3 colors = mat4x3(A.rgb, B.rgb, C.rgb, D.rgb) - center_matrix; + mat4x3 YCbCr = YCBCR_MATRIX * colors; + vec4 color_dist = vec3(1.0) * YCbCr; + color_dist *= color_dist; + vec4 alpha = vec4(A.a, B.a, C.a, D.a); + + return sqrt((color_dist + abs(center_alpha - alpha)) * alpha * center_alpha); +} + +void main() { + vec4 bl = textureLodOffset(input_texture, tex_coord, 0.0, ivec2(-1, -1)); + vec4 bc = textureLodOffset(input_texture, tex_coord, 0.0, ivec2(0, -1)); + vec4 br = textureLodOffset(input_texture, tex_coord, 0.0, ivec2(1, -1)); + vec4 cl = textureLodOffset(input_texture, tex_coord, 0.0, ivec2(-1, 0)); + vec4 cc = textureLod(input_texture, tex_coord, 0.0); + vec4 cr = textureLodOffset(input_texture, tex_coord, 0.0, ivec2(1, 0)); + vec4 tl = textureLodOffset(input_texture, tex_coord, 0.0, ivec2(-1, 1)); + vec4 tc = textureLodOffset(input_texture, tex_coord, 0.0, ivec2(0, 1)); + vec4 tr = textureLodOffset(input_texture, tex_coord, 0.0, ivec2(1, 1)); + + + tex_size = vec2(textureSize(input_texture, 0)); + inv_tex_size = 1.0 / tex_size; + center_matrix = mat4x3(cc.rgb, cc.rgb, cc.rgb, cc.rgb); + center_alpha = cc.aaaa; + + vec4 offset_tl = ColorDist(tl, tc, tr, cr); + vec4 offset_br = ColorDist(br, bc, bl, cl); + + // Calculate how different cc is from the texels around it + float total_dist = dot(offset_tl + offset_br, vec4(1.0)); + + // Add together all the distances with direction taken into account + vec4 tmp = offset_tl - offset_br; + vec2 total_offset = tmp.wy + tmp.zz + vec2(-tmp.x, tmp.x); + + if (total_dist == 0.0) { + // Doing bicubic filtering just past the edges where the offset is 0 causes black floaters + // and it doesn't really matter which filter is used when the colors aren't changing. + frag_color = vec4(cc.rgb, 1.0f); + } else { + // When the image has thin points, they tend to split apart. + // This is because the texels all around are different + // and total_offset reaches into clear areas. + // This works pretty well to keep the offset in bounds for these cases. + float clamp_val = length(total_offset) / total_dist; + vec2 final_offset = clamp(total_offset, -clamp_val, clamp_val) * inv_tex_size; + + frag_color = vec4(textureBicubic(tex_coord - final_offset).rgb, 1.0f); + } +} diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 0f7b69c6df..71a5e3adfa 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -21,7 +21,9 @@ #include "core/memory.h" #include "core/perf_stats.h" #include "core/telemetry_session.h" +#include "video_core/host_shaders/opengl_present_bicubic_frag.h" #include "video_core/host_shaders/opengl_present_frag.h" +#include "video_core/host_shaders/opengl_present_scaleforce_frag.h" #include "video_core/host_shaders/opengl_present_vert.h" #include "video_core/renderer_opengl/gl_rasterizer.h" #include "video_core/renderer_opengl/gl_shader_manager.h" @@ -252,7 +254,11 @@ void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color void RendererOpenGL::InitOpenGLObjects() { // Create shader programs present_vertex = CreateProgram(HostShaders::OPENGL_PRESENT_VERT, GL_VERTEX_SHADER); - present_fragment = CreateProgram(HostShaders::OPENGL_PRESENT_FRAG, GL_FRAGMENT_SHADER); + present_bilinear_fragment = CreateProgram(HostShaders::OPENGL_PRESENT_FRAG, GL_FRAGMENT_SHADER); + present_bicubic_fragment = + CreateProgram(HostShaders::OPENGL_PRESENT_BICUBIC_FRAG, GL_FRAGMENT_SHADER); + present_scaleforce_fragment = + CreateProgram(HostShaders::OPENGL_PRESENT_SCALEFORCE_FRAG, GL_FRAGMENT_SHADER); // Generate presentation sampler present_sampler.Create(); @@ -337,7 +343,24 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { // Set projection matrix const std::array ortho_matrix = MakeOrthographicMatrix(static_cast(layout.width), static_cast(layout.height)); - program_manager.BindPresentPrograms(present_vertex.handle, present_fragment.handle); + + GLuint fragment_handle; + const auto filter = Settings::values.scaling_filter.GetValue(); + switch (filter) { + case Settings::ScalingFilter::Bilinear: + fragment_handle = present_bilinear_fragment.handle; + break; + case Settings::ScalingFilter::Bicubic: + fragment_handle = present_bicubic_fragment.handle; + break; + case Settings::ScalingFilter::ScaleForce: + fragment_handle = present_scaleforce_fragment.handle; + break; + default: + fragment_handle = present_bilinear_fragment.handle; + break; + } + program_manager.BindPresentPrograms(present_vertex.handle, fragment_handle); glProgramUniformMatrix3x2fv(present_vertex.handle, ModelViewMatrixLocation, 1, GL_FALSE, ortho_matrix.data()); diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index d455f572f2..bf3d3502cd 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -111,7 +111,9 @@ private: OGLSampler present_sampler; OGLBuffer vertex_buffer; OGLProgram present_vertex; - OGLProgram present_fragment; + OGLProgram present_bilinear_fragment; + OGLProgram present_bicubic_fragment; + OGLProgram present_scaleforce_fragment; OGLFramebuffer screenshot_framebuffer; // GPU address of the vertex buffer diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index 7051e65595..19d91ecfc0 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp +++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp @@ -12,11 +12,14 @@ #include "common/assert.h" #include "common/common_types.h" #include "common/math_util.h" +#include "common/settings.h" #include "core/core.h" #include "core/frontend/emu_window.h" #include "core/memory.h" #include "video_core/gpu.h" +#include "video_core/host_shaders/vulkan_present_bicubic_frag_spv.h" #include "video_core/host_shaders/vulkan_present_frag_spv.h" +#include "video_core/host_shaders/vulkan_present_scaleforce_frag_spv.h" #include "video_core/host_shaders/vulkan_present_vert_spv.h" #include "video_core/renderer_vulkan/renderer_vulkan.h" #include "video_core/renderer_vulkan/vk_blit_screen.h" @@ -258,8 +261,22 @@ VkSemaphore VKBlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer, .offset = {0, 0}, .extent = size, }; + const auto filter = Settings::values.scaling_filter.GetValue(); cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE); - cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); + switch (filter) { + case Settings::ScalingFilter::Bilinear: + cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *bilinear_pipeline); + break; + case Settings::ScalingFilter::Bicubic: + cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *bicubic_pipeline); + break; + case Settings::ScalingFilter::ScaleForce: + cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *scaleforce_pipeline); + break; + default: + cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *bilinear_pipeline); + break; + } cmdbuf.SetViewport(0, viewport); cmdbuf.SetScissor(0, scissor); @@ -324,7 +341,9 @@ void VKBlitScreen::RefreshResources(const Tegra::FramebufferConfig& framebuffer) void VKBlitScreen::CreateShaders() { vertex_shader = BuildShader(device, VULKAN_PRESENT_VERT_SPV); - fragment_shader = BuildShader(device, VULKAN_PRESENT_FRAG_SPV); + bilinear_fragment_shader = BuildShader(device, VULKAN_PRESENT_FRAG_SPV); + bicubic_fragment_shader = BuildShader(device, VULKAN_PRESENT_BICUBIC_FRAG_SPV); + scaleforce_fragment_shader = BuildShader(device, VULKAN_PRESENT_SCALEFORCE_FRAG_SPV); } void VKBlitScreen::CreateSemaphores() { @@ -468,7 +487,7 @@ void VKBlitScreen::CreatePipelineLayout() { } void VKBlitScreen::CreateGraphicsPipeline() { - const std::array shader_stages{{ + const std::array bilinear_shader_stages{{ { .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, .pNext = nullptr, @@ -483,7 +502,49 @@ void VKBlitScreen::CreateGraphicsPipeline() { .pNext = nullptr, .flags = 0, .stage = VK_SHADER_STAGE_FRAGMENT_BIT, - .module = *fragment_shader, + .module = *bilinear_fragment_shader, + .pName = "main", + .pSpecializationInfo = nullptr, + }, + }}; + + const std::array bicubic_shader_stages{{ + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .stage = VK_SHADER_STAGE_VERTEX_BIT, + .module = *vertex_shader, + .pName = "main", + .pSpecializationInfo = nullptr, + }, + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .stage = VK_SHADER_STAGE_FRAGMENT_BIT, + .module = *bicubic_fragment_shader, + .pName = "main", + .pSpecializationInfo = nullptr, + }, + }}; + + const std::array scaleforce_shader_stages{{ + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .stage = VK_SHADER_STAGE_VERTEX_BIT, + .module = *vertex_shader, + .pName = "main", + .pSpecializationInfo = nullptr, + }, + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .stage = VK_SHADER_STAGE_FRAGMENT_BIT, + .module = *scaleforce_fragment_shader, .pName = "main", .pSpecializationInfo = nullptr, }, @@ -583,12 +644,56 @@ void VKBlitScreen::CreateGraphicsPipeline() { .pDynamicStates = dynamic_states.data(), }; - const VkGraphicsPipelineCreateInfo pipeline_ci{ + const VkGraphicsPipelineCreateInfo bilinear_pipeline_ci{ + .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .stageCount = static_cast(bilinear_shader_stages.size()), + .pStages = bilinear_shader_stages.data(), + .pVertexInputState = &vertex_input_ci, + .pInputAssemblyState = &input_assembly_ci, + .pTessellationState = nullptr, + .pViewportState = &viewport_state_ci, + .pRasterizationState = &rasterization_ci, + .pMultisampleState = &multisampling_ci, + .pDepthStencilState = nullptr, + .pColorBlendState = &color_blend_ci, + .pDynamicState = &dynamic_state_ci, + .layout = *pipeline_layout, + .renderPass = *renderpass, + .subpass = 0, + .basePipelineHandle = 0, + .basePipelineIndex = 0, + }; + + const VkGraphicsPipelineCreateInfo bicubic_pipeline_ci{ + .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .stageCount = static_cast(bicubic_shader_stages.size()), + .pStages = bicubic_shader_stages.data(), + .pVertexInputState = &vertex_input_ci, + .pInputAssemblyState = &input_assembly_ci, + .pTessellationState = nullptr, + .pViewportState = &viewport_state_ci, + .pRasterizationState = &rasterization_ci, + .pMultisampleState = &multisampling_ci, + .pDepthStencilState = nullptr, + .pColorBlendState = &color_blend_ci, + .pDynamicState = &dynamic_state_ci, + .layout = *pipeline_layout, + .renderPass = *renderpass, + .subpass = 0, + .basePipelineHandle = 0, + .basePipelineIndex = 0, + }; + + const VkGraphicsPipelineCreateInfo scaleforce_pipeline_ci{ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .pNext = nullptr, .flags = 0, - .stageCount = static_cast(shader_stages.size()), - .pStages = shader_stages.data(), + .stageCount = static_cast(scaleforce_shader_stages.size()), + .pStages = scaleforce_shader_stages.data(), .pVertexInputState = &vertex_input_ci, .pInputAssemblyState = &input_assembly_ci, .pTessellationState = nullptr, @@ -605,7 +710,9 @@ void VKBlitScreen::CreateGraphicsPipeline() { .basePipelineIndex = 0, }; - pipeline = device.GetLogical().CreateGraphicsPipeline(pipeline_ci); + bilinear_pipeline = device.GetLogical().CreateGraphicsPipeline(bilinear_pipeline_ci); + bicubic_pipeline = device.GetLogical().CreateGraphicsPipeline(bicubic_pipeline_ci); + scaleforce_pipeline = device.GetLogical().CreateGraphicsPipeline(scaleforce_pipeline_ci); } void VKBlitScreen::CreateSampler() { diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.h b/src/video_core/renderer_vulkan/vk_blit_screen.h index 430bcfbcad..d3a16f0ba2 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.h +++ b/src/video_core/renderer_vulkan/vk_blit_screen.h @@ -107,11 +107,15 @@ private: const VKScreenInfo& screen_info; vk::ShaderModule vertex_shader; - vk::ShaderModule fragment_shader; + vk::ShaderModule bilinear_fragment_shader; + vk::ShaderModule bicubic_fragment_shader; + vk::ShaderModule scaleforce_fragment_shader; vk::DescriptorPool descriptor_pool; vk::DescriptorSetLayout descriptor_set_layout; vk::PipelineLayout pipeline_layout; - vk::Pipeline pipeline; + vk::Pipeline bilinear_pipeline; + vk::Pipeline bicubic_pipeline; + vk::Pipeline scaleforce_pipeline; vk::RenderPass renderpass; std::vector framebuffers; vk::DescriptorSets descriptor_sets; diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 7ed833203c..3803bf501a 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -825,6 +825,7 @@ void Config::ReadRendererValues() { ReadGlobalSetting(Settings::values.fullscreen_mode); ReadGlobalSetting(Settings::values.aspect_ratio); ReadGlobalSetting(Settings::values.resolution_setup); + ReadGlobalSetting(Settings::values.scaling_filter); ReadGlobalSetting(Settings::values.max_anisotropy); ReadGlobalSetting(Settings::values.use_speed_limit); ReadGlobalSetting(Settings::values.speed_limit); @@ -1371,6 +1372,10 @@ void Config::SaveRendererValues() { static_cast(Settings::values.resolution_setup.GetValue(global)), static_cast(Settings::values.resolution_setup.GetDefault()), Settings::values.resolution_setup.UsingGlobal()); + WriteSetting(QString::fromStdString(Settings::values.scaling_filter.GetLabel()), + static_cast(Settings::values.scaling_filter.GetValue(global)), + static_cast(Settings::values.scaling_filter.GetDefault()), + Settings::values.scaling_filter.UsingGlobal()); WriteGlobalSetting(Settings::values.max_anisotropy); WriteGlobalSetting(Settings::values.use_speed_limit); WriteGlobalSetting(Settings::values.speed_limit); diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index fbb91d3125..97dc1bb47b 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h @@ -190,5 +190,6 @@ Q_DECLARE_METATYPE(Settings::GPUAccuracy); Q_DECLARE_METATYPE(Settings::FullscreenMode); Q_DECLARE_METATYPE(Settings::NvdecEmulation); Q_DECLARE_METATYPE(Settings::ResolutionSetup); +Q_DECLARE_METATYPE(Settings::ScalingFilter); Q_DECLARE_METATYPE(Settings::RendererBackend); Q_DECLARE_METATYPE(Settings::ShaderBackend); diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index 4f08ae3e07..e01efaeda5 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -89,6 +89,7 @@ void ConfigureGraphics::SetConfiguration() { ui->use_asynchronous_gpu_emulation->setEnabled(runtime_lock); ui->use_disk_shader_cache->setEnabled(runtime_lock); ui->nvdec_emulation_widget->setEnabled(runtime_lock); + ui->resolution_combobox->setEnabled(runtime_lock); ui->accelerate_astc->setEnabled(runtime_lock); ui->use_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache.GetValue()); ui->use_asynchronous_gpu_emulation->setChecked( @@ -104,6 +105,8 @@ void ConfigureGraphics::SetConfiguration() { ui->aspect_ratio_combobox->setCurrentIndex(Settings::values.aspect_ratio.GetValue()); ui->resolution_combobox->setCurrentIndex( static_cast(Settings::values.resolution_setup.GetValue())); + ui->scaling_filter_combobox->setCurrentIndex( + static_cast(Settings::values.scaling_filter.GetValue())); } else { ConfigurationShared::SetPerGameSetting(ui->api, &Settings::values.renderer_backend); ConfigurationShared::SetHighlight(ui->api_widget, @@ -129,6 +132,11 @@ void ConfigureGraphics::SetConfiguration() { ConfigurationShared::SetHighlight(ui->resolution_label, !Settings::values.resolution_setup.UsingGlobal()); + ConfigurationShared::SetPerGameSetting(ui->scaling_filter_combobox, + &Settings::values.scaling_filter); + ConfigurationShared::SetHighlight(ui->scaling_filter_label, + !Settings::values.scaling_filter.UsingGlobal()); + ui->bg_combobox->setCurrentIndex(Settings::values.bg_red.UsingGlobal() ? 0 : 1); ui->bg_button->setEnabled(!Settings::values.bg_red.UsingGlobal()); ConfigurationShared::SetHighlight(ui->bg_layout, !Settings::values.bg_red.UsingGlobal()); @@ -144,6 +152,10 @@ void ConfigureGraphics::ApplyConfiguration() { ui->resolution_combobox->currentIndex() - ((Settings::IsConfiguringGlobal()) ? 0 : ConfigurationShared::USE_GLOBAL_OFFSET)); + const auto scaling_filter = static_cast( + ui->scaling_filter_combobox->currentIndex() - + ((Settings::IsConfiguringGlobal()) ? 0 : ConfigurationShared::USE_GLOBAL_OFFSET)); + ConfigurationShared::ApplyPerGameSetting(&Settings::values.fullscreen_mode, ui->fullscreen_mode_combobox); ConfigurationShared::ApplyPerGameSetting(&Settings::values.aspect_ratio, @@ -178,6 +190,9 @@ void ConfigureGraphics::ApplyConfiguration() { if (Settings::values.resolution_setup.UsingGlobal()) { Settings::values.resolution_setup.SetValue(resolution_setup); } + if (Settings::values.scaling_filter.UsingGlobal()) { + Settings::values.scaling_filter.SetValue(scaling_filter); + } } else { if (ui->resolution_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { Settings::values.resolution_setup.SetGlobal(true); @@ -185,6 +200,12 @@ void ConfigureGraphics::ApplyConfiguration() { Settings::values.resolution_setup.SetGlobal(false); Settings::values.resolution_setup.SetValue(resolution_setup); } + if (ui->scaling_filter_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { + Settings::values.scaling_filter.SetGlobal(true); + } else { + Settings::values.scaling_filter.SetGlobal(false); + Settings::values.scaling_filter.SetValue(scaling_filter); + } if (ui->api->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { Settings::values.renderer_backend.SetGlobal(true); Settings::values.shader_backend.SetGlobal(true); @@ -333,6 +354,7 @@ void ConfigureGraphics::SetupPerGameUI() { ui->fullscreen_mode_combobox->setEnabled(Settings::values.fullscreen_mode.UsingGlobal()); ui->aspect_ratio_combobox->setEnabled(Settings::values.aspect_ratio.UsingGlobal()); ui->resolution_combobox->setEnabled(Settings::values.resolution_setup.UsingGlobal()); + ui->scaling_filter_combobox->setEnabled(Settings::values.scaling_filter.UsingGlobal()); ui->use_asynchronous_gpu_emulation->setEnabled( Settings::values.use_asynchronous_gpu_emulation.UsingGlobal()); ui->nvdec_emulation->setEnabled(Settings::values.nvdec_emulation.UsingGlobal()); @@ -364,6 +386,9 @@ void ConfigureGraphics::SetupPerGameUI() { ConfigurationShared::SetColoredComboBox( ui->resolution_combobox, ui->resolution_label, static_cast(Settings::values.resolution_setup.GetValue(true))); + ConfigurationShared::SetColoredComboBox( + ui->scaling_filter_combobox, ui->scaling_filter_label, + static_cast(Settings::values.scaling_filter.GetValue(true))); ConfigurationShared::InsertGlobalItem( ui->api, static_cast(Settings::values.renderer_backend.GetValue(true))); ConfigurationShared::InsertGlobalItem( diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui index 1b6ac3cbba..d5e0d4e897 100644 --- a/src/yuzu/configuration/configure_graphics.ui +++ b/src/yuzu/configuration/configure_graphics.ui @@ -340,32 +340,66 @@ - 0.75X (540p/810p) + 1X (720p/1080p) - 1X (720p/1080p) + 2X (1440p/2160[4K]p) - 1.5X (1080p/1620p) + 3X (2160p[4K]/3240p[6K]) - 2X (1440p/2160[4K]p) + 4X (2880p/4320p[8K]) + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Window Adapting Filter: + + + + + - 3X (2160p[4K]/3240p[6K]) + Bilinear - 4X (2880p/4320p[8K]) + Bicubic + + + + + ScaleForce -- cgit v1.2.3 From d99a6e8e4734d1a8ed9f66453c962b6f0f8d6357 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: video_core: Misc resolution scaling related refactoring --- src/common/settings.cpp | 2 +- src/video_core/renderer_opengl/gl_rasterizer.cpp | 4 +-- .../renderer_opengl/gl_texture_cache.cpp | 31 +++++++++------------- src/video_core/renderer_opengl/gl_texture_cache.h | 11 +++++--- src/video_core/renderer_vulkan/vk_state_tracker.h | 10 ++++--- .../renderer_vulkan/vk_texture_cache.cpp | 31 +++++++++++++--------- src/video_core/renderer_vulkan/vk_texture_cache.h | 7 +++-- src/video_core/texture_cache/texture_cache.h | 2 -- 8 files changed, 51 insertions(+), 47 deletions(-) (limited to 'src/common/settings.cpp') 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 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 -#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 rescale_draw_fbos; std::array 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& 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& color) { if (info.type == ImageType::e3D) { flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT; } - const auto scale_up = [&](u32 value) { return std::max((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& 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(info.resources.levels), @@ -163,12 +160,11 @@ constexpr VkBorderColor ConvertBorderColor(const std::array& 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((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 -#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

::CopyImage(ImageId dst_id, ImageId src_id, std::vector Date: Fri, 15 Oct 2021 22:59:16 +0200 Subject: Texture Cahe: Fix downscaling on SMO. --- src/common/settings.cpp | 2 ++ src/common/settings.h | 1 + src/video_core/texture_cache/image_info.cpp | 4 ++++ src/video_core/texture_cache/image_info.h | 1 + src/video_core/texture_cache/texture_cache.h | 3 +++ 5 files changed, 11 insertions(+) (limited to 'src/common/settings.cpp') diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 12fdb0f9b6..bc2c8c7d7e 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -109,10 +109,12 @@ float Volume() { void UpdateRescalingInfo() { const auto setup = values.resolution_setup.GetValue(); auto& info = values.resolution_info; + info.downscale = false; switch (setup) { case ResolutionSetup::Res1_2X: info.up_scale = 1; info.down_shift = 1; + info.downscale = true; break; case ResolutionSetup::Res1X: info.up_scale = 1; diff --git a/src/common/settings.h b/src/common/settings.h index 09f7cdd842..a09db08225 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -72,6 +72,7 @@ struct ResolutionScalingInfo { f32 up_factor{1.0f}; f32 down_factor{1.0f}; bool active{}; + bool downscale{}; s32 ScaleUp(s32 value) const { if (value == 0) { diff --git a/src/video_core/texture_cache/image_info.cpp b/src/video_core/texture_cache/image_info.cpp index 7fa8fd4fe0..d8e414247e 100644 --- a/src/video_core/texture_cache/image_info.cpp +++ b/src/video_core/texture_cache/image_info.cpp @@ -102,6 +102,7 @@ ImageInfo::ImageInfo(const TICEntry& config) noexcept { layer_stride = CalculateLayerStride(*this); maybe_unaligned_layer_stride = CalculateLayerSize(*this); rescaleable &= (block.depth == 0) && resources.levels == 1; + downscaleable = size.height > 512; } } @@ -135,6 +136,7 @@ ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs, size_t index) size.depth = rt.depth; } else { rescaleable = block.depth == 0 && size.height > 256; + downscaleable = size.height > 512; type = ImageType::e2D; resources.layers = rt.depth; } @@ -164,6 +166,7 @@ ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs) noexcept { size.depth = regs.zeta_depth; } else { rescaleable = block.depth == 0 && size.height > 256; + downscaleable = size.height > 512; type = ImageType::e2D; resources.layers = regs.zeta_depth; } @@ -197,6 +200,7 @@ ImageInfo::ImageInfo(const Tegra::Engines::Fermi2D::Surface& config) noexcept { .depth = 1, }; rescaleable = block.depth == 0 && size.height > 256; + downscaleable = size.height > 512; } } diff --git a/src/video_core/texture_cache/image_info.h b/src/video_core/texture_cache/image_info.h index e874d28702..5932dcabaf 100644 --- a/src/video_core/texture_cache/image_info.h +++ b/src/video_core/texture_cache/image_info.h @@ -34,6 +34,7 @@ struct ImageInfo { u32 num_samples = 1; u32 tile_width_spacing = 0; bool rescaleable = false; + bool downscaleable = false; }; } // namespace VideoCommon diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index c1fb12679b..261cb6c48a 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -798,6 +798,9 @@ bool TextureCache

::ImageCanRescale(ImageBase& image) { if (!image.info.rescaleable || True(image.flags & ImageFlagBits::Blacklisted)) { return false; } + if (Settings::values.resolution_info.downscale && !image.info.downscaleable) { + return false; + } if (True(image.flags & (ImageFlagBits::Rescaled | ImageFlagBits::CheckingRescalable))) { return true; } -- cgit v1.2.3 From 43200a46fe0537e1c5fa020bd541412ca5c8fca2 Mon Sep 17 00:00:00 2001 From: FernandoS27 Date: Wed, 20 Oct 2021 18:56:34 +0200 Subject: VideoCore: Add more rescaling option. --- src/common/settings.cpp | 13 +++++++++++++ src/common/settings.h | 11 +++++++---- src/yuzu/configuration/configure_graphics.ui | 21 ++++++++++++++++++--- 3 files changed, 38 insertions(+), 7 deletions(-) (limited to 'src/common/settings.cpp') diff --git a/src/common/settings.cpp b/src/common/settings.cpp index bc2c8c7d7e..84ac937e52 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -116,6 +116,11 @@ void UpdateRescalingInfo() { info.down_shift = 1; info.downscale = true; break; + case ResolutionSetup::Res3_4X: + info.up_scale = 3; + info.down_shift = 2; + info.downscale = true; + break; case ResolutionSetup::Res1X: info.up_scale = 1; info.down_shift = 0; @@ -132,6 +137,14 @@ void UpdateRescalingInfo() { info.up_scale = 4; info.down_shift = 0; break; + case ResolutionSetup::Res5X: + info.up_scale = 5; + info.down_shift = 0; + break; + case ResolutionSetup::Res6X: + info.up_scale = 6; + info.down_shift = 0; + break; default: UNREACHABLE(); info.up_scale = 1; diff --git a/src/common/settings.h b/src/common/settings.h index 84dab52174..f6acf5bdf1 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -54,10 +54,13 @@ enum class NvdecEmulation : u32 { enum class ResolutionSetup : u32 { Res1_2X = 0, - Res1X = 1, - Res2X = 2, - Res3X = 3, - Res4X = 4, + Res3_4X = 1, + Res1X = 2, + Res2X = 3, + Res3X = 4, + Res4X = 5, + Res5X = 6, + Res6X = 7, }; enum class ScalingFilter : u32 { diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui index fe2f6bb7f3..c1d7e83494 100644 --- a/src/yuzu/configuration/configure_graphics.ui +++ b/src/yuzu/configuration/configure_graphics.ui @@ -335,7 +335,12 @@ - 0.5X (360p/540p) + 0.5X (360p/540p)[MAY BREAK] + + + + + 0.75X (540p/810p)[MAY BREAK] @@ -350,12 +355,22 @@ - 3X (2160p[4K]/3240p[6K]) + 3X (2160p[4K]/3240p) + + + + + 4X (2880p/4320p) + + + + + 5X (3600p/5400p) - 4X (2880p/4320p[8K]) + 6X (4320p/6480p) -- cgit v1.2.3 From d5d689d3aa4f317428d6a81610549dcc43f79ad4 Mon Sep 17 00:00:00 2001 From: Marshall Mohror Date: Wed, 20 Oct 2021 18:32:11 -0500 Subject: Settings: Add anti-aliasing method setting --- src/common/settings.cpp | 1 + src/common/settings.h | 6 ++++++ 2 files changed, 7 insertions(+) (limited to 'src/common/settings.cpp') diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 84ac937e52..3bcaa072f6 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -49,6 +49,7 @@ void LogSettings() { log_setting("CPU_Accuracy", values.cpu_accuracy.GetValue()); log_setting("Renderer_UseResolutionScaling", values.resolution_setup.GetValue()); log_setting("Renderer_ScalingFilter", values.scaling_filter.GetValue()); + log_setting("Renderer_AntiAliasing", values.anti_aliasing.GetValue()); log_setting("Renderer_UseSpeedLimit", values.use_speed_limit.GetValue()); log_setting("Renderer_SpeedLimit", values.speed_limit.GetValue()); log_setting("Renderer_UseDiskShaderCache", values.use_disk_shader_cache.GetValue()); diff --git a/src/common/settings.h b/src/common/settings.h index e926a3268a..ca1c3c1aa9 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -73,6 +73,11 @@ enum class ScalingFilter : u32 { LastFilter = Fsr, }; +enum class AntiAliasing : u32 { + None = 0, + Fxaa = 1, +}; + struct ResolutionScalingInfo { u32 up_scale{1}; u32 down_shift{0}; @@ -498,6 +503,7 @@ struct Values { ResolutionScalingInfo resolution_info{}; Setting resolution_setup{ResolutionSetup::Res1X, "resolution_setup"}; Setting scaling_filter{ScalingFilter::Bilinear, "scaling_filter"}; + Setting anti_aliasing{AntiAliasing::None, "anti_aliasing"}; // *nix platforms may have issues with the borderless windowed fullscreen mode. // Default to exclusive fullscreen on these platforms for now. RangedSetting fullscreen_mode{ -- cgit v1.2.3