rsx: Workaround for G8B8 render targets

- Mainly affected are colormasks and read swizzles

NOTES:
- Writes to G write to the second and fourth component (YW)
- Writes to B write to first and third component (XZ)
- This means the actual format layout is BGBG (RGBA) making RG mapping actually GR
- Clear does not seem to have any intended effect on this format (TLOU)
This commit is contained in:
kd-11 2018-04-01 16:41:57 +03:00 committed by kd-11
parent bd1d4de422
commit c5cd758700
4 changed files with 76 additions and 21 deletions

View file

@ -976,25 +976,41 @@ void GLGSRender::clear_surface(u32 arg)
mask |= GLenum(gl::buffers::stencil);
}
if (arg & 0xf0)
if (auto colormask = (arg & 0xf0))
{
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();
u8 clear_b = rsx::method_registers.clear_color_b();
gl_state.color_mask(arg & 0xf0);
gl_state.clear_color(clear_r, clear_g, clear_b, clear_a);
mask |= GLenum(gl::buffers::color);
for (auto &rtt : m_rtts.m_bound_render_targets)
switch (rsx::method_registers.surface_color())
{
if (std::get<0>(rtt) != 0)
case rsx::surface_color_format::x32:
case rsx::surface_color_format::w16z16y16x16:
case rsx::surface_color_format::w32z32y32x32:
case rsx::surface_color_format::g8b8:
{
//NOP
break;
}
default:
{
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();
u8 clear_b = rsx::method_registers.clear_color_b();
gl_state.color_mask(colormask);
gl_state.clear_color(clear_r, clear_g, clear_b, clear_a);
mask |= GLenum(gl::buffers::color);
for (auto &rtt : m_rtts.m_bound_render_targets)
{
std::get<1>(rtt)->set_cleared(true);
std::get<1>(rtt)->old_contents = nullptr;
if (std::get<0>(rtt) != 0)
{
std::get<1>(rtt)->set_cleared(true);
std::get<1>(rtt)->old_contents = nullptr;
}
}
break;
}
}
}
@ -1153,6 +1169,12 @@ void GLGSRender::update_draw_state()
bool color_mask_r = rsx::method_registers.color_mask_r();
bool color_mask_a = rsx::method_registers.color_mask_a();
if (rsx::method_registers.surface_color() == rsx::surface_color_format::g8b8)
{
//Map GB components onto RG
rsx::get_g8b8_r8g8_colormask(color_mask_r, color_mask_g, color_mask_b, color_mask_a);
}
gl_state.color_mask(color_mask_r, color_mask_g, color_mask_b, color_mask_a);
gl_state.depth_mask(rsx::method_registers.depth_write_enabled());
gl_state.stencil_mask(rsx::method_registers.stencil_mask());

View file

@ -52,7 +52,8 @@ color_format rsx::internals::surface_color_format_to_gl(rsx::surface_color_forma
{ ::gl::texture::channel::one, ::gl::texture::channel::r, ::gl::texture::channel::r, ::gl::texture::channel::r } };
case rsx::surface_color_format::g8b8:
return{ ::gl::texture::type::ubyte, ::gl::texture::format::rg, false, 2, 1 };
return{ ::gl::texture::type::ubyte, ::gl::texture::format::rg, false, 2, 1,
{ ::gl::texture::channel::g, ::gl::texture::channel::r, ::gl::texture::channel::g, ::gl::texture::channel::r } };
case rsx::surface_color_format::x32:
return{ ::gl::texture::type::f32, ::gl::texture::format::r, true, 1, 4 };

View file

@ -100,7 +100,10 @@ namespace vk
}
case rsx::surface_color_format::g8b8:
return std::make_pair(VK_FORMAT_R8G8_UNORM, vk::default_component_map());
{
VkComponentMapping gb_rg = { VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R };
return std::make_pair(VK_FORMAT_R8G8_UNORM, gb_rg);
}
case rsx::surface_color_format::x32:
return std::make_pair(VK_FORMAT_R32_SFLOAT, vk::default_component_map());
@ -1728,6 +1731,7 @@ void VKGSRender::clear_surface(u32 mask)
if (clear_descriptors.size() > 0)
{
//TODO: Implement lw_graphics_pipe objects to manage the color write mask!
vk::enter_uninterruptible();
begin_render_pass();
vkCmdClearAttachments(*m_current_command_buffer, (u32)clear_descriptors.size(), clear_descriptors.data(), 1, &region);
@ -2167,11 +2171,22 @@ void VKGSRender::load_program(const vk::vertex_upload_info& vertex_info)
properties.att_state[i].blendEnable = VK_FALSE;
}
bool color_mask_b = rsx::method_registers.color_mask_b();
bool color_mask_g = rsx::method_registers.color_mask_g();
bool color_mask_r = rsx::method_registers.color_mask_r();
bool color_mask_a = rsx::method_registers.color_mask_a();
if (rsx::method_registers.surface_color() == rsx::surface_color_format::g8b8)
{
//Map GB components onto RG
rsx::get_g8b8_r8g8_colormask(color_mask_r, color_mask_g, color_mask_b, color_mask_a);
}
VkColorComponentFlags mask = 0;
if (rsx::method_registers.color_mask_a()) mask |= VK_COLOR_COMPONENT_A_BIT;
if (rsx::method_registers.color_mask_b()) mask |= VK_COLOR_COMPONENT_B_BIT;
if (rsx::method_registers.color_mask_g()) mask |= VK_COLOR_COMPONENT_G_BIT;
if (rsx::method_registers.color_mask_r()) mask |= VK_COLOR_COMPONENT_R_BIT;
if (color_mask_a) mask |= VK_COLOR_COMPONENT_A_BIT;
if (color_mask_b) mask |= VK_COLOR_COMPONENT_B_BIT;
if (color_mask_g) mask |= VK_COLOR_COMPONENT_G_BIT;
if (color_mask_r) mask |= VK_COLOR_COMPONENT_R_BIT;
for (u8 idx = 0; idx < m_draw_buffers_count; ++idx)
{

View file

@ -411,4 +411,21 @@ namespace rsx
return ((u64)index + index_base) & 0x000FFFFF;
}
// Convert color write mask for G8B8 to R8G8
static inline u32 get_g8b8_r8g8_colormask(u32 mask)
{
u32 result = 0;
if (mask & 0x40) result |= 0x40;
if (mask & 0x80) result |= 0x20;
return result;
}
static inline void get_g8b8_r8g8_colormask(bool &red, bool &green, bool &blue, bool &alpha)
{
red = blue;
green = green;
blue = false;
alpha = false;
}
}