From fdfcc6c5eace07e9ecb24b27882beff8ac2759e4 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Wed, 19 Apr 2023 03:09:41 +0300 Subject: [PATCH] gl: Refactor attachment clear logic - Make the whole thing a standalone command to avoid unnecessary state meddling. --- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 48 +++++++++++++++----------------- rpcs3/Emu/RSX/GL/GLTexture.cpp | 30 ++++++++++++++++++++ rpcs3/Emu/RSX/GL/GLTexture.h | 30 ++++++++++++++++++++ rpcs3/Emu/RSX/GL/glutils/fbo.cpp | 9 ------ rpcs3/Emu/RSX/GL/glutils/fbo.h | 1 - 5 files changed, 83 insertions(+), 35 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index e60a8381cc..7efb0a681e 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -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(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() diff --git a/rpcs3/Emu/RSX/GL/GLTexture.cpp b/rpcs3/Emu/RSX/GL/GLTexture.cpp index 2ae9aa4110..f8f020e58c 100644 --- a/rpcs3/Emu/RSX/GL/GLTexture.cpp +++ b/rpcs3/Emu/RSX/GL/GLTexture.cpp @@ -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); + } } diff --git a/rpcs3/Emu/RSX/GL/GLTexture.h b/rpcs3/Emu/RSX/GL/GLTexture.h index 8793a2718b..5515e1177a 100644 --- a/rpcs3/Emu/RSX/GL/GLTexture.h +++ b/rpcs3/Emu/RSX/GL/GLTexture.h @@ -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 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& subresources_layout); + void clear_attachments(gl::command_context& cmd, const clear_cmd_info& info); + namespace debug { extern std::unique_ptr g_vis_texture; diff --git a/rpcs3/Emu/RSX/GL/glutils/fbo.cpp b/rpcs3/Emu/RSX/GL/glutils/fbo.cpp index 38bddb8740..66c977d392 100644 --- a/rpcs3/Emu/RSX/GL/glutils/fbo.cpp +++ b/rpcs3/Emu/RSX/GL/glutils/fbo.cpp @@ -169,15 +169,6 @@ namespace gl glClear(static_cast(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); diff --git a/rpcs3/Emu/RSX/GL/glutils/fbo.h b/rpcs3/Emu/RSX/GL/glutils/fbo.h index 785c0b03eb..da86051ede 100644 --- a/rpcs3/Emu/RSX/GL/glutils/fbo.h +++ b/rpcs3/Emu/RSX/GL/glutils/fbo.h @@ -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;