mirror of
https://github.com/citra-emu/citra-canary.git
synced 2024-12-22 18:05:28 +00:00
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
|
@ -44,11 +44,12 @@ vk::MemoryPropertyFlags MakePropertyFlags(BufferType type) {
|
|||
}
|
||||
|
||||
/// Find a memory type with the passed requirements
|
||||
std::optional<u32> FindMemoryType(const vk::PhysicalDeviceMemoryProperties& properties,
|
||||
vk::MemoryPropertyFlags wanted) {
|
||||
std::optional<u32> FindMemoryType(
|
||||
const vk::PhysicalDeviceMemoryProperties& properties, vk::MemoryPropertyFlags wanted,
|
||||
vk::MemoryPropertyFlags excluded = vk::MemoryPropertyFlagBits::eProtected) {
|
||||
for (u32 i = 0; i < properties.memoryTypeCount; ++i) {
|
||||
const auto flags = properties.memoryTypes[i].propertyFlags;
|
||||
if ((flags & wanted) == wanted) {
|
||||
if (((flags & wanted) == wanted) && (!(flags & excluded))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
@ -166,25 +167,46 @@ void StreamBuffer::CreateBuffers(u64 prefered_size) {
|
|||
static_cast<bool>(mem_type.propertyFlags & vk::MemoryPropertyFlagBits::eHostCoherent);
|
||||
|
||||
// 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`
|
||||
const VkDeviceSize allocable_size = heap_size / 2;
|
||||
const vk::DeviceSize allocable_size = heap_size / 2;
|
||||
buffer = device.createBuffer({
|
||||
.size = std::min(prefered_size, allocable_size),
|
||||
.usage = usage,
|
||||
});
|
||||
|
||||
const auto requirements = device.getBufferMemoryRequirements(buffer);
|
||||
stream_buffer_size = static_cast<u64>(requirements.size);
|
||||
const auto requirements_chain =
|
||||
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 {}",
|
||||
BufferTypeName(type), stream_buffer_size / 1024,
|
||||
vk::to_string(mem_type.propertyFlags));
|
||||
|
||||
memory = device.allocateMemory({
|
||||
.allocationSize = requirements.size,
|
||||
.memoryTypeIndex = preferred_type,
|
||||
});
|
||||
if (dedicated_requirements.prefersDedicatedAllocation) {
|
||||
vk::StructureChain<vk::MemoryAllocateInfo, vk::MemoryDedicatedAllocateInfo> alloc_chain =
|
||||
{};
|
||||
|
||||
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);
|
||||
mapped = reinterpret_cast<u8*>(device.mapMemory(memory, 0, VK_WHOLE_SIZE));
|
||||
|
|
Loading…
Reference in a new issue