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:
parent
901861c20b
commit
ab557a2eed
@ -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,10 +88,13 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
DxvkBuffer::~DxvkBuffer() {
|
DxvkBuffer::~DxvkBuffer() {
|
||||||
for (const auto& buffer : m_buffers)
|
for (const auto& buffer : m_buffers) {
|
||||||
m_vkd->vkDestroyBuffer(m_vkd->device(), buffer.buffer, nullptr);
|
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;
|
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 (m_vkd->vkBindBufferMemory(m_vkd->device(), handle.buffer,
|
if (!handle.buffer && (!handle.memory.buffer() || (handle.memory.getBufferUsage() & info.usage) != info.usage))
|
||||||
handle.memory.memory(), handle.memory.offset()) != VK_SUCCESS)
|
handle.buffer = createBuffer(info);
|
||||||
throw DxvkError("DxvkBuffer: Failed to bind device memory");
|
|
||||||
|
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))
|
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();
|
||||||
|
|
||||||
|
@ -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
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user