From 339877ea7dd1d4cd2f995a20d30b7d56bab3e65c Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sun, 7 Jun 2026 17:20:52 +0300 Subject: [PATCH] rsx: Handle mipmap sampling edge case when SNORM emulation is active --- rpcs3/Emu/RSX/GL/GLDraw.cpp | 22 +++++++++++++++++++++- rpcs3/Emu/RSX/GL/glutils/sampler.cpp | 4 ++-- rpcs3/Emu/RSX/VK/VKDraw.cpp | 1 + 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLDraw.cpp b/rpcs3/Emu/RSX/GL/GLDraw.cpp index 57a9b08a17..9c09a96d39 100644 --- a/rpcs3/Emu/RSX/GL/GLDraw.cpp +++ b/rpcs3/Emu/RSX/GL/GLDraw.cpp @@ -8,6 +8,8 @@ namespace gl { + extern GLenum tex_min_filter(rsx::texture_minify_filter min_filter); + inline GLenum comparison_op(rsx::comparison_function op) { return static_cast(op); @@ -410,8 +412,26 @@ void GLGSRender::load_texture_env() if (is_depth_reconstructed || is_snorm) { + GLint adjusted_min_filter = GL_NEAREST; + if (!is_depth_reconstructed) [[ unlikely ]] + { + switch (gl::tex_min_filter(tex.min_filter())) + { + default: + break; + case GL_LINEAR_MIPMAP_LINEAR: + case GL_LINEAR_MIPMAP_NEAREST: + case GL_NEAREST_MIPMAP_LINEAR: + case GL_NEAREST_MIPMAP_NEAREST: + // This is a hack and an unfortunate one at that as there is no feasible workaround. + // Doing full trilinear filtering in a shader is just dumb, approximate it instead with NEAREST_NEAREST. + adjusted_min_filter = GL_NEAREST_MIPMAP_NEAREST; + break; + } + } + // Depth format redirected to BGRA8 resample stage. Do not filter to avoid bits leaking. - m_fs_sampler_states[i].set_parameteri(GL_TEXTURE_MIN_FILTER, GL_NEAREST); + m_fs_sampler_states[i].set_parameteri(GL_TEXTURE_MIN_FILTER, adjusted_min_filter); m_fs_sampler_states[i].set_parameteri(GL_TEXTURE_MAG_FILTER, GL_NEAREST); } } diff --git a/rpcs3/Emu/RSX/GL/glutils/sampler.cpp b/rpcs3/Emu/RSX/GL/glutils/sampler.cpp index 4b1b603fc6..005f6fa1d6 100644 --- a/rpcs3/Emu/RSX/GL/glutils/sampler.cpp +++ b/rpcs3/Emu/RSX/GL/glutils/sampler.cpp @@ -45,7 +45,7 @@ namespace gl return 1.0f; } - int tex_min_filter(rsx::texture_minify_filter min_filter) + GLenum tex_min_filter(rsx::texture_minify_filter min_filter) { switch (min_filter) { @@ -60,7 +60,7 @@ namespace gl fmt::throw_exception("Unknown min filter"); } - int tex_mag_filter(rsx::texture_magnify_filter mag_filter) + GLenum tex_mag_filter(rsx::texture_magnify_filter mag_filter) { switch (mag_filter) { diff --git a/rpcs3/Emu/RSX/VK/VKDraw.cpp b/rpcs3/Emu/RSX/VK/VKDraw.cpp index 8a6789213b..132f832416 100644 --- a/rpcs3/Emu/RSX/VK/VKDraw.cpp +++ b/rpcs3/Emu/RSX/VK/VKDraw.cpp @@ -457,6 +457,7 @@ void VKGSRender::load_texture_env() { mag_filter = VK_FILTER_NEAREST; min_filter.filter = VK_FILTER_NEAREST; + min_filter.mipmap_mode = VK_SAMPLER_MIPMAP_MODE_NEAREST; } if (min_filter.sample_mipmaps && mipmap_count > 1)