rsx: Rework how depth/stencil initialization+clear works

This commit is contained in:
kd-11 2021-09-19 22:01:25 +03:00 committed by kd-11
parent 0a8d9a12ab
commit dabfce5c82
3 changed files with 39 additions and 22 deletions

View File

@ -496,14 +496,14 @@ void GLGSRender::clear_surface(u32 arg)
if (skip_current_frame) return; if (skip_current_frame) return;
// If stencil write mask is disabled, remove clear_stencil bit // If stencil write mask is disabled, remove clear_stencil bit
if (!rsx::method_registers.stencil_mask()) arg &= ~0x2u; if (!rsx::method_registers.stencil_mask()) arg &= ~RSX_GCM_CLEAR_STENCIL_BIT;
// Ignore invalid clear flags // Ignore invalid clear flags
if ((arg & 0xf3) == 0) return; if ((arg & RSX_GCM_CLEAR_ANY_MASK) == 0) return;
u8 ctx = rsx::framebuffer_creation_context::context_draw; u8 ctx = rsx::framebuffer_creation_context::context_draw;
if (arg & 0xF0) ctx |= rsx::framebuffer_creation_context::context_clear_color; if (arg & RSX_GCM_CLEAR_COLOR_MASK) ctx |= rsx::framebuffer_creation_context::context_clear_color;
if (arg & 0x3) ctx |= rsx::framebuffer_creation_context::context_clear_depth; 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); init_buffers(static_cast<rsx::framebuffer_creation_context>(ctx), true);
@ -521,9 +521,9 @@ void GLGSRender::clear_surface(u32 arg)
bool update_color = false, update_z = false; bool update_color = false, update_z = false;
rsx::surface_depth_format2 surface_depth_format = rsx::method_registers.surface_depth_fmt(); rsx::surface_depth_format2 surface_depth_format = rsx::method_registers.surface_depth_fmt();
if (auto ds = std::get<1>(m_rtts.m_bound_depth_stencil); arg & 0x3) if (auto ds = std::get<1>(m_rtts.m_bound_depth_stencil); arg & RSX_GCM_CLEAR_DEPTH_STENCIL_MASK)
{ {
if (arg & 0x1) if (arg & RSX_GCM_CLEAR_DEPTH_BIT)
{ {
u32 max_depth_value = get_max_depth_value(surface_depth_format); u32 max_depth_value = get_max_depth_value(surface_depth_format);
u32 clear_depth = rsx::method_registers.z_clear_value(is_depth_stencil_format(surface_depth_format)); u32 clear_depth = rsx::method_registers.z_clear_value(is_depth_stencil_format(surface_depth_format));
@ -535,7 +535,7 @@ void GLGSRender::clear_surface(u32 arg)
if (is_depth_stencil_format(surface_depth_format)) if (is_depth_stencil_format(surface_depth_format))
{ {
if (arg & 0x2) if (arg & RSX_GCM_CLEAR_STENCIL_BIT)
{ {
u8 clear_stencil = rsx::method_registers.stencil_clear_value(); u8 clear_stencil = rsx::method_registers.stencil_clear_value();
@ -544,7 +544,8 @@ void GLGSRender::clear_surface(u32 arg)
mask |= GLenum(gl::buffers::stencil); mask |= GLenum(gl::buffers::stencil);
} }
if ((arg & 0x3) != 0x3 || !full_frame) if (const auto ds_mask = (arg & RSX_GCM_CLEAR_DEPTH_STENCIL_MASK);
ds_mask != RSX_GCM_CLEAR_DEPTH_STENCIL_MASK || !full_frame)
{ {
ensure(mask); ensure(mask);
@ -552,14 +553,14 @@ void GLGSRender::clear_surface(u32 arg)
ds->old_contents.empty() && !g_cfg.video.read_depth_buffer) // No way to load data from memory, so no initialization given ds->old_contents.empty() && !g_cfg.video.read_depth_buffer) // No way to load data from memory, so no initialization given
{ {
// Only one aspect was cleared. Make sure to memory initialize the other before removing dirty flag // Only one aspect was cleared. Make sure to memory initialize the other before removing dirty flag
if (arg == 1) if (ds_mask == RSX_GCM_CLEAR_DEPTH_BIT)
{ {
// Depth was cleared, initialize stencil // Depth was cleared, initialize stencil
gl_state.stencil_mask(0xFF); gl_state.stencil_mask(0xFF);
gl_state.clear_stencil(0xFF); gl_state.clear_stencil(0xFF);
mask |= GLenum(gl::buffers::stencil); mask |= GLenum(gl::buffers::stencil);
} }
else else if (ds_mask == RSX_GCM_CLEAR_STENCIL_BIT)
{ {
// Stencil was cleared, initialize depth // Stencil was cleared, initialize depth
gl_state.depth_mask(GL_TRUE); gl_state.depth_mask(GL_TRUE);

View File

@ -1197,14 +1197,14 @@ void VKGSRender::clear_surface(u32 mask)
if (skip_current_frame || swapchain_unavailable) return; if (skip_current_frame || swapchain_unavailable) return;
// If stencil write mask is disabled, remove clear_stencil bit // If stencil write mask is disabled, remove clear_stencil bit
if (!rsx::method_registers.stencil_mask()) mask &= ~0x2u; if (!rsx::method_registers.stencil_mask()) mask &= ~RSX_GCM_CLEAR_STENCIL_BIT;
// Ignore invalid clear flags // Ignore invalid clear flags
if (!(mask & 0xF3)) return; if (!(mask & RSX_GCM_CLEAR_ANY_MASK)) return;
u8 ctx = rsx::framebuffer_creation_context::context_draw; u8 ctx = rsx::framebuffer_creation_context::context_draw;
if (mask & 0xF0) ctx |= rsx::framebuffer_creation_context::context_clear_color; if (mask & RSX_GCM_CLEAR_COLOR_MASK) ctx |= rsx::framebuffer_creation_context::context_clear_color;
if (mask & 0x3) ctx |= rsx::framebuffer_creation_context::context_clear_depth; if (mask & RSX_GCM_CLEAR_DEPTH_STENCIL_MASK) ctx |= rsx::framebuffer_creation_context::context_clear_depth;
init_buffers(rsx::framebuffer_creation_context{ctx}); init_buffers(rsx::framebuffer_creation_context{ctx});
if (!framebuffer_status_valid) return; if (!framebuffer_status_valid) return;
@ -1232,9 +1232,9 @@ void VKGSRender::clear_surface(u32 mask)
bool update_color = false, update_z = false; bool update_color = false, update_z = false;
auto surface_depth_format = rsx::method_registers.surface_depth_fmt(); auto surface_depth_format = rsx::method_registers.surface_depth_fmt();
if (auto ds = std::get<1>(m_rtts.m_bound_depth_stencil); mask & 0x3) if (auto ds = std::get<1>(m_rtts.m_bound_depth_stencil); mask & RSX_GCM_CLEAR_DEPTH_STENCIL_MASK)
{ {
if (mask & 0x1) if (mask & RSX_GCM_CLEAR_DEPTH_BIT)
{ {
u32 max_depth_value = get_max_depth_value(surface_depth_format); u32 max_depth_value = get_max_depth_value(surface_depth_format);
@ -1249,7 +1249,7 @@ void VKGSRender::clear_surface(u32 mask)
if (is_depth_stencil_format(surface_depth_format)) if (is_depth_stencil_format(surface_depth_format))
{ {
if (mask & 0x2) if (mask & RSX_GCM_CLEAR_STENCIL_BIT)
{ {
u8 clear_stencil = rsx::method_registers.stencil_clear_value(); u8 clear_stencil = rsx::method_registers.stencil_clear_value();
depth_stencil_clear_values.depthStencil.stencil = clear_stencil; depth_stencil_clear_values.depthStencil.stencil = clear_stencil;
@ -1273,13 +1273,14 @@ void VKGSRender::clear_surface(u32 mask)
ds->old_contents.empty() && !g_cfg.video.read_depth_buffer) // No way to load data from memory, so no initialization given ds->old_contents.empty() && !g_cfg.video.read_depth_buffer) // No way to load data from memory, so no initialization given
{ {
// Only one aspect was cleared. Make sure to memory initialize the other before removing dirty flag // Only one aspect was cleared. Make sure to memory initialize the other before removing dirty flag
if (mask == 1) const auto ds_mask = (mask & RSX_GCM_CLEAR_DEPTH_STENCIL_MASK);
if (ds_mask == RSX_GCM_CLEAR_DEPTH_BIT && (ds->aspect() & VK_IMAGE_ASPECT_STENCIL_BIT))
{ {
// Depth was cleared, initialize stencil // Depth was cleared, initialize stencil
depth_stencil_clear_values.depthStencil.stencil = 0xFF; depth_stencil_clear_values.depthStencil.stencil = 0xFF;
depth_stencil_mask |= VK_IMAGE_ASPECT_STENCIL_BIT; depth_stencil_mask |= VK_IMAGE_ASPECT_STENCIL_BIT;
} }
else else if (ds_mask == RSX_GCM_CLEAR_STENCIL_BIT)
{ {
// Stencil was cleared, initialize depth // Stencil was cleared, initialize depth
depth_stencil_clear_values.depthStencil.depth = 1.f; depth_stencil_clear_values.depthStencil.depth = 1.f;
@ -1294,7 +1295,7 @@ void VKGSRender::clear_surface(u32 mask)
} }
} }
if (auto colormask = (mask & 0xF0)) if (auto colormask = (mask & RSX_GCM_CLEAR_COLOR_MASK))
{ {
if (!m_draw_buffers.empty()) if (!m_draw_buffers.empty())
{ {
@ -1318,7 +1319,7 @@ void VKGSRender::clear_surface(u32 mask)
{ {
rsx::get_g8b8_clear_color(clear_r, clear_g, clear_b, clear_a); rsx::get_g8b8_clear_color(clear_r, clear_g, clear_b, clear_a);
colormask = rsx::get_g8b8_r8g8_colormask(colormask); colormask = rsx::get_g8b8_r8g8_colormask(colormask);
use_fast_clear = (colormask == (0x10 | 0x20)); use_fast_clear = (colormask == (RSX_GCM_CLEAR_RED_BIT | RSX_GCM_CLEAR_GREEN_BIT));
break; break;
} }
case rsx::surface_color_format::a8b8g8r8: case rsx::surface_color_format::a8b8g8r8:
@ -1331,7 +1332,7 @@ void VKGSRender::clear_surface(u32 mask)
} }
default: default:
{ {
use_fast_clear = (colormask == (0x10 | 0x20 | 0x40 | 0x80)); use_fast_clear = (colormask == RSX_GCM_CLEAR_COLOR_MASK);
break; break;
} }
} }

View File

@ -1177,3 +1177,18 @@ enum
CELL_GCM_FOG_MODE_EXP2_ABS = 0x0803, CELL_GCM_FOG_MODE_EXP2_ABS = 0x0803,
CELL_GCM_FOG_MODE_LINEAR_ABS = 0x0804, CELL_GCM_FOG_MODE_LINEAR_ABS = 0x0804,
}; };
// Surface clear bitfields (aggregates)
enum
{
RSX_GCM_CLEAR_DEPTH_BIT = 0x01,
RSX_GCM_CLEAR_STENCIL_BIT = 0x02,
RSX_GCM_CLEAR_RED_BIT = 0x10,
RSX_GCM_CLEAR_GREEN_BIT = 0x20,
RSX_GCM_CLEAR_BLUE_BIT = 0x40,
RSX_GCM_CLEAR_ALPHA_BIT = 0x80,
RSX_GCM_CLEAR_COLOR_MASK = 0xF0,
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)
};