vk: Restructure commandbuffer scoping to allow faults in vertex upload

- Defer renderpass open to allow recovery after fault in the middle of vertex upload
This commit is contained in:
kd-11 2019-09-05 14:38:33 +03:00 committed by kd-11
parent d0db7ca6bd
commit 360c0e9af6
1 changed files with 26 additions and 57 deletions

View File

@ -693,14 +693,15 @@ bool VKGSRender::on_access_violation(u32 address, bool is_writing)
m_flush_requests.post(false);
has_queue_ref = true;
}
else if (!vk::is_uninterruptible())
{
//Flush primary cb queue to sync pending changes (e.g image transitions!)
flush_command_queue();
}
else
{
//LOG_ERROR(RSX, "Fault in uninterruptible code!");
if (vk::is_uninterruptible())
{
LOG_ERROR(RSX, "Fault in uninterruptible code!");
}
//Flush primary cb queue to sync pending changes (e.g image transitions!)
flush_command_queue();
}
if (has_queue_ref)
@ -1135,6 +1136,13 @@ void VKGSRender::emit_geometry(u32 sub_index)
m_program->bind_uniform(m_vertex_layout_storage->value, VERTEX_BUFFERS_FIRST_BIND_SLOT + 2, m_current_frame->descriptor_set);
}
if (!m_render_pass_open)
{
vkCmdBindPipeline(*m_current_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_program->pipeline);
update_draw_state();
begin_render_pass();
}
// Bind the new set of descriptors for use with this draw call
vkCmdBindDescriptorSets(*m_current_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &m_current_frame->descriptor_set, 0, nullptr);
@ -1694,64 +1702,19 @@ void VKGSRender::end()
vk::get_appropriate_topology(rsx::method_registers.current_draw_clause.primitive, primitive_emulated);
// Apply write memory barriers
if (true)//g_cfg.video.strict_rendering_mode)
if (ds) ds->write_barrier(*m_current_command_buffer);
for (auto &rtt : m_rtts.m_bound_render_targets)
{
if (ds) ds->write_barrier(*m_current_command_buffer);
for (auto &rtt : m_rtts.m_bound_render_targets)
if (auto surface = std::get<1>(rtt))
{
if (auto surface = std::get<1>(rtt))
{
surface->write_barrier(*m_current_command_buffer);
}
}
begin_render_pass();
}
else
{
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, buffers_to_clear.size(),
buffers_to_clear.data(), 1, &rect);
surface->write_barrier(*m_current_command_buffer);
}
}
// Final heap check...
check_heap_status(VK_HEAP_CHECK_VERTEX_STORAGE | VK_HEAP_CHECK_VERTEX_LAYOUT_STORAGE);
// 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();
vkCmdBindPipeline(*m_current_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_program->pipeline);
update_draw_state();
u32 sub_index = 0;
rsx::method_registers.current_draw_clause.begin();
do
@ -1760,8 +1723,8 @@ void VKGSRender::end()
}
while (rsx::method_registers.current_draw_clause.next());
// Close any open passes unconditionally
close_render_pass();
vk::leave_uninterruptible();
m_rtts.on_write(m_framebuffer_layout.color_write_enabled.data(), m_framebuffer_layout.zeta_write_enabled);
@ -2810,6 +2773,12 @@ void VKGSRender::close_and_submit_command_buffer(VkFence fence, VkSemaphore wait
VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
}
// End any active renderpasses; the caller should handle reopening
if (m_render_pass_open)
{
close_render_pass();
}
// End open queries. Flags will be automatically reset by the submit routine
if (m_current_command_buffer->flags & vk::command_buffer::cb_has_open_query)
{