diff --git a/src/dxvk/dxvk_buffer.cpp b/src/dxvk/dxvk_buffer.cpp index f2fbf5c5..4fd2a263 100644 --- a/src/dxvk/dxvk_buffer.cpp +++ b/src/dxvk/dxvk_buffer.cpp @@ -62,9 +62,35 @@ namespace dxvk { } + DxvkBuffer::DxvkBuffer( + DxvkDevice* device, + const DxvkBufferCreateInfo& createInfo, + const DxvkBufferImportInfo& importInfo, + VkMemoryPropertyFlags memFlags) + : m_vkd (device->vkd()), + m_info (createInfo), + m_import (importInfo), + m_memAlloc (nullptr), + m_memFlags (memFlags), + m_shaderStages (util::shaderStages(createInfo.stages)) { + m_physSliceLength = createInfo.size; + m_physSliceStride = createInfo.size; + m_physSliceCount = 1; + m_physSliceMaxCount = 1; + + m_physSlice.handle = importInfo.buffer; + m_physSlice.offset = importInfo.offset; + m_physSlice.length = createInfo.size; + m_physSlice.mapPtr = importInfo.mapPtr; + + m_lazyAlloc = false; + } + + DxvkBuffer::~DxvkBuffer() { for (const auto& buffer : m_buffers) m_vkd->vkDestroyBuffer(m_vkd->device(), buffer.buffer, nullptr); + m_vkd->vkDestroyBuffer(m_vkd->device(), m_buffer.buffer, nullptr); } diff --git a/src/dxvk/dxvk_buffer.h b/src/dxvk/dxvk_buffer.h index a82fbd0e..5be99406 100644 --- a/src/dxvk/dxvk_buffer.h +++ b/src/dxvk/dxvk_buffer.h @@ -55,6 +55,22 @@ namespace dxvk { }; + /** + * \brief Buffer import info + * + * Used to import an existing Vulkan buffer. Note + * that imported buffers must not be renamed. + */ + struct DxvkBufferImportInfo { + /// Buffer handle + VkBuffer buffer = VK_NULL_HANDLE; + /// Buffer offset + VkDeviceSize offset = 0; + /// Pointer to mapped memory region + void* mapPtr = nullptr; + }; + + /** * \brief Buffer info * @@ -95,7 +111,7 @@ namespace dxvk { } }; - + /** * \brief Virtual buffer resource * @@ -112,7 +128,13 @@ namespace dxvk { const DxvkBufferCreateInfo& createInfo, DxvkMemoryAllocator& memAlloc, VkMemoryPropertyFlags memFlags); - + + DxvkBuffer( + DxvkDevice* device, + const DxvkBufferCreateInfo& createInfo, + const DxvkBufferImportInfo& importInfo, + VkMemoryPropertyFlags memFlags); + ~DxvkBuffer(); /** @@ -294,10 +316,19 @@ namespace dxvk { m_nextSlices.push_back(slice); } + /** + * \brief Checks whether the buffer is imported + * \returns \c true if the buffer is imported + */ + bool isForeign() const { + return m_import.buffer != VK_NULL_HANDLE; + } + private: Rc m_vkd; DxvkBufferCreateInfo m_info; + DxvkBufferImportInfo m_import; DxvkMemoryAllocator* m_memAlloc; VkMemoryPropertyFlags m_memFlags; VkShaderStageFlags m_shaderStages; diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index dce568a5..18138b4b 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -6155,6 +6155,10 @@ namespace dxvk { if (buffer->info().flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) return false; + // Don't discard imported buffers + if (buffer->isForeign()) + return false; + // Suspend the current render pass if transform feedback is active prior to // invalidating the buffer, since otherwise we may invalidate a bound buffer. if ((buffer->info().usage & VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT)