mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-06 20:58:37 +01:00
[dxvk] Add helpers to compute more granular image address ranges
This commit is contained in:
parent
1f0ad760e1
commit
baaf72a373
3 changed files with 66 additions and 17 deletions
|
@ -7942,26 +7942,25 @@ namespace dxvk {
|
|||
|
||||
uint32_t layerCount = image.info().numLayers;
|
||||
|
||||
DxvkAddressRange range;
|
||||
range.resource = image.getResourceId();
|
||||
range.accessOp = accessOp;
|
||||
|
||||
if (subresources.levelCount == 1u || subresources.layerCount == layerCount) {
|
||||
DxvkAddressRange range;
|
||||
range.resource = image.getResourceId();
|
||||
range.accessOp = accessOp;
|
||||
range.rangeStart = subresources.baseMipLevel * layerCount + subresources.baseArrayLayer;
|
||||
range.rangeEnd = (subresources.baseMipLevel + subresources.levelCount - 1u) * layerCount
|
||||
+ (subresources.baseArrayLayer + subresources.layerCount - 1u);
|
||||
range.rangeStart = image.getTrackingAddress(
|
||||
subresources.baseMipLevel, subresources.baseArrayLayer);
|
||||
range.rangeEnd = image.getTrackingAddress(
|
||||
subresources.baseMipLevel + subresources.levelCount,
|
||||
subresources.baseArrayLayer + subresources.layerCount) - 1u;
|
||||
|
||||
if (hasWrite)
|
||||
m_barrierTracker.insertRange(range, DxvkAccess::Write);
|
||||
if (hasRead)
|
||||
m_barrierTracker.insertRange(range, DxvkAccess::Read);
|
||||
} else {
|
||||
DxvkAddressRange range;
|
||||
range.resource = image.getResourceId();
|
||||
range.accessOp = accessOp;
|
||||
|
||||
for (uint32_t i = subresources.baseMipLevel; i < subresources.baseMipLevel + subresources.levelCount; i++) {
|
||||
range.rangeStart = i * layerCount + subresources.baseArrayLayer;
|
||||
range.rangeEnd = range.rangeStart + subresources.layerCount - 1u;
|
||||
range.rangeStart = image.getTrackingAddress(i, subresources.baseArrayLayer);
|
||||
range.rangeEnd = image.getTrackingAddress(i, subresources.baseArrayLayer + subresources.layerCount) - 1u;
|
||||
|
||||
if (hasWrite)
|
||||
m_barrierTracker.insertRange(range, DxvkAccess::Write);
|
||||
|
@ -8223,9 +8222,11 @@ namespace dxvk {
|
|||
DxvkAddressRange range;
|
||||
range.resource = image.getResourceId();
|
||||
range.accessOp = accessOp;
|
||||
range.rangeStart = subresources.baseMipLevel * layerCount + subresources.baseArrayLayer;
|
||||
range.rangeEnd = (subresources.baseMipLevel + subresources.levelCount - 1u) * layerCount
|
||||
+ (subresources.baseArrayLayer + subresources.layerCount - 1u);
|
||||
range.rangeStart = image.getTrackingAddress(
|
||||
subresources.baseMipLevel, subresources.baseArrayLayer);
|
||||
range.rangeEnd = image.getTrackingAddress(
|
||||
subresources.baseMipLevel + subresources.levelCount,
|
||||
subresources.baseArrayLayer + subresources.layerCount) - 1u;
|
||||
|
||||
// Probe all subresources first, only check individual mip levels
|
||||
// if there are overlaps and if we are checking a subset of array
|
||||
|
@ -8236,8 +8237,8 @@ namespace dxvk {
|
|||
return dirty;
|
||||
|
||||
for (uint32_t i = subresources.baseMipLevel; i < subresources.baseMipLevel + subresources.levelCount && !dirty; i++) {
|
||||
range.rangeStart = i * layerCount + subresources.baseArrayLayer;
|
||||
range.rangeEnd = range.rangeStart + subresources.layerCount - 1u;
|
||||
range.rangeStart = image.getTrackingAddress(i, subresources.baseArrayLayer);
|
||||
range.rangeEnd = image.getTrackingAddress(i, subresources.baseArrayLayer + subresources.layerCount) - 1u;
|
||||
|
||||
dirty = m_barrierTracker.findRange(range, access);
|
||||
}
|
||||
|
|
|
@ -114,6 +114,29 @@ namespace dxvk {
|
|||
}
|
||||
|
||||
|
||||
uint64_t DxvkImage::getTrackingAddress(uint32_t mip, uint32_t layer, VkOffset3D coord) const {
|
||||
// For 2D and 3D images, use morton codes to linearize the address ranges
|
||||
// of pixel blocks. This helps reduce false positives in common use cases
|
||||
// where the application copies aligned power-of-two blocks around.
|
||||
uint64_t base = getTrackingAddress(mip, layer);
|
||||
|
||||
if (likely(m_info.type == VK_IMAGE_TYPE_2D))
|
||||
return base + bit::interleave(coord.x, coord.y);
|
||||
|
||||
// For 1D we can simply use the pixel coordinate as-is
|
||||
if (m_info.type == VK_IMAGE_TYPE_1D)
|
||||
return base + coord.x;
|
||||
|
||||
// 3D is uncommon, but there are different use cases. Assume that if the
|
||||
// format is block-compressed, the app will access one layer at a time.
|
||||
if (formatInfo()->flags.test(DxvkFormatFlag::BlockCompressed))
|
||||
return base + bit::interleave(coord.x, coord.y) + (uint64_t(coord.z) << 32u);
|
||||
|
||||
// Otherwise, it may want to copy actual 3D blocks around.
|
||||
return base + bit::interleave(coord.x, coord.y, coord.z);
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkImageView> DxvkImage::createView(
|
||||
const DxvkImageViewKey& info) {
|
||||
std::unique_lock lock(m_viewMutex);
|
||||
|
|
|
@ -582,6 +582,31 @@ namespace dxvk {
|
|||
return bit::uint48_t(reinterpret_cast<uintptr_t>(m_storage.ptr()) / (Align & -Align));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Computes virtual offset of a subresource
|
||||
*
|
||||
* Used for hazard tracking. Ignores the aspect mask and
|
||||
* only takes the mip level and array layer into account.
|
||||
* \param [in] mip Mip level index
|
||||
* \param [in] layer Array layer index
|
||||
*/
|
||||
uint64_t getTrackingAddress(uint32_t mip, uint32_t layer) const {
|
||||
// Put layers within the same mip into a contiguous range. This works well
|
||||
// for not only transfer operations but also most image view use cases.
|
||||
return uint64_t((m_info.numLayers * mip) + layer) << 48u;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Computes virtual offset of a specific image region
|
||||
*
|
||||
* Used for more granular hazard tracking. This interleaves coordinate
|
||||
* bits in order to compute a unique address for each pixel.
|
||||
* \param [in] mip Mip level index
|
||||
* \param [in] layer Array layer index
|
||||
* \param [in] coord Pixel coordinate within the subresource
|
||||
*/
|
||||
uint64_t getTrackingAddress(uint32_t mip, uint32_t layer, VkOffset3D coord) const;
|
||||
|
||||
/**
|
||||
* \brief Creates or retrieves an image view
|
||||
*
|
||||
|
|
Loading…
Add table
Reference in a new issue