Add output scaling filtering options, migrate FSR checkbox to these options

This commit is contained in:
xperia64 2023-01-15 17:13:25 -05:00 committed by Megamouse
parent bd69466e94
commit 240cb2d627
16 changed files with 118 additions and 32 deletions

View File

@ -35,7 +35,7 @@ namespace gl
fbo.create();
m_sampler.create();
m_sampler.apply_defaults(input_filter);
m_sampler.apply_defaults(static_cast<GLenum>(m_input_filter));
m_vertex_data_buffer.create();
@ -322,7 +322,7 @@ namespace gl
"}\n";
// Smooth filtering required for inputs
input_filter = GL_LINEAR;
m_input_filter = gl::filter::linear;
}
gl::texture_view* ui_overlay_renderer::load_simple_image(rsx::overlays::image_info* desc, bool temp_resource, u32 owner_uid)
@ -603,11 +603,17 @@ namespace gl
" ocol = color;\n"
"}\n";
input_filter = GL_LINEAR;
m_input_filter = gl::filter::linear;
}
void video_out_calibration_pass::run(gl::command_context& cmd, const areau& viewport, const rsx::simple_array<GLuint>& source, f32 gamma, bool limited_rgb, bool _3d)
void video_out_calibration_pass::run(gl::command_context& cmd, const areau& viewport, const rsx::simple_array<GLuint>& source, f32 gamma, bool limited_rgb, bool _3d, gl::filter input_filter)
{
if (m_input_filter != input_filter)
{
m_input_filter = input_filter;
m_sampler.set_parameteri(GL_TEXTURE_MIN_FILTER, static_cast<GLenum>(m_input_filter));
m_sampler.set_parameteri(GL_TEXTURE_MAG_FILTER, static_cast<GLenum>(m_input_filter));
}
program_handle.uniforms["gamma"] = gamma;
program_handle.uniforms["limit_range"] = limited_rgb + 0;
program_handle.uniforms["stereo"] = _3d + 0;

View File

@ -33,7 +33,7 @@ namespace gl
u32 num_drawable_elements = 4;
GLenum primitives = GL_TRIANGLE_STRIP;
GLenum input_filter = GL_NEAREST;
gl::filter m_input_filter = gl::filter::nearest;
u32 m_write_aspect_mask = gl::image_aspect::color | gl::image_aspect::depth;
bool enable_depth_writes = false;
@ -93,7 +93,7 @@ namespace gl
{
video_out_calibration_pass();
void run(gl::command_context& cmd, const areau& viewport, const rsx::simple_array<GLuint>& source, f32 gamma, bool limited_rgb, bool _3d);
void run(gl::command_context& cmd, const areau& viewport, const rsx::simple_array<GLuint>& source, f32 gamma, bool limited_rgb, bool _3d, gl::filter input_filter);
};
struct rp_ssbo_to_generic_texture : public overlay_pass

View File

@ -265,6 +265,8 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info)
const areai screen_area = coordi({}, { static_cast<int>(buffer_width), static_cast<int>(buffer_height) });
const bool use_full_rgb_range_output = g_cfg.video.full_rgb_range_output.get();
// TODO: Implement FSR for OpenGL and remove this fallback to bilinear
const gl::filter filter = g_cfg.video.output_scaling == output_scaling_mode::nearest ? gl::filter::nearest : gl::filter::linear;
if (use_full_rgb_range_output && rsx::fcmp(avconfig.gamma, 1.f) && !avconfig._3d)
{
@ -274,7 +276,7 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info)
m_flip_fbo.color = image_to_flip;
m_flip_fbo.read_buffer(m_flip_fbo.color);
m_flip_fbo.draw_buffer(m_flip_fbo.color);
m_flip_fbo.blit(gl::screen, screen_area, aspect_ratio.flipped_vertical(), gl::buffers::color, gl::filter::linear);
m_flip_fbo.blit(gl::screen, screen_area, aspect_ratio.flipped_vertical(), gl::buffers::color, filter);
}
else
{
@ -283,7 +285,7 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info)
const rsx::simple_array<GLuint> images{ image_to_flip, image_to_flip2 };
gl::screen.bind();
m_video_output_pass.run(cmd, areau(aspect_ratio), images, gamma, limited_range, avconfig._3d);
m_video_output_pass.run(cmd, areau(aspect_ratio), images, gamma, limited_range, avconfig._3d, filter);
}
}

View File

@ -74,7 +74,7 @@ private:
std::unique_ptr<vk::text_writer> m_text_writer;
std::unique_ptr<vk::upscaler> m_upscaler;
bool m_use_fsr_upscaling{false};
output_scaling_mode m_output_scaling{output_scaling_mode::bilinear};
std::unique_ptr<vk::buffer> m_cond_render_buffer;
u64 m_cond_render_sync_tag = 0;

View File

@ -6,6 +6,7 @@
#include "upscalers/bilinear_pass.hpp"
#include "upscalers/fsr_pass.h"
#include "upscalers/nearest_pass.hpp"
#include "util/asm.hpp"
#include "util/video_provider.h"
@ -590,13 +591,17 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
target_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
}
const bool use_fsr_upscaling = g_cfg.video.vk.fsr_upscaling.get();
const output_scaling_mode output_scaling = g_cfg.video.output_scaling.get();
if (!m_upscaler || m_use_fsr_upscaling != use_fsr_upscaling)
if (!m_upscaler || m_output_scaling != output_scaling)
{
m_use_fsr_upscaling = use_fsr_upscaling;
m_output_scaling = output_scaling;
if (m_use_fsr_upscaling)
if (m_output_scaling == output_scaling_mode::nearest)
{
m_upscaler = std::make_unique<vk::nearest_upscale_pass>();
}
else if (m_output_scaling == output_scaling_mode::fsr)
{
m_upscaler = std::make_unique<vk::fsr_upscale_pass>();
}
@ -615,7 +620,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
if (image_to_flip) calibration_src.push_back(image_to_flip);
if (image_to_flip2) calibration_src.push_back(image_to_flip2);
if (m_use_fsr_upscaling && !avconfig._3d) // 3D will be implemented later
if (m_output_scaling == output_scaling_mode::fsr && !avconfig._3d) // 3D will be implemented later
{
// Run upscaling pass before the rest of the output effects pipeline
// This can be done with all upscalers but we already get bilinear upscaling for free if we just out the filters directly

View File

@ -0,0 +1,32 @@
#pragma once
#include "upscaling.h"
namespace vk
{
struct nearest_upscale_pass : public upscaler
{
vk::viewable_image* scale_output(
const vk::command_buffer& cmd, // CB
vk::viewable_image* src, // Source input
VkImage present_surface, // Present target. May be VK_NULL_HANDLE for some passes
VkImageLayout present_surface_layout, // Present surface layout, or VK_IMAGE_LAYOUT_UNDEFINED if no present target is provided
const VkImageBlit& request, // Scaling request information
rsx::flags32_t mode // Mode
) override
{
if (mode & UPSCALE_AND_COMMIT)
{
ensure(present_surface);
src->push_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
vkCmdBlitImage(cmd, src->value, src->current_layout, present_surface, present_surface_layout, 1, &request, VK_FILTER_NEAREST);
src->pop_layout(cmd);
return nullptr;
}
// Upscaling source only is unsupported
return src;
}
};
}

View File

@ -177,6 +177,7 @@ struct cfg_root : cfg::node
cfg::_bool decr_memory_layout{ this, "DECR memory layout", false}; // Force enable increased allowed main memory range as DECR console
cfg::_bool host_label_synchronization{ this, "Allow Host GPU Labels", false };
cfg::_bool disable_msl_fast_math{ this, "Disable MSL Fast Math", false };
cfg::_enum<output_scaling_mode> output_scaling{ this, "Output Scaling Mode", output_scaling_mode::bilinear };
struct node_vk : cfg::node
{
@ -187,7 +188,6 @@ struct cfg_root : cfg::node
cfg::_bool force_primitive_restart{ this, "Force primitive restart flag" };
cfg::_enum<vk_exclusive_fs_mode> exclusive_fullscreen_mode{ this, "Exclusive Fullscreen Mode", vk_exclusive_fs_mode::unspecified};
cfg::_bool asynchronous_texture_streaming{ this, "Asynchronous Texture Streaming 2", false };
cfg::_bool fsr_upscaling{ this, "Enable FidelityFX Super Resolution Upscaling", false, true };
cfg::uint<0, 100> rcas_sharpening_intensity{ this, "FidelityFX CAS Sharpening Intensity", 50, true };
cfg::_enum<vk_gpu_scheduler_mode> asynchronous_scheduler{ this, "Asynchronous Queue Scheduler", vk_gpu_scheduler_mode::safe };

View File

@ -631,3 +631,19 @@ void fmt_class_string<vk_exclusive_fs_mode>::format(std::string& out, u64 arg)
return unknown;
});
}
template <>
void fmt_class_string<output_scaling_mode>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](output_scaling_mode value)
{
switch (value)
{
case output_scaling_mode::nearest: return "Nearest";
case output_scaling_mode::bilinear: return "Bilinear";
case output_scaling_mode::fsr: return "FidelityFX Super Resolution";
}
return unknown;
});
}

View File

@ -305,3 +305,10 @@ enum class gpu_preset_level
low,
_auto
};
enum class output_scaling_mode
{
nearest,
bilinear,
fsr
};

View File

@ -13,6 +13,7 @@
<ItemGroup>
<ClInclude Include="Emu\RSX\VK\upscalers\bilinear_pass.hpp" />
<ClInclude Include="Emu\RSX\VK\upscalers\fsr_pass.h" />
<ClInclude Include="Emu\RSX\VK\upscalers\nearest_pass.hpp" />
<ClInclude Include="Emu\RSX\VK\upscalers\upscaling.h" />
<ClInclude Include="Emu\RSX\VK\VKAsyncScheduler.h" />
<ClInclude Include="Emu\RSX\VK\VKCommandStream.h" />

View File

@ -168,6 +168,9 @@
<Filter>upscalers</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\VK\VKGSRenderTypes.hpp" />
<ClInclude Include="Emu\RSX\VK\upscalers\nearest_pass.hpp">
<Filter>upscalers</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="vkutils">

View File

@ -977,6 +977,14 @@ QString emu_settings::GetLocalizedSetting(const QString& original, emu_settings_
case gpu_preset_level::low: return tr("Low", "Shader Precision");
}
break;
case emu_settings_type::OutputScalingMode:
switch (static_cast<output_scaling_mode>(index))
{
case output_scaling_mode::nearest: return tr("Nearest", "Output Scaling Mode");
case output_scaling_mode::bilinear: return tr("Bilinear", "Output Scaling Mode");
case output_scaling_mode::fsr: return tr("FidelityFX Super Resolution", "Output Scaling Mode");
}
break;
case emu_settings_type::AudioRenderer:
switch (static_cast<audio_renderer>(index))
{

View File

@ -83,7 +83,6 @@ enum class emu_settings_type
TextureLodBias,
ResolutionScale,
MinimumScalableDimension,
FsrUpscalingEnable,
FsrSharpeningStrength,
ExclusiveFullscreenMode,
ForceCPUBlitEmulation,
@ -101,6 +100,7 @@ enum class emu_settings_type
VulkanAsyncSchedulerDriver,
AllowHostGPULabels,
DisableMSLFastMath,
OutputScalingMode,
// Performance Overlay
PerfOverlayEnabled,
@ -272,11 +272,11 @@ inline static const QMap<emu_settings_type, cfg_location> settings_location =
{ emu_settings_type::DriverWakeUpDelay, { "Video", "Driver Wake-Up Delay"}},
{ emu_settings_type::AllowHostGPULabels, { "Video", "Allow Host GPU Labels"}},
{ emu_settings_type::DisableMSLFastMath, { "Video", "Disable MSL Fast Math"}},
{ emu_settings_type::OutputScalingMode, { "Video", "Output Scaling Mode"}},
// Vulkan
{ emu_settings_type::VulkanAsyncTextureUploads, { "Video", "Vulkan", "Asynchronous Texture Streaming 2"}},
{ emu_settings_type::VulkanAsyncSchedulerDriver, { "Video", "Vulkan", "Asynchronous Queue Scheduler"}},
{ emu_settings_type::FsrUpscalingEnable, { "Video", "Vulkan", "Enable FidelityFX Super Resolution Upscaling"}},
{ emu_settings_type::FsrSharpeningStrength, { "Video", "Vulkan", "FidelityFX CAS Sharpening Intensity"}},
{ emu_settings_type::ExclusiveFullscreenMode, { "Video", "Vulkan", "Exclusive Fullscreen Mode"}},

View File

@ -599,6 +599,9 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
});
SubscribeTooltip(ui->gbZCULL, tooltips.settings.zcull_operation_mode);
m_emu_settings->EnhanceComboBox(ui->outputScalingMode, emu_settings_type::OutputScalingMode);
SubscribeTooltip(ui->outputScalingMode, tooltips.settings.output_scaling_mode);
// Checkboxes: main options
m_emu_settings->EnhanceCheckBox(ui->dumpColor, emu_settings_type::WriteColorBuffers);
SubscribeTooltip(ui->dumpColor, tooltips.settings.dump_color);
@ -634,9 +637,6 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
m_emu_settings->EnhanceCheckBox(ui->asyncTextureStreaming, emu_settings_type::VulkanAsyncTextureUploads);
SubscribeTooltip(ui->asyncTextureStreaming, tooltips.settings.async_texture_streaming);
m_emu_settings->EnhanceCheckBox(ui->fsrUpscalingEnable, emu_settings_type::FsrUpscalingEnable);
SubscribeTooltip(ui->fsrUpscalingEnable, tooltips.settings.fsr_upscaling);
// Radio buttons
SubscribeTooltip(ui->rb_legacy_recompiler, tooltips.settings.legacy_shader_recompiler);
@ -866,15 +866,25 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
const bool is_vulkan = (text == r_creator->Vulkan.name);
ui->asyncTextureStreaming->setEnabled(is_vulkan);
ui->vulkansched->setEnabled(is_vulkan);
ui->fsrUpscalingEnable->setEnabled(is_vulkan);
ui->fsrSharpeningStrength->setEnabled(is_vulkan);
ui->fsrSharpeningStrengthReset->setEnabled(is_vulkan);
};
const auto apply_fsr_specific_options = [r_creator, this]()
{
const bool is_vulkan = (ui->renderBox->currentText() == r_creator->Vulkan.name);
const QVariantList var_list = ui->outputScalingMode->itemData(ui->outputScalingMode->currentIndex()).toList();
ensure(var_list.size() == 2 && var_list[1].canConvert<int>());
const bool fsr_selected = static_cast<output_scaling_mode>(var_list[1].toInt()) == output_scaling_mode::fsr;
ui->fsrSharpeningStrength->setEnabled(is_vulkan && fsr_selected);
ui->fsrSharpeningStrengthReset->setEnabled(is_vulkan && fsr_selected);
};
// Handle connects to disable specific checkboxes that depend on GUI state.
on_strict_rendering_mode(ui->strictModeRendering->isChecked());
apply_renderer_specific_options(ui->renderBox->currentText()); // Init
apply_fsr_specific_options();
connect(ui->renderBox, &QComboBox::currentTextChanged, apply_renderer_specific_options);
connect(ui->renderBox, &QComboBox::currentTextChanged, this, apply_fsr_specific_options);
connect(ui->outputScalingMode, QOverload<int>::of(&QComboBox::currentIndexChanged), this, apply_fsr_specific_options);
// _ _ _______ _
// /\ | (_) |__ __| | |

View File

@ -738,17 +738,13 @@
</layout>
</item>
<item>
<widget class="QGroupBox" name="gb_Upscaling">
<widget class="QGroupBox" name="gb_outputScaling">
<property name="title">
<string>Upscaling</string>
<string>Output Scaling</string>
</property>
<layout class="QVBoxLayout" name="gb_Upscaling_layout">
<item>
<widget class="QCheckBox" name="fsrUpscalingEnable">
<property name="text">
<string>Enable FSR Upscaling</string>
</property>
</widget>
<widget class="QComboBox" name="outputScalingMode"/>
</item>
<item>
<widget class="Line" name="line">

View File

@ -182,8 +182,8 @@ public:
const QString async_texture_streaming = tr("Stream textures to GPU in parallel with 3D rendering using asynchronous compute.\nCan improve performance on more powerful GPUs that have spare headroom.\nOnly works with Vulkan renderer and greatly benefits from having MTRSX enabled if you have a capable CPU.");
const QString exclusive_fullscreen_mode = tr("Controls which fullscreen mode RPCS3 requests from drivers when using Vulkan renderer.\nAutomatic will let the driver choose an appropriate mode, while the other options will hint the drivers on whether they should use exclusive or borderless fullscreen.\nUsing Prefer borderless fullscreen option can help if you have issues with streaming RPCS3 gameplay or if your system incorrectly enables HDR mode when using fullscreen.");
const QString fsr_upscaling = tr("Enable FidelityFX Super Resolution upscaling filter to improve the look of upscaled images.\nIf the game is rendering at an internal resolution lower than your window resolution, FidelityFX will handle the upscale.\nCan cause visual artifacts.\nDoes not work with stereo 3D output for now.");
const QString fsr_rcas_strength = tr("Control the sharpening strength applied by FidelityFX Super Resolution. Higher values will give sharper output but may introduce artifacts.");
const QString output_scaling_mode = tr("Final image filtering. Nearest applies no filtering, Bilinear smooths the image, and FidelityFX Super Resolution enhances upscaled images.\nIf the game is rendering at an internal resolution lower than your window resolution, FidelityFX will handle the upscale.\nFidelityFX can cause visual artifacts.\nFidelityFX does not work with stereo 3D output for now.");
const QString fsr_rcas_strength = tr("Control the sharpening strength applied by FidelityFX Super Resolution. Higher values will give sharper output but may introduce artifacts.");
const QString texture_lod_bias = tr("Changes Texture sampling accuracy. (Small changes have a big effect.)\nAvoid using values outside the range of -12 to +12 if you're unsure.\n-3 to +3 is plenty for most usecases");