1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-13 16:08:50 +01:00

[dxvk] Simplify barrier image and buffer slice implementations

Pre-process the given ranges so that compare and merge
operations become both simpler and faster.
This commit is contained in:
Philip Rebohle 2022-08-10 23:45:19 +02:00
parent 8aae9c85bb
commit 4c7da80c14
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99

View File

@ -20,10 +20,12 @@ namespace dxvk {
public: public:
DxvkBarrierBufferSlice() DxvkBarrierBufferSlice()
: m_offset(0), m_length(0), m_access(0) { } : m_loAddr(0), m_hiAddr(0), m_access(0) { }
DxvkBarrierBufferSlice(VkDeviceSize offset, VkDeviceSize length, DxvkAccessFlags access) DxvkBarrierBufferSlice(VkDeviceSize offset, VkDeviceSize length, DxvkAccessFlags access)
: m_offset(offset), m_length(length), m_access(access) { } : m_loAddr(offset),
m_hiAddr(offset + length),
m_access(access) { }
/** /**
* \brief Checks whether two slices overlap * \brief Checks whether two slices overlap
@ -32,8 +34,8 @@ namespace dxvk {
* \returns \c true if the two slices overlap * \returns \c true if the two slices overlap
*/ */
bool overlaps(const DxvkBarrierBufferSlice& slice) const { bool overlaps(const DxvkBarrierBufferSlice& slice) const {
return m_offset + m_length > slice.m_offset return m_hiAddr > slice.m_loAddr
&& m_offset < slice.m_offset + slice.m_length; && m_loAddr < slice.m_hiAddr;
} }
/** /**
@ -58,11 +60,11 @@ namespace dxvk {
*/ */
bool canMerge(const DxvkBarrierBufferSlice& slice) const { bool canMerge(const DxvkBarrierBufferSlice& slice) const {
if (m_access == slice.m_access) { if (m_access == slice.m_access) {
return m_offset + m_length >= slice.m_offset return m_hiAddr >= slice.m_loAddr
&& m_offset <= slice.m_offset + slice.m_length; && m_loAddr <= slice.m_hiAddr;
} else { } else {
return m_offset == slice.m_offset return m_loAddr == slice.m_loAddr
&& m_length == slice.m_length; && m_hiAddr == slice.m_hiAddr;
} }
} }
@ -75,10 +77,8 @@ namespace dxvk {
* \param [in] slice The slice to merge * \param [in] slice The slice to merge
*/ */
void merge(const DxvkBarrierBufferSlice& slice) { void merge(const DxvkBarrierBufferSlice& slice) {
VkDeviceSize end = std::max(m_offset + m_length, slice.m_offset + slice.m_length); m_loAddr = std::min(m_loAddr, slice.m_loAddr);
m_hiAddr = std::max(m_hiAddr, slice.m_hiAddr);
m_offset = std::min(m_offset, slice.m_offset);
m_length = end - m_offset;
m_access.set(slice.m_access); m_access.set(slice.m_access);
} }
@ -87,13 +87,13 @@ namespace dxvk {
* \returns Access flags * \returns Access flags
*/ */
DxvkAccessFlags getAccess() const { DxvkAccessFlags getAccess() const {
return m_access; return DxvkAccessFlags(m_access);
} }
private: private:
VkDeviceSize m_offset; VkDeviceSize m_loAddr;
VkDeviceSize m_length; VkDeviceSize m_hiAddr;
DxvkAccessFlags m_access; DxvkAccessFlags m_access;
}; };
@ -110,10 +110,20 @@ namespace dxvk {
public: public:
DxvkBarrierImageSlice() DxvkBarrierImageSlice()
: m_range(VkImageSubresourceRange()), m_access(0) { } : m_aspects(0),
m_minLayer(0),
m_maxLayer(0),
m_minLevel(0),
m_maxLevel(0),
m_access(0) { }
DxvkBarrierImageSlice(VkImageSubresourceRange range, DxvkAccessFlags access) DxvkBarrierImageSlice(VkImageSubresourceRange range, DxvkAccessFlags access)
: m_range(range), m_access(access) { } : m_aspects(range.aspectMask),
m_minLayer(range.baseArrayLayer),
m_maxLayer(range.baseArrayLayer + range.layerCount),
m_minLevel(range.baseMipLevel),
m_maxLevel(range.baseMipLevel + range.levelCount),
m_access(access) { }
/** /**
* \brief Checks whether two slices overlap * \brief Checks whether two slices overlap
@ -122,11 +132,11 @@ namespace dxvk {
* \returns \c true if the two slices overlap * \returns \c true if the two slices overlap
*/ */
bool overlaps(const DxvkBarrierImageSlice& slice) const { bool overlaps(const DxvkBarrierImageSlice& slice) const {
return (m_range.aspectMask & slice.m_range.aspectMask) return (m_aspects & slice.m_aspects)
&& (m_range.baseArrayLayer < slice.m_range.baseArrayLayer + slice.m_range.layerCount) && (m_minLayer < slice.m_maxLayer)
&& (m_range.baseArrayLayer + m_range.layerCount > slice.m_range.baseArrayLayer) && (m_maxLayer > slice.m_minLayer)
&& (m_range.baseMipLevel < slice.m_range.baseMipLevel + slice.m_range.levelCount) && (m_minLevel < slice.m_maxLevel)
&& (m_range.baseMipLevel + m_range.levelCount > slice.m_range.baseMipLevel); && (m_maxLevel > slice.m_minLevel);
} }
/** /**
@ -143,18 +153,30 @@ namespace dxvk {
/** /**
* \brief Checks whether two slices can be merged * \brief Checks whether two slices can be merged
* *
* This is a simplified implementation that does not check for * This is a simplified implementation that does only
* adjacent or overlapping layers or levels, and instead only * checks for adjacent subresources in one dimension.
* returns \c true if both slices contain the same mip levels
* and array layers. Access flags and image aspects may differ.
* \param [in] slice The other image slice to check * \param [in] slice The other image slice to check
* \returns \c true if the slices can be merged. * \returns \c true if the slices can be merged.
*/ */
bool canMerge(const DxvkBarrierImageSlice& slice) const { bool canMerge(const DxvkBarrierImageSlice& slice) const {
return m_range.baseMipLevel == slice.m_range.baseMipLevel bool sameLayers = m_minLayer == slice.m_minLayer
&& m_range.levelCount == slice.m_range.levelCount && m_maxLayer == slice.m_maxLayer;
&& m_range.baseArrayLayer == slice.m_range.baseArrayLayer bool sameLevels = m_minLevel == slice.m_minLevel
&& m_range.layerCount == slice.m_range.layerCount; && m_maxLevel == slice.m_maxLevel;
if (sameLayers == sameLevels)
return sameLayers;
if (m_access != slice.m_access)
return false;
if (sameLayers) {
return m_maxLevel >= slice.m_minLevel
&& m_minLevel <= slice.m_maxLevel;
} else /* if (sameLevels) */ {
return m_maxLayer >= slice.m_minLayer
&& m_minLayer <= slice.m_maxLayer;
}
} }
/** /**
@ -166,15 +188,11 @@ namespace dxvk {
* \param [in] slice The slice to merge * \param [in] slice The slice to merge
*/ */
void merge(const DxvkBarrierImageSlice& slice) { void merge(const DxvkBarrierImageSlice& slice) {
uint32_t maxMipLevel = std::max(m_range.baseMipLevel + m_range.levelCount, m_aspects |= slice.m_aspects;
slice.m_range.baseMipLevel + slice.m_range.levelCount); m_minLayer = std::min(m_minLayer, slice.m_minLayer);
uint32_t maxArrayLayer = std::max(m_range.baseArrayLayer + m_range.layerCount, m_maxLayer = std::max(m_maxLayer, slice.m_maxLayer);
slice.m_range.baseArrayLayer + slice.m_range.layerCount); m_minLevel = std::min(m_minLevel, slice.m_minLevel);
m_range.aspectMask |= slice.m_range.aspectMask; m_maxLevel = std::max(m_maxLevel, slice.m_maxLevel);
m_range.baseMipLevel = std::min(m_range.baseMipLevel, slice.m_range.baseMipLevel);
m_range.levelCount = maxMipLevel - m_range.baseMipLevel;
m_range.baseArrayLayer = std::min(m_range.baseMipLevel, slice.m_range.baseArrayLayer);
m_range.layerCount = maxArrayLayer - m_range.baseArrayLayer;
m_access.set(slice.m_access); m_access.set(slice.m_access);
} }
@ -188,7 +206,11 @@ namespace dxvk {
private: private:
VkImageSubresourceRange m_range; VkImageAspectFlags m_aspects;
uint32_t m_minLayer;
uint32_t m_maxLayer;
uint32_t m_minLevel;
uint32_t m_maxLevel;
DxvkAccessFlags m_access; DxvkAccessFlags m_access;
}; };