kiba-engine
allocator.c
1 #include <kiba/renderer/vulkan/allocator.h>
2 
3 #include <kiba/core/log.h>
4 #include <kiba/core/memory.h>
5 
6 // TODO: think about the allocation scopes. Allocations that will be forgotten quickly could use a simpler allocator
7 // like the linear one. After the scope finished, the allocator could be reset instead of individually freeing the
8 // memory.
9 
10 const char *vulkan_allocation_scope_names[] = {
11  "VK_SYSTEM_ALLOCATION_SCOPE_COMMAND",
12  "VK_SYSTEM_ALLOCATION_SCOPE_OBJECT",
13  "VK_SYSTEM_ALLOCATION_SCOPE_CACHE",
14  "VK_SYSTEM_ALLOCATION_SCOPE_DEVICE",
15  "VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE",
16 };
17 
18 void *vulkan_allocation_function(void *pUserData,
19  size_t size,
20  size_t alignment,
21  VkSystemAllocationScope allocationScope);
22 
23 void vulkan_free_function(void *pUserData, void *pMemory);
24 
25 void vulkan_internal_allocation_notification(void *pUserData,
26  size_t size,
27  VkInternalAllocationType allocationType,
28  VkSystemAllocationScope allocationScope);
29 
30 void vulkan_internal_free_notification(void *pUserData,
31  size_t size,
32  VkInternalAllocationType allocationType,
33  VkSystemAllocationScope allocationScope);
34 
35 void *vulkan_reallocation_function(void *pUserData,
36  void *pOriginal,
37  size_t size,
38  size_t alignment,
39  VkSystemAllocationScope allocationScope);
40 
41 b8 vulkan_allocator_create(vulkan_allocator *alloc) {
42  if (!allocator_create(&alloc->kiba_alloc, ALLOCATOR_FREE_LIST, 2048)) {
43  KB_ERROR("could not create kiba allocator for vulkan allocator");
44  return false;
45  }
46 
47  alloc->vulkan_callbacks.pUserData = alloc;
48  alloc->vulkan_callbacks.pfnAllocation = vulkan_allocation_function;
49  alloc->vulkan_callbacks.pfnFree = vulkan_free_function;
50  alloc->vulkan_callbacks.pfnInternalAllocation = vulkan_internal_allocation_notification;
51  alloc->vulkan_callbacks.pfnInternalFree = vulkan_internal_free_notification;
52  alloc->vulkan_callbacks.pfnReallocation = vulkan_reallocation_function;
53  return true;
54 }
55 
56 void vulkan_allocator_destroy(vulkan_allocator *alloc) {
57  alloc->vulkan_callbacks.pUserData = KB_NULL;
58  alloc->vulkan_callbacks.pfnAllocation = KB_NULL;
59  alloc->vulkan_callbacks.pfnFree = KB_NULL;
60  alloc->vulkan_callbacks.pfnInternalAllocation = KB_NULL;
61  alloc->vulkan_callbacks.pfnInternalFree = KB_NULL;
62  alloc->vulkan_callbacks.pfnReallocation = KB_NULL;
63  allocator_destroy(&alloc->kiba_alloc);
64 }
65 
66 void *vulkan_allocation_function(void *pUserData,
67  size_t size,
68  size_t alignment,
69  VkSystemAllocationScope allocationScope) {
70  UNUSED(allocationScope);
71  KB_TRACE("vulkan allocating {usize} bytes aligned to {usize} with scope {raw_string}",
72  size,
73  alignment,
74  vulkan_allocation_scope_names[allocationScope]);
75  vulkan_allocator *alloc = pUserData;
76  void *ret = allocator_allocate_aligned(&alloc->kiba_alloc, size, alignment);
77  uptr misalignment = (uptr) ret % alignment;
78  KB_ASSERT(misalignment == 0, "allcation must be aligned as requested");
79  return ret;
80 }
81 
82 void vulkan_free_function(void *pUserData, void *pMemory) {
83  KB_TRACE("vulkan freeing {pointer}", pMemory);
84  vulkan_allocator *alloc = pUserData;
85  if (pMemory != KB_NULL) {
86  allocator_free(&alloc->kiba_alloc, pMemory);
87  }
88 }
89 
90 void vulkan_internal_allocation_notification(void *pUserData,
91  size_t size,
92  VkInternalAllocationType allocationType,
93  VkSystemAllocationScope allocationScope) {
94  UNUSED(pUserData);
95  UNUSED(size);
96  UNUSED(allocationType);
97  UNUSED(allocationScope);
98  KB_DEBUG("vulkan allocating {usize} bytes of type {u32} with scope {raw_string}",
99  size,
100  allocationType,
101  vulkan_allocation_scope_names[allocationScope]);
102 }
103 
104 void vulkan_internal_free_notification(void *pUserData,
105  size_t size,
106  VkInternalAllocationType allocationType,
107  VkSystemAllocationScope allocationScope) {
108  UNUSED(pUserData);
109  UNUSED(size);
110  UNUSED(allocationType);
111  UNUSED(allocationScope);
112  KB_DEBUG("vulkan freeing {usize} bytes of type {u32} with scope {raw_string}",
113  size,
114  allocationType,
115  vulkan_allocation_scope_names[allocationScope]);
116 }
117 
118 void *vulkan_reallocation_function(void *pUserData,
119  void *pOriginal,
120  size_t size,
121  size_t alignment,
122  VkSystemAllocationScope allocationScope) {
123  UNUSED(allocationScope);
124  KB_TRACE("vulkan reallocating {pointer} to {usize} bytes aligned to {usize} with scope {raw_string}",
125  pOriginal,
126  size,
127  alignment,
128  vulkan_allocation_scope_names[allocationScope]);
129  vulkan_allocator *alloc = pUserData;
130 
131  if (pOriginal == KB_NULL) {
132  return vulkan_allocation_function(pUserData, size, alignment, allocationScope);
133  }
134  if (size == 0) {
135  vulkan_free_function(pUserData, pOriginal);
136  return 0;
137  }
138  void *ret = allocator_reallocate_aligned(&alloc->kiba_alloc, pOriginal, size, alignment);
139  uptr misalignment = (uptr) ret % alignment;
140  KB_ASSERT(misalignment == 0, "reallcation must be aligned as requested");
141  return ret;
142 }
void * allocator_allocate_aligned(allocator *alloc, usize size, usize alignment)
Allocate aligned memory.
Definition: allocator.c:94
void allocator_free(allocator *alloc, void *mem)
Give back memory to the allocator.
Definition: allocator.c:134
b8 allocator_create(allocator *alloc, allocator_type type, usize size)
Create an allocator of a specific type.
Definition: allocator.c:66
void allocator_destroy(allocator *alloc)
Destroy an allocator.
Definition: allocator.c:84
void * allocator_reallocate_aligned(allocator *alloc, void *original, usize new_size, usize alignment)
Rellocate aligned memory.
Definition: allocator.c:111
Lightweight layer between platform and other engine components to enable tracing/monitoring.
#define UNUSED(x)
Mark parameter as unused.
Definition: defines.h:21
#define KB_NULL
Value of an invalid ptr (nullptr).
Definition: defines.h:18
Logging system.
#define KB_DEBUG(...)
Log entry with debug log level.
Definition: log.h:163
#define KB_ASSERT(expr,...)
Perform runtime assertion and log failures.
Definition: log.h:133
#define KB_ERROR(...)
Log entry with error log level.
Definition: log.h:142
#define KB_TRACE(...)
Log entry with trace log level.
Definition: log.h:164