]> git.tdb.fi Git - libs/gl.git/blob - source/backends/vulkan/memoryallocator.h
Avoid allocating buffers and images too close together
[libs/gl.git] / source / backends / vulkan / memoryallocator.h
1 #ifndef MSP_GL_VULKAN_MEMORYALLOCATOR_H_
2 #define MSP_GL_VULKAN_MEMORYALLOCATOR_H_
3
4 #include <vector>
5 #include <msp/core/noncopyable.h>
6 #include <msp/graphics/vulkancontext.h>
7 #include "handles.h"
8
9 namespace Msp {
10 namespace GL {
11
12 class Device;
13
14 enum MemoryType
15 {
16         UNKNOWN_MEMORY,
17         DEVICE_MEMORY,
18         STAGING_MEMORY,
19         STREAMING_MEMORY
20 };
21
22 class MemoryAllocator: public NonCopyable
23 {
24 private:
25         enum BlockType
26         {
27                 UNDECIDED,
28                 BUFFER,
29                 IMAGE
30         };
31
32         struct Pool
33         {
34                 MemoryType type = UNKNOWN_MEMORY;
35                 std::vector<unsigned> free_blocks;
36                 int largest_free_buffer = -1;
37                 int largest_free_image = -1;
38                 bool can_consolidate = false;
39         };
40
41         struct Region
42         {
43                 int pool = -1;
44                 bool direct = false;
45                 VkDeviceMemory memory = 0;
46                 std::size_t size = 0;
47                 void *mapped_address = 0;
48                 unsigned map_count = 0;
49         };
50
51         struct Block
52         {
53                 int region = -1;
54                 bool allocated = false;
55                 BlockType type = UNDECIDED;
56                 std::size_t offset = 0;
57                 std::size_t size = 0;
58                 int prev = -1;
59                 int next = -1;
60         };
61
62         Device &device;
63         VkPhysicalDevice phys_device;
64         std::size_t total_device_memory = 0;
65         std::size_t default_region_size = 0;
66         std::size_t direct_alloc_threshold = 0;
67         std::size_t min_alignment = 256;
68         std::size_t buffer_image_granularity = 131072;
69         std::vector<Pool> pools;
70         std::vector<Region> regions;
71         std::vector<Block> blocks;
72
73 public:
74         MemoryAllocator(Device &);
75         ~MemoryAllocator();
76
77 private:
78         unsigned find_memory_pool(unsigned, MemoryType) const;
79         unsigned create_region(unsigned, size_t, bool);
80         std::vector<unsigned>::iterator lower_bound_by_size(std::vector<unsigned> &, std::size_t) const;
81         std::size_t get_alloc_offset(const Block &, std::size_t, std::size_t, BlockType) const;
82         void update_largest_free(Pool &);
83         unsigned allocate(std::size_t, std::size_t, unsigned, MemoryType, BlockType);
84         unsigned split_block(unsigned, std::size_t);
85         void consolidate(unsigned);
86         void merge_block_with_next(unsigned);
87
88 public:
89         unsigned allocate(VkBuffer, MemoryType);
90         unsigned allocate(VkImage, MemoryType);
91         void release(unsigned);
92
93         void *map(unsigned);
94         void unmap(unsigned);
95
96         std::string get_debug() const;
97 };
98
99 } // namespace GL
100 } // namespace Msp
101
102 #endif