gl: Refactor attachment clear logic

- Make the whole thing a standalone command to avoid unnecessary state meddling.
This commit is contained in:
kd-11 2023-04-19 03:09:41 +03:00 committed by kd-11
parent b86ecf7441
commit fdfcc6c5ea
5 changed files with 83 additions and 35 deletions

View File

@ -546,7 +546,7 @@ void GLGSRender::clear_surface(u32 arg)
if (!m_graphics_state.test(rsx::rtt_config_valid)) return;
GLbitfield mask = 0;
gl::clear_cmd_info clear_cmd{};
gl::command_context cmd{ gl_state };
const bool full_frame =
@ -565,26 +565,23 @@ void GLGSRender::clear_surface(u32 arg)
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));
gl_state.depth_mask(GL_TRUE);
gl_state.clear_depth(f32(clear_depth) / max_depth_value);
mask |= GLenum(gl::buffers::depth);
clear_cmd.clear_depth.value = f32(clear_depth) / max_depth_value;
clear_cmd.aspect_mask |= gl::image_aspect::depth;
}
if (is_depth_stencil_format(surface_depth_format))
{
if (arg & RSX_GCM_CLEAR_STENCIL_BIT)
{
u8 clear_stencil = rsx::method_registers.stencil_clear_value();
gl_state.stencil_mask(rsx::method_registers.stencil_mask());
gl_state.clear_stencil(clear_stencil);
mask |= GLenum(gl::buffers::stencil);
clear_cmd.clear_stencil.mask = rsx::method_registers.stencil_mask();
clear_cmd.clear_stencil.value = rsx::method_registers.stencil_clear_value();
clear_cmd.aspect_mask |= gl::image_aspect::stencil;
}
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(clear_cmd.aspect_mask);
if (ds->state_flags & rsx::surface_state_flags::erase_bkgnd && // Needs initialization
ds->old_contents.empty() && !g_cfg.video.read_depth_buffer) // No way to load data from memory, so no initialization given
@ -593,16 +590,15 @@ void GLGSRender::clear_surface(u32 arg)
if (ds_mask == RSX_GCM_CLEAR_DEPTH_BIT)
{
// Depth was cleared, initialize stencil
gl_state.stencil_mask(0xFF);
gl_state.clear_stencil(0xFF);
mask |= GLenum(gl::buffers::stencil);
clear_cmd.clear_stencil.mask = 0xff;
clear_cmd.clear_stencil.value = 0xff;
clear_cmd.aspect_mask |= gl::image_aspect::stencil;
}
else if (ds_mask == RSX_GCM_CLEAR_STENCIL_BIT)
{
// Stencil was cleared, initialize depth
gl_state.depth_mask(GL_TRUE);
gl_state.clear_depth(1.f);
mask |= GLenum(gl::buffers::depth);
clear_cmd.clear_depth.value = 1.f;
clear_cmd.aspect_mask |= gl::image_aspect::depth;
}
}
else
@ -612,7 +608,7 @@ void GLGSRender::clear_surface(u32 arg)
}
}
if (mask)
if (clear_cmd.aspect_mask)
{
// Memory has been initialized
update_z = true;
@ -679,18 +675,20 @@ void GLGSRender::clear_surface(u32 arg)
if (colormask)
{
gl_state.clear_color(clear_r, clear_g, clear_b, clear_a);
mask |= GLenum(gl::buffers::color);
clear_cmd.clear_color.mask = colormask;
clear_cmd.clear_color.attachment_count = static_cast<u8>(m_rtts.m_bound_render_target_ids.size());
clear_cmd.clear_color.r = clear_r;
clear_cmd.clear_color.g = clear_g;
clear_cmd.clear_color.b = clear_b;
clear_cmd.clear_color.a = clear_a;
clear_cmd.aspect_mask |= gl::image_aspect::color;
int hw_index = 0;
for (const auto& index : m_rtts.m_bound_render_target_ids)
if (!full_frame)
{
if (!full_frame)
for (const auto& index : m_rtts.m_bound_render_target_ids)
{
m_rtts.m_bound_render_targets[index].second->write_barrier(cmd);
}
gl_state.color_maski(hw_index++, colormask);
}
update_color = true;
@ -707,7 +705,7 @@ void GLGSRender::clear_surface(u32 arg)
gl_state.enable(GL_SCISSOR_TEST);
}
glClear(mask);
gl::clear_attachments(cmd, clear_cmd);
}
bool GLGSRender::load_program()

View File

@ -1101,4 +1101,34 @@ namespace gl
const coord3u dst_area = { {}, dst->size3D() };
copy_typeless(cmd, dst, src, dst_area, src_area);
}
void clear_attachments(gl::command_context& cmd, const clear_cmd_info& info)
{
// Compile the clear command at the end. Other intervening operations will
GLbitfield clear_mask = 0;
if (info.aspect_mask & gl::image_aspect::color)
{
for (u32 buffer_id = 0; buffer_id < info.clear_color.attachment_count; ++buffer_id)
{
cmd->color_maski(buffer_id, info.clear_color.mask);
}
cmd->clear_color(info.clear_color.r, info.clear_color.g, info.clear_color.b, info.clear_color.a);
clear_mask |= GL_COLOR_BUFFER_BIT;
}
if (info.aspect_mask & gl::image_aspect::depth)
{
cmd->depth_mask(GL_TRUE);
cmd->clear_depth(info.clear_depth.value);
clear_mask |= GL_DEPTH_BUFFER_BIT;
}
if (info.aspect_mask & gl::image_aspect::stencil)
{
cmd->stencil_mask(info.clear_stencil.mask);
cmd->clear_stencil(info.clear_stencil.value);
clear_mask |= GL_STENCIL_BUFFER_BIT;
}
glClear(clear_mask);
}
}

View File

@ -31,6 +31,34 @@ namespace gl
u64 memory_required;
};
struct clear_cmd_info
{
GLbitfield aspect_mask = 0;
struct
{
f32 value = 0;
}
clear_depth;
struct
{
u8 mask = 0;
u8 value = 0;
}
clear_stencil;
struct {
u32 mask = 0;
u8 attachment_count = 0;
u8 r = 0;
u8 g = 0;
u8 b = 0;
u8 a = 0;
}
clear_color;
};
GLenum get_target(rsx::texture_dimension_extended type);
GLenum get_sized_internal_format(u32 texture_format);
std::tuple<GLenum, GLenum> get_format_type(u32 texture_format);
@ -51,6 +79,8 @@ namespace gl
void upload_texture(gl::command_context& cmd, texture* dst, u32 gcm_format, bool is_swizzled, const std::vector<rsx::subresource_layout>& subresources_layout);
void clear_attachments(gl::command_context& cmd, const clear_cmd_info& info);
namespace debug
{
extern std::unique_ptr<texture> g_vis_texture;

View File

@ -169,15 +169,6 @@ namespace gl
glClear(static_cast<GLbitfield>(buffers_));
}
void fbo::clear(buffers buffers_, color4f color_value, double depth_value, u8 stencil_value) const
{
save_binding_state save(*this);
glClearColor(color_value.r, color_value.g, color_value.b, color_value.a);
glClearDepth(depth_value);
glClearStencil(stencil_value);
clear(buffers_);
}
void fbo::copy_from(const void* pixels, const sizei& size, gl::texture::format format_, gl::texture::type type_, class pixel_unpack_settings pixel_settings) const
{
save_binding_state save(*this);

View File

@ -211,7 +211,6 @@ namespace gl
void draw_elements(const buffer& buffer, GLenum mode, GLsizei count, const GLuint* indices) const;
void clear(buffers buffers_) const;
void clear(buffers buffers_, color4f color_value, double depth_value, u8 stencil_value) const;
void copy_from(const void* pixels, const sizei& size, gl::texture::format format_, gl::texture::type type_, class pixel_unpack_settings pixel_settings = pixel_unpack_settings()) const;
void copy_from(const buffer& buf, const sizei& size, gl::texture::format format_, gl::texture::type type_, class pixel_unpack_settings pixel_settings = pixel_unpack_settings()) const;