mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-06 20:58:37 +01:00
[dxvk] Add barrier helpers for granular image access tracking
This commit is contained in:
parent
1be692801a
commit
d683c3f3df
2 changed files with 188 additions and 0 deletions
|
@ -7972,6 +7972,91 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkContext::accessImageRegion(
|
||||||
|
DxvkCmdBuffer cmdBuffer,
|
||||||
|
DxvkImage& image,
|
||||||
|
const VkImageSubresourceLayers& subresources,
|
||||||
|
VkOffset3D offset,
|
||||||
|
VkExtent3D extent,
|
||||||
|
VkImageLayout srcLayout,
|
||||||
|
VkPipelineStageFlags2 srcStages,
|
||||||
|
VkAccessFlags2 srcAccess,
|
||||||
|
DxvkAccessOp accessOp) {
|
||||||
|
accessImageRegion(cmdBuffer, image, subresources,
|
||||||
|
offset, extent, srcLayout, srcStages, srcAccess,
|
||||||
|
image.info().layout, image.info().stages, image.info().access,
|
||||||
|
accessOp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkContext::accessImageRegion(
|
||||||
|
DxvkCmdBuffer cmdBuffer,
|
||||||
|
DxvkImage& image,
|
||||||
|
const VkImageSubresourceLayers& subresources,
|
||||||
|
VkOffset3D offset,
|
||||||
|
VkExtent3D extent,
|
||||||
|
VkImageLayout srcLayout,
|
||||||
|
VkPipelineStageFlags2 srcStages,
|
||||||
|
VkAccessFlags2 srcAccess,
|
||||||
|
VkImageLayout dstLayout,
|
||||||
|
VkPipelineStageFlags2 dstStages,
|
||||||
|
VkAccessFlags2 dstAccess,
|
||||||
|
DxvkAccessOp accessOp) {
|
||||||
|
// If the image layout needs to change, access the entire image
|
||||||
|
if (srcLayout != dstLayout) {
|
||||||
|
accessImage(cmdBuffer, image, vk::makeSubresourceRange(subresources),
|
||||||
|
srcLayout, srcStages, srcAccess,
|
||||||
|
dstLayout, dstStages, dstAccess, accessOp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No layout transition, just emit a plain memory barrier
|
||||||
|
auto& batch = getBarrierBatch(cmdBuffer);
|
||||||
|
|
||||||
|
VkMemoryBarrier2 barrier = { VK_STRUCTURE_TYPE_MEMORY_BARRIER_2 };
|
||||||
|
barrier.srcStageMask = srcStages;
|
||||||
|
barrier.srcAccessMask = srcAccess;
|
||||||
|
barrier.dstStageMask = dstStages;
|
||||||
|
barrier.dstAccessMask = dstAccess;
|
||||||
|
|
||||||
|
batch.addMemoryBarrier(barrier);
|
||||||
|
|
||||||
|
if (cmdBuffer == DxvkCmdBuffer::ExecBuffer) {
|
||||||
|
bool hasWrite = (srcAccess & vk::AccessWriteMask) || (srcLayout != dstLayout);
|
||||||
|
bool hasRead = (srcAccess & vk::AccessReadMask);
|
||||||
|
|
||||||
|
DxvkAddressRange range;
|
||||||
|
range.resource = image.getResourceId();
|
||||||
|
range.accessOp = accessOp;
|
||||||
|
|
||||||
|
if (extent == image.mipLevelExtent(subresources.mipLevel)) {
|
||||||
|
range.rangeStart = image.getTrackingAddress(subresources.mipLevel, subresources.baseArrayLayer);
|
||||||
|
range.rangeEnd = image.getTrackingAddress(subresources.mipLevel, subresources.baseArrayLayer + subresources.layerCount) - 1u;
|
||||||
|
|
||||||
|
if (hasWrite)
|
||||||
|
m_barrierTracker.insertRange(range, DxvkAccess::Write);
|
||||||
|
if (hasRead)
|
||||||
|
m_barrierTracker.insertRange(range, DxvkAccess::Read);
|
||||||
|
} else {
|
||||||
|
VkOffset3D maxCoord = offset;
|
||||||
|
maxCoord.x += extent.width - 1u;
|
||||||
|
maxCoord.y += extent.height - 1u;
|
||||||
|
maxCoord.z += extent.depth - 1u;
|
||||||
|
|
||||||
|
for (uint32_t i = subresources.baseArrayLayer; i < subresources.baseArrayLayer + subresources.layerCount; i++) {
|
||||||
|
range.rangeStart = image.getTrackingAddress(subresources.mipLevel, i, offset);
|
||||||
|
range.rangeEnd = image.getTrackingAddress(subresources.mipLevel, i, maxCoord);
|
||||||
|
|
||||||
|
if (hasWrite)
|
||||||
|
m_barrierTracker.insertRange(range, DxvkAccess::Write);
|
||||||
|
if (hasRead)
|
||||||
|
m_barrierTracker.insertRange(range, DxvkAccess::Read);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkContext::accessBuffer(
|
void DxvkContext::accessBuffer(
|
||||||
DxvkCmdBuffer cmdBuffer,
|
DxvkCmdBuffer cmdBuffer,
|
||||||
DxvkBuffer& buffer,
|
DxvkBuffer& buffer,
|
||||||
|
@ -8163,6 +8248,25 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkContext::flushPendingAccesses(
|
||||||
|
DxvkImage& image,
|
||||||
|
const VkImageSubresourceLayers& subresources,
|
||||||
|
VkOffset3D offset,
|
||||||
|
VkExtent3D extent,
|
||||||
|
DxvkAccess access) {
|
||||||
|
bool flush = resourceHasAccess(image, subresources,
|
||||||
|
offset, extent, DxvkAccess::Write, DxvkAccessOp::None);
|
||||||
|
|
||||||
|
if (access == DxvkAccess::Write && !flush) {
|
||||||
|
flush = resourceHasAccess(image, subresources,
|
||||||
|
offset, extent, DxvkAccess::Read, DxvkAccessOp::None);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flush)
|
||||||
|
flushBarriers();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkContext::flushPendingAccesses(
|
void DxvkContext::flushPendingAccesses(
|
||||||
DxvkImageView& imageView,
|
DxvkImageView& imageView,
|
||||||
DxvkAccess access) {
|
DxvkAccess access) {
|
||||||
|
@ -8247,6 +8351,50 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool DxvkContext::resourceHasAccess(
|
||||||
|
DxvkImage& image,
|
||||||
|
const VkImageSubresourceLayers& subresources,
|
||||||
|
VkOffset3D offset,
|
||||||
|
VkExtent3D extent,
|
||||||
|
DxvkAccess access,
|
||||||
|
DxvkAccessOp accessOp) {
|
||||||
|
DxvkAddressRange range;
|
||||||
|
range.resource = image.getResourceId();
|
||||||
|
range.accessOp = accessOp;
|
||||||
|
|
||||||
|
// If there are multiple subresources, check whether any of them have been
|
||||||
|
// touched before checking individual regions. If the given region covers
|
||||||
|
// the entire image, there is also no need to check more granularly.
|
||||||
|
bool isFullSize = image.mipLevelExtent(subresources.mipLevel) == extent;
|
||||||
|
|
||||||
|
if (subresources.layerCount > 1u || isFullSize) {
|
||||||
|
range.rangeStart = image.getTrackingAddress(subresources.mipLevel, subresources.baseArrayLayer);
|
||||||
|
range.rangeEnd = image.getTrackingAddress(subresources.mipLevel, subresources.baseArrayLayer + subresources.layerCount) - 1u;
|
||||||
|
|
||||||
|
bool dirty = m_barrierTracker.findRange(range, access);
|
||||||
|
|
||||||
|
if (!dirty || isFullSize)
|
||||||
|
return dirty;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check given image region in each subresource
|
||||||
|
VkOffset3D maxCoord = offset;
|
||||||
|
maxCoord.x += extent.width - 1u;
|
||||||
|
maxCoord.y += extent.height - 1u;
|
||||||
|
maxCoord.z += extent.depth - 1u;
|
||||||
|
|
||||||
|
for (uint32_t i = subresources.baseArrayLayer; i < subresources.baseArrayLayer + subresources.layerCount; i++) {
|
||||||
|
range.rangeStart = image.getTrackingAddress(subresources.mipLevel, i, offset);
|
||||||
|
range.rangeEnd = image.getTrackingAddress(subresources.mipLevel, i, maxCoord);
|
||||||
|
|
||||||
|
if (m_barrierTracker.findRange(range, access))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool DxvkContext::resourceHasAccess(
|
bool DxvkContext::resourceHasAccess(
|
||||||
DxvkImageView& imageView,
|
DxvkImageView& imageView,
|
||||||
DxvkAccess access,
|
DxvkAccess access,
|
||||||
|
|
|
@ -1948,6 +1948,31 @@ namespace dxvk {
|
||||||
VkAccessFlags2 dstAccess,
|
VkAccessFlags2 dstAccess,
|
||||||
DxvkAccessOp accessOp);
|
DxvkAccessOp accessOp);
|
||||||
|
|
||||||
|
void accessImageRegion(
|
||||||
|
DxvkCmdBuffer cmdBuffer,
|
||||||
|
DxvkImage& image,
|
||||||
|
const VkImageSubresourceLayers& subresources,
|
||||||
|
VkOffset3D offset,
|
||||||
|
VkExtent3D extent,
|
||||||
|
VkImageLayout srcLayout,
|
||||||
|
VkPipelineStageFlags2 srcStages,
|
||||||
|
VkAccessFlags2 srcAccess,
|
||||||
|
DxvkAccessOp accessOp);
|
||||||
|
|
||||||
|
void accessImageRegion(
|
||||||
|
DxvkCmdBuffer cmdBuffer,
|
||||||
|
DxvkImage& image,
|
||||||
|
const VkImageSubresourceLayers& subresources,
|
||||||
|
VkOffset3D offset,
|
||||||
|
VkExtent3D extent,
|
||||||
|
VkImageLayout srcLayout,
|
||||||
|
VkPipelineStageFlags2 srcStages,
|
||||||
|
VkAccessFlags2 srcAccess,
|
||||||
|
VkImageLayout dstLayout,
|
||||||
|
VkPipelineStageFlags2 dstStages,
|
||||||
|
VkAccessFlags2 dstAccess,
|
||||||
|
DxvkAccessOp accessOp);
|
||||||
|
|
||||||
void accessBuffer(
|
void accessBuffer(
|
||||||
DxvkCmdBuffer cmdBuffer,
|
DxvkCmdBuffer cmdBuffer,
|
||||||
DxvkBuffer& buffer,
|
DxvkBuffer& buffer,
|
||||||
|
@ -2024,6 +2049,13 @@ namespace dxvk {
|
||||||
const VkImageSubresourceRange& subresources,
|
const VkImageSubresourceRange& subresources,
|
||||||
DxvkAccess access);
|
DxvkAccess access);
|
||||||
|
|
||||||
|
void flushPendingAccesses(
|
||||||
|
DxvkImage& image,
|
||||||
|
const VkImageSubresourceLayers& subresources,
|
||||||
|
VkOffset3D offset,
|
||||||
|
VkExtent3D extent,
|
||||||
|
DxvkAccess access);
|
||||||
|
|
||||||
void flushPendingAccesses(
|
void flushPendingAccesses(
|
||||||
DxvkImageView& imageView,
|
DxvkImageView& imageView,
|
||||||
DxvkAccess access);
|
DxvkAccess access);
|
||||||
|
@ -2048,6 +2080,14 @@ namespace dxvk {
|
||||||
DxvkAccess access,
|
DxvkAccess access,
|
||||||
DxvkAccessOp accessOp);
|
DxvkAccessOp accessOp);
|
||||||
|
|
||||||
|
bool resourceHasAccess(
|
||||||
|
DxvkImage& image,
|
||||||
|
const VkImageSubresourceLayers& subresources,
|
||||||
|
VkOffset3D offset,
|
||||||
|
VkExtent3D extent,
|
||||||
|
DxvkAccess access,
|
||||||
|
DxvkAccessOp accessOp);
|
||||||
|
|
||||||
bool resourceHasAccess(
|
bool resourceHasAccess(
|
||||||
DxvkImageView& imageView,
|
DxvkImageView& imageView,
|
||||||
DxvkAccess access,
|
DxvkAccess access,
|
||||||
|
|
Loading…
Add table
Reference in a new issue