diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index d87fc25957..e1a26c3f66 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -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(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: diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index a07f3c1e80..e832cabb05 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -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; } } diff --git a/rpcs3/Emu/RSX/gcm_enums.h b/rpcs3/Emu/RSX/gcm_enums.h index 3c60bdab47..bb80505668 100644 --- a/rpcs3/Emu/RSX/gcm_enums.h +++ b/rpcs3/Emu/RSX/gcm_enums.h @@ -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) }; diff --git a/rpcs3/Emu/RSX/rsx_utils.h b/rpcs3/Emu/RSX/rsx_utils.h index d9e10306b9..636f61c590 100644 --- a/rpcs3/Emu/RSX/rsx_utils.h +++ b/rpcs3/Emu/RSX/rsx_utils.h @@ -798,6 +798,38 @@ namespace rsx std::swap(red, blue); } + template + requires std::is_integral_v && std::is_integral_v + u8 renormalize_color8(T input, U base) + { + // Base will be some POT-1 value + const int value = static_cast(input & base); + return static_cast((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(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(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((raw_value & (1 << 15)) ? 255 : 0); + alpha = alpha_override; + } + static inline u32 get_b8_clearmask(u32 mask) { u32 result = 0;