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
2acf4d3c51
commit
1be692801a
3 changed files with 66 additions and 17 deletions
|
@ -7942,26 +7942,25 @@ namespace dxvk {
|
||||||
|
|
||||||
uint32_t layerCount = image.info().numLayers;
|
uint32_t layerCount = image.info().numLayers;
|
||||||
|
|
||||||
if (subresources.levelCount == 1u || subresources.layerCount == layerCount) {
|
|
||||||
DxvkAddressRange range;
|
DxvkAddressRange range;
|
||||||
range.resource = image.getResourceId();
|
range.resource = image.getResourceId();
|
||||||
range.accessOp = accessOp;
|
range.accessOp = accessOp;
|
||||||
range.rangeStart = subresources.baseMipLevel * layerCount + subresources.baseArrayLayer;
|
|
||||||
range.rangeEnd = (subresources.baseMipLevel + subresources.levelCount - 1u) * layerCount
|
if (subresources.levelCount == 1u || subresources.layerCount == 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)
|
if (hasWrite)
|
||||||
m_barrierTracker.insertRange(range, DxvkAccess::Write);
|
m_barrierTracker.insertRange(range, DxvkAccess::Write);
|
||||||
if (hasRead)
|
if (hasRead)
|
||||||
m_barrierTracker.insertRange(range, DxvkAccess::Read);
|
m_barrierTracker.insertRange(range, DxvkAccess::Read);
|
||||||
} else {
|
} else {
|
||||||
DxvkAddressRange range;
|
|
||||||
range.resource = image.getResourceId();
|
|
||||||
range.accessOp = accessOp;
|
|
||||||
|
|
||||||
for (uint32_t i = subresources.baseMipLevel; i < subresources.baseMipLevel + subresources.levelCount; i++) {
|
for (uint32_t i = subresources.baseMipLevel; i < subresources.baseMipLevel + subresources.levelCount; i++) {
|
||||||
range.rangeStart = i * layerCount + subresources.baseArrayLayer;
|
range.rangeStart = image.getTrackingAddress(i, subresources.baseArrayLayer);
|
||||||
range.rangeEnd = range.rangeStart + subresources.layerCount - 1u;
|
range.rangeEnd = image.getTrackingAddress(i, subresources.baseArrayLayer + subresources.layerCount) - 1u;
|
||||||
|
|
||||||
if (hasWrite)
|
if (hasWrite)
|
||||||
m_barrierTracker.insertRange(range, DxvkAccess::Write);
|
m_barrierTracker.insertRange(range, DxvkAccess::Write);
|
||||||
|
@ -8223,9 +8222,11 @@ namespace dxvk {
|
||||||
DxvkAddressRange range;
|
DxvkAddressRange range;
|
||||||
range.resource = image.getResourceId();
|
range.resource = image.getResourceId();
|
||||||
range.accessOp = accessOp;
|
range.accessOp = accessOp;
|
||||||
range.rangeStart = subresources.baseMipLevel * layerCount + subresources.baseArrayLayer;
|
range.rangeStart = image.getTrackingAddress(
|
||||||
range.rangeEnd = (subresources.baseMipLevel + subresources.levelCount - 1u) * layerCount
|
subresources.baseMipLevel, subresources.baseArrayLayer);
|
||||||
+ (subresources.baseArrayLayer + subresources.layerCount - 1u);
|
range.rangeEnd = image.getTrackingAddress(
|
||||||
|
subresources.baseMipLevel + subresources.levelCount,
|
||||||
|
subresources.baseArrayLayer + subresources.layerCount) - 1u;
|
||||||
|
|
||||||
// Probe all subresources first, only check individual mip levels
|
// Probe all subresources first, only check individual mip levels
|
||||||
// if there are overlaps and if we are checking a subset of array
|
// if there are overlaps and if we are checking a subset of array
|
||||||
|
@ -8236,8 +8237,8 @@ namespace dxvk {
|
||||||
return dirty;
|
return dirty;
|
||||||
|
|
||||||
for (uint32_t i = subresources.baseMipLevel; i < subresources.baseMipLevel + subresources.levelCount && !dirty; i++) {
|
for (uint32_t i = subresources.baseMipLevel; i < subresources.baseMipLevel + subresources.levelCount && !dirty; i++) {
|
||||||
range.rangeStart = i * layerCount + subresources.baseArrayLayer;
|
range.rangeStart = image.getTrackingAddress(i, subresources.baseArrayLayer);
|
||||||
range.rangeEnd = range.rangeStart + subresources.layerCount - 1u;
|
range.rangeEnd = image.getTrackingAddress(i, subresources.baseArrayLayer + subresources.layerCount) - 1u;
|
||||||
|
|
||||||
dirty = m_barrierTracker.findRange(range, access);
|
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(
|
Rc<DxvkImageView> DxvkImage::createView(
|
||||||
const DxvkImageViewKey& info) {
|
const DxvkImageViewKey& info) {
|
||||||
std::unique_lock lock(m_viewMutex);
|
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));
|
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
|
* \brief Creates or retrieves an image view
|
||||||
*
|
*
|
||||||
|
|
Loading…
Add table
Reference in a new issue