1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-02 19:24:12 +01:00

[dxvk] Use global buffer whenever possible

Drastically reduces the number of Vulkan buffer objects allocated.
This commit is contained in:
Philip Rebohle 2024-09-13 13:17:36 +02:00
parent 901861c20b
commit ab557a2eed
2 changed files with 46 additions and 43 deletions

View File

@ -37,7 +37,7 @@ namespace dxvk {
m_buffer = allocBuffer(m_physSliceCount, m_physSliceCount > 1); m_buffer = allocBuffer(m_physSliceCount, m_physSliceCount > 1);
m_physSlice.handle = m_buffer.buffer; m_physSlice.handle = m_buffer.buffer;
m_physSlice.offset = 0; m_physSlice.offset = m_buffer.getBaseOffset();
m_physSlice.length = m_physSliceLength; m_physSlice.length = m_physSliceLength;
m_physSlice.mapPtr = m_buffer.memory.mapPtr(0); m_physSlice.mapPtr = m_buffer.memory.mapPtr(0);
@ -88,9 +88,12 @@ namespace dxvk {
DxvkBuffer::~DxvkBuffer() { DxvkBuffer::~DxvkBuffer() {
for (const auto& buffer : m_buffers) for (const auto& buffer : m_buffers) {
if (buffer.buffer != buffer.memory.buffer())
m_vkd->vkDestroyBuffer(m_vkd->device(), buffer.buffer, nullptr); m_vkd->vkDestroyBuffer(m_vkd->device(), buffer.buffer, nullptr);
}
if (m_buffer.buffer != m_buffer.memory.buffer())
m_vkd->vkDestroyBuffer(m_vkd->device(), m_buffer.buffer, nullptr); m_vkd->vkDestroyBuffer(m_vkd->device(), m_buffer.buffer, nullptr);
} }
@ -104,31 +107,21 @@ namespace dxvk {
DxvkBufferHandle handle; DxvkBufferHandle handle;
if (m_vkd->vkCreateBuffer(m_vkd->device(), &info, nullptr, &handle.buffer)) {
throw DxvkError(str::format(
"DxvkBuffer: Failed to create buffer:"
"\n flags: ", std::hex, info.flags,
"\n size: ", std::dec, info.size,
"\n usage: ", std::hex, info.usage));
}
// Query memory requirements and whether to use a dedicated allocation // Query memory requirements and whether to use a dedicated allocation
DxvkMemoryRequirements memoryRequirements = { }; DxvkMemoryRequirements memoryRequirements = { };
memoryRequirements.tiling = VK_IMAGE_TILING_LINEAR; memoryRequirements.tiling = VK_IMAGE_TILING_LINEAR;
memoryRequirements.dedicated = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS }; memoryRequirements.dedicated = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS };
memoryRequirements.core = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, &memoryRequirements.dedicated }; memoryRequirements.core = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, &memoryRequirements.dedicated };
VkBufferMemoryRequirementsInfo2 memoryRequirementInfo = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2 }; m_memAlloc->getBufferMemoryRequirements(info, memoryRequirements.core);
memoryRequirementInfo.buffer = handle.buffer;
m_vkd->vkGetBufferMemoryRequirements2(m_vkd->device(),
&memoryRequirementInfo, &memoryRequirements.core);
// Fill in desired memory properties // Fill in desired memory properties
DxvkMemoryProperties memoryProperties = { }; DxvkMemoryProperties memoryProperties = { };
memoryProperties.flags = m_memFlags; memoryProperties.flags = m_memFlags;
if (memoryRequirements.dedicated.prefersDedicatedAllocation) { if (memoryRequirements.dedicated.prefersDedicatedAllocation) {
handle.buffer = createBuffer(info);
memoryProperties.dedicated = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO }; memoryProperties.dedicated = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO };
memoryProperties.dedicated.buffer = handle.buffer; memoryProperties.dedicated.buffer = handle.buffer;
} }
@ -152,9 +145,16 @@ namespace dxvk {
handle.memory = m_memAlloc->alloc(memoryRequirements, memoryProperties, hints); handle.memory = m_memAlloc->alloc(memoryRequirements, memoryProperties, hints);
if (!handle.buffer && (!handle.memory.buffer() || (handle.memory.getBufferUsage() & info.usage) != info.usage))
handle.buffer = createBuffer(info);
if (handle.buffer) {
if (m_vkd->vkBindBufferMemory(m_vkd->device(), handle.buffer, if (m_vkd->vkBindBufferMemory(m_vkd->device(), handle.buffer,
handle.memory.memory(), handle.memory.offset()) != VK_SUCCESS) handle.memory.memory(), handle.memory.offset()) != VK_SUCCESS)
throw DxvkError("DxvkBuffer: Failed to bind device memory"); throw DxvkError("DxvkBuffer: Failed to bind device memory");
} else {
handle.buffer = handle.memory.buffer();
}
if (clear && (m_memFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) if (clear && (m_memFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT))
std::memset(handle.memory.mapPtr(0), 0, info.size); std::memset(handle.memory.mapPtr(0), 0, info.size);
@ -185,6 +185,21 @@ namespace dxvk {
} }
VkBuffer DxvkBuffer::createBuffer(const VkBufferCreateInfo& info) const {
VkBuffer buffer = VK_NULL_HANDLE;
if (m_vkd->vkCreateBuffer(m_vkd->device(), &info, nullptr, &buffer)) {
throw DxvkError(str::format(
"DxvkBuffer: Failed to create buffer:"
"\n flags: ", std::hex, info.flags,
"\n size: ", std::dec, info.size,
"\n usage: ", std::hex, info.usage));
}
return buffer;
}
VkDeviceSize DxvkBuffer::computeSliceAlignment(DxvkDevice* device) const { VkDeviceSize DxvkBuffer::computeSliceAlignment(DxvkDevice* device) const {
const auto& devInfo = device->properties(); const auto& devInfo = device->properties();

View File

@ -80,6 +80,12 @@ namespace dxvk {
struct DxvkBufferHandle { struct DxvkBufferHandle {
VkBuffer buffer = VK_NULL_HANDLE; VkBuffer buffer = VK_NULL_HANDLE;
DxvkMemory memory; DxvkMemory memory;
VkDeviceSize getBaseOffset() const {
return buffer == memory.buffer()
? memory.offset()
: 0u;
}
}; };
@ -218,16 +224,6 @@ namespace dxvk {
return result; return result;
} }
/**
* \brief Retrieves dynamic offset
*
* \param [in] offset Offset into the buffer
* \returns Offset for dynamic descriptors
*/
VkDeviceSize getDynamicOffset(VkDeviceSize offset) const {
return m_physSlice.offset + offset;
}
/** /**
* \brief Replaces backing resource * \brief Replaces backing resource
* *
@ -356,9 +352,9 @@ namespace dxvk {
void pushSlice(const DxvkBufferHandle& handle, uint32_t index) { void pushSlice(const DxvkBufferHandle& handle, uint32_t index) {
DxvkBufferSliceHandle slice; DxvkBufferSliceHandle slice;
slice.handle = handle.buffer; slice.handle = handle.buffer;
slice.offset = handle.getBaseOffset() + m_physSliceStride * index;
slice.length = m_physSliceLength; slice.length = m_physSliceLength;
slice.offset = m_physSliceStride * index; slice.mapPtr = handle.memory.mapPtr(m_physSliceStride * index);
slice.mapPtr = handle.memory.mapPtr(slice.offset);
m_freeSlices.push_back(slice); m_freeSlices.push_back(slice);
} }
@ -368,6 +364,8 @@ namespace dxvk {
DxvkBufferHandle createSparseBuffer() const; DxvkBufferHandle createSparseBuffer() const;
VkBuffer createBuffer(const VkBufferCreateInfo& info) const;
VkDeviceSize computeSliceAlignment( VkDeviceSize computeSliceAlignment(
DxvkDevice* device) const; DxvkDevice* device) const;
@ -495,16 +493,6 @@ namespace dxvk {
return m_buffer->getDescriptor(m_offset, m_length); return m_buffer->getDescriptor(m_offset, m_length);
} }
/**
* \brief Retrieves dynamic offset
*
* Used for descriptor set binding.
* \returns Buffer slice offset
*/
VkDeviceSize getDynamicOffset() const {
return m_buffer->getDynamicOffset(m_offset);
}
/** /**
* \brief Pointer to mapped memory region * \brief Pointer to mapped memory region
* *