mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-30 12:32:43 +00:00
rsx: Reorganize write barrier implementation (either clear or memory barrier)
This commit is contained in:
parent
9c45ce6d37
commit
1ffadbe086
@ -210,58 +210,9 @@ void GLGSRender::end()
|
||||
}
|
||||
};
|
||||
|
||||
//Check if we have any 'recycled' surfaces in memory and if so, clear them
|
||||
std::vector<int> 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<gl::render_target*>(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<int> 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);
|
||||
|
||||
|
@ -1332,42 +1332,8 @@ void VKGSRender::end()
|
||||
|
||||
std::chrono::time_point<steady_clock> textures_start = steady_clock::now();
|
||||
|
||||
// Clear any 'dirty' surfaces - possible is a recycled cache surface is used
|
||||
rsx::simple_array<VkClearAttachment> 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<VkClearAttachment> 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
|
||||
|
Loading…
x
Reference in New Issue
Block a user