mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-30 21:32:50 +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);
|
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() &&
|
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)
|
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
|
// Unconditionally enable stencil test if it was disabled before
|
||||||
gl_state.enable(GL_TRUE, GL_SCISSOR_TEST);
|
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();
|
std::chrono::time_point<steady_clock> textures_start = steady_clock::now();
|
||||||
|
|
||||||
// Clear any 'dirty' surfaces - possible is a recycled cache surface is used
|
// Check for data casts
|
||||||
rsx::simple_array<VkClearAttachment> buffers_to_clear;
|
|
||||||
auto ds = std::get<1>(m_rtts.m_bound_depth_stencil);
|
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 (ds && ds->old_contents)
|
||||||
{
|
{
|
||||||
if (UNLIKELY(ds->old_contents->info.format == VK_FORMAT_B8G8R8A8_UNORM))
|
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
|
//Load textures
|
||||||
{
|
{
|
||||||
std::lock_guard lock(m_sampler_mutex);
|
std::lock_guard lock(m_sampler_mutex);
|
||||||
@ -1699,6 +1647,20 @@ void VKGSRender::end()
|
|||||||
m_current_command_buffer->flags |= cb_has_occlusion_task;
|
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
|
// 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
|
// Only textures are synchronized tightly with the GPU and they have been read back above
|
||||||
vk::enter_uninterruptible();
|
vk::enter_uninterruptible();
|
||||||
@ -1707,6 +1669,35 @@ void VKGSRender::end()
|
|||||||
update_draw_state();
|
update_draw_state();
|
||||||
begin_render_pass();
|
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;
|
u32 sub_index = 0;
|
||||||
rsx::method_registers.current_draw_clause.begin();
|
rsx::method_registers.current_draw_clause.begin();
|
||||||
do
|
do
|
||||||
|
Loading…
x
Reference in New Issue
Block a user