1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-02 10: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_physSlice.handle = m_buffer.buffer;
m_physSlice.offset = 0;
m_physSlice.offset = m_buffer.getBaseOffset();
m_physSlice.length = m_physSliceLength;
m_physSlice.mapPtr = m_buffer.memory.mapPtr(0);
@ -88,10 +88,13 @@ namespace dxvk {
DxvkBuffer::~DxvkBuffer() {
for (const auto& buffer : m_buffers)
m_vkd->vkDestroyBuffer(m_vkd->device(), buffer.buffer, nullptr);
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(), m_buffer.buffer, nullptr);
if (m_buffer.buffer != m_buffer.memory.buffer())
m_vkd->vkDestroyBuffer(m_vkd->device(), m_buffer.buffer, nullptr);
}
@ -104,31 +107,21 @@ namespace dxvk {
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
DxvkMemoryRequirements memoryRequirements = { };
memoryRequirements.tiling = VK_IMAGE_TILING_LINEAR;
memoryRequirements.dedicated = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS };
memoryRequirements.core = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, &memoryRequirements.dedicated };
VkBufferMemoryRequirementsInfo2 memoryRequirementInfo = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2 };
memoryRequirementInfo.buffer = handle.buffer;
m_vkd->vkGetBufferMemoryRequirements2(m_vkd->device(),
&memoryRequirementInfo, &memoryRequirements.core);
m_memAlloc->getBufferMemoryRequirements(info, memoryRequirements.core);
// Fill in desired memory properties
DxvkMemoryProperties memoryProperties = { };
memoryProperties.flags = m_memFlags;
if (memoryRequirements.dedicated.prefersDedicatedAllocation) {
handle.buffer = createBuffer(info);
memoryProperties.dedicated = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO };
memoryProperties.dedicated.buffer = handle.buffer;
}
@ -151,10 +144,17 @@ namespace dxvk {
hints.set(DxvkMemoryFlag::Transient);
handle.memory = m_memAlloc->alloc(memoryRequirements, memoryProperties, hints);
if (m_vkd->vkBindBufferMemory(m_vkd->device(), handle.buffer,
handle.memory.memory(), handle.memory.offset()) != VK_SUCCESS)
throw DxvkError("DxvkBuffer: Failed to bind device memory");
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,
handle.memory.memory(), handle.memory.offset()) != VK_SUCCESS)
throw DxvkError("DxvkBuffer: Failed to bind device memory");
} else {
handle.buffer = handle.memory.buffer();
}
if (clear && (m_memFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT))
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 {
const auto& devInfo = device->properties();

View File

@ -80,6 +80,12 @@ namespace dxvk {
struct DxvkBufferHandle {
VkBuffer buffer = VK_NULL_HANDLE;
DxvkMemory memory;
VkDeviceSize getBaseOffset() const {
return buffer == memory.buffer()
? memory.offset()
: 0u;
}
};
@ -218,16 +224,6 @@ namespace dxvk {
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
*
@ -356,9 +352,9 @@ namespace dxvk {
void pushSlice(const DxvkBufferHandle& handle, uint32_t index) {
DxvkBufferSliceHandle slice;
slice.handle = handle.buffer;
slice.offset = handle.getBaseOffset() + m_physSliceStride * index;
slice.length = m_physSliceLength;
slice.offset = m_physSliceStride * index;
slice.mapPtr = handle.memory.mapPtr(slice.offset);
slice.mapPtr = handle.memory.mapPtr(m_physSliceStride * index);
m_freeSlices.push_back(slice);
}
@ -368,6 +364,8 @@ namespace dxvk {
DxvkBufferHandle createSparseBuffer() const;
VkBuffer createBuffer(const VkBufferCreateInfo& info) const;
VkDeviceSize computeSliceAlignment(
DxvkDevice* device) const;
@ -494,16 +492,6 @@ namespace dxvk {
DxvkDescriptorInfo getDescriptor() const {
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