forked from KhronosGroup/Vulkan-Tutorial
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmemory_pool.h
More file actions
197 lines (173 loc) · 6.7 KB
/
memory_pool.h
File metadata and controls
197 lines (173 loc) · 6.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#pragma once
#include <vulkan/vulkan_raii.hpp>
#include <memory>
#include <vector>
#include <unordered_map>
#include <mutex>
#include <cstdint>
#include <utility>
/**
* @brief Memory pool allocator for Vulkan resources
*
* This class implements a memory pool system to reduce memory fragmentation
* and improve allocation performance by pre-allocating large chunks of memory
* and sub-allocating from them.
*/
class MemoryPool {
public:
/**
* @brief Types of memory pools based on usage patterns
*/
enum class PoolType {
VERTEX_BUFFER, // Device-local memory for vertex data
INDEX_BUFFER, // Device-local memory for index data
UNIFORM_BUFFER, // Host-visible memory for uniform data
STAGING_BUFFER, // Host-visible memory for staging operations
TEXTURE_IMAGE // Device-local memory for texture images
};
/**
* @brief Allocation information for a memory block
*/
struct Allocation {
vk::DeviceMemory memory; // The underlying device memory
vk::DeviceSize offset; // Offset within the memory block
vk::DeviceSize size; // Size of the allocation
uint32_t memoryTypeIndex; // Memory type index
bool isMapped; // Whether the memory is persistently mapped
void* mappedPtr; // Mapped pointer (if applicable)
};
/**
* @brief Memory block within a pool
*/
struct MemoryBlock {
vk::raii::DeviceMemory memory; // RAII wrapper for device memory
vk::DeviceSize size; // Total size of the block
vk::DeviceSize used; // Currently used bytes
uint32_t memoryTypeIndex; // Memory type index
bool isMapped; // Whether the block is mapped
void* mappedPtr; // Mapped pointer (if applicable)
std::vector<bool> freeList; // Free list for sub-allocations
vk::DeviceSize allocationUnit; // Size of each allocation unit
};
private:
const vk::raii::Device& device;
const vk::raii::PhysicalDevice& physicalDevice;
vk::PhysicalDeviceMemoryProperties memPropsCache{};
// Pool configurations
struct PoolConfig {
vk::DeviceSize blockSize; // Size of each memory block
vk::DeviceSize allocationUnit; // Minimum allocation unit
vk::MemoryPropertyFlags properties; // Memory properties
};
// Memory pools for different types
std::unordered_map<PoolType, std::vector<std::unique_ptr<MemoryBlock>>> pools;
std::unordered_map<PoolType, PoolConfig> poolConfigs;
// Thread safety
mutable std::mutex poolMutex;
// Optional rendering state flag (no allocation restrictions enforced)
bool renderingActive = false;
// Helper methods
uint32_t findMemoryType(uint32_t typeFilter, vk::MemoryPropertyFlags properties) const;
std::unique_ptr<MemoryBlock> createMemoryBlock(PoolType poolType, vk::DeviceSize size);
// Create a memory block with an explicit memory type index (used for images requiring a specific type)
std::unique_ptr<MemoryBlock> createMemoryBlockWithType(PoolType poolType, vk::DeviceSize size, uint32_t memoryTypeIndex);
std::pair<MemoryBlock*, size_t> findSuitableBlock(PoolType poolType, vk::DeviceSize size, vk::DeviceSize alignment);
public:
/**
* @brief Constructor
* @param device Vulkan device
* @param physicalDevice Vulkan physical device
*/
MemoryPool(const vk::raii::Device& device, const vk::raii::PhysicalDevice& physicalDevice);
/**
* @brief Destructor
*/
~MemoryPool();
/**
* @brief Initialize the memory pool with default configurations
* @return True if initialization was successful
*/
bool initialize();
/**
* @brief Allocate memory from a specific pool
* @param poolType Type of pool to allocate from
* @param size Size of the allocation
* @param alignment Required alignment
* @return Allocation information, or nullptr if allocation failed
*/
std::unique_ptr<Allocation> allocate(PoolType poolType, vk::DeviceSize size, vk::DeviceSize alignment = 1);
/**
* @brief Free a previously allocated memory block
* @param allocation The allocation to free
*/
void deallocate(std::unique_ptr<Allocation> allocation);
/**
* @brief Create a buffer using pooled memory
* @param size Size of the buffer
* @param usage Buffer usage flags
* @param properties Memory properties
* @return Pair of buffer and allocation info
*/
std::pair<vk::raii::Buffer, std::unique_ptr<Allocation>> createBuffer(
vk::DeviceSize size,
vk::BufferUsageFlags usage,
vk::MemoryPropertyFlags properties
);
/**
* @brief Create an image using pooled memory
* @param width Image width
* @param height Image height
* @param format Image format
* @param tiling Image tiling
* @param usage Image usage flags
* @param properties Memory properties
* @return Pair of image and allocation info
*/
std::pair<vk::raii::Image, std::unique_ptr<Allocation>> createImage(
uint32_t width,
uint32_t height,
vk::Format format,
vk::ImageTiling tiling,
vk::ImageUsageFlags usage,
vk::MemoryPropertyFlags properties
);
/**
* @brief Get memory usage statistics
* @param poolType Type of pool to query
* @return Pair of (used bytes, total bytes)
*/
std::pair<vk::DeviceSize, vk::DeviceSize> getMemoryUsage(PoolType poolType) const;
/**
* @brief Get total memory usage across all pools
* @return Pair of (used bytes, total bytes)
*/
std::pair<vk::DeviceSize, vk::DeviceSize> getTotalMemoryUsage() const;
/**
* @brief Configure a specific pool type
* @param poolType Type of pool to configure
* @param blockSize Size of each memory block
* @param allocationUnit Minimum allocation unit
* @param properties Memory properties
*/
void configurePool(
PoolType poolType,
vk::DeviceSize blockSize,
vk::DeviceSize allocationUnit,
vk::MemoryPropertyFlags properties
);
/**
* @brief Pre-allocate initial memory blocks for configured pools
* @return True if pre-allocation was successful
*/
bool preAllocatePools();
/**
* @brief Set rendering active state flag (informational only)
* @param active Whether rendering is currently active
*/
void setRenderingActive(bool active);
/**
* @brief Check if rendering is currently active (informational only)
* @return True if rendering is active
*/
bool isRenderingActive() const;
};