GPU: Add Lanczos scaling option
This commit is contained in:
parent
99e81f1559
commit
ecbb79c4bf
|
@ -132,6 +132,10 @@ bool GPUPresenter::CompileDisplayPipelines(bool display, bool deinterlace, bool
|
|||
fs = shadergen.GenerateDisplayFragmentShader(true, false);
|
||||
break;
|
||||
|
||||
case DisplayScalingMode::Lanczos:
|
||||
fs = shadergen.GenerateDisplayLanczosFragmentShader();
|
||||
break;
|
||||
|
||||
case DisplayScalingMode::Nearest:
|
||||
case DisplayScalingMode::NearestInteger:
|
||||
default:
|
||||
|
@ -654,6 +658,8 @@ void GPUPresenter::DrawDisplay(const GSVector2i target_size, const GSVector2i fi
|
|||
} uniforms;
|
||||
std::memset(uniforms.params, 0, sizeof(uniforms.params));
|
||||
|
||||
const GSVector2 display_texture_size = GSVector2(m_display_texture->GetSizeVec());
|
||||
|
||||
switch (g_gpu_settings.display_scaling)
|
||||
{
|
||||
case DisplayScalingMode::Nearest:
|
||||
|
@ -665,6 +671,14 @@ void GPUPresenter::DrawDisplay(const GSVector2i target_size, const GSVector2i fi
|
|||
texture_filter_linear = true;
|
||||
break;
|
||||
|
||||
case DisplayScalingMode::Lanczos:
|
||||
{
|
||||
const GSVector2 fdisplay_rect_size = GSVector2(display_rect.rsize());
|
||||
GSVector2::store<true>(&uniforms.params[0], fdisplay_rect_size);
|
||||
GSVector2::store<true>(&uniforms.params[2], GSVector2::cxpr(1.0f) / (fdisplay_rect_size / display_texture_size));
|
||||
}
|
||||
break;
|
||||
|
||||
case DisplayScalingMode::BilinearSharp:
|
||||
{
|
||||
texture_filter_linear = true;
|
||||
|
@ -689,7 +703,6 @@ void GPUPresenter::DrawDisplay(const GSVector2i target_size, const GSVector2i fi
|
|||
|
||||
// For bilinear, clamp to 0.5/SIZE-0.5 to avoid bleeding from the adjacent texels in VRAM. This is because
|
||||
// 1.0 in UV space is not the bottom-right texel, but a mix of the bottom-right and wrapped/next texel.
|
||||
const GSVector2 display_texture_size = GSVector2(m_display_texture->GetSizeVec());
|
||||
const GSVector4 display_texture_size4 = GSVector4::xyxy(display_texture_size);
|
||||
const GSVector4 uv_rect = GSVector4(GSVector4i(m_display_texture_view_x, m_display_texture_view_y,
|
||||
m_display_texture_view_x + m_display_texture_view_width,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
#include "gpu_shadergen.h"
|
||||
|
@ -95,6 +95,62 @@ std::string GPUShaderGen::GenerateDisplaySharpBilinearFragmentShader() const
|
|||
return ss.str();
|
||||
}
|
||||
|
||||
std::string GPUShaderGen::GenerateDisplayLanczosFragmentShader() const
|
||||
{
|
||||
std::stringstream ss;
|
||||
WriteHeader(ss);
|
||||
WriteDisplayUniformBuffer(ss);
|
||||
DeclareTexture(ss, "samp0", 0, false);
|
||||
|
||||
ss << R"(
|
||||
CONSTANT int KERNEL_SIZE = 3;
|
||||
CONSTANT float PI = 3.14159265359;
|
||||
|
||||
float lanczos(float x)
|
||||
{
|
||||
x = abs(x);
|
||||
if (x < 0.0001)
|
||||
return 1.0;
|
||||
|
||||
if (x > float(KERNEL_SIZE))
|
||||
return 0.0;
|
||||
|
||||
float px = PI * x;
|
||||
return (float(KERNEL_SIZE) * sin(px) * sin(px / float(KERNEL_SIZE))) / (px * px);
|
||||
}
|
||||
|
||||
)";
|
||||
|
||||
DeclareFragmentEntryPoint(ss, 0, 1);
|
||||
ss << R"(
|
||||
{
|
||||
float2 pixel = v_tex0 * u_params.xy;
|
||||
float2 src_pixel = pixel * u_params.zw;
|
||||
float2 src = floor(src_pixel - 0.5) + 0.5;
|
||||
|
||||
float3 color = float3(0.0, 0.0, 0.0);
|
||||
float total_weight = 0.0;
|
||||
|
||||
for (int i = -KERNEL_SIZE; i <= KERNEL_SIZE; i++)
|
||||
{
|
||||
for (int j = -KERNEL_SIZE; j <= KERNEL_SIZE; j++)
|
||||
{
|
||||
float2 offset = float2(int2(i, j));
|
||||
float2 sample_pos = (src + offset) * u_src_size.zw;
|
||||
float2 dxdy = src_pixel - (src + offset);
|
||||
float weight = lanczos(dxdy.x) * lanczos(dxdy.y);
|
||||
|
||||
color += SAMPLE_TEXTURE_LEVEL(samp0, ClampUV(sample_pos), 0.0).rgb * weight;
|
||||
total_weight += weight;
|
||||
}
|
||||
}
|
||||
|
||||
o_col0 = float4(color / total_weight, 1.0);
|
||||
})";
|
||||
|
||||
return std::move(ss).str();
|
||||
}
|
||||
|
||||
std::string GPUShaderGen::GenerateDeinterlaceWeaveFragmentShader() const
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
#pragma once
|
||||
|
@ -14,6 +14,7 @@ public:
|
|||
std::string GenerateDisplayVertexShader() const;
|
||||
std::string GenerateDisplayFragmentShader(bool clamp_uv, bool nearest) const;
|
||||
std::string GenerateDisplaySharpBilinearFragmentShader() const;
|
||||
std::string GenerateDisplayLanczosFragmentShader() const;
|
||||
|
||||
std::string GenerateDeinterlaceWeaveFragmentShader() const;
|
||||
std::string GenerateDeinterlaceBlendFragmentShader() const;
|
||||
|
|
|
@ -1900,7 +1900,7 @@ const char* Settings::GetForceVideoTimingDisplayName(ForceVideoTimingMode mode)
|
|||
}
|
||||
|
||||
static constexpr const std::array s_display_scaling_names = {
|
||||
"Nearest", "NearestInteger", "BilinearSmooth", "BilinearSharp", "BilinearInteger",
|
||||
"Nearest", "NearestInteger", "BilinearSmooth", "BilinearSharp", "BilinearInteger", "Lanczos",
|
||||
};
|
||||
static constexpr const std::array s_display_scaling_display_names = {
|
||||
TRANSLATE_DISAMBIG_NOOP("Settings", "Nearest-Neighbor", "DisplayScalingMode"),
|
||||
|
@ -1908,6 +1908,7 @@ static constexpr const std::array s_display_scaling_display_names = {
|
|||
TRANSLATE_DISAMBIG_NOOP("Settings", "Bilinear (Smooth)", "DisplayScalingMode"),
|
||||
TRANSLATE_DISAMBIG_NOOP("Settings", "Bilinear (Sharp)", "DisplayScalingMode"),
|
||||
TRANSLATE_DISAMBIG_NOOP("Settings", "Bilinear (Integer)", "DisplayScalingMode"),
|
||||
TRANSLATE_DISAMBIG_NOOP("Settings", "Lanczos (Sharp)", "DisplayScalingMode"),
|
||||
};
|
||||
|
||||
std::optional<DisplayScalingMode> Settings::ParseDisplayScaling(const char* str)
|
||||
|
|
|
@ -184,6 +184,7 @@ enum class DisplayScalingMode : u8
|
|||
BilinearSmooth,
|
||||
BilinearSharp,
|
||||
BilinearInteger,
|
||||
Lanczos,
|
||||
Count
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue