1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-20 19:54:19 +01:00

[dxvk] Add new barrier batch helper

Separates batching from tracking. This is useful because init
and transfer queue barriers do not need any tracking.
This commit is contained in:
Philip Rebohle 2024-10-10 16:05:45 +02:00 committed by Philip Rebohle
parent c6c85d7532
commit 756ff73c8a
2 changed files with 152 additions and 0 deletions

View File

@ -410,6 +410,96 @@ namespace dxvk {
DxvkBarrierBatch::DxvkBarrierBatch(DxvkCmdBuffer cmdBuffer)
: m_cmdBuffer(cmdBuffer) { }
DxvkBarrierBatch::~DxvkBarrierBatch() {
}
void DxvkBarrierBatch::addMemoryBarrier(
const VkMemoryBarrier2& barrier) {
if (unlikely(barrier.dstAccessMask & vk::AccessHostMask)) {
m_hostSrcStages |= barrier.srcStageMask & vk::StageDeviceMask;
m_hostDstAccess |= barrier.dstAccessMask & vk::AccessHostMask;
}
m_memoryBarrier.srcStageMask |= barrier.srcStageMask & vk::StageDeviceMask;
m_memoryBarrier.srcAccessMask |= barrier.srcAccessMask & vk::AccessWriteMask;
m_memoryBarrier.dstStageMask |= barrier.dstStageMask & vk::StageDeviceMask;
m_memoryBarrier.dstAccessMask |= barrier.dstAccessMask & vk::AccessDeviceMask;
}
void DxvkBarrierBatch::addImageBarrier(
const VkImageMemoryBarrier2& barrier) {
if (unlikely(barrier.dstAccessMask & vk::AccessHostMask)) {
m_hostSrcStages |= barrier.srcStageMask & vk::StageDeviceMask;
m_hostDstAccess |= barrier.dstAccessMask & vk::AccessHostMask;
}
if (barrier.oldLayout != barrier.newLayout || barrier.srcQueueFamilyIndex != barrier.dstQueueFamilyIndex) {
auto& entry = m_imageBarriers.emplace_back(barrier);
entry.srcStageMask &= vk::StageDeviceMask;
entry.srcAccessMask &= vk::AccessWriteMask;
entry.dstStageMask &= vk::StageDeviceMask;
entry.dstAccessMask &= vk::AccessDeviceMask;
} else {
m_memoryBarrier.srcStageMask |= barrier.srcStageMask & vk::StageDeviceMask;
m_memoryBarrier.srcAccessMask |= barrier.srcAccessMask & vk::AccessWriteMask;
m_memoryBarrier.dstStageMask |= barrier.dstStageMask & vk::StageDeviceMask;
m_memoryBarrier.dstAccessMask |= barrier.dstAccessMask & vk::AccessDeviceMask;
}
}
void DxvkBarrierBatch::flush(
const Rc<DxvkCommandList>& list) {
VkDependencyInfo depInfo = { VK_STRUCTURE_TYPE_DEPENDENCY_INFO };
if (m_memoryBarrier.srcStageMask | m_memoryBarrier.dstStageMask) {
depInfo.memoryBarrierCount = 1;
depInfo.pMemoryBarriers = &m_memoryBarrier;
}
if (!m_imageBarriers.empty()) {
depInfo.imageMemoryBarrierCount = m_imageBarriers.size();
depInfo.pImageMemoryBarriers = m_imageBarriers.data();
}
if (!(depInfo.memoryBarrierCount | depInfo.imageMemoryBarrierCount))
return;
list->cmdPipelineBarrier(m_cmdBuffer, &depInfo);
m_memoryBarrier.srcStageMask = 0u;
m_memoryBarrier.srcAccessMask = 0u;
m_memoryBarrier.dstStageMask = 0u;
m_memoryBarrier.dstAccessMask = 0u;
m_imageBarriers.clear();
}
void DxvkBarrierBatch::finalize(
const Rc<DxvkCommandList>& list) {
if (m_hostDstAccess) {
m_memoryBarrier.srcStageMask |= m_hostSrcStages;
m_memoryBarrier.dstStageMask |= VK_PIPELINE_STAGE_2_HOST_BIT;
m_memoryBarrier.dstAccessMask |= m_hostDstAccess;
m_hostSrcStages = 0u;
m_hostDstAccess = 0u;
}
flush(list);
}
DxvkBarrierSet:: DxvkBarrierSet(DxvkCmdBuffer cmdBuffer)
: m_cmdBuffer(cmdBuffer) {

View File

@ -200,6 +200,68 @@ namespace dxvk {
};
/**
* \brief Barrier batch
*
* Simple helper class to accumulate barriers that can then
* be recorded into a command buffer in a single step.
*/
class DxvkBarrierBatch {
public:
DxvkBarrierBatch(DxvkCmdBuffer cmdBuffer);
~DxvkBarrierBatch();
/**
* \brief Adds a memory barrier
*
* Host read access will only be flushed
* at the end of a command list.
* \param [in] barrier Memory barrier
*/
void addMemoryBarrier(
const VkMemoryBarrier2& barrier);
/**
* \brief Adds an image barrier
*
* This will automatically turn into a normal memory barrier
* if no queue family ownership transfer or layout transition
* happens.
* \param [in] barrier Memory barrier
*/
void addImageBarrier(
const VkImageMemoryBarrier2& barrier);
/**
* \brief Flushes batched memory barriers
* \param [in] list Command list
*/
void flush(
const Rc<DxvkCommandList>& list);
/**
* \brief Flushes batched memory and host barriers
* \param [in] list Command list
*/
void finalize(
const Rc<DxvkCommandList>& list);
private:
DxvkCmdBuffer m_cmdBuffer;
VkMemoryBarrier2 m_memoryBarrier = { VK_STRUCTURE_TYPE_MEMORY_BARRIER_2 };
VkPipelineStageFlags2 m_hostSrcStages = 0u;
VkAccessFlags2 m_hostDstAccess = 0u;
std::vector<VkImageMemoryBarrier2> m_imageBarriers = { };
};
/**
* \brief Buffer slice for barrier tracking
*