diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 9d577208e4..c7565d4c48 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -210,58 +210,9 @@ void GLGSRender::end() } }; - //Check if we have any 'recycled' surfaces in memory and if so, clear them - std::vector buffers_to_clear; - bool clear_all_color = true; - bool clear_depth = false; - - for (int index = 0; index < 4; index++) - { - if (std::get<0>(m_rtts.m_bound_render_targets[index]) != 0) - { - if (std::get<1>(m_rtts.m_bound_render_targets[index])->cleared()) - clear_all_color = false; - else - buffers_to_clear.push_back(index); - } - } - gl::render_target *ds = std::get<1>(m_rtts.m_bound_depth_stencil); - if (ds && !ds->cleared()) - { - clear_depth = true; - } - - if (clear_depth || buffers_to_clear.size() > 0) - { - gl_state.enable(GL_FALSE, GL_SCISSOR_TEST); - GLenum mask = 0; - - if (clear_depth) - { - gl_state.depth_mask(GL_TRUE); - gl_state.clear_depth(1.f); - gl_state.clear_stencil(255); - mask |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; - } - - if (clear_all_color) - mask |= GL_COLOR_BUFFER_BIT; - - glClear(mask); - - if (buffers_to_clear.size() > 0 && !clear_all_color) - { - GLfloat colors[] = { 0.f, 0.f, 0.f, 0.f }; - //It is impossible for the render target to be type A or B here (clear all would have been flagged) - for (auto &i : buffers_to_clear) - glClearBufferfv(m_draw_fbo->id(), i, colors); - } - - if (clear_depth) - gl_state.depth_mask(rsx::method_registers.depth_write_enabled()); - } + // Handle special memory barrier for ARGB8->D24S8 in an active DSV if (ds && ds->old_contents != nullptr && ds->get_rsx_pitch() == static_cast(ds->old_contents)->get_rsx_pitch() && ds->old_contents->get_internal_format() == gl::texture::internal_format::rgba8) { @@ -453,6 +404,56 @@ void GLGSRender::end() } } + rsx::simple_array buffers_to_clear; + bool clear_all_color = true; + bool clear_depth = false; + + for (int index = 0; index < 4; index++) + { + if (std::get<0>(m_rtts.m_bound_render_targets[index]) != 0) + { + if (std::get<1>(m_rtts.m_bound_render_targets[index])->cleared()) + clear_all_color = false; + else + buffers_to_clear.push_back(index); + } + } + + if (ds && !ds->cleared()) + { + clear_depth = true; + } + + if (clear_depth || buffers_to_clear.size() > 0) + { + gl_state.enable(GL_FALSE, GL_SCISSOR_TEST); + GLenum mask = 0; + + if (clear_depth) + { + gl_state.depth_mask(GL_TRUE); + gl_state.clear_depth(1.f); + gl_state.clear_stencil(255); + mask |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; + } + + if (clear_all_color) + mask |= GL_COLOR_BUFFER_BIT; + + glClear(mask); + + if (buffers_to_clear.size() > 0 && !clear_all_color) + { + GLfloat colors[] = { 0.f, 0.f, 0.f, 0.f }; + //It is impossible for the render target to be type A or B here (clear all would have been flagged) + for (auto &i : buffers_to_clear) + glClearBufferfv(m_draw_fbo->id(), i, colors); + } + + if (clear_depth) + gl_state.depth_mask(rsx::method_registers.depth_write_enabled()); + } + // Unconditionally enable stencil test if it was disabled before gl_state.enable(GL_TRUE, GL_SCISSOR_TEST); diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 5465dfda22..1d81a3d2d5 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -1332,42 +1332,8 @@ void VKGSRender::end() std::chrono::time_point textures_start = steady_clock::now(); - // Clear any 'dirty' surfaces - possible is a recycled cache surface is used - rsx::simple_array buffers_to_clear; + // Check for data casts auto ds = std::get<1>(m_rtts.m_bound_depth_stencil); - - //Check for memory clears - if (ds && ds->dirty) - { - //Clear this surface before drawing on it - VkClearValue clear_value = {}; - clear_value.depthStencil = { 1.f, 255 }; - buffers_to_clear.push_back({ vk::get_aspect_flags(ds->info.format), 0, clear_value }); - } - - for (u32 index = 0; index < m_draw_buffers.size(); ++index) - { - if (auto rtt = std::get<1>(m_rtts.m_bound_render_targets[index])) - { - if (rtt->dirty) - { - buffers_to_clear.push_back({ VK_IMAGE_ASPECT_COLOR_BIT, index, {} }); - } - } - } - - if (UNLIKELY(!buffers_to_clear.empty())) - { - begin_render_pass(); - - VkClearRect rect = { {{0, 0}, {m_draw_fbo->width(), m_draw_fbo->height()}}, 0, 1 }; - vkCmdClearAttachments(*m_current_command_buffer, (u32)buffers_to_clear.size(), - buffers_to_clear.data(), 1, &rect); - - close_render_pass(); - } - - //Check for data casts if (ds && ds->old_contents) { if (UNLIKELY(ds->old_contents->info.format == VK_FORMAT_B8G8R8A8_UNORM)) @@ -1385,24 +1351,6 @@ void VKGSRender::end() } } - if (g_cfg.video.strict_rendering_mode) - { - //Prepare surfaces if needed - for (auto &rtt : m_rtts.m_bound_render_targets) - { - if (auto surface = std::get<1>(rtt)) - { - if (surface->old_contents != nullptr) - surface->memory_barrier(*m_current_command_buffer); - } - } - - if (ds && ds->old_contents) - { - ds->memory_barrier(*m_current_command_buffer); - } - } - //Load textures { std::lock_guard lock(m_sampler_mutex); @@ -1699,6 +1647,20 @@ void VKGSRender::end() m_current_command_buffer->flags |= cb_has_occlusion_task; } + // Apply write memory barriers + if (g_cfg.video.strict_rendering_mode) + { + if (ds) ds->memory_barrier(*m_current_command_buffer); + + for (auto &rtt : m_rtts.m_bound_render_targets) + { + if (auto surface = std::get<1>(rtt)) + { + surface->memory_barrier(*m_current_command_buffer); + } + } + } + // While vertex upload is an interruptible process, if we made it this far, there's no need to sync anything that occurs past this point // Only textures are synchronized tightly with the GPU and they have been read back above vk::enter_uninterruptible(); @@ -1707,6 +1669,35 @@ void VKGSRender::end() update_draw_state(); begin_render_pass(); + // Clear any 'dirty' surfaces - possible is a recycled cache surface is used + rsx::simple_array buffers_to_clear; + + if (ds && ds->dirty) + { + // Clear this surface before drawing on it + VkClearValue clear_value = {}; + clear_value.depthStencil = { 1.f, 255 }; + buffers_to_clear.push_back({ vk::get_aspect_flags(ds->info.format), 0, clear_value }); + } + + for (u32 index = 0; index < m_draw_buffers.size(); ++index) + { + if (auto rtt = std::get<1>(m_rtts.m_bound_render_targets[index])) + { + if (rtt->dirty) + { + buffers_to_clear.push_back({ VK_IMAGE_ASPECT_COLOR_BIT, index, {} }); + } + } + } + + if (UNLIKELY(!buffers_to_clear.empty())) + { + VkClearRect rect = { {{0, 0}, {m_draw_fbo->width(), m_draw_fbo->height()}}, 0, 1 }; + vkCmdClearAttachments(*m_current_command_buffer, (u32)buffers_to_clear.size(), + buffers_to_clear.data(), 1, &rect); + } + u32 sub_index = 0; rsx::method_registers.current_draw_clause.begin(); do