[dxvk] Use synchronization2 functions for barriers

We don't really use the new stage/access flags yet, and I'm not sure
whether we will move to them since the benefits seem rather limited.
However, using the functions means we can bypass a lot of internal
translation inside some Vulkan drivers.
This commit is contained in:
Philip Rebohle 2022-07-18 15:43:19 +02:00
parent 0d65142136
commit adb906b18c
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
5 changed files with 87 additions and 98 deletions

View File

@ -44,13 +44,13 @@ namespace dxvk {
VkAccessFlags dstAccess) {
DxvkAccessFlags access = this->getAccessTypes(srcAccess);
m_srcStages |= srcStages;
m_dstStages |= dstStages;
m_srcAccess |= srcAccess & AccessWriteMask;
m_allBarrierSrcStages |= srcStages;
m_memBarrier.srcStageMask |= srcStages;
m_memBarrier.srcAccessMask |= srcAccess & AccessWriteMask;
m_memBarrier.dstStageMask |= dstStages;
if (access.test(DxvkAccess::Write))
m_dstAccess |= dstAccess;
m_memBarrier.dstAccessMask |= dstAccess;
}
@ -62,17 +62,13 @@ namespace dxvk {
VkAccessFlags dstAccess) {
DxvkAccessFlags access = this->getAccessTypes(srcAccess);
if (srcStages == VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
|| dstStages == VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT)
access.set(DxvkAccess::Write);
m_allBarrierSrcStages |= srcStages;
m_memBarrier.srcStageMask |= srcStages;
m_memBarrier.srcAccessMask |= srcAccess & AccessWriteMask;
m_memBarrier.dstStageMask |= dstStages;
m_srcStages |= srcStages;
m_dstStages |= dstStages;
m_srcAccess |= srcAccess & AccessWriteMask;
if (access.test(DxvkAccess::Write))
m_dstAccess |= dstAccess;
m_memBarrier.dstAccessMask |= dstAccess;
m_bufSlices.insert(bufSlice.handle,
DxvkBarrierBufferSlice(bufSlice.offset, bufSlice.length, access));
@ -90,22 +86,20 @@ namespace dxvk {
VkAccessFlags dstAccess) {
DxvkAccessFlags access = this->getAccessTypes(srcAccess);
if (srcStages == VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
|| dstStages == VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
|| srcLayout != dstLayout)
access.set(DxvkAccess::Write);
m_srcStages |= srcStages;
m_dstStages |= dstStages;
m_allBarrierSrcStages |= srcStages;
if (srcLayout == dstLayout) {
m_srcAccess |= srcAccess & AccessWriteMask;
m_memBarrier.srcStageMask |= srcStages;
m_memBarrier.srcAccessMask |= srcAccess & AccessWriteMask;
m_memBarrier.dstStageMask |= dstStages;
if (access.test(DxvkAccess::Write))
m_dstAccess |= dstAccess;
m_memBarrier.dstAccessMask |= dstAccess;
} else {
VkImageMemoryBarrier barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
VkImageMemoryBarrier2 barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 };
barrier.srcStageMask = srcStages;
barrier.srcAccessMask = srcAccess & AccessWriteMask;
barrier.dstStageMask = dstStages;
barrier.dstAccessMask = dstAccess;
barrier.oldLayout = srcLayout;
barrier.newLayout = dstLayout;
@ -115,6 +109,8 @@ namespace dxvk {
barrier.subresourceRange = subresources;
barrier.subresourceRange.aspectMask = image->formatInfo()->aspectMask;
m_imgBarriers.push_back(barrier);
access.set(DxvkAccess::Write);
}
m_imgSlices.insert(image->handle(),
@ -133,11 +129,12 @@ namespace dxvk {
VkAccessFlags dstAccess) {
auto& release = *this;
release.m_srcStages |= srcStages;
acquire.m_dstStages |= dstStages;
m_allBarrierSrcStages |= srcStages;
VkBufferMemoryBarrier barrier = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER };
VkBufferMemoryBarrier2 barrier = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2 };
barrier.srcStageMask = srcStages;
barrier.srcAccessMask = srcAccess & AccessWriteMask;
barrier.dstStageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT;
barrier.dstAccessMask = 0;
barrier.srcQueueFamilyIndex = srcQueue;
barrier.dstQueueFamilyIndex = dstQueue;
@ -146,7 +143,9 @@ namespace dxvk {
barrier.size = bufSlice.length;
release.m_bufBarriers.push_back(barrier);
barrier.srcStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT;
barrier.srcAccessMask = 0;
barrier.dstStageMask = dstStages;
barrier.dstAccessMask = dstAccess;
acquire.m_bufBarriers.push_back(barrier);
@ -172,13 +171,12 @@ namespace dxvk {
VkAccessFlags dstAccess) {
auto& release = *this;
release.m_srcStages |= srcStages;
acquire.m_dstStages |= dstStages;
m_allBarrierSrcStages |= srcStages;
VkImageMemoryBarrier barrier;
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.pNext = nullptr;
VkImageMemoryBarrier2 barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 };
barrier.srcStageMask = srcStages;
barrier.srcAccessMask = srcAccess & AccessWriteMask;
barrier.dstStageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT;
barrier.dstAccessMask = 0;
barrier.oldLayout = srcLayout;
barrier.newLayout = dstLayout;
@ -192,7 +190,9 @@ namespace dxvk {
if (srcQueue == dstQueue)
barrier.oldLayout = dstLayout;
barrier.srcStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT;
barrier.srcAccessMask = 0;
barrier.dstStageMask = dstStages;
barrier.dstAccessMask = dstAccess;
acquire.m_imgBarriers.push_back(barrier);
@ -237,29 +237,25 @@ namespace dxvk {
void DxvkBarrierSet::recordCommands(const Rc<DxvkCommandList>& commandList) {
if (m_srcStages | m_dstStages) {
VkPipelineStageFlags srcFlags = m_srcStages;
VkPipelineStageFlags dstFlags = m_dstStages;
if (!srcFlags) srcFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
if (!dstFlags) dstFlags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
VkDependencyInfo depInfo = { VK_STRUCTURE_TYPE_DEPENDENCY_INFO };
VkMemoryBarrier memBarrier = { VK_STRUCTURE_TYPE_MEMORY_BARRIER };
memBarrier.srcAccessMask = m_srcAccess;
memBarrier.dstAccessMask = m_dstAccess;
if (m_memBarrier.srcStageMask | m_memBarrier.dstStageMask) {
depInfo.memoryBarrierCount = 1;
depInfo.pMemoryBarriers = &m_memBarrier;
}
VkMemoryBarrier* pMemBarrier = nullptr;
if (m_srcAccess | m_dstAccess)
pMemBarrier = &memBarrier;
commandList->cmdPipelineBarrier(
m_cmdBuffer, srcFlags, dstFlags, 0,
pMemBarrier ? 1 : 0, pMemBarrier,
m_bufBarriers.size(),
m_bufBarriers.data(),
m_imgBarriers.size(),
m_imgBarriers.data());
if (!m_bufBarriers.empty()) {
depInfo.bufferMemoryBarrierCount = m_bufBarriers.size();
depInfo.pBufferMemoryBarriers = m_bufBarriers.data();
}
if (!m_imgBarriers.empty()) {
depInfo.imageMemoryBarrierCount = m_imgBarriers.size();
depInfo.pImageMemoryBarriers = m_imgBarriers.data();
}
if (depInfo.memoryBarrierCount + depInfo.bufferMemoryBarrierCount + depInfo.imageMemoryBarrierCount) {
commandList->cmdPipelineBarrier(m_cmdBuffer, &depInfo);
commandList->addStatCtr(DxvkStatCounter::CmdBarrierCount, 1);
this->reset();
@ -268,11 +264,12 @@ namespace dxvk {
void DxvkBarrierSet::reset() {
m_srcStages = 0;
m_dstStages = 0;
m_allBarrierSrcStages = 0;
m_srcAccess = 0;
m_dstAccess = 0;
m_memBarrier.srcStageMask = 0;
m_memBarrier.srcAccessMask = 0;
m_memBarrier.dstStageMask = 0;
m_memBarrier.dstAccessMask = 0;
m_bufBarriers.resize(0);
m_imgBarriers.resize(0);

View File

@ -538,7 +538,7 @@ namespace dxvk {
const VkImageSubresourceRange& imgSubres);
VkPipelineStageFlags getSrcStages() {
return m_srcStages;
return m_allBarrierSrcStages;
}
void recordCommands(
@ -567,15 +567,12 @@ namespace dxvk {
};
DxvkCmdBuffer m_cmdBuffer;
VkPipelineStageFlags m_srcStages = 0;
VkPipelineStageFlags m_dstStages = 0;
VkAccessFlags m_srcAccess = 0;
VkAccessFlags m_dstAccess = 0;
std::vector<VkBufferMemoryBarrier> m_bufBarriers;
std::vector<VkImageMemoryBarrier> m_imgBarriers;
VkPipelineStageFlags2 m_allBarrierSrcStages = 0;
VkMemoryBarrier2 m_memBarrier = { VK_STRUCTURE_TYPE_MEMORY_BARRIER_2 };
std::vector<VkBufferMemoryBarrier2> m_bufBarriers;
std::vector<VkImageMemoryBarrier2> m_imgBarriers;
DxvkBarrierSubresourceSet<VkBuffer, DxvkBarrierBufferSlice> m_bufSlices;
DxvkBarrierSubresourceSet<VkImage, DxvkBarrierImageSlice> m_imgSlices;

View File

@ -607,22 +607,10 @@ namespace dxvk {
void cmdPipelineBarrier(
DxvkCmdBuffer cmdBuffer,
VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
VkDependencyFlags dependencyFlags,
uint32_t memoryBarrierCount,
const VkMemoryBarrier* pMemoryBarriers,
uint32_t bufferMemoryBarrierCount,
const VkBufferMemoryBarrier* pBufferMemoryBarriers,
uint32_t imageMemoryBarrierCount,
const VkImageMemoryBarrier* pImageMemoryBarriers) {
const VkDependencyInfo* dependencyInfo) {
m_cmdBuffersUsed.set(cmdBuffer);
m_vkd->vkCmdPipelineBarrier(getCmdBuffer(cmdBuffer),
srcStageMask, dstStageMask, dependencyFlags,
memoryBarrierCount, pMemoryBarriers,
bufferMemoryBarrierCount, pBufferMemoryBarriers,
imageMemoryBarrierCount, pImageMemoryBarriers);
m_vkd->vkCmdPipelineBarrier2(getCmdBuffer(cmdBuffer), dependencyInfo);
}

View File

@ -950,7 +950,7 @@ namespace dxvk {
srcBufferSlice.handle, tmpBufferSlice.handle,
1, &copyRegion);
emitMemoryBarrier(0,
emitMemoryBarrier(
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
@ -1456,7 +1456,8 @@ namespace dxvk {
VkImageLayout initialLayout) {
if (initialLayout == VK_IMAGE_LAYOUT_PREINITIALIZED) {
m_initBarriers.accessImage(image, subresources,
initialLayout, 0, 0,
initialLayout,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0,
image->info().layout,
image->info().stages,
image->info().access);
@ -1466,7 +1467,9 @@ namespace dxvk {
VkImageLayout clearLayout = image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
m_execAcquires.accessImage(image, subresources,
initialLayout, 0, 0, clearLayout,
initialLayout,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0,
clearLayout,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT);
m_execAcquires.recordCommands(m_cmd);
@ -2261,7 +2264,8 @@ namespace dxvk {
// Discard previous subresource contents
barriers->accessImage(image,
vk::makeSubresourceRange(subresources),
VK_IMAGE_LAYOUT_UNDEFINED, 0, 0,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0,
image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT);
@ -4545,14 +4549,16 @@ namespace dxvk {
srcBarrier.stages |= pipelineBarrier.stages;
srcBarrier.access |= pipelineBarrier.access;
DxvkAccessFlags access = DxvkBarrierSet::getAccessTypes(srcBarrier.access);
DxvkGlobalPipelineBarrier dstBarrier = access.test(DxvkAccess::Write)
? m_globalRwGraphicsBarrier
: m_globalRoGraphicsBarrier;
if (srcBarrier.stages) {
DxvkAccessFlags access = DxvkBarrierSet::getAccessTypes(srcBarrier.access);
DxvkGlobalPipelineBarrier dstBarrier = access.test(DxvkAccess::Write)
? m_globalRwGraphicsBarrier
: m_globalRoGraphicsBarrier;
m_execBarriers.accessMemory(
srcBarrier.stages, srcBarrier.access,
dstBarrier.stages, dstBarrier.access);
m_execBarriers.accessMemory(
srcBarrier.stages, srcBarrier.access,
dstBarrier.stages, dstBarrier.access);
}
m_flags.clr(DxvkContextFlag::GpDirtyPipelineState);
return true;
@ -5664,19 +5670,21 @@ namespace dxvk {
void DxvkContext::emitMemoryBarrier(
VkDependencyFlags flags,
VkPipelineStageFlags srcStages,
VkAccessFlags srcAccess,
VkPipelineStageFlags dstStages,
VkAccessFlags dstAccess) {
VkMemoryBarrier barrier = { VK_STRUCTURE_TYPE_MEMORY_BARRIER };
VkMemoryBarrier2 barrier = { VK_STRUCTURE_TYPE_MEMORY_BARRIER_2 };
barrier.srcStageMask = srcStages;
barrier.srcAccessMask = srcAccess;
barrier.dstStageMask = dstStages;
barrier.dstAccessMask = dstAccess;
m_cmd->cmdPipelineBarrier(
DxvkCmdBuffer::ExecBuffer, srcStages, dstStages,
flags, 1, &barrier, 0, nullptr, 0, nullptr);
VkDependencyInfo depInfo = { VK_STRUCTURE_TYPE_DEPENDENCY_INFO };
depInfo.memoryBarrierCount = 1;
depInfo.pMemoryBarriers = &barrier;
m_cmd->cmdPipelineBarrier(DxvkCmdBuffer::ExecBuffer, &depInfo);
m_cmd->addStatCtr(DxvkStatCounter::CmdBarrierCount, 1);
}

View File

@ -1404,7 +1404,6 @@ namespace dxvk {
VkAccessFlags access);
void emitMemoryBarrier(
VkDependencyFlags flags,
VkPipelineStageFlags srcStages,
VkAccessFlags srcAccess,
VkPipelineStageFlags dstStages,