feat(renderer): Add ScaleFX pixel art upscaling filter

Implements ScaleFX algorithm for pixel art upscaling with edge
preservation. Supports both OpenGL and Vulkan with FP16/FP32
variants for hardware optimization.

ScaleFX is designed to reduce pixelation while preserving sharp
edges, ideal for low-resolution and pixel art games.

Signed-off-by: Zephyron <zephyron@citron-emu.org>
This commit is contained in:
Zephyron
2025-10-11 13:35:19 +10:00
parent 0c5c1bbf7f
commit 568ab699f6
12 changed files with 201 additions and 0 deletions

View File

@@ -10,6 +10,8 @@
#include "video_core/host_shaders/vulkan_present_frag_spv.h"
#include "video_core/host_shaders/vulkan_present_scaleforce_fp16_frag_spv.h"
#include "video_core/host_shaders/vulkan_present_scaleforce_fp32_frag_spv.h"
#include "video_core/host_shaders/vulkan_present_scalefx_fp16_frag_spv.h"
#include "video_core/host_shaders/vulkan_present_scalefx_fp32_frag_spv.h"
#include "video_core/renderer_vulkan/present/filters.h"
#include "video_core/renderer_vulkan/present/util.h"
#include "video_core/renderer_vulkan/vk_shader_util.h"
@@ -27,6 +29,14 @@ vk::ShaderModule SelectScaleForceShader(const Device& device) {
}
}
vk::ShaderModule SelectScaleFxShader(const Device& device) {
if (device.IsFloat16Supported()) {
return BuildShader(device, VULKAN_PRESENT_SCALEFX_FP16_FRAG_SPV);
} else {
return BuildShader(device, VULKAN_PRESENT_SCALEFX_FP32_FRAG_SPV);
}
}
} // Anonymous namespace
std::unique_ptr<WindowAdaptPass> MakeNearestNeighbor(const Device& device, VkFormat frame_format) {
@@ -55,6 +65,11 @@ std::unique_ptr<WindowAdaptPass> MakeScaleForce(const Device& device, VkFormat f
SelectScaleForceShader(device));
}
std::unique_ptr<WindowAdaptPass> MakeScaleFx(const Device& device, VkFormat frame_format) {
return std::make_unique<WindowAdaptPass>(device, frame_format, CreateBilinearSampler(device),
SelectScaleFxShader(device));
}
std::unique_ptr<WindowAdaptPass> MakeLanczos(const Device& device, VkFormat frame_format) {
return std::make_unique<WindowAdaptPass>(device, frame_format, CreateNearestNeighborSampler(device),
BuildShader(device, PRESENT_LANCZOS_FRAG_SPV));

View File

@@ -16,5 +16,6 @@ std::unique_ptr<WindowAdaptPass> MakeBicubic(const Device& device, VkFormat fram
std::unique_ptr<WindowAdaptPass> MakeLanczos(const Device& device, VkFormat frame_format);
std::unique_ptr<WindowAdaptPass> MakeGaussian(const Device& device, VkFormat frame_format);
std::unique_ptr<WindowAdaptPass> MakeScaleForce(const Device& device, VkFormat frame_format);
std::unique_ptr<WindowAdaptPass> MakeScaleFx(const Device& device, VkFormat frame_format);
} // namespace Vulkan