mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 10:42:36 +01:00
vk: Improve events
- Make events properly managed objects. - Add a workaround for AMD's broken event status query
This commit is contained in:
parent
5eb314fbbb
commit
9af52d12a8
@ -902,12 +902,12 @@ namespace vk
|
||||
}
|
||||
}
|
||||
|
||||
VkResult wait_for_event(VkEvent event, u64 timeout)
|
||||
VkResult wait_for_event(event* pEvent, u64 timeout)
|
||||
{
|
||||
u64 t = 0;
|
||||
while (true)
|
||||
{
|
||||
switch (const auto status = vkGetEventStatus(*g_current_renderer, event))
|
||||
switch (const auto status = pEvent->status())
|
||||
{
|
||||
case VK_EVENT_SET:
|
||||
return VK_SUCCESS;
|
||||
|
@ -115,6 +115,7 @@ namespace vk
|
||||
struct gpu_formats_support;
|
||||
struct fence;
|
||||
struct pipeline_binding_table;
|
||||
class event;
|
||||
|
||||
const vk::context *get_current_thread_ctx();
|
||||
void set_current_thread_ctx(const vk::context &ctx);
|
||||
@ -227,7 +228,7 @@ namespace vk
|
||||
// Fence reset with driver workarounds in place
|
||||
void reset_fence(fence* pFence);
|
||||
VkResult wait_for_fence(fence* pFence, u64 timeout = 0ull);
|
||||
VkResult wait_for_event(VkEvent pEvent, u64 timeout = 0ull);
|
||||
VkResult wait_for_event(event* pEvent, u64 timeout = 0ull);
|
||||
|
||||
// Handle unexpected submit with dangling occlusion query
|
||||
// TODO: Move queries out of the renderer!
|
||||
@ -1736,6 +1737,86 @@ private:
|
||||
VkDevice m_device;
|
||||
};
|
||||
|
||||
class event
|
||||
{
|
||||
VkDevice m_device = VK_NULL_HANDLE;
|
||||
VkEvent m_vk_event = VK_NULL_HANDLE;
|
||||
|
||||
std::unique_ptr<buffer> m_buffer;
|
||||
volatile uint32_t* m_value = nullptr;
|
||||
|
||||
public:
|
||||
event(const render_device& dev)
|
||||
{
|
||||
m_device = dev;
|
||||
if (dev.gpu().get_driver_vendor() != driver_vendor::AMD)
|
||||
{
|
||||
VkEventCreateInfo info
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0
|
||||
};
|
||||
vkCreateEvent(dev, &info, nullptr, &m_vk_event);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Work around AMD's broken event signals
|
||||
m_buffer = std::make_unique<buffer>
|
||||
(
|
||||
dev,
|
||||
4,
|
||||
dev.get_memory_mapping().host_visible_coherent,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
|
||||
VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
0
|
||||
);
|
||||
|
||||
m_value = reinterpret_cast<uint32_t*>(m_buffer->map(0, 4));
|
||||
*m_value = 0xCAFEBABE;
|
||||
}
|
||||
}
|
||||
|
||||
~event()
|
||||
{
|
||||
if (m_vk_event) [[likely]]
|
||||
{
|
||||
vkDestroyEvent(m_device, m_vk_event, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_buffer->unmap();
|
||||
m_buffer.reset();
|
||||
m_value = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void signal(const command_buffer& cmd, VkPipelineStageFlags stages)
|
||||
{
|
||||
if (m_vk_event) [[likely]]
|
||||
{
|
||||
vkCmdSetEvent(cmd, m_vk_event, stages);
|
||||
}
|
||||
else
|
||||
{
|
||||
insert_execution_barrier(cmd, stages, VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
vkCmdFillBuffer(cmd, m_buffer->value, 0, 4, 0xDEADBEEF);
|
||||
}
|
||||
}
|
||||
|
||||
VkResult status() const
|
||||
{
|
||||
if (m_vk_event) [[likely]]
|
||||
{
|
||||
return vkGetEventStatus(m_device, m_vk_event);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (*m_value == 0xDEADBEEF)? VK_EVENT_SET : VK_EVENT_RESET;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct sampler
|
||||
{
|
||||
VkSampler value;
|
||||
|
@ -14,7 +14,7 @@ namespace vk
|
||||
std::vector<std::unique_ptr<vk::buffer>> m_disposed_buffers;
|
||||
std::vector<std::unique_ptr<vk::image_view>> m_disposed_image_views;
|
||||
std::vector<std::unique_ptr<vk::image>> m_disposed_images;
|
||||
rsx::simple_array<VkEvent> m_disposed_events;
|
||||
std::vector<std::unique_ptr<vk::event>> m_disposed_events;
|
||||
|
||||
eid_scope_t(u64 _eid):
|
||||
eid(_eid), m_device(vk::get_current_renderer())
|
||||
@ -27,17 +27,8 @@ namespace vk
|
||||
|
||||
void discard()
|
||||
{
|
||||
if (!m_disposed_events.empty())
|
||||
{
|
||||
for (auto &ev : m_disposed_events)
|
||||
{
|
||||
vkDestroyEvent(*m_device, ev, nullptr);
|
||||
}
|
||||
|
||||
m_disposed_events.clear();
|
||||
}
|
||||
|
||||
m_disposed_buffers.clear();
|
||||
m_disposed_events.clear();
|
||||
m_disposed_image_views.clear();
|
||||
m_disposed_images.clear();
|
||||
}
|
||||
@ -146,9 +137,9 @@ namespace vk
|
||||
get_current_eid_scope().m_disposed_images.emplace_back(std::move(img));
|
||||
}
|
||||
|
||||
void dispose(VkEvent& event)
|
||||
void dispose(std::unique_ptr<vk::event>& event)
|
||||
{
|
||||
get_current_eid_scope().m_disposed_events.push_back(event);
|
||||
get_current_eid_scope().m_disposed_events.emplace_back(std::move(event));
|
||||
event = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ namespace vk
|
||||
std::unique_ptr<vk::viewable_image> managed_texture = nullptr;
|
||||
|
||||
//DMA relevant data
|
||||
VkEvent dma_fence = VK_NULL_HANDLE;
|
||||
std::unique_ptr<vk::event> dma_fence;
|
||||
vk::render_device* m_device = nullptr;
|
||||
vk::viewable_image *vram_texture = nullptr;
|
||||
|
||||
@ -169,16 +169,15 @@ namespace vk
|
||||
{
|
||||
verify(HERE), src->samples() == 1;
|
||||
|
||||
if (m_device == nullptr)
|
||||
if (!m_device)
|
||||
{
|
||||
m_device = &cmd.get_command_pool().get_owner();
|
||||
}
|
||||
|
||||
if (dma_fence == VK_NULL_HANDLE)
|
||||
if (dma_fence)
|
||||
{
|
||||
VkEventCreateInfo createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
|
||||
vkCreateEvent(*m_device, &createInfo, nullptr, &dma_fence);
|
||||
verify(HERE), synchronized;
|
||||
vk::get_resource_manager()->dispose(dma_fence);
|
||||
}
|
||||
|
||||
src->push_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
@ -284,23 +283,12 @@ namespace vk
|
||||
|
||||
src->pop_layout(cmd);
|
||||
|
||||
if (synchronized) [[unlikely]]
|
||||
{
|
||||
// Replace the wait event with a new one to avoid premature signaling!
|
||||
vk::get_resource_manager()->dispose(dma_fence);
|
||||
|
||||
VkEventCreateInfo createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
|
||||
vkCreateEvent(*m_device, &createInfo, nullptr, &dma_fence);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If this is speculated, it should only occur once
|
||||
verify(HERE), vkGetEventStatus(*m_device, dma_fence) == VK_EVENT_RESET;
|
||||
}
|
||||
// Create event object for this transfer and queue signal op
|
||||
dma_fence = std::make_unique<vk::event>(*m_device);
|
||||
dma_fence->signal(cmd, VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
|
||||
// Set cb flag for queued dma operations
|
||||
cmd.set_flag(vk::command_buffer::cb_has_dma_transfer);
|
||||
vkCmdSetEvent(cmd, dma_fence, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
|
||||
synchronized = true;
|
||||
sync_timestamp = get_system_time();
|
||||
@ -396,8 +384,7 @@ namespace vk
|
||||
AUDIT(synchronized);
|
||||
|
||||
// Synchronize, reset dma_fence after waiting
|
||||
vk::wait_for_event(dma_fence, GENERAL_WAIT_TIMEOUT);
|
||||
vkResetEvent(*m_device, dma_fence);
|
||||
vk::wait_for_event(dma_fence.get(), GENERAL_WAIT_TIMEOUT);
|
||||
|
||||
const auto range = get_confirmed_range();
|
||||
vk::flush_dma(range.start, range.length());
|
||||
|
Loading…
Reference in New Issue
Block a user