From 6b272ed5636410dec1c42310bc7cdceb62b8d17d Mon Sep 17 00:00:00 2001 From: kd-11 Date: Tue, 10 Feb 2026 01:42:47 +0300 Subject: [PATCH] rsx: Re-work value remapping capabilities to match real hardware - Drop heurestics and use what real hardware is doing instead --- rpcs3/Emu/RSX/Common/TextureUtils.cpp | 41 +++++++++++++++++++++++---- rpcs3/Emu/RSX/Common/TextureUtils.h | 18 +++++++++++- rpcs3/Emu/RSX/RSXThread.cpp | 28 ++++++++++++++---- 3 files changed, 75 insertions(+), 12 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.cpp b/rpcs3/Emu/RSX/Common/TextureUtils.cpp index 96f87111ff..5fda3c6131 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.cpp +++ b/rpcs3/Emu/RSX/Common/TextureUtils.cpp @@ -1200,27 +1200,56 @@ namespace rsx fmt::throw_exception("Unknown format 0x%x", texture_format); } - bool is_int8_remapped_format(u32 format) + rsx::flags32_t get_format_features(u32 texture_format) { - switch (format) + switch (texture_format) { + case CELL_GCM_TEXTURE_B8: + case CELL_GCM_TEXTURE_A1R5G5B5: + case CELL_GCM_TEXTURE_A4R4G4B4: + case CELL_GCM_TEXTURE_R5G6B5: + case CELL_GCM_TEXTURE_A8R8G8B8: + case CELL_GCM_TEXTURE_COMPRESSED_DXT1: + case CELL_GCM_TEXTURE_COMPRESSED_DXT23: + case CELL_GCM_TEXTURE_COMPRESSED_DXT45: + case CELL_GCM_TEXTURE_G8B8: + case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8: + case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8: + case CELL_GCM_TEXTURE_R6G5B5: + case CELL_GCM_TEXTURE_R5G5B5A1: + case CELL_GCM_TEXTURE_D1R5G5B5: + case CELL_GCM_TEXTURE_D8R8G8B8: + // Base texture formats - everything is supported + return RSX_FORMAT_FEATURE_SIGNED_COMPONENTS | RSX_FORMAT_FEATURE_GAMMA_CORRECTION | RSX_FORMAT_FEATURE_BIASED_NORMALIZATION; + case CELL_GCM_TEXTURE_DEPTH24_D8: case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: case CELL_GCM_TEXTURE_DEPTH16: case CELL_GCM_TEXTURE_DEPTH16_FLOAT: + // Depth textures will hang the hardware if BX2 or GAMMA is active. ARGB8_SIGNED has no impact. + return 0; + case CELL_GCM_TEXTURE_X16: case CELL_GCM_TEXTURE_Y16_X16: + // X16 | Y16 - GAMMA causes hangs. ARGB8_SIGNED is ignored. UNSIGNED_REMAP=BIASED works. + return RSX_FORMAT_FEATURE_BIASED_NORMALIZATION; + case CELL_GCM_TEXTURE_COMPRESSED_HILO8: + // GAMMA causes GPU hangs. ARGB8_SIGNED is ignored. UNSIGNED_REMAP=BIASED works. + return RSX_FORMAT_FEATURE_BIASED_NORMALIZATION; + case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8: + // GAMMA causes hangs. Other flags ignored. + return 0; + case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: case CELL_GCM_TEXTURE_X32_FLOAT: case CELL_GCM_TEXTURE_Y16_X16_FLOAT: - // NOTE: Special data formats (XY, HILO, DEPTH) are not RGB formats - return false; - default: - return true; + // Floating point textures. Nothing works. + return 0; } + fmt::throw_exception("Unknown format 0x%x", texture_format); } /** diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.h b/rpcs3/Emu/RSX/Common/TextureUtils.h index cc40305721..3928e22874 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.h +++ b/rpcs3/Emu/RSX/Common/TextureUtils.h @@ -9,6 +9,8 @@ namespace rsx { + using flags32_t = u32; + enum texture_upload_context : u32 { shader_read = 1, @@ -125,6 +127,15 @@ namespace rsx using namespace format_class_; + enum format_features : u8 + { + RSX_FORMAT_FEATURE_SIGNED_COMPONENTS = (1 << 0), + RSX_FORMAT_FEATURE_BIASED_NORMALIZATION = (1 << 1), + RSX_FORMAT_FEATURE_GAMMA_CORRECTION = (1 << 2), + }; + + using enum format_features; + // Sampled image descriptor class sampled_image_descriptor_base { @@ -257,7 +268,12 @@ namespace rsx u8 get_format_sample_count(rsx::surface_antialiasing antialias); u32 get_max_depth_value(rsx::surface_depth_format2 format); bool is_depth_stencil_format(rsx::surface_depth_format2 format); - bool is_int8_remapped_format(u32 format); // Returns true if the format is treated as INT8 by the RSX remapper. + + /** + * Format feature support. There is not simple format to determine what is supported here, results are from hw tests + * Returns a bitmask of supported features. + */ + rsx::flags32_t get_format_features(u32 texture_format); /** * Returns number of texel rows encoded in one pitch-length line of bytes diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 44e8d8fb3f..447e32db9b 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -2321,17 +2321,35 @@ namespace rsx } } - if (rsx::is_int8_remapped_format(format)) + if (const auto format_features = rsx::get_format_features(format); format_features != 0) { // Special operations applied to 8-bit formats such as gamma correction and sign conversion // NOTE: The unsigned_remap=bias flag being set flags the texture as being compressed normal (2n-1 / BX2) (UE3) // NOTE: The ARGB8_signed flag means to reinterpret the raw bytes as signed. This is different than unsigned_remap=bias which does range decompression. // This is a separate method of setting the format to signed mode without doing so per-channel - // Precedence = SNORM > GAMMA > UNSIGNED_REMAP (See Resistance 3 for GAMMA/BX2 relationship, UE3 for BX2 effect) + // Precedence = SNORM > GAMMA > UNSIGNED_REMAP/BX2 + // Games using mixed flags: (See Resistance 3 for GAMMA/BX2 relationship, UE3 for BX2 effect) + u32 argb8_signed = 0; + u32 unsigned_remap = 0; + u32 gamma = 0; + + if (format_features & RSX_FORMAT_FEATURE_SIGNED_COMPONENTS) + { + argb8_signed = tex.argb_signed(); + } + + if (format_features & RSX_FORMAT_FEATURE_GAMMA_CORRECTION) + { + gamma = tex.gamma() & ~(argb8_signed); + } + + if (format_features & RSX_FORMAT_FEATURE_BIASED_NORMALIZATION) + { + // The renormalization flag applies to all channels + unsigned_remap = (tex.unsigned_remap() == CELL_GCM_TEXTURE_UNSIGNED_REMAP_NORMAL) ? 0u : 0xF; + unsigned_remap &= ~(argb8_signed | gamma); + } - const u32 argb8_signed = tex.argb_signed(); // _SNROM - const u32 gamma = tex.gamma() & ~argb8_signed; // _SRGB - const u32 unsigned_remap = (tex.unsigned_remap() == CELL_GCM_TEXTURE_UNSIGNED_REMAP_NORMAL)? 0u : (~(gamma | argb8_signed) & 0xF); // _BX2 u32 argb8_convert = gamma; // The options are mutually exclusive