rsx: Implement signed normalized texture formats

- Already partially supported via EXP option in the shader opcode, but format decoding was disabled.
- Noticed in some UE3 games which use _SNORM variants on PC but _UNORM on rpcs3
This commit is contained in:
kd-11 2020-06-11 00:52:39 +03:00 committed by kd-11
parent 6892399699
commit ce587f43a0
4 changed files with 56 additions and 8 deletions

View File

@ -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"

View File

@ -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);

View File

@ -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;

View File

@ -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;
}
}