diff --git a/rpcs3/Emu/RSX/Common/GLSLCommon.h b/rpcs3/Emu/RSX/Common/GLSLCommon.h index 839f90be7..2860e1109 100644 --- a/rpcs3/Emu/RSX/Common/GLSLCommon.h +++ b/rpcs3/Emu/RSX/Common/GLSLCommon.h @@ -753,10 +753,28 @@ namespace glsl " rgba /= 255.;" " }\n" "\n" - " //TODO: Verify gamma control bit ordering, looks to be 0x7 for rgb, 0xF for rgba\n" - " uvec4 mask = uvec4(control_bits & 0xFu) & uvec4(0x1, 0x2, 0x4, 0x8);\n" - " vec4 convert = srgb_to_linear(rgba);\n" - " return _select(rgba, convert, notEqual(mask, uvec4(0)));\n" + " uvec4 mask;\n" + " vec4 convert;\n" + " uint op_mask = control_bits & 0x3C0u;\n" + "\n" + " if (op_mask != 0)\n" + " {\n" + " // Expand to signed normalized\n" + " mask = uvec4(op_mask) & uvec4(0x80, 0x100, 0x200, 0x40);\n" + " convert = (rgba * 2.f - 1.f);\n" + " rgba = _select(rgba, convert, notEqual(mask, uvec4(0)));\n" + " }\n" + "\n" + " op_mask = control_bits & 0xFu;\n" + " if (op_mask != 0u)\n" + " {\n" + " // Gamma correction\n" + " mask = uvec4(op_mask) & uvec4(0x1, 0x2, 0x4, 0x8);\n" + " convert = srgb_to_linear(rgba);\n" + " return _select(rgba, convert, notEqual(mask, uvec4(0)));\n" + " }\n" + "\n" + " return rgba;\n" "}\n\n" "#define TEX_NAME(index) tex##index\n" diff --git a/rpcs3/Emu/RSX/RSXTexture.cpp b/rpcs3/Emu/RSX/RSXTexture.cpp index db8c614ab..82ba1535b 100644 --- a/rpcs3/Emu/RSX/RSXTexture.cpp +++ b/rpcs3/Emu/RSX/RSXTexture.cpp @@ -267,6 +267,11 @@ namespace rsx return ((registers[NV4097_SET_TEXTURE_FILTER + (m_index * 8)] >> 13) & 0xf); } + u8 fragment_texture::argb_signed() const + { + return ((registers[NV4097_SET_TEXTURE_FILTER + (m_index * 8)] >> 28) & 0xf); + } + bool fragment_texture::a_signed() const { return ((registers[NV4097_SET_TEXTURE_FILTER + (m_index * 8)] >> 28) & 0x1); diff --git a/rpcs3/Emu/RSX/RSXTexture.h b/rpcs3/Emu/RSX/RSXTexture.h index f9a420e72..60570fd28 100644 --- a/rpcs3/Emu/RSX/RSXTexture.h +++ b/rpcs3/Emu/RSX/RSXTexture.h @@ -69,6 +69,7 @@ namespace rsx rsx::texture_minify_filter min_filter() const; rsx::texture_magnify_filter mag_filter() const; u8 convolution_filter() const; + u8 argb_signed() const; bool a_signed() const; bool r_signed() const; bool g_signed() const; diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 2ba5ef559..04a507473 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -1727,7 +1727,31 @@ namespace rsx } } - if (const auto srgb_mask = tex.gamma()) + // Special operations applied to 8-bit formats such as gamma correction and sign conversion + // NOTE: The unsigned_remap being set to anything other than 0 flags the texture as being signed + // This is a separate method of setting the format to signed mode without doing so per-channel + // NOTE2: Modifier precedence is not respected here. This is another TODO (kd-11) + u32 argb8_convert = tex.gamma(); + if (const u32 sign_convert = tex.unsigned_remap() ? 0xF : tex.argb_signed()) + { + // Apply remap to avoid mapping 1 to -1. Only the sign conversion needs this check + // TODO: Use actual remap mask to account for 0 and 1 overrides in default mapping + // TODO: Replace this clusterfuck of texture control with matrix transformation + const auto remap_ctrl = (tex.remap() >> 8) & 0xAA; + if (remap_ctrl == 0xAA) + { + argb8_convert |= (sign_convert & 0xFu) << 6; + } + else + { + if (remap_ctrl & 0x03) argb8_convert |= (sign_convert & 0x1u) << 6; + if (remap_ctrl & 0x0C) argb8_convert |= (sign_convert & 0x2u) << 6; + if (remap_ctrl & 0x30) argb8_convert |= (sign_convert & 0x4u) << 6; + if (remap_ctrl & 0xC0) argb8_convert |= (sign_convert & 0x8u) << 6; + } + } + + if (argb8_convert) { switch (format) { @@ -1743,11 +1767,11 @@ namespace rsx case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: case CELL_GCM_TEXTURE_X32_FLOAT: case CELL_GCM_TEXTURE_Y16_X16_FLOAT: - //Special data formats (XY, HILO, DEPTH) are not RGB formats - //Ignore gamma flags + // Special data formats (XY, HILO, DEPTH) are not RGB formats + // Ignore gamma flags break; default: - texture_control |= srgb_mask; + texture_control |= argb8_convert; break; } }