mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-04 02:45:12 +00:00
vk: Fix event signal race when speculation fails to avoid a cache miss
- TODO: Proper GC for stale events
This commit is contained in:
parent
b5d5113803
commit
ce04a797c3
@ -36,6 +36,7 @@ namespace vk
|
|||||||
|
|
||||||
//DMA relevant data
|
//DMA relevant data
|
||||||
VkEvent dma_fence = VK_NULL_HANDLE;
|
VkEvent dma_fence = VK_NULL_HANDLE;
|
||||||
|
VkEvent prev_event = VK_NULL_HANDLE;
|
||||||
vk::render_device* m_device = nullptr;
|
vk::render_device* m_device = nullptr;
|
||||||
vk::viewable_image *vram_texture = nullptr;
|
vk::viewable_image *vram_texture = nullptr;
|
||||||
std::unique_ptr<vk::buffer> dma_buffer;
|
std::unique_ptr<vk::buffer> dma_buffer;
|
||||||
@ -73,7 +74,8 @@ namespace vk
|
|||||||
{
|
{
|
||||||
// Reset fence
|
// Reset fence
|
||||||
verify(HERE), m_device, dma_buffer, dma_fence != VK_NULL_HANDLE;
|
verify(HERE), m_device, dma_buffer, dma_fence != VK_NULL_HANDLE;
|
||||||
vkResetEvent(*m_device, dma_fence);
|
vkDestroyEvent(*m_device, dma_fence, nullptr);
|
||||||
|
dma_fence = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized = false;
|
synchronized = false;
|
||||||
@ -96,6 +98,8 @@ namespace vk
|
|||||||
vkDestroyEvent(*m_device, dma_fence, nullptr);
|
vkDestroyEvent(*m_device, dma_fence, nullptr);
|
||||||
dma_fence = VK_NULL_HANDLE;
|
dma_fence = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
verify(HERE), prev_event == VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,15 +286,26 @@ namespace vk
|
|||||||
vkCmdCopyBuffer(cmd, mem_target->value, dma_buffer->value, 1, ©);
|
vkCmdCopyBuffer(cmd, mem_target->value, dma_buffer->value, 1, ©);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LIKELY(!miss))
|
if (UNLIKELY(synchronized))
|
||||||
{
|
{
|
||||||
// If this is speculated, it should only occur once
|
// Save old event for deletion
|
||||||
verify(HERE), vkGetEventStatus(*m_device, dma_fence) == VK_EVENT_RESET;
|
verify(HERE), miss, prev_event == VK_NULL_HANDLE;
|
||||||
|
prev_event = dma_fence;
|
||||||
|
|
||||||
|
// Replace the wait event with a new one to avoid premature signaling!
|
||||||
|
VkEventCreateInfo createInfo = {};
|
||||||
|
createInfo.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
|
||||||
|
vkCreateEvent(*m_device, &createInfo, nullptr, &dma_fence);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// This is the only acceptable situation where a sync can occur twice, due to flush_always being set
|
// 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);
|
vkResetEvent(*m_device, dma_fence);
|
||||||
|
|
||||||
|
// If this is speculated, it should only occur once
|
||||||
|
// verify(HERE), vkGetEventStatus(*m_device, dma_fence) == VK_EVENT_RESET;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.set_flag(vk::command_buffer::cb_has_dma_transfer);
|
cmd.set_flag(vk::command_buffer::cb_has_dma_transfer);
|
||||||
@ -311,6 +326,13 @@ namespace vk
|
|||||||
vk::wait_for_event(dma_fence, GENERAL_WAIT_TIMEOUT);
|
vk::wait_for_event(dma_fence, GENERAL_WAIT_TIMEOUT);
|
||||||
vkResetEvent(*m_device, dma_fence);
|
vkResetEvent(*m_device, dma_fence);
|
||||||
|
|
||||||
|
if (prev_event)
|
||||||
|
{
|
||||||
|
// Remove the stale event if it still exists
|
||||||
|
vkDestroyEvent(*m_device, prev_event, nullptr);
|
||||||
|
prev_event = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
return dma_buffer->map(offset, size);
|
return dma_buffer->map(offset, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user