vk: Handle emergency commandbuffer close with dangling queries

- TODO: Refactoring
This commit is contained in:
kd-11 2019-06-28 21:35:43 +03:00 committed by kd-11
parent d69e8288ad
commit ae93b417ec
5 changed files with 47 additions and 7 deletions

View File

@ -2828,6 +2828,7 @@ void VKGSRender::close_and_submit_command_buffer(VkFence fence, VkSemaphore wait
{
auto open_query = m_occlusion_map[m_active_query_info->driver_handle].indices.back();
m_occlusion_query_pool.end_query(*m_current_command_buffer, open_query);
m_current_command_buffer->flags &= ~vk::command_buffer::cb_has_open_query;
}
m_current_command_buffer->end();
@ -3606,6 +3607,18 @@ void VKGSRender::discard_occlusion_query(rsx::reports::occlusion_query_info* que
data.indices.clear();
}
void VKGSRender::emergency_query_cleanup(vk::command_buffer* commands)
{
verify("Command list mismatch" HERE), commands == static_cast<vk::command_buffer*>(m_current_command_buffer);
if (m_current_command_buffer->flags & vk::command_buffer::cb_has_open_query)
{
auto open_query = m_occlusion_map[m_active_query_info->driver_handle].indices.back();
m_occlusion_query_pool.end_query(*m_current_command_buffer, open_query);
m_current_command_buffer->flags &= ~vk::command_buffer::cb_has_open_query;
}
}
bool VKGSRender::on_decompiler_task()
{
return m_prog_buffer->async_update(8, *m_device, pipeline_layout).first;

View File

@ -471,6 +471,9 @@ public:
void get_occlusion_query_result(rsx::reports::occlusion_query_info* query) override;
void discard_occlusion_query(rsx::reports::occlusion_query_info* query) override;
// External callback in case we need to suddenly submit a commandlist unexpectedly, e.g in a violation handler
void emergency_query_cleanup(vk::command_buffer* commands);
protected:
void begin() override;
void end() override;

View File

@ -1,5 +1,6 @@
#include "stdafx.h"
#include "VKHelpers.h"
#include "VKGSRender.h"
#include "VKCompute.h"
#include "VKRenderPass.h"
#include "VKFramebuffer.h"
@ -771,6 +772,14 @@ namespace vk
}
}
void do_query_cleanup(vk::command_buffer& cmd)
{
auto renderer = dynamic_cast<VKGSRender*>(rsx::get_current_renderer());
verify(HERE), renderer;
renderer->emergency_query_cleanup(&cmd);
}
void die_with_error(const char* faulting_addr, VkResult error_code)
{
std::string error_message;

View File

@ -190,6 +190,10 @@ namespace vk
VkResult wait_for_fence(VkFence pFence, u64 timeout = 0ull);
VkResult wait_for_event(VkEvent pEvent, u64 timeout = 0ull);
// Handle unexpected submit with dangling occlusion query
// TODO: Move queries out of the renderer!
void do_query_cleanup(vk::command_buffer& cmd);
void die_with_error(const char* faulting_addr, VkResult error_code);
struct memory_type_mapping
@ -1008,6 +1012,9 @@ private:
return;
}
// Check for hanging queries to avoid driver hang
verify("close and submit of commandbuffer with a hanging query!" HERE), (flags & cb_has_open_query) == 0;
if (!fence)
{
fence = m_submit_fence;

View File

@ -1,4 +1,4 @@
#pragma once
#pragma once
#include "stdafx.h"
#include "VKRenderTargets.h"
#include "VKGSRender.h"
@ -292,13 +292,8 @@ namespace vk
}
else
{
// HACK
// Deletion of queued objects and subsequent driver reuse of handles is causing race conditions here
// TODO: Proper garbage collection for these things
vkResetEvent(*m_device, dma_fence);
// If this is speculated, it should only occur once
// verify(HERE), vkGetEventStatus(*m_device, dma_fence) == VK_EVENT_RESET;
verify(HERE), vkGetEventStatus(*m_device, dma_fence) == VK_EVENT_RESET;
}
cmd.set_flag(vk::command_buffer::cb_has_dma_transfer);
@ -1090,6 +1085,13 @@ namespace vk
void cleanup_after_dma_transfers(vk::command_buffer& cmd) override
{
bool occlusion_query_active = !!(cmd.flags & vk::command_buffer::cb_has_open_query);
if (occlusion_query_active)
{
// We really stepped in it
vk::do_query_cleanup(cmd);
}
// End recording
cmd.end();
@ -1116,6 +1118,12 @@ namespace vk
}
verify(HERE), cmd.flags == 0;
if (occlusion_query_active)
{
verify(HERE), cmd.is_recording();
cmd.flags |= vk::command_buffer::cb_load_occluson_task;
}
}
public: