rsx: Fix dirty flag reset after a partial attachment initialization

- D24S8 targets have 2 aspects that are dealt with separately; Forcefully initialize the remaining data if a partial init is done. Its 'free' anyway
- It seems that the stencil mask matters when clearing unlike the depth mask and color mask
This commit is contained in:
kd-11 2018-12-30 23:47:15 +03:00 committed by kd-11
parent c80c7f06bb
commit 475cc99117
2 changed files with 85 additions and 37 deletions

View File

@ -1119,29 +1119,56 @@ void GLGSRender::clear_surface(u32 arg)
rsx::surface_depth_format surface_depth_format = rsx::method_registers.surface_depth_fmt();
if (arg & 0x1)
if (auto ds = std::get<1>(m_rtts.m_bound_depth_stencil); arg & 0x3)
{
u32 max_depth_value = get_max_depth_value(surface_depth_format);
u32 clear_depth = rsx::method_registers.z_clear_value(surface_depth_format == rsx::surface_depth_format::z24s8);
gl_state.depth_mask(GL_TRUE);
gl_state.clear_depth(f32(clear_depth) / max_depth_value);
mask |= GLenum(gl::buffers::depth);
if (const auto address = std::get<0>(m_rtts.m_bound_depth_stencil))
if (arg & 0x1)
{
m_rtts.on_write(address);
u32 max_depth_value = get_max_depth_value(surface_depth_format);
u32 clear_depth = rsx::method_registers.z_clear_value(surface_depth_format == rsx::surface_depth_format::z24s8);
gl_state.depth_mask(GL_TRUE);
gl_state.clear_depth(f32(clear_depth) / max_depth_value);
mask |= GLenum(gl::buffers::depth);
}
}
if (surface_depth_format == rsx::surface_depth_format::z24s8 && (arg & 0x2))
{
u8 clear_stencil = rsx::method_registers.stencil_clear_value();
if (surface_depth_format == rsx::surface_depth_format::z24s8)
{
if (arg & 0x2)
{
u8 clear_stencil = rsx::method_registers.stencil_clear_value();
gl_state.stencil_mask(0xFF);
gl_state.clear_stencil(clear_stencil);
gl_state.stencil_mask(rsx::method_registers.stencil_mask());
gl_state.clear_stencil(clear_stencil);
mask |= GLenum(gl::buffers::stencil);
}
mask |= GLenum(gl::buffers::stencil);
if ((arg & 0x3) != 0x3 && ds->dirty)
{
verify(HERE), mask;
// Only one aspect was cleared. Make sure to memory intialize the other before removing dirty flag
if (arg == 1)
{
// Depth was cleared, initialize stencil
gl_state.stencil_mask(0xFF);
gl_state.clear_stencil(0xFF);
mask |= GLenum(gl::buffers::stencil);
}
else
{
// Stencil was cleared, initialize depth
gl_state.depth_mask(GL_TRUE);
gl_state.clear_depth(1.f);
mask |= GLenum(gl::buffers::depth);
}
}
}
if (mask)
{
// Memory has been initialized
m_rtts.on_write(std::get<0>(m_rtts.m_bound_depth_stencil));
}
}
if (auto colormask = (arg & 0xf0))

View File

@ -1901,28 +1901,49 @@ void VKGSRender::clear_surface(u32 mask)
auto surface_depth_format = rsx::method_registers.surface_depth_fmt();
if (mask & 0x1)
if (auto ds = std::get<1>(m_rtts.m_bound_depth_stencil); mask & 0x3)
{
u32 max_depth_value = get_max_depth_value(surface_depth_format);
u32 clear_depth = rsx::method_registers.z_clear_value(surface_depth_format == rsx::surface_depth_format::z24s8);
float depth_clear = (float)clear_depth / max_depth_value;
depth_stencil_clear_values.depthStencil.depth = depth_clear;
depth_stencil_clear_values.depthStencil.stencil = stencil_clear;
depth_stencil_mask |= VK_IMAGE_ASPECT_DEPTH_BIT;
}
if (mask & 0x2)
{
if (surface_depth_format == rsx::surface_depth_format::z24s8 &&
rsx::method_registers.stencil_mask() != 0)
if (mask & 0x1)
{
u8 clear_stencil = rsx::method_registers.stencil_clear_value();
depth_stencil_clear_values.depthStencil.stencil = clear_stencil;
u32 max_depth_value = get_max_depth_value(surface_depth_format);
depth_stencil_mask |= VK_IMAGE_ASPECT_STENCIL_BIT;
u32 clear_depth = rsx::method_registers.z_clear_value(surface_depth_format == rsx::surface_depth_format::z24s8);
float depth_clear = (float)clear_depth / max_depth_value;
depth_stencil_clear_values.depthStencil.depth = depth_clear;
depth_stencil_clear_values.depthStencil.stencil = stencil_clear;
depth_stencil_mask |= VK_IMAGE_ASPECT_DEPTH_BIT;
}
if (surface_depth_format == rsx::surface_depth_format::z24s8)
{
if (mask & 0x2 && rsx::method_registers.stencil_mask() != 0)
{
u8 clear_stencil = rsx::method_registers.stencil_clear_value();
depth_stencil_clear_values.depthStencil.stencil = clear_stencil;
depth_stencil_mask |= VK_IMAGE_ASPECT_STENCIL_BIT;
}
if ((mask & 0x3) != 0x3 && ds->dirty)
{
verify(HERE), depth_stencil_mask;
// Only one aspect was cleared. Make sure to memory intialize the other before removing dirty flag
if (mask == 1)
{
// Depth was cleared, initialize stencil
depth_stencil_clear_values.depthStencil.stencil = 0xFF;
depth_stencil_mask |= VK_IMAGE_ASPECT_STENCIL_BIT;
}
else
{
// Stencil was cleared, initialize depth
depth_stencil_clear_values.depthStencil.depth = 1.f;
depth_stencil_mask |= VK_IMAGE_ASPECT_DEPTH_BIT;
}
}
}
}
@ -2015,7 +2036,7 @@ void VKGSRender::clear_surface(u32 mask)
}
}
if (mask & 0x3)
if (depth_stencil_mask)
{
if (const auto address = std::get<0>(m_rtts.m_bound_depth_stencil))
{