1 #include <msp/core/algorithm.h>
2 #include <msp/graphics/vulkancontext_platform.h>
5 #include "memoryallocator.h"
13 MemoryAllocator::MemoryAllocator(Device &d):
15 phys_device(handle_cast<VkPhysicalDevice>(device.get_context().get_private().physical_device))
17 const VulkanFunctions &vk = device.get_functions();
19 VkPhysicalDeviceMemoryProperties mem_props;
20 vk.GetPhysicalDeviceMemoryProperties(mem_props);
22 const VkMemoryPropertyFlags host_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
23 memory_types.reserve(mem_props.memoryTypeCount);
24 for(unsigned i=0; i<mem_props.memoryTypeCount; ++i)
26 VkMemoryPropertyFlags flags = mem_props.memoryTypes[i].propertyFlags;
27 MemoryType type = UNKNOWN_MEMORY;
28 if(flags&VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
30 if((flags&host_flags)==host_flags)
31 type = STREAMING_MEMORY;
35 else if((flags&host_flags)==host_flags)
36 type = STAGING_MEMORY;
37 memory_types.push_back(type);
41 unsigned MemoryAllocator::find_memory_type_index(unsigned mask, MemoryType type)
43 for(unsigned i=0; i<memory_types.size(); ++i)
44 if((mask&(1<<i)) && memory_types[i]==type)
46 if(type==DEVICE_MEMORY || type==STAGING_MEMORY)
47 return find_memory_type_index(mask, STREAMING_MEMORY);
48 throw runtime_error("Unable to find suitable memory type");
51 unsigned MemoryAllocator::allocate(size_t size, unsigned type_bits, MemoryType type)
53 const VulkanFunctions &vk = device.get_functions();
55 VkMemoryAllocateInfo alloc_info = { };
56 alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
57 alloc_info.allocationSize = size;
58 alloc_info.memoryTypeIndex = find_memory_type_index(type_bits, type);
61 vk.AllocateMemory(alloc_info, alloc.memory);
65 allocations.push_back(alloc);
67 return allocations.size();
70 MemoryAllocator::Allocation &MemoryAllocator::get_allocation(unsigned id)
72 return allocations[id-1];
75 const MemoryAllocator::Allocation &MemoryAllocator::get_allocation(unsigned id) const
77 return allocations[id-1];
80 unsigned MemoryAllocator::allocate(VkBuffer buffer, MemoryType type)
82 const VulkanFunctions &vk = device.get_functions();
84 VkMemoryRequirements requirements;
85 vk.GetBufferMemoryRequirements(buffer, requirements);
87 unsigned id = allocate(requirements.size, requirements.memoryTypeBits, type);
89 vk.BindBufferMemory(buffer, get_allocation(id).memory, 0);
94 void MemoryAllocator::release(unsigned id)
96 Allocation &alloc = get_allocation(id);
98 throw invalid_operation("MemoryAllocator::release");
100 const VulkanFunctions &vk = device.get_functions();
102 vk.FreeMemory(alloc.memory);
105 size_t MemoryAllocator::get_allocation_size(unsigned id) const
107 return get_allocation(id).size;
110 void *MemoryAllocator::map(unsigned id, size_t offset, size_t size)
112 Allocation &alloc = get_allocation(id);
113 if(alloc.mapped_address)
114 throw invalid_operation("MemoryAllocator::map");
116 const VulkanFunctions &vk = device.get_functions();
118 vk.MapMemory(alloc.memory, offset, size, 0, &alloc.mapped_address);
120 return alloc.mapped_address;
123 void MemoryAllocator::unmap(void *ptr)
125 auto i = find_member(allocations, ptr, &Allocation::mapped_address);
126 if(i==allocations.end())
127 throw invalid_operation("MemoryAllocator::unmap");
129 const VulkanFunctions &vk = device.get_functions();
131 vk.UnmapMemory(i->memory);
132 i->mapped_address = 0;