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:
parent
c6c85d7532
commit
756ff73c8a
@ -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) {
|
||||
|
@ -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
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user