2017-10-15 17:56:06 +02:00
|
|
|
#include "dxvk_barrier.h"
|
|
|
|
|
|
|
|
namespace dxvk {
|
|
|
|
|
2019-04-02 12:14:15 +02:00
|
|
|
DxvkBarrierSet:: DxvkBarrierSet(DxvkCmdBuffer cmdBuffer)
|
|
|
|
: m_cmdBuffer(cmdBuffer) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DxvkBarrierSet::~DxvkBarrierSet() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-10-15 17:56:06 +02:00
|
|
|
|
2017-11-26 13:24:01 +01:00
|
|
|
void DxvkBarrierSet::accessBuffer(
|
2019-01-09 15:03:17 +01:00
|
|
|
const DxvkBufferSliceHandle& bufSlice,
|
2017-12-05 13:00:06 +01:00
|
|
|
VkPipelineStageFlags srcStages,
|
|
|
|
VkAccessFlags srcAccess,
|
|
|
|
VkPipelineStageFlags dstStages,
|
|
|
|
VkAccessFlags dstAccess) {
|
2018-06-16 11:53:06 +02:00
|
|
|
DxvkAccessFlags access = this->getAccessTypes(srcAccess);
|
2017-11-26 13:24:01 +01:00
|
|
|
|
2019-04-02 15:01:37 +02:00
|
|
|
if (srcStages == VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
|
|
|
|
|| dstStages == VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT)
|
|
|
|
access.set(DxvkAccess::Write);
|
|
|
|
|
2017-12-05 13:00:06 +01:00
|
|
|
m_srcStages |= srcStages;
|
|
|
|
m_dstStages |= dstStages;
|
2017-11-26 13:24:01 +01:00
|
|
|
|
2019-04-02 14:48:39 +02:00
|
|
|
m_srcAccess |= srcAccess;
|
|
|
|
m_dstAccess |= dstAccess;
|
2018-06-16 11:53:06 +02:00
|
|
|
|
|
|
|
m_bufSlices.push_back({ bufSlice, access });
|
2017-10-15 17:56:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-05 13:00:06 +01:00
|
|
|
void DxvkBarrierSet::accessImage(
|
2017-12-01 17:52:05 +01:00
|
|
|
const Rc<DxvkImage>& image,
|
|
|
|
const VkImageSubresourceRange& subresources,
|
2017-12-05 13:00:06 +01:00
|
|
|
VkImageLayout srcLayout,
|
|
|
|
VkPipelineStageFlags srcStages,
|
|
|
|
VkAccessFlags srcAccess,
|
2017-12-01 17:52:05 +01:00
|
|
|
VkImageLayout dstLayout,
|
|
|
|
VkPipelineStageFlags dstStages,
|
|
|
|
VkAccessFlags dstAccess) {
|
2018-06-16 11:53:06 +02:00
|
|
|
DxvkAccessFlags access = this->getAccessTypes(srcAccess);
|
2018-06-18 14:35:11 +02:00
|
|
|
|
2019-04-02 15:01:37 +02:00
|
|
|
if (srcStages == VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
|
|
|
|
|| dstStages == VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
|
|
|
|
|| srcLayout != dstLayout)
|
|
|
|
access.set(DxvkAccess::Write);
|
|
|
|
|
2017-12-05 13:00:06 +01:00
|
|
|
m_srcStages |= srcStages;
|
2017-12-01 17:52:05 +01:00
|
|
|
m_dstStages |= dstStages;
|
|
|
|
|
2019-04-02 14:48:39 +02:00
|
|
|
if (srcLayout == dstLayout) {
|
|
|
|
m_srcAccess |= srcAccess;
|
|
|
|
m_dstAccess |= dstAccess;
|
|
|
|
} else {
|
2017-12-05 13:00:06 +01:00
|
|
|
VkImageMemoryBarrier barrier;
|
2018-01-30 15:44:18 +01:00
|
|
|
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
|
|
|
barrier.pNext = nullptr;
|
|
|
|
barrier.srcAccessMask = srcAccess;
|
|
|
|
barrier.dstAccessMask = dstAccess;
|
|
|
|
barrier.oldLayout = srcLayout;
|
|
|
|
barrier.newLayout = dstLayout;
|
|
|
|
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
|
|
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
|
|
barrier.image = image->handle();
|
|
|
|
barrier.subresourceRange = subresources;
|
|
|
|
barrier.subresourceRange.aspectMask = image->formatInfo()->aspectMask;
|
2017-12-05 13:00:06 +01:00
|
|
|
m_imgBarriers.push_back(barrier);
|
|
|
|
}
|
2018-06-18 14:35:11 +02:00
|
|
|
|
2021-02-20 14:35:22 +01:00
|
|
|
m_imgSlices.push_back({ image->handle(), subresources, access });
|
2017-12-01 17:52:05 +01:00
|
|
|
}
|
2019-01-22 14:16:24 +01:00
|
|
|
|
|
|
|
|
2019-06-28 02:01:22 +02:00
|
|
|
void DxvkBarrierSet::releaseBuffer(
|
|
|
|
DxvkBarrierSet& acquire,
|
|
|
|
const DxvkBufferSliceHandle& bufSlice,
|
|
|
|
uint32_t srcQueue,
|
|
|
|
VkPipelineStageFlags srcStages,
|
|
|
|
VkAccessFlags srcAccess,
|
|
|
|
uint32_t dstQueue,
|
|
|
|
VkPipelineStageFlags dstStages,
|
|
|
|
VkAccessFlags dstAccess) {
|
|
|
|
auto& release = *this;
|
|
|
|
|
|
|
|
release.m_srcStages |= srcStages;
|
|
|
|
acquire.m_dstStages |= dstStages;
|
|
|
|
|
|
|
|
VkBufferMemoryBarrier barrier;
|
|
|
|
barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
|
|
|
|
barrier.pNext = nullptr;
|
|
|
|
barrier.srcAccessMask = srcAccess;
|
|
|
|
barrier.dstAccessMask = 0;
|
|
|
|
barrier.srcQueueFamilyIndex = srcQueue;
|
|
|
|
barrier.dstQueueFamilyIndex = dstQueue;
|
|
|
|
barrier.buffer = bufSlice.handle;
|
|
|
|
barrier.offset = bufSlice.offset;
|
|
|
|
barrier.size = bufSlice.length;
|
|
|
|
release.m_bufBarriers.push_back(barrier);
|
|
|
|
|
|
|
|
barrier.srcAccessMask = 0;
|
|
|
|
barrier.dstAccessMask = dstAccess;
|
|
|
|
acquire.m_bufBarriers.push_back(barrier);
|
|
|
|
|
|
|
|
DxvkAccessFlags access(DxvkAccess::Read, DxvkAccess::Write);
|
|
|
|
release.m_bufSlices.push_back({ bufSlice, access });
|
|
|
|
acquire.m_bufSlices.push_back({ bufSlice, access });
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DxvkBarrierSet::releaseImage(
|
|
|
|
DxvkBarrierSet& acquire,
|
|
|
|
const Rc<DxvkImage>& image,
|
|
|
|
const VkImageSubresourceRange& subresources,
|
|
|
|
uint32_t srcQueue,
|
|
|
|
VkImageLayout srcLayout,
|
|
|
|
VkPipelineStageFlags srcStages,
|
|
|
|
VkAccessFlags srcAccess,
|
|
|
|
uint32_t dstQueue,
|
|
|
|
VkImageLayout dstLayout,
|
|
|
|
VkPipelineStageFlags dstStages,
|
|
|
|
VkAccessFlags dstAccess) {
|
|
|
|
auto& release = *this;
|
|
|
|
|
|
|
|
release.m_srcStages |= srcStages;
|
|
|
|
acquire.m_dstStages |= dstStages;
|
|
|
|
|
|
|
|
VkImageMemoryBarrier barrier;
|
|
|
|
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
|
|
|
barrier.pNext = nullptr;
|
|
|
|
barrier.srcAccessMask = srcAccess;
|
|
|
|
barrier.dstAccessMask = 0;
|
|
|
|
barrier.oldLayout = srcLayout;
|
|
|
|
barrier.newLayout = dstLayout;
|
|
|
|
barrier.srcQueueFamilyIndex = srcQueue;
|
|
|
|
barrier.dstQueueFamilyIndex = dstQueue;
|
|
|
|
barrier.image = image->handle();
|
|
|
|
barrier.subresourceRange = subresources;
|
|
|
|
barrier.subresourceRange.aspectMask = image->formatInfo()->aspectMask;
|
|
|
|
release.m_imgBarriers.push_back(barrier);
|
|
|
|
|
|
|
|
if (srcQueue == dstQueue)
|
|
|
|
barrier.oldLayout = dstLayout;
|
|
|
|
|
|
|
|
barrier.srcAccessMask = 0;
|
|
|
|
barrier.dstAccessMask = dstAccess;
|
|
|
|
acquire.m_imgBarriers.push_back(barrier);
|
|
|
|
|
|
|
|
DxvkAccessFlags access(DxvkAccess::Read, DxvkAccess::Write);
|
2021-02-20 14:35:22 +01:00
|
|
|
release.m_imgSlices.push_back({ image->handle(), subresources, access });
|
|
|
|
acquire.m_imgSlices.push_back({ image->handle(), subresources, access });
|
2019-06-28 02:01:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-16 11:53:06 +02:00
|
|
|
bool DxvkBarrierSet::isBufferDirty(
|
2019-01-09 15:03:17 +01:00
|
|
|
const DxvkBufferSliceHandle& bufSlice,
|
2018-06-16 11:53:06 +02:00
|
|
|
DxvkAccessFlags bufAccess) {
|
2019-04-02 14:48:39 +02:00
|
|
|
bool result = false;
|
2018-06-16 11:53:06 +02:00
|
|
|
|
|
|
|
for (uint32_t i = 0; i < m_bufSlices.size() && !result; i++) {
|
2019-01-09 15:03:17 +01:00
|
|
|
const DxvkBufferSliceHandle& dstSlice = m_bufSlices[i].slice;
|
|
|
|
|
|
|
|
result = (bufSlice.handle == dstSlice.handle) && (bufAccess | m_bufSlices[i].access).test(DxvkAccess::Write)
|
|
|
|
&& (bufSlice.offset + bufSlice.length > dstSlice.offset)
|
|
|
|
&& (bufSlice.offset < dstSlice.offset + dstSlice.length);
|
2018-06-16 11:53:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-18 14:35:11 +02:00
|
|
|
bool DxvkBarrierSet::isImageDirty(
|
|
|
|
const Rc<DxvkImage>& image,
|
|
|
|
const VkImageSubresourceRange& imgSubres,
|
|
|
|
DxvkAccessFlags imgAccess) {
|
2019-04-02 14:48:39 +02:00
|
|
|
bool result = false;
|
2018-06-18 14:35:11 +02:00
|
|
|
|
|
|
|
for (uint32_t i = 0; i < m_imgSlices.size() && !result; i++) {
|
|
|
|
const VkImageSubresourceRange& dstSubres = m_imgSlices[i].subres;
|
|
|
|
|
2021-02-20 14:35:22 +01:00
|
|
|
result = (image->handle() == m_imgSlices[i].image) && (imgAccess | m_imgSlices[i].access).test(DxvkAccess::Write)
|
2019-01-09 15:03:17 +01:00
|
|
|
&& (imgSubres.baseArrayLayer < dstSubres.baseArrayLayer + dstSubres.layerCount)
|
|
|
|
&& (imgSubres.baseArrayLayer + imgSubres.layerCount > dstSubres.baseArrayLayer)
|
|
|
|
&& (imgSubres.baseMipLevel < dstSubres.baseMipLevel + dstSubres.levelCount)
|
|
|
|
&& (imgSubres.baseMipLevel + imgSubres.levelCount > dstSubres.baseMipLevel);
|
2018-06-18 14:35:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2019-02-07 00:26:40 +01:00
|
|
|
|
|
|
|
|
|
|
|
DxvkAccessFlags DxvkBarrierSet::getBufferAccess(
|
|
|
|
const DxvkBufferSliceHandle& bufSlice) {
|
2019-04-02 14:48:39 +02:00
|
|
|
DxvkAccessFlags access;
|
2019-02-07 00:26:40 +01:00
|
|
|
|
|
|
|
for (uint32_t i = 0; i < m_bufSlices.size(); i++) {
|
|
|
|
const DxvkBufferSliceHandle& dstSlice = m_bufSlices[i].slice;
|
|
|
|
|
|
|
|
if ((bufSlice.handle == dstSlice.handle)
|
|
|
|
&& (bufSlice.offset + bufSlice.length > dstSlice.offset)
|
|
|
|
&& (bufSlice.offset < dstSlice.offset + dstSlice.length))
|
|
|
|
access = access | m_bufSlices[i].access;
|
|
|
|
}
|
|
|
|
|
|
|
|
return access;
|
|
|
|
}
|
|
|
|
|
2018-06-18 14:35:11 +02:00
|
|
|
|
2019-02-07 00:26:40 +01:00
|
|
|
DxvkAccessFlags DxvkBarrierSet::getImageAccess(
|
|
|
|
const Rc<DxvkImage>& image,
|
|
|
|
const VkImageSubresourceRange& imgSubres) {
|
2019-04-02 14:48:39 +02:00
|
|
|
DxvkAccessFlags access;
|
2019-02-07 00:26:40 +01:00
|
|
|
|
|
|
|
for (uint32_t i = 0; i < m_imgSlices.size(); i++) {
|
|
|
|
const VkImageSubresourceRange& dstSubres = m_imgSlices[i].subres;
|
|
|
|
|
2021-02-20 14:35:22 +01:00
|
|
|
if ((image->handle() == m_imgSlices[i].image)
|
2019-02-07 00:26:40 +01:00
|
|
|
&& (imgSubres.baseArrayLayer < dstSubres.baseArrayLayer + dstSubres.layerCount)
|
|
|
|
&& (imgSubres.baseArrayLayer + imgSubres.layerCount > dstSubres.baseArrayLayer)
|
|
|
|
&& (imgSubres.baseMipLevel < dstSubres.baseMipLevel + dstSubres.levelCount)
|
|
|
|
&& (imgSubres.baseMipLevel + imgSubres.levelCount > dstSubres.baseMipLevel))
|
|
|
|
access = access | m_imgSlices[i].access;
|
|
|
|
}
|
|
|
|
|
|
|
|
return access;
|
|
|
|
}
|
|
|
|
|
2018-06-18 14:35:11 +02:00
|
|
|
|
2017-12-01 10:51:58 +01:00
|
|
|
void DxvkBarrierSet::recordCommands(const Rc<DxvkCommandList>& commandList) {
|
2019-01-22 14:16:24 +01:00
|
|
|
if (m_srcStages | m_dstStages) {
|
2017-11-26 13:24:01 +01:00
|
|
|
VkPipelineStageFlags srcFlags = m_srcStages;
|
|
|
|
VkPipelineStageFlags dstFlags = m_dstStages;
|
|
|
|
|
2019-01-22 14:16:24 +01:00
|
|
|
if (!srcFlags) srcFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
|
|
|
if (!dstFlags) dstFlags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
|
|
|
|
|
|
|
|
VkMemoryBarrier memBarrier;
|
|
|
|
memBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
|
|
|
|
memBarrier.pNext = nullptr;
|
|
|
|
memBarrier.srcAccessMask = m_srcAccess;
|
|
|
|
memBarrier.dstAccessMask = m_dstAccess;
|
|
|
|
|
|
|
|
VkMemoryBarrier* pMemBarrier = nullptr;
|
|
|
|
if (m_srcAccess | m_dstAccess)
|
|
|
|
pMemBarrier = &memBarrier;
|
2017-11-26 13:24:01 +01:00
|
|
|
|
2017-12-01 10:51:58 +01:00
|
|
|
commandList->cmdPipelineBarrier(
|
2019-04-02 12:14:15 +02:00
|
|
|
m_cmdBuffer, srcFlags, dstFlags, 0,
|
2019-01-22 14:16:24 +01:00
|
|
|
pMemBarrier ? 1 : 0, pMemBarrier,
|
2019-06-28 02:01:22 +02:00
|
|
|
m_bufBarriers.size(),
|
|
|
|
m_bufBarriers.data(),
|
2019-04-02 14:48:39 +02:00
|
|
|
m_imgBarriers.size(),
|
|
|
|
m_imgBarriers.data());
|
2017-11-26 13:24:01 +01:00
|
|
|
|
|
|
|
this->reset();
|
|
|
|
}
|
2017-10-15 17:56:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-11-26 13:24:01 +01:00
|
|
|
void DxvkBarrierSet::reset() {
|
|
|
|
m_srcStages = 0;
|
|
|
|
m_dstStages = 0;
|
2019-04-02 15:05:44 +02:00
|
|
|
|
|
|
|
m_srcAccess = 0;
|
|
|
|
m_dstAccess = 0;
|
2017-10-15 17:56:06 +02:00
|
|
|
|
2019-06-28 02:01:22 +02:00
|
|
|
m_bufBarriers.resize(0);
|
2017-11-26 13:24:01 +01:00
|
|
|
m_imgBarriers.resize(0);
|
2018-06-16 11:53:06 +02:00
|
|
|
|
|
|
|
m_bufSlices.resize(0);
|
2018-06-18 14:35:11 +02:00
|
|
|
m_imgSlices.resize(0);
|
2017-10-15 17:56:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-16 10:40:30 +02:00
|
|
|
DxvkAccessFlags DxvkBarrierSet::getAccessTypes(VkAccessFlags flags) const {
|
2017-11-26 13:24:01 +01:00
|
|
|
const VkAccessFlags rflags
|
|
|
|
= VK_ACCESS_INDIRECT_COMMAND_READ_BIT
|
|
|
|
| VK_ACCESS_INDEX_READ_BIT
|
|
|
|
| VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT
|
|
|
|
| VK_ACCESS_UNIFORM_READ_BIT
|
|
|
|
| VK_ACCESS_INPUT_ATTACHMENT_READ_BIT
|
|
|
|
| VK_ACCESS_SHADER_READ_BIT
|
|
|
|
| VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
|
|
|
|
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
|
|
|
|
| VK_ACCESS_TRANSFER_READ_BIT
|
|
|
|
| VK_ACCESS_HOST_READ_BIT
|
2018-09-06 13:06:14 +02:00
|
|
|
| VK_ACCESS_MEMORY_READ_BIT
|
|
|
|
| VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT;
|
2017-11-26 13:24:01 +01:00
|
|
|
|
|
|
|
const VkAccessFlags wflags
|
|
|
|
= VK_ACCESS_SHADER_WRITE_BIT
|
|
|
|
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
|
|
|
|
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
|
|
|
|
| VK_ACCESS_TRANSFER_WRITE_BIT
|
|
|
|
| VK_ACCESS_HOST_WRITE_BIT
|
2018-09-06 13:06:14 +02:00
|
|
|
| VK_ACCESS_MEMORY_WRITE_BIT
|
|
|
|
| VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT
|
|
|
|
| VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT;
|
2017-10-15 17:56:06 +02:00
|
|
|
|
2018-06-16 10:40:30 +02:00
|
|
|
DxvkAccessFlags result;
|
|
|
|
if (flags & rflags) result.set(DxvkAccess::Read);
|
|
|
|
if (flags & wflags) result.set(DxvkAccess::Write);
|
2017-11-26 13:24:01 +01:00
|
|
|
return result;
|
2017-10-15 17:56:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|