From 5c2f56c9cc02861b8b96a67acf83d213e55499d6 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sun, 22 Sep 2024 11:27:14 +0200 Subject: [PATCH] [dxvk] Introduce DxvkBufferAllocation For now, this is merely a wrapper around the existing buffer slice struct in order to allow easier refactoring. --- src/dxvk/dxvk_buffer.h | 94 ++++++++++++++++++++++++++++++++++++--- src/dxvk/dxvk_context.cpp | 17 ++++--- src/dxvk/dxvk_context.h | 6 ++- 3 files changed, 105 insertions(+), 12 deletions(-) diff --git a/src/dxvk/dxvk_buffer.h b/src/dxvk/dxvk_buffer.h index 1bd7ba52c..1a3fccaf1 100644 --- a/src/dxvk/dxvk_buffer.h +++ b/src/dxvk/dxvk_buffer.h @@ -100,10 +100,10 @@ namespace dxvk { * to the mapped region.. */ struct DxvkBufferSliceHandle { - VkBuffer handle; - VkDeviceSize offset; - VkDeviceSize length; - void* mapPtr; + VkBuffer handle = VK_NULL_HANDLE; + VkDeviceSize offset = 0u; + VkDeviceSize length = 0u; + void* mapPtr = nullptr; bool eq(const DxvkBufferSliceHandle& other) const { return handle == other.handle @@ -121,6 +121,61 @@ namespace dxvk { }; + /** + * \brief Buffer allocation + * + * References a buffer allocation and stores + * the offset. Used when renaming a buffer. + */ + class DxvkBufferAllocation { + friend class DxvkBuffer; + friend class DxvkContext; /* TODO remove */ + public: + + DxvkBufferAllocation() = default; + + explicit DxvkBufferAllocation(DxvkBufferSliceHandle slice) + : m_slice(slice) { } + + DxvkBufferAllocation(const DxvkBufferAllocation&) = default; + DxvkBufferAllocation& operator = (const DxvkBufferAllocation&) = default; + + DxvkBufferAllocation(DxvkBufferAllocation&& other) + : m_slice(other.m_slice) { + other.m_slice = DxvkBufferSliceHandle(); + } + + DxvkBufferAllocation& operator = (DxvkBufferAllocation&& other) { + m_slice = other.m_slice; + other.m_slice = DxvkBufferSliceHandle(); + return *this; + } + + ~DxvkBufferAllocation() = default; + + /** + * \brief Retrieves CPU pointer + * \returns Pointer to the mapped buffer slice + */ + void* mapPtr() const { + return m_slice.mapPtr; + } + + /** + * \brief Checks whether the slice is valid + * \returns \c true if the slice is valid + */ + explicit operator bool () const { + return m_slice.handle != VK_NULL_HANDLE; + } + + private: + + DxvkBufferSliceHandle m_slice = { }; + + }; + + /** * \brief Virtual buffer resource * @@ -247,7 +302,7 @@ namespace dxvk { DxvkBufferSliceHandle rename(const DxvkBufferSliceHandle& slice) { return std::exchange(m_physSlice, slice); } - + /** * \brief Transform feedback vertex stride * @@ -269,7 +324,7 @@ namespace dxvk { void setXfbVertexStride(uint32_t stride) { m_vertexStride = stride; } - + /** * \brief Allocates new buffer slice * \returns The new buffer slice @@ -309,7 +364,34 @@ namespace dxvk { m_freeSlices.pop_back(); return result; } + + /** + * \brief Allocates a new buffer slice + * \returns New buffer slice + */ + DxvkBufferAllocation allocateSlice() { + return DxvkBufferAllocation(allocSlice()); + } + /** + * \brief Replaces backing storage + * + * Implicitly invalidates all views created for the buffer. + * \param [in] slice New buffer slice + * \returns Previous buffer allocation for lifetime tracking. + */ + DxvkBufferAllocation assignSlice(DxvkBufferAllocation&& slice) { + return DxvkBufferAllocation(rename(slice.m_slice)); + } + + /** + * \brief Retrieves current backing storage + * \returns Current buffer allocation + */ + DxvkBufferAllocation getAllocation() const { + return DxvkBufferAllocation(m_physSlice); + } + /** * \brief Frees a buffer slice * diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index b62484489..d95303194 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -1828,10 +1828,10 @@ namespace dxvk { void DxvkContext::invalidateBuffer( const Rc& buffer, - const DxvkBufferSliceHandle& slice) { + DxvkBufferAllocation&& slice) { // Allocate new backing resource - DxvkBufferSliceHandle prevSlice = buffer->rename(slice); - m_cmd->freeBufferSlice(buffer, prevSlice); + DxvkBufferAllocation prevSlice = buffer->assignSlice(std::move(slice)); + m_cmd->freeBufferSlice(buffer, prevSlice.m_slice); // We also need to update all bindings that the buffer // may be bound to either directly or through views. @@ -1865,6 +1865,13 @@ namespace dxvk { } + void DxvkContext::invalidateBuffer( + const Rc& buffer, + const DxvkBufferSliceHandle& slice) { + invalidateBuffer(buffer, DxvkBufferAllocation(slice)); + } + + void DxvkContext::resolveImage( const Rc& dstImage, const Rc& srcImage, @@ -6385,10 +6392,10 @@ namespace dxvk { && (m_flags.test(DxvkContextFlag::GpXfbActive))) this->spillRenderPass(true); - this->invalidateBuffer(buffer, buffer->allocSlice()); + this->invalidateBuffer(buffer, buffer->allocateSlice()); return true; } - + DxvkGraphicsPipeline* DxvkContext::lookupGraphicsPipeline( const DxvkGraphicsPipelineShaders& shaders) { diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index 3e4d9da06..46b284d9f 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -959,8 +959,12 @@ namespace dxvk { * \warning If the buffer is used by another context, * invalidating it will result in undefined behaviour. * \param [in] buffer The buffer to invalidate - * \param [in] slice New buffer slice handle + * \param [in] slice New buffer slice */ + void invalidateBuffer( + const Rc& buffer, + DxvkBufferAllocation&& slice); + void invalidateBuffer( const Rc& buffer, const DxvkBufferSliceHandle& slice);