From f501ebce973d26d1d4e86911526ec73690f6208e Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Mon, 3 Jun 2019 20:14:27 +0200 Subject: [PATCH] [dxvk] Avoid redundant descriptor set updates when binding buffers Reduces unnecessary overhead when binding a different range of the same buffer, e.g. through D3D11 VSSetConstantBuffers1. --- src/dxvk/dxvk_buffer.h | 41 ++++++++++++++++++++++++++++++++++++++- src/dxvk/dxvk_context.cpp | 10 +++++++++- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/dxvk/dxvk_buffer.h b/src/dxvk/dxvk_buffer.h index 7adde6945..785a84cbf 100644 --- a/src/dxvk/dxvk_buffer.h +++ b/src/dxvk/dxvk_buffer.h @@ -434,7 +434,7 @@ namespace dxvk { ? m_buffer->mapPtr(m_offset + offset) : nullptr; } - + /** * \brief Checks whether two slices are equal * @@ -448,6 +448,45 @@ namespace dxvk { && this->m_offset == other.m_offset && this->m_length == other.m_length; } + + /** + * \brief Checks whether two slices are from the same buffer + * + * This returns \c true if the two slices are taken + * from the same buffer, but may have different ranges. + * \param [in] other The slice to compare to + * \returns \c true if the buffer objects are the same + */ + bool matchesBuffer(const DxvkBufferSlice& other) const { + return this->m_buffer == other.m_buffer; + } + + /** + * \brief Checks whether two slices have the same range + * + * This returns \c true if the two slices have the same + * offset and size, even if the buffers are different. + * May be useful if the buffers are know to be the same. + * \param [in] other The slice to compare to + * \returns \c true if the buffer objects are the same + */ + bool matchesRange(const DxvkBufferSlice& other) const { + return this->m_offset == other.m_offset + && this->m_length == other.m_length; + } + + /** + * \brief Changes offset and size, but not the buffer + * + * Slightly faster alternative to overriding the full + * buffer slice object in case only the range changes. + * \param [in] offset New slice offset + * \param [in] length New slice length + */ + void updateRange(VkDeviceSize offset, VkDeviceSize length) { + m_offset = offset; + m_length = length; + } private: diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 7c2d3a815..f96ef2937 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -158,12 +158,20 @@ namespace dxvk { void DxvkContext::bindResourceBuffer( uint32_t slot, const DxvkBufferSlice& buffer) { - if (!m_rc[slot].bufferSlice.matches(buffer)) { + if (!m_rc[slot].bufferSlice.matchesBuffer(buffer)) { m_rc[slot].bufferSlice = buffer; m_flags.set( DxvkContextFlag::CpDirtyResources, DxvkContextFlag::GpDirtyResources); + } else if (!m_rc[slot].bufferSlice.matchesRange(buffer)) { + m_rc[slot].bufferSlice.updateRange( + buffer.offset(), + buffer.length()); + + m_flags.set( + DxvkContextFlag::CpDirtyDescriptorOffsets, + DxvkContextFlag::GpDirtyDescriptorOffsets); } }