From a5956cfa82883831822f634fbf0bb6643872824f Mon Sep 17 00:00:00 2001 From: kd-11 Date: Thu, 27 Jun 2024 01:12:53 +0300 Subject: [PATCH] rsx: Fix wrapped/clamped MSAA sampling behavior with dynamic flags --- rpcs3/Emu/RSX/Common/TextureUtils.cpp | 22 +++++++++++++++++++ rpcs3/Emu/RSX/Common/TextureUtils.h | 2 ++ rpcs3/Emu/RSX/Program/GLSLCommon.cpp | 3 +++ rpcs3/Emu/RSX/Program/GLSLCommon.h | 3 +++ .../RSXFragmentTextureMSAAOpsInternal.glsl | 14 +++++++++++- .../RSXProg/RSXFragmentTextureOps.glsl | 3 +++ rpcs3/Emu/RSX/RSXThread.cpp | 15 +++++++++++-- 7 files changed, 59 insertions(+), 3 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.cpp b/rpcs3/Emu/RSX/Common/TextureUtils.cpp index e8f265d2dd..ff934431ad 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.cpp +++ b/rpcs3/Emu/RSX/Common/TextureUtils.cpp @@ -1549,4 +1549,26 @@ namespace rsx { return get_format_block_size_in_bytes(format) == 2 ? 0xFFFF : 0xFFFFFF; } + + bool is_texcoord_wrapping_mode(rsx::texture_wrap_mode mode) + { + switch (mode) + { + // Clamping modes + default: + rsx_log.error("Unknown texture wrap mode: %d", static_cast(mode)); + [[ fallthrough ]]; + case rsx::texture_wrap_mode::border: + case rsx::texture_wrap_mode::clamp: + case rsx::texture_wrap_mode::clamp_to_edge: + case rsx::texture_wrap_mode::mirror_once_clamp_to_edge: + case rsx::texture_wrap_mode::mirror_once_border: + case rsx::texture_wrap_mode::mirror_once_clamp: + return false; + // Wrapping modes + case rsx::texture_wrap_mode::wrap: + case rsx::texture_wrap_mode::mirror: + return true; + } + } } diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.h b/rpcs3/Emu/RSX/Common/TextureUtils.h index ade53ae788..17069587c2 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.h +++ b/rpcs3/Emu/RSX/Common/TextureUtils.h @@ -286,4 +286,6 @@ namespace rsx format_class classify_format(rsx::surface_depth_format2 format); format_class classify_format(u32 gcm_format); + + bool is_texcoord_wrapping_mode(rsx::texture_wrap_mode mode); } diff --git a/rpcs3/Emu/RSX/Program/GLSLCommon.cpp b/rpcs3/Emu/RSX/Program/GLSLCommon.cpp index 8c1fc79686..5bd2278b77 100644 --- a/rpcs3/Emu/RSX/Program/GLSLCommon.cpp +++ b/rpcs3/Emu/RSX/Program/GLSLCommon.cpp @@ -332,6 +332,9 @@ namespace glsl { "SEXT_G_BIT" , rsx::texture_control_bits::SEXT_G }, { "SEXT_B_BIT" , rsx::texture_control_bits::SEXT_B }, { "SEXT_A_BIT" , rsx::texture_control_bits::SEXT_A }, + { "WRAP_S_BIT", rsx::texture_control_bits::WRAP_S }, + { "WRAP_T_BIT", rsx::texture_control_bits::WRAP_T }, + { "WRAP_R_BIT", rsx::texture_control_bits::WRAP_R }, { "ALPHAKILL ", rsx::texture_control_bits::ALPHAKILL }, { "RENORMALIZE ", rsx::texture_control_bits::RENORMALIZE }, diff --git a/rpcs3/Emu/RSX/Program/GLSLCommon.h b/rpcs3/Emu/RSX/Program/GLSLCommon.h index b9c1f2fda4..942374436e 100644 --- a/rpcs3/Emu/RSX/Program/GLSLCommon.h +++ b/rpcs3/Emu/RSX/Program/GLSLCommon.h @@ -34,6 +34,9 @@ namespace rsx FILTERED_MIN, UNNORMALIZED_COORDS, CLAMP_TEXCOORDS_BIT, + WRAP_S, + WRAP_T, + WRAP_R, GAMMA_CTRL_MASK = (1 << GAMMA_R) | (1 << GAMMA_G) | (1 << GAMMA_B) | (1 << GAMMA_A), EXPAND_MASK = (1 << EXPAND_R) | (1 << EXPAND_G) | (1 << EXPAND_B) | (1 << EXPAND_A), diff --git a/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureMSAAOpsInternal.glsl b/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureMSAAOpsInternal.glsl index 4509a66e50..e7c21f0621 100644 --- a/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureMSAAOpsInternal.glsl +++ b/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureMSAAOpsInternal.glsl @@ -1,4 +1,16 @@ R"( +vec2 texture2DMSCoord(const in vec2 coords, const in uint flags) +{ + if (0u == (flags & (WRAP_S_MASK | WRAP_T_MASK))) + { + return coords; + } + + const vec2 wrapped_coords = mod(coords, vec2(1.0)); + const bvec2 wrap_control_mask = bvec2(uvec2(flags) & uvec2(WRAP_S_MASK, WRAP_T_MASK)); + return _select(coords, wrapped_coords, wrap_control_mask); +} + vec4 texelFetch2DMS(in _MSAA_SAMPLER_TYPE_ tex, const in vec2 sample_count, const in ivec2 icoords, const in int index, const in ivec2 offset) { const vec2 resolve_coords = vec2(icoords + offset); @@ -12,7 +24,7 @@ vec4 sampleTexture2DMS(in _MSAA_SAMPLER_TYPE_ tex, const in vec2 coords, const i { const uint flags = TEX_FLAGS(index); const vec2 scaled_coords = COORD_SCALE2(index, coords); - const vec2 normalized_coords = mod(scaled_coords, vec2(1.0)); + const vec2 normalized_coords = texture2DMSCoord(scaled_coords, flags); const vec2 sample_count = vec2(2., textureSamples(tex) * 0.5); const vec2 image_size = textureSize(tex) * sample_count; const ivec2 icoords = ivec2(normalized_coords * image_size); diff --git a/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureOps.glsl b/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureOps.glsl index 2b04b9f392..16e420d547 100644 --- a/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureOps.glsl +++ b/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureOps.glsl @@ -11,6 +11,9 @@ R"( #define SEXT_G_MASK (1 << SEXT_G_BIT) #define SEXT_B_MASK (1 << SEXT_B_BIT) #define SEXT_A_MASK (1 << SEXT_A_BIT) +#define WRAP_S_MASK (1 << WRAP_S_BIT) +#define WRAP_T_MASK (1 << WRAP_T_BIT) +#define WRAP_R_MASK (1 << WRAP_R_BIT) #define GAMMA_CTRL_MASK (GAMMA_R_MASK | GAMMA_G_MASK | GAMMA_B_MASK | GAMMA_A_MASK) #define SIGN_EXPAND_MASK (EXPAND_R_MASK | EXPAND_G_MASK | EXPAND_B_MASK | EXPAND_A_MASK) diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 43e2319b97..5c36664b4c 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -2525,14 +2525,25 @@ namespace rsx } } - if (backend_config.supports_hw_msaa && - sampler_descriptors[i]->samples > 1) + if (backend_config.supports_hw_msaa && sampler_descriptors[i]->samples > 1) { current_fp_texture_state.multisampled_textures |= (1 << i); texture_control |= (static_cast(tex.zfunc()) << texture_control_bits::DEPTH_COMPARE_OP); texture_control |= (static_cast(tex.mag_filter() != rsx::texture_magnify_filter::nearest) << texture_control_bits::FILTERED_MAG); texture_control |= (static_cast(tex.min_filter() != rsx::texture_minify_filter::nearest) << texture_control_bits::FILTERED_MIN); texture_control |= (((tex.format() & CELL_GCM_TEXTURE_UN) >> 6) << texture_control_bits::UNNORMALIZED_COORDS); + + if (rsx::is_texcoord_wrapping_mode(tex.wrap_s())) { + texture_control |= (1 << texture_control_bits::WRAP_S); + } + + if (rsx::is_texcoord_wrapping_mode(tex.wrap_t())) { + texture_control |= (1 << texture_control_bits::WRAP_T); + } + + if (rsx::is_texcoord_wrapping_mode(tex.wrap_r())) { + texture_control |= (1 << texture_control_bits::WRAP_R); + } } if (sampler_descriptors[i]->format_class != RSX_FORMAT_CLASS_COLOR)