mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-08-18 00:11:20 +00:00
vk: Use pipeline barriers for proper event sync
This commit is contained in:
parent
593f850693
commit
92992a5406
5 changed files with 58 additions and 23 deletions
|
@ -204,22 +204,16 @@ namespace vk
|
||||||
|
|
||||||
src->pop_layout(cmd);
|
src->pop_layout(cmd);
|
||||||
|
|
||||||
// Inserting a buffer memory barrier into the pipe fixes sync on RADV. Adding the same barrier as an event dep does not work.
|
VkBufferMemoryBarrier2KHR mem_barrier =
|
||||||
// The dependencies in the CmdSetEvents2 command are handled in a different path from regular pipeline deps.
|
|
||||||
vk::insert_buffer_memory_barrier(cmd,
|
|
||||||
dma_mapping.second->value, dma_mapping.first, valid_range.length(),
|
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
|
||||||
VK_ACCESS_TRANSFER_WRITE_BIT, 0);
|
|
||||||
|
|
||||||
// Not providing any deps to the signal makes AMDVLK hang (event never gets signaled)
|
|
||||||
// We also need to set this up correctly as the buffer barrier above by itself does not work for AMD/AMDVLK.
|
|
||||||
VkMemoryBarrier2KHR mem_barrier =
|
|
||||||
{
|
{
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR,
|
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2_KHR,
|
||||||
.srcStageMask = VK_PIPELINE_STAGE_2_COPY_BIT_KHR,
|
.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, // Finish all transfer...
|
||||||
.srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT_KHR,
|
.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR,
|
||||||
.dstStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT,
|
.dstStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR, // ...before proceeding with any command
|
||||||
.dstAccessMask = 0
|
.dstAccessMask = 0,
|
||||||
|
.buffer = dma_mapping.second->value,
|
||||||
|
.offset = dma_mapping.first,
|
||||||
|
.size = valid_range.length()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create event object for this transfer and queue signal op
|
// Create event object for this transfer and queue signal op
|
||||||
|
@ -227,8 +221,8 @@ namespace vk
|
||||||
dma_fence->signal(cmd,
|
dma_fence->signal(cmd,
|
||||||
{
|
{
|
||||||
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
|
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
|
||||||
.memoryBarrierCount = 1,
|
.bufferMemoryBarrierCount = 1,
|
||||||
.pMemoryBarriers = &mem_barrier
|
.pBufferMemoryBarriers = &mem_barrier
|
||||||
});
|
});
|
||||||
|
|
||||||
// Set cb flag for queued dma operations
|
// Set cb flag for queued dma operations
|
||||||
|
|
|
@ -721,6 +721,7 @@ namespace vk
|
||||||
{
|
{
|
||||||
_vkCmdSetEvent2KHR = reinterpret_cast<PFN_vkCmdSetEvent2KHR>(vkGetDeviceProcAddr(dev, "vkCmdSetEvent2KHR"));
|
_vkCmdSetEvent2KHR = reinterpret_cast<PFN_vkCmdSetEvent2KHR>(vkGetDeviceProcAddr(dev, "vkCmdSetEvent2KHR"));
|
||||||
_vkCmdWaitEvents2KHR = reinterpret_cast<PFN_vkCmdWaitEvents2KHR>(vkGetDeviceProcAddr(dev, "vkCmdWaitEvents2KHR"));
|
_vkCmdWaitEvents2KHR = reinterpret_cast<PFN_vkCmdWaitEvents2KHR>(vkGetDeviceProcAddr(dev, "vkCmdWaitEvents2KHR"));
|
||||||
|
_vkCmdPipelineBarrier2KHR = reinterpret_cast<PFN_vkCmdPipelineBarrier2KHR>(vkGetDeviceProcAddr(dev, "vkCmdPipelineBarrier2KHR"));
|
||||||
}
|
}
|
||||||
|
|
||||||
memory_map = vk::get_memory_mapping(pdev);
|
memory_map = vk::get_memory_mapping(pdev);
|
||||||
|
|
|
@ -138,6 +138,7 @@ namespace vk
|
||||||
PFN_vkCmdInsertDebugUtilsLabelEXT _vkCmdInsertDebugUtilsLabelEXT = nullptr;
|
PFN_vkCmdInsertDebugUtilsLabelEXT _vkCmdInsertDebugUtilsLabelEXT = nullptr;
|
||||||
PFN_vkCmdSetEvent2KHR _vkCmdSetEvent2KHR = nullptr;
|
PFN_vkCmdSetEvent2KHR _vkCmdSetEvent2KHR = nullptr;
|
||||||
PFN_vkCmdWaitEvents2KHR _vkCmdWaitEvents2KHR = nullptr;
|
PFN_vkCmdWaitEvents2KHR _vkCmdWaitEvents2KHR = nullptr;
|
||||||
|
PFN_vkCmdPipelineBarrier2KHR _vkCmdPipelineBarrier2KHR = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
render_device() = default;
|
render_device() = default;
|
||||||
|
|
|
@ -200,17 +200,54 @@ namespace vk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void event::signal(const command_buffer& cmd, const VkDependencyInfoKHR& dependency)
|
void event::resolve_dependencies(const command_buffer& cmd, const VkDependencyInfoKHR& dependency)
|
||||||
{
|
{
|
||||||
if (v2) [[ likely ]]
|
if (v2)
|
||||||
{
|
{
|
||||||
m_device->_vkCmdSetEvent2KHR(cmd, m_vk_event, &dependency);
|
m_device->_vkCmdPipelineBarrier2KHR(cmd, &dependency);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Legacy fallback. Should be practically unused with the exception of in-development drivers.
|
const auto src_stages = v1_utils::gather_src_stages(dependency);
|
||||||
const auto stages = v1_utils::gather_src_stages(dependency);
|
const auto dst_stages = v1_utils::gather_dst_stages(dependency);
|
||||||
vkCmdSetEvent(cmd, m_vk_event, stages);
|
const auto memory_barriers = v1_utils::get_memory_barriers(dependency);
|
||||||
|
const auto image_memory_barriers = v1_utils::get_image_memory_barriers(dependency);
|
||||||
|
const auto buffer_memory_barriers = v1_utils::get_buffer_memory_barriers(dependency);
|
||||||
|
|
||||||
|
vkCmdPipelineBarrier(cmd, src_stages, dst_stages, dependency.dependencyFlags,
|
||||||
|
::size32(memory_barriers), memory_barriers.data(),
|
||||||
|
::size32(buffer_memory_barriers), buffer_memory_barriers.data(),
|
||||||
|
::size32(image_memory_barriers), image_memory_barriers.data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void event::signal(const command_buffer& cmd, const VkDependencyInfoKHR& dependency)
|
||||||
|
{
|
||||||
|
// Resolve the actual dependencies on a pipeline barrier
|
||||||
|
resolve_dependencies(cmd, dependency);
|
||||||
|
|
||||||
|
// Signalling won't wait. The caller is responsible for setting up the dependencies correctly.
|
||||||
|
if (v2) [[ likely ]]
|
||||||
|
{
|
||||||
|
// We need a memory barrier to keep AMDVLK from hanging
|
||||||
|
VkMemoryBarrier2KHR mem_barrier =
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR,
|
||||||
|
.srcStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR,
|
||||||
|
.srcAccessMask = VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT
|
||||||
|
};
|
||||||
|
// Empty dependency that does nothing
|
||||||
|
VkDependencyInfoKHR empty_dependency
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR,
|
||||||
|
.memoryBarrierCount = 1,
|
||||||
|
.pMemoryBarriers = &mem_barrier
|
||||||
|
};
|
||||||
|
m_device->_vkCmdSetEvent2KHR(cmd, m_vk_event, &empty_dependency);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vkCmdSetEvent(cmd, m_vk_event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,8 @@ namespace vk
|
||||||
VkEvent m_vk_event = VK_NULL_HANDLE;
|
VkEvent m_vk_event = VK_NULL_HANDLE;
|
||||||
bool v2 = true;
|
bool v2 = true;
|
||||||
|
|
||||||
|
void resolve_dependencies(const command_buffer& cmd, const VkDependencyInfoKHR& dependency);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
event(const render_device& dev, sync_domain domain);
|
event(const render_device& dev, sync_domain domain);
|
||||||
~event();
|
~event();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue