vk: Fix some regressions in synchronization2 behavior

This commit is contained in:
kd-11 2023-06-30 02:38:08 +03:00 committed by kd-11
parent 7ebabddfe0
commit c4acea6c82
3 changed files with 49 additions and 9 deletions

View File

@ -217,7 +217,7 @@ namespace vk
}; };
// Create event object for this transfer and queue signal op // Create event object for this transfer and queue signal op
dma_fence = std::make_unique<vk::event>(*m_device, sync_domain::any); dma_fence = std::make_unique<vk::event>(*m_device, sync_domain::host);
dma_fence->signal(cmd, dma_fence->signal(cmd,
{ {
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,

View File

@ -209,13 +209,13 @@ namespace vk
} }
event::event(const render_device& dev, sync_domain domain) event::event(const render_device& dev, sync_domain domain)
: m_device(&dev) : m_device(&dev), m_domain(domain)
{ {
m_backend = dev.get_synchronization2_support() m_backend = dev.get_synchronization2_support()
? sync_backend::events_v2 ? sync_backend::events_v2
: sync_backend::events_v1; : sync_backend::events_v1;
if (domain != sync_domain::gpu && if (domain == sync_domain::host &&
vk::get_driver_vendor() == vk::driver_vendor::AMD && vk::get_driver_vendor() == vk::driver_vendor::AMD &&
vk::get_chip_family() < vk::chip_class::AMD_navi1x) vk::get_chip_family() < vk::chip_class::AMD_navi1x)
{ {
@ -280,10 +280,30 @@ namespace vk
return; return;
} }
// Resolve the actual dependencies on a pipeline barrier ensure(m_vk_event);
if (m_domain != sync_domain::host)
{
// As long as host is not involved, keep things consistent.
// The expectation is that this will be awaited using the gpu_wait function.
if (m_backend == sync_backend::events_v2) [[ likely ]]
{
m_device->_vkCmdSetEvent2KHR(cmd, m_vk_event, &dependency);
}
else
{
const auto dst_stages = v1_utils::gather_dst_stages(dependency);
vkCmdSetEvent(cmd, m_vk_event, dst_stages);
}
return;
}
// Host sync doesn't behave intuitively with events, so we use some workarounds.
// 1. Resolve the actual dependencies on a pipeline barrier.
resolve_dependencies(cmd, dependency); resolve_dependencies(cmd, dependency);
// Signalling won't wait. The caller is responsible for setting up the dependencies correctly. // 2. Signalling won't wait. The caller is responsible for setting up the dependencies correctly.
if (m_backend == sync_backend::events_v2) if (m_backend == sync_backend::events_v2)
{ {
// We need a memory barrier to keep AMDVLK from hanging // We need a memory barrier to keep AMDVLK from hanging
@ -293,6 +313,7 @@ namespace vk
.srcStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR, .srcStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR,
.srcAccessMask = VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT .srcAccessMask = VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT
}; };
// Empty dependency that does nothing // Empty dependency that does nothing
VkDependencyInfoKHR empty_dependency VkDependencyInfoKHR empty_dependency
{ {
@ -310,13 +331,19 @@ namespace vk
void event::host_signal() const void event::host_signal() const
{ {
ensure(m_vk_event); if (m_backend != sync_backend::gpu_label) [[ likely ]]
vkSetEvent(*m_device, m_vk_event); {
ensure(m_vk_event);
vkSetEvent(*m_device, m_vk_event);
return;
}
m_label->set();
} }
void event::gpu_wait(const command_buffer& cmd, const VkDependencyInfoKHR& dependency) const void event::gpu_wait(const command_buffer& cmd, const VkDependencyInfoKHR& dependency) const
{ {
ensure(m_vk_event); ensure(m_vk_event && m_domain != sync_domain::host);
if (m_backend == sync_backend::events_v2) [[ likely ]] if (m_backend == sync_backend::events_v2) [[ likely ]]
{ {
@ -363,6 +390,15 @@ namespace vk
: pdev(&dev), m_count(count) : pdev(&dev), m_count(count)
{} {}
gpu_label_pool::~gpu_label_pool()
{
if (m_mapped)
{
ensure(m_buffer);
m_buffer->unmap();
}
}
std::tuple<VkBuffer, u64, volatile u32*> gpu_label_pool::allocate() std::tuple<VkBuffer, u64, volatile u32*> gpu_label_pool::allocate()
{ {
if (!m_buffer || m_offset >= m_count) if (!m_buffer || m_offset >= m_count)

View File

@ -14,7 +14,7 @@ namespace vk
enum class sync_domain enum class sync_domain
{ {
any = 0, host = 0,
gpu = 1 gpu = 1
}; };
@ -64,6 +64,7 @@ namespace vk
}; };
const vk::render_device* m_device = nullptr; const vk::render_device* m_device = nullptr;
sync_domain m_domain = sync_domain::any;
sync_backend m_backend = sync_backend::events_v1; sync_backend m_backend = sync_backend::events_v1;
// For events_v1 and events_v2 // For events_v1 and events_v2
@ -106,6 +107,8 @@ namespace vk
{ {
public: public:
gpu_label_pool(const vk::render_device& dev, u32 count); gpu_label_pool(const vk::render_device& dev, u32 count);
virtual ~gpu_label_pool();
std::tuple<VkBuffer, u64, volatile u32*> allocate(); std::tuple<VkBuffer, u64, volatile u32*> allocate();
private: private:
@ -137,6 +140,7 @@ namespace vk
void signal(const vk::command_buffer& cmd, const VkDependencyInfoKHR& dependency); void signal(const vk::command_buffer& cmd, const VkDependencyInfoKHR& dependency);
void reset() { *m_ptr = label_constants::reset_; } void reset() { *m_ptr = label_constants::reset_; }
void set() { *m_ptr = label_constants::set_; }
bool signaled() const { return label_constants::set_ == *m_ptr; } bool signaled() const { return label_constants::set_ == *m_ptr; }
}; };