From 691e09473edac08967d970f0eebe17565f8f35ac Mon Sep 17 00:00:00 2001 From: Stuart Kenny Date: Wed, 31 May 2023 09:55:46 +0100 Subject: [PATCH] video_core: Add MMPX texture filter (#6564) * video_core: Add MMPX texture shader * mmpx: Apply mix to mask alpha edge artifacting * mmpx: Do not use deprecated texture fuction. --- .../configuration/configure_enhancements.ui | 5 + src/common/settings.cpp | 2 + src/common/settings.h | 1 + src/video_core/host_shaders/CMakeLists.txt | 1 + .../host_shaders/texture_filtering/mmpx.frag | 134 ++++++++++++++++++ .../renderer_opengl/gl_blit_helper.cpp | 15 +- .../renderer_opengl/gl_blit_helper.h | 3 + 7 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 src/video_core/host_shaders/texture_filtering/mmpx.frag diff --git a/src/citra_qt/configuration/configure_enhancements.ui b/src/citra_qt/configuration/configure_enhancements.ui index 6f644d835d..08465ef295 100644 --- a/src/citra_qt/configuration/configure_enhancements.ui +++ b/src/citra_qt/configuration/configure_enhancements.ui @@ -199,6 +199,11 @@ xBRZ + + + MMPX + + diff --git a/src/common/settings.cpp b/src/common/settings.cpp index eea0a6f719..19a52263c6 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -62,6 +62,8 @@ std::string_view GetTextureFilterName(TextureFilter filter) { return "ScaleForce"; case TextureFilter::xBRZ: return "xBRZ"; + case TextureFilter::MMPX: + return "MMPX"; default: return "Invalid"; } diff --git a/src/common/settings.h b/src/common/settings.h index da0b661ade..f80205ba96 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -74,6 +74,7 @@ enum class TextureFilter : u32 { NearestNeighbor = 3, ScaleForce = 4, xBRZ = 5, + MMPX = 6 }; namespace NativeButton { diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index 3e3dae7c97..1f49435187 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt @@ -12,6 +12,7 @@ set(SHADER_FILES texture_filtering/scale_force.frag texture_filtering/tex_coord.vert texture_filtering/xbrz_freescale.frag + texture_filtering/mmpx.frag texture_filtering/x_gradient.frag texture_filtering/y_gradient.frag full_screen_triangle.vert diff --git a/src/video_core/host_shaders/texture_filtering/mmpx.frag b/src/video_core/host_shaders/texture_filtering/mmpx.frag new file mode 100644 index 0000000000..fbfa2517be --- /dev/null +++ b/src/video_core/host_shaders/texture_filtering/mmpx.frag @@ -0,0 +1,134 @@ +// Copyright 2023 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +//? #version 430 core +precision mediump float; + +layout(location = 0) in vec2 tex_coord; +layout(location = 0) out vec4 frag_color; +layout(binding = 0) uniform sampler2D tex; + +vec2 source_size = vec2(textureSize(tex, 0)); +vec2 pos = fract(tex_coord * source_size) - vec2(0.5, 0.5); +vec2 coord = tex_coord - pos / source_size; + +vec4 src(float x, float y) +{ + return texture(tex, coord + vec2(x, y) * 1 / source_size); +} + +float luma(vec4 col){ + return dot(col.rgb, vec3(0.2126, 0.7152, 0.0722)) * (1 - col.a); +} + +bool same(vec4 B, vec4 A0){ + return all(equal(B, A0)); +} + +bool notsame(vec4 B, vec4 A0){ + return any(notEqual(B, A0)); +} + +bool all_eq2(vec4 B, vec4 A0, vec4 A1) { + return (same(B,A0) && same(B,A1)); +} + +bool all_eq3(vec4 B, vec4 A0, vec4 A1, vec4 A2) { + return (same(B,A0) && same(B,A1) && same(B,A2)); +} + +bool all_eq4(vec4 B, vec4 A0, vec4 A1, vec4 A2, vec4 A3) { + return (same(B,A0) && same(B,A1) && same(B,A2) && same(B,A3)); +} + +bool any_eq3(vec4 B, vec4 A0, vec4 A1, vec4 A2) { + return (same(B,A0) || same(B,A1) || same(B,A2)); +} + +bool none_eq2(vec4 B, vec4 A0, vec4 A1) { + return (notsame(B,A0) && notsame(B,A1)); +} + +bool none_eq4(vec4 B, vec4 A0, vec4 A1, vec4 A2, vec4 A3) { + return (notsame(B,A0) && notsame(B,A1) && notsame(B,A2) && notsame(B,A3)); +} + +void main() +{ + vec4 E = src(0.0,0.0); + + vec4 A = src(-1.0,-1.0); + vec4 B = src(0.0,-1.0); + vec4 C = src(1.0,-1.0); + + vec4 D = src(-1.0,0.0); + vec4 F = src(1.0,0.0); + + vec4 G = src(-1.0,1.0); + vec4 H = src(0.0,1.0); + vec4 I = src(1.0,1.0); + + vec4 J = E; + vec4 K = E; + vec4 L = E; + vec4 M = E; + + frag_color = E; + + if(same(E,A) && same(E,B) && same(E,C) && same(E,D) && same(E,F) && same(E,G) && same(E,H) && same(E,I)) return; + + vec4 P = src(0.0,2.0); + vec4 Q = src(-2.0,0.0); + vec4 R = src(2.0,0.0); + vec4 S = src(0.0,2.0); + + float Bl = luma(B); + float Dl = luma(D); + float El = luma(E); + float Fl = luma(F); + float Hl = luma(H); + + if (((same(D,B) && notsame(D,H) && notsame(D,F))) && ((El>=Dl) || same(E,A)) && any_eq3(E,A,C,G) && ((El=Bl) || same(E,C)) && any_eq3(E,A,C,I) && ((El=Hl) || same(E,G)) && any_eq3(E,A,G,I) && ((El=Fl) || same(E,I)) && any_eq3(E,C,G,I) && ((El src_rect) { glProgramUniform2f( diff --git a/src/video_core/renderer_opengl/gl_blit_helper.h b/src/video_core/renderer_opengl/gl_blit_helper.h index a0cf2a4bec..01ce770cb0 100644 --- a/src/video_core/renderer_opengl/gl_blit_helper.h +++ b/src/video_core/renderer_opengl/gl_blit_helper.h @@ -40,6 +40,8 @@ private: void FilterXbrz(Surface& surface, const VideoCore::TextureBlit& blit); + void FilterMMPX(Surface& surface, const VideoCore::TextureBlit& blit); + void SetParams(OGLProgram& program, const VideoCore::Extent& src_extent, Common::Rectangle src_rect); @@ -58,6 +60,7 @@ private: OGLProgram nearest_program; OGLProgram scale_force_program; OGLProgram xbrz_program; + OGLProgram mmpx_program; OGLProgram gradient_x_program; OGLProgram gradient_y_program; OGLProgram refine_program;