1 #include <msp/core/algorithm.h>
2 #include <msp/core/maputils.h>
3 #include <msp/graphics/vulkancontext_platform.h>
6 #include "memoryallocator.h"
14 MemoryAllocator::MemoryAllocator(Device &d):
16 phys_device(handle_cast<VkPhysicalDevice>(device.get_context().get_private().physical_device))
18 const VulkanFunctions &vk = device.get_functions();
20 VkPhysicalDeviceMemoryProperties mem_props;
21 vk.GetPhysicalDeviceMemoryProperties(mem_props);
23 const VkMemoryPropertyFlags host_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
24 memory_types.reserve(mem_props.memoryTypeCount);
25 for(unsigned i=0; i<mem_props.memoryTypeCount; ++i)
27 VkMemoryPropertyFlags flags = mem_props.memoryTypes[i].propertyFlags;
28 MemoryType type = UNKNOWN_MEMORY;
29 if(flags&VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
31 if((flags&host_flags)==host_flags)
32 type = STREAMING_MEMORY;
36 else if((flags&host_flags)==host_flags)
37 type = STAGING_MEMORY;
38 memory_types.push_back(type);
42 unsigned MemoryAllocator::find_memory_type_index(unsigned mask, MemoryType type)
44 for(unsigned i=0; i<memory_types.size(); ++i)
45 if((mask&(1<<i)) && memory_types[i]==type)
47 if(type==DEVICE_MEMORY || type==STAGING_MEMORY)
48 return find_memory_type_index(mask, STREAMING_MEMORY);
49 throw runtime_error("Unable to find suitable memory type");
52 unsigned MemoryAllocator::allocate(size_t size, unsigned type_bits, MemoryType type)
54 const VulkanFunctions &vk = device.get_functions();
56 VkMemoryAllocateInfo alloc_info = { };
57 alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
58 alloc_info.allocationSize = size;
59 alloc_info.memoryTypeIndex = find_memory_type_index(type_bits, type);
62 vk.AllocateMemory(alloc_info, alloc.memory);
66 allocations.push_back(alloc);
68 return allocations.size()-1;
71 unsigned MemoryAllocator::allocate(VkBuffer buffer, MemoryType type)
73 const VulkanFunctions &vk = device.get_functions();
75 VkMemoryRequirements requirements;
76 vk.GetBufferMemoryRequirements(buffer, requirements);
78 unsigned index = allocate(requirements.size, requirements.memoryTypeBits, type);
80 vk.BindBufferMemory(buffer, allocations[index].memory, 0);
85 unsigned MemoryAllocator::allocate(VkImage image, MemoryType type)
87 const VulkanFunctions &vk = device.get_functions();
89 VkMemoryRequirements requirements;
90 vk.GetImageMemoryRequirements(image, requirements);
92 unsigned index = allocate(requirements.size, requirements.memoryTypeBits, type);
94 vk.BindImageMemory(image, allocations[index].memory, 0);
99 void MemoryAllocator::release(unsigned id)
101 if(!id || id>allocations.size() || !allocations[id-1].memory)
104 const VulkanFunctions &vk = device.get_functions();
106 vk.FreeMemory(allocations[id-1].memory);
109 void *MemoryAllocator::map(unsigned id)
111 if(!id || id>allocations.size() || !allocations[id-1].memory)
114 Allocation &alloc = allocations[id-1];
116 const VulkanFunctions &vk = device.get_functions();
118 vk.MapMemory(alloc.memory, 0, alloc.size, 0, &alloc.mapped_address);
120 return alloc.mapped_address;
123 void MemoryAllocator::unmap(unsigned id)
125 if(!id || id>allocations.size() || !allocations[id-1].memory)
128 Allocation &alloc = allocations[id-1];
129 if(!alloc.mapped_address)
130 throw invalid_operation("MemoryAllocator::unmap");
132 const VulkanFunctions &vk = device.get_functions();
134 vk.UnmapMemory(alloc.memory);
135 alloc.mapped_address = 0;