rsx: Fix clear color for formats with less than 32-bit width

This commit is contained in:
kd-11 2022-10-31 03:04:51 +03:00 committed by kd-11
parent 8d5a9dc722
commit b156b40f8f
4 changed files with 74 additions and 10 deletions

View File

@ -503,7 +503,7 @@ void GLGSRender::clear_surface(u32 arg)
if ((arg & RSX_GCM_CLEAR_ANY_MASK) == 0) return;
u8 ctx = rsx::framebuffer_creation_context::context_draw;
if (arg & RSX_GCM_CLEAR_COLOR_MASK) ctx |= rsx::framebuffer_creation_context::context_clear_color;
if (arg & RSX_GCM_CLEAR_COLOR_RGBA_MASK) ctx |= rsx::framebuffer_creation_context::context_clear_color;
if (arg & RSX_GCM_CLEAR_DEPTH_STENCIL_MASK) ctx |= rsx::framebuffer_creation_context::context_clear_depth;
init_buffers(static_cast<rsx::framebuffer_creation_context>(ctx), true);
@ -612,6 +612,21 @@ void GLGSRender::clear_surface(u32 arg)
colormask = rsx::get_g8b8_r8g8_clearmask(colormask);
break;
}
case rsx::surface_color_format::r5g6b5:
{
rsx::get_rgb565_clear_color(clear_r, clear_g, clear_b, clear_a);
break;
}
case rsx::surface_color_format::x1r5g5b5_o1r5g5b5:
{
rsx::get_a1rgb555_clear_color(clear_r, clear_g, clear_b, clear_a, 255);
break;
}
case rsx::surface_color_format::x1r5g5b5_z1r5g5b5:
{
rsx::get_a1rgb555_clear_color(clear_r, clear_g, clear_b, clear_a, 0);
break;
}
case rsx::surface_color_format::a8b8g8r8:
case rsx::surface_color_format::x8b8g8r8_o8b8g8r8:
case rsx::surface_color_format::x8b8g8r8_z8b8g8r8:

View File

@ -1246,7 +1246,7 @@ void VKGSRender::clear_surface(u32 mask)
if (!(mask & RSX_GCM_CLEAR_ANY_MASK)) return;
u8 ctx = rsx::framebuffer_creation_context::context_draw;
if (mask & RSX_GCM_CLEAR_COLOR_MASK) ctx |= rsx::framebuffer_creation_context::context_clear_color;
if (mask & RSX_GCM_CLEAR_COLOR_RGBA_MASK) ctx |= rsx::framebuffer_creation_context::context_clear_color;
if (mask & RSX_GCM_CLEAR_DEPTH_STENCIL_MASK) ctx |= rsx::framebuffer_creation_context::context_clear_depth;
init_buffers(rsx::framebuffer_creation_context{ctx});
@ -1338,11 +1338,11 @@ void VKGSRender::clear_surface(u32 mask)
}
}
if (auto colormask = (mask & RSX_GCM_CLEAR_COLOR_MASK))
if (auto colormask = (mask & RSX_GCM_CLEAR_COLOR_RGBA_MASK))
{
if (!m_draw_buffers.empty())
{
bool use_fast_clear = false;
bool use_fast_clear = (colormask == RSX_GCM_CLEAR_COLOR_RGBA_MASK);;
u8 clear_a = rsx::method_registers.clear_color_a();
u8 clear_r = rsx::method_registers.clear_color_r();
u8 clear_g = rsx::method_registers.clear_color_g();
@ -1362,14 +1362,30 @@ void VKGSRender::clear_surface(u32 mask)
{
rsx::get_b8_clear_color(clear_r, clear_g, clear_b, clear_a);
colormask = rsx::get_b8_clearmask(colormask);
use_fast_clear = (colormask == RSX_GCM_CLEAR_RED_BIT);
use_fast_clear = (colormask & RSX_GCM_CLEAR_RED_BIT);
break;
}
case rsx::surface_color_format::g8b8:
{
rsx::get_g8b8_clear_color(clear_r, clear_g, clear_b, clear_a);
colormask = rsx::get_g8b8_r8g8_clearmask(colormask);
use_fast_clear = (colormask == (RSX_GCM_CLEAR_RED_BIT | RSX_GCM_CLEAR_GREEN_BIT));
use_fast_clear = ((colormask & RSX_GCM_CLEAR_COLOR_RG_MASK) == RSX_GCM_CLEAR_COLOR_RG_MASK);
break;
}
case rsx::surface_color_format::r5g6b5:
{
rsx::get_rgb565_clear_color(clear_r, clear_g, clear_b, clear_a);
use_fast_clear = ((colormask & RSX_GCM_CLEAR_COLOR_RGB_MASK) == RSX_GCM_CLEAR_COLOR_RGB_MASK);
break;
}
case rsx::surface_color_format::x1r5g5b5_o1r5g5b5:
{
rsx::get_a1rgb555_clear_color(clear_r, clear_g, clear_b, clear_a, 255);
break;
}
case rsx::surface_color_format::x1r5g5b5_z1r5g5b5:
{
rsx::get_a1rgb555_clear_color(clear_r, clear_g, clear_b, clear_a, 0);
break;
}
case rsx::surface_color_format::a8b8g8r8:
@ -1378,11 +1394,10 @@ void VKGSRender::clear_surface(u32 mask)
{
rsx::get_abgr8_clear_color(clear_r, clear_g, clear_b, clear_a);
colormask = rsx::get_abgr8_clearmask(colormask);
[[fallthrough]];
break;
}
default:
{
use_fast_clear = (colormask == RSX_GCM_CLEAR_COLOR_MASK);
break;
}
}

View File

@ -1188,7 +1188,9 @@ enum
RSX_GCM_CLEAR_BLUE_BIT = 0x40,
RSX_GCM_CLEAR_ALPHA_BIT = 0x80,
RSX_GCM_CLEAR_COLOR_MASK = 0xF0,
RSX_GCM_CLEAR_COLOR_RG_MASK = (RSX_GCM_CLEAR_RED_BIT | RSX_GCM_CLEAR_GREEN_BIT),
RSX_GCM_CLEAR_COLOR_RGB_MASK = (RSX_GCM_CLEAR_RED_BIT | RSX_GCM_CLEAR_GREEN_BIT | RSX_GCM_CLEAR_BLUE_BIT),
RSX_GCM_CLEAR_COLOR_RGBA_MASK = (RSX_GCM_CLEAR_COLOR_RGB_MASK | RSX_GCM_CLEAR_ALPHA_BIT),
RSX_GCM_CLEAR_DEPTH_STENCIL_MASK = (RSX_GCM_CLEAR_DEPTH_BIT | RSX_GCM_CLEAR_STENCIL_BIT),
RSX_GCM_CLEAR_ANY_MASK = (RSX_GCM_CLEAR_COLOR_MASK | RSX_GCM_CLEAR_DEPTH_STENCIL_MASK)
RSX_GCM_CLEAR_ANY_MASK = (RSX_GCM_CLEAR_COLOR_RGBA_MASK | RSX_GCM_CLEAR_DEPTH_STENCIL_MASK)
};

View File

@ -798,6 +798,38 @@ namespace rsx
std::swap(red, blue);
}
template <typename T, typename U>
requires std::is_integral_v<T> && std::is_integral_v<U>
u8 renormalize_color8(T input, U base)
{
// Base will be some POT-1 value
const int value = static_cast<u8>(input & base);
return static_cast<u8>((value * 255) / base);
}
static inline void get_rgb565_clear_color(u8& red, u8& green, u8& blue, u8& /*alpha*/)
{
// RSX clear color is just a memcpy, so in this case the input is ARGB8 so only BG have the 16-bit input
const u16 raw_value = static_cast<u16>(green) << 8 | blue;
blue = renormalize_color8(raw_value, 0x1f);
green = renormalize_color8(raw_value >> 5, 0x3f);
red = renormalize_color8(raw_value >> 11, 0x1f);
}
static inline void get_a1rgb555_clear_color(u8& red, u8& green, u8& blue, u8& alpha, u8 alpha_override)
{
// RSX clear color is just a memcpy, so in this case the input is ARGB8 so only BG have the 16-bit input
const u16 raw_value = static_cast<u16>(green) << 8 | blue;
blue = renormalize_color8(raw_value, 0x1f);
green = renormalize_color8(raw_value >> 5, 0x1f);
red = renormalize_color8(raw_value >> 10, 0x1f);
// Alpha can technically be encoded into the clear but the format normally just injects constants.
// Will require hardware tests when possible to determine which approach makes more sense.
// alpha = static_cast<u8>((raw_value & (1 << 15)) ? 255 : 0);
alpha = alpha_override;
}
static inline u32 get_b8_clearmask(u32 mask)
{
u32 result = 0;