vk_stream_buf: Allow dedicated allocations (#7103)
* vk_stream_buf: Avoid protected memory heaps * Add an "Exclude" argument when finding a memory-type that avoids `VK_MEMORY_PROPERTY_PROTECTED_BIT` by default * vk_stream_buf: Utilize dedicated allocations when preferred by driver `VK_KHR_dedicated_allocation` is part of the core Vulkan 1.1 specification and should be utilized when `prefersDedicatedAllocation` is set.
This commit is contained in:
parent
998b9a9525
commit
1cf64ffaef
1 changed files with 33 additions and 11 deletions
|
@ -44,11 +44,12 @@ vk::MemoryPropertyFlags MakePropertyFlags(BufferType type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find a memory type with the passed requirements
|
/// Find a memory type with the passed requirements
|
||||||
std::optional<u32> FindMemoryType(const vk::PhysicalDeviceMemoryProperties& properties,
|
std::optional<u32> FindMemoryType(
|
||||||
vk::MemoryPropertyFlags wanted) {
|
const vk::PhysicalDeviceMemoryProperties& properties, vk::MemoryPropertyFlags wanted,
|
||||||
|
vk::MemoryPropertyFlags excluded = vk::MemoryPropertyFlagBits::eProtected) {
|
||||||
for (u32 i = 0; i < properties.memoryTypeCount; ++i) {
|
for (u32 i = 0; i < properties.memoryTypeCount; ++i) {
|
||||||
const auto flags = properties.memoryTypes[i].propertyFlags;
|
const auto flags = properties.memoryTypes[i].propertyFlags;
|
||||||
if ((flags & wanted) == wanted) {
|
if (((flags & wanted) == wanted) && (!(flags & excluded))) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -166,25 +167,46 @@ void StreamBuffer::CreateBuffers(u64 prefered_size) {
|
||||||
static_cast<bool>(mem_type.propertyFlags & vk::MemoryPropertyFlagBits::eHostCoherent);
|
static_cast<bool>(mem_type.propertyFlags & vk::MemoryPropertyFlagBits::eHostCoherent);
|
||||||
|
|
||||||
// Substract from the preferred heap size some bytes to avoid getting out of memory.
|
// Substract from the preferred heap size some bytes to avoid getting out of memory.
|
||||||
const VkDeviceSize heap_size = memory_properties.memoryHeaps[preferred_heap].size;
|
const vk::DeviceSize heap_size = memory_properties.memoryHeaps[preferred_heap].size;
|
||||||
// As per DXVK's example, using `heap_size / 2`
|
// As per DXVK's example, using `heap_size / 2`
|
||||||
const VkDeviceSize allocable_size = heap_size / 2;
|
const vk::DeviceSize allocable_size = heap_size / 2;
|
||||||
buffer = device.createBuffer({
|
buffer = device.createBuffer({
|
||||||
.size = std::min(prefered_size, allocable_size),
|
.size = std::min(prefered_size, allocable_size),
|
||||||
.usage = usage,
|
.usage = usage,
|
||||||
});
|
});
|
||||||
|
|
||||||
const auto requirements = device.getBufferMemoryRequirements(buffer);
|
const auto requirements_chain =
|
||||||
stream_buffer_size = static_cast<u64>(requirements.size);
|
device
|
||||||
|
.getBufferMemoryRequirements2<vk::MemoryRequirements2, vk::MemoryDedicatedRequirements>(
|
||||||
|
{.buffer = buffer});
|
||||||
|
|
||||||
|
const auto& requirements = requirements_chain.get<vk::MemoryRequirements2>();
|
||||||
|
const auto& dedicated_requirements = requirements_chain.get<vk::MemoryDedicatedRequirements>();
|
||||||
|
|
||||||
|
stream_buffer_size = static_cast<u64>(requirements.memoryRequirements.size);
|
||||||
|
|
||||||
LOG_INFO(Render_Vulkan, "Creating {} buffer with size {} KB with flags {}",
|
LOG_INFO(Render_Vulkan, "Creating {} buffer with size {} KB with flags {}",
|
||||||
BufferTypeName(type), stream_buffer_size / 1024,
|
BufferTypeName(type), stream_buffer_size / 1024,
|
||||||
vk::to_string(mem_type.propertyFlags));
|
vk::to_string(mem_type.propertyFlags));
|
||||||
|
|
||||||
memory = device.allocateMemory({
|
if (dedicated_requirements.prefersDedicatedAllocation) {
|
||||||
.allocationSize = requirements.size,
|
vk::StructureChain<vk::MemoryAllocateInfo, vk::MemoryDedicatedAllocateInfo> alloc_chain =
|
||||||
.memoryTypeIndex = preferred_type,
|
{};
|
||||||
});
|
|
||||||
|
auto& alloc_info = alloc_chain.get<vk::MemoryAllocateInfo>();
|
||||||
|
alloc_info.allocationSize = requirements.memoryRequirements.size;
|
||||||
|
alloc_info.memoryTypeIndex = preferred_type;
|
||||||
|
|
||||||
|
auto& dedicated_alloc_info = alloc_chain.get<vk::MemoryDedicatedAllocateInfo>();
|
||||||
|
dedicated_alloc_info.buffer = buffer;
|
||||||
|
|
||||||
|
memory = device.allocateMemory(alloc_chain.get());
|
||||||
|
} else {
|
||||||
|
memory = device.allocateMemory({
|
||||||
|
.allocationSize = requirements.memoryRequirements.size,
|
||||||
|
.memoryTypeIndex = preferred_type,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
device.bindBufferMemory(buffer, memory, 0);
|
device.bindBufferMemory(buffer, memory, 0);
|
||||||
mapped = reinterpret_cast<u8*>(device.mapMemory(memory, 0, VK_WHOLE_SIZE));
|
mapped = reinterpret_cast<u8*>(device.mapMemory(memory, 0, VK_WHOLE_SIZE));
|
||||||
|
|
Loading…
Reference in a new issue