mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-10 00:41:26 +12: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
4 changed files with 98 additions and 39 deletions
|
@ -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;
|
u64 t = 0;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
switch (const auto status = vkGetEventStatus(*g_current_renderer, event))
|
switch (const auto status = pEvent->status())
|
||||||
{
|
{
|
||||||
case VK_EVENT_SET:
|
case VK_EVENT_SET:
|
||||||
return VK_SUCCESS;
|
return VK_SUCCESS;
|
||||||
|
|
|
@ -115,6 +115,7 @@ namespace vk
|
||||||
struct gpu_formats_support;
|
struct gpu_formats_support;
|
||||||
struct fence;
|
struct fence;
|
||||||
struct pipeline_binding_table;
|
struct pipeline_binding_table;
|
||||||
|
class event;
|
||||||
|
|
||||||
const vk::context *get_current_thread_ctx();
|
const vk::context *get_current_thread_ctx();
|
||||||
void set_current_thread_ctx(const vk::context &ctx);
|
void set_current_thread_ctx(const vk::context &ctx);
|
||||||
|
@ -227,7 +228,7 @@ namespace vk
|
||||||
// Fence reset with driver workarounds in place
|
// Fence reset with driver workarounds in place
|
||||||
void reset_fence(fence* pFence);
|
void reset_fence(fence* pFence);
|
||||||
VkResult wait_for_fence(fence* pFence, u64 timeout = 0ull);
|
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
|
// Handle unexpected submit with dangling occlusion query
|
||||||
// TODO: Move queries out of the renderer!
|
// TODO: Move queries out of the renderer!
|
||||||
|
@ -1736,6 +1737,86 @@ private:
|
||||||
VkDevice m_device;
|
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
|
struct sampler
|
||||||
{
|
{
|
||||||
VkSampler value;
|
VkSampler value;
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace vk
|
||||||
std::vector<std::unique_ptr<vk::buffer>> m_disposed_buffers;
|
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_view>> m_disposed_image_views;
|
||||||
std::vector<std::unique_ptr<vk::image>> m_disposed_images;
|
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_scope_t(u64 _eid):
|
||||||
eid(_eid), m_device(vk::get_current_renderer())
|
eid(_eid), m_device(vk::get_current_renderer())
|
||||||
|
@ -27,17 +27,8 @@ namespace vk
|
||||||
|
|
||||||
void discard()
|
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_buffers.clear();
|
||||||
|
m_disposed_events.clear();
|
||||||
m_disposed_image_views.clear();
|
m_disposed_image_views.clear();
|
||||||
m_disposed_images.clear();
|
m_disposed_images.clear();
|
||||||
}
|
}
|
||||||
|
@ -146,9 +137,9 @@ namespace vk
|
||||||
get_current_eid_scope().m_disposed_images.emplace_back(std::move(img));
|
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;
|
event = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace vk
|
||||||
std::unique_ptr<vk::viewable_image> managed_texture = nullptr;
|
std::unique_ptr<vk::viewable_image> managed_texture = nullptr;
|
||||||
|
|
||||||
//DMA relevant data
|
//DMA relevant data
|
||||||
VkEvent dma_fence = VK_NULL_HANDLE;
|
std::unique_ptr<vk::event> dma_fence;
|
||||||
vk::render_device* m_device = nullptr;
|
vk::render_device* m_device = nullptr;
|
||||||
vk::viewable_image *vram_texture = nullptr;
|
vk::viewable_image *vram_texture = nullptr;
|
||||||
|
|
||||||
|
@ -169,16 +169,15 @@ namespace vk
|
||||||
{
|
{
|
||||||
verify(HERE), src->samples() == 1;
|
verify(HERE), src->samples() == 1;
|
||||||
|
|
||||||
if (m_device == nullptr)
|
if (!m_device)
|
||||||
{
|
{
|
||||||
m_device = &cmd.get_command_pool().get_owner();
|
m_device = &cmd.get_command_pool().get_owner();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dma_fence == VK_NULL_HANDLE)
|
if (dma_fence)
|
||||||
{
|
{
|
||||||
VkEventCreateInfo createInfo = {};
|
verify(HERE), synchronized;
|
||||||
createInfo.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
|
vk::get_resource_manager()->dispose(dma_fence);
|
||||||
vkCreateEvent(*m_device, &createInfo, nullptr, &dma_fence);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
src->push_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
src->push_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||||
|
@ -284,23 +283,12 @@ namespace vk
|
||||||
|
|
||||||
src->pop_layout(cmd);
|
src->pop_layout(cmd);
|
||||||
|
|
||||||
if (synchronized) [[unlikely]]
|
// Create event object for this transfer and queue signal op
|
||||||
{
|
dma_fence = std::make_unique<vk::event>(*m_device);
|
||||||
// Replace the wait event with a new one to avoid premature signaling!
|
dma_fence->signal(cmd, VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Set cb flag for queued dma operations
|
||||||
cmd.set_flag(vk::command_buffer::cb_has_dma_transfer);
|
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;
|
synchronized = true;
|
||||||
sync_timestamp = get_system_time();
|
sync_timestamp = get_system_time();
|
||||||
|
@ -396,8 +384,7 @@ namespace vk
|
||||||
AUDIT(synchronized);
|
AUDIT(synchronized);
|
||||||
|
|
||||||
// Synchronize, reset dma_fence after waiting
|
// Synchronize, reset dma_fence after waiting
|
||||||
vk::wait_for_event(dma_fence, GENERAL_WAIT_TIMEOUT);
|
vk::wait_for_event(dma_fence.get(), GENERAL_WAIT_TIMEOUT);
|
||||||
vkResetEvent(*m_device, dma_fence);
|
|
||||||
|
|
||||||
const auto range = get_confirmed_range();
|
const auto range = get_confirmed_range();
|
||||||
vk::flush_dma(range.start, range.length());
|
vk::flush_dma(range.start, range.length());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue