kiba-engine
allocator.c
1 #include <kiba/gpu/vulkan/allocator.h>
2 
3 #include <kiba/core/log.h>
4 #include <kiba/core/memory.h>
5 
6 struct vk_alloc vk_alloc = {0};
7 
8 // TODO: think about the allocation scopes. Allocations that will be forgotten quickly could use a simpler allocator
9 // like the linear one. After the scope finished, the allocator could be reset instead of individually freeing the
10 // memory.
11 
12 const char *vk_allocation_scope_names[] = {
13  "VK_SYSTEM_ALLOCATION_SCOPE_COMMAND",
14  "VK_SYSTEM_ALLOCATION_SCOPE_OBJECT",
15  "VK_SYSTEM_ALLOCATION_SCOPE_CACHE",
16  "VK_SYSTEM_ALLOCATION_SCOPE_DEVICE",
17  "VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE",
18 };
19 
20 void *vk_allocation_function(void *pUserData, size_t size, size_t alignment, VkSystemAllocationScope allocationScope);
21 
22 void vk_free_function(void *pUserData, void *pMemory);
23 
24 void vk_internal_allocation_notification(void *pUserData,
25  size_t size,
26  VkInternalAllocationType allocationType,
27  VkSystemAllocationScope allocationScope);
28 
29 void vk_internal_free_notification(void *pUserData,
30  size_t size,
31  VkInternalAllocationType allocationType,
32  VkSystemAllocationScope allocationScope);
33 
34 void *vk_reallocation_function(void *pUserData,
35  void *pOriginal,
36  size_t size,
37  size_t alignment,
38  VkSystemAllocationScope allocationScope);
39 
40 b8 vk_allocator_initialize(void) {
41  if (!allocator_create(&vk_alloc.kiba_alloc, ALLOCATOR_FREE_LIST, 2048)) {
42  KB_ERROR("could not create kiba allocator for vulkan allocator");
43  return false;
44  }
45 
46  vk_alloc.vulkan_callbacks.pUserData = &vk_alloc;
47  vk_alloc.vulkan_callbacks.pfnAllocation = vk_allocation_function;
48  vk_alloc.vulkan_callbacks.pfnFree = vk_free_function;
49  vk_alloc.vulkan_callbacks.pfnInternalAllocation = vk_internal_allocation_notification;
50  vk_alloc.vulkan_callbacks.pfnInternalFree = vk_internal_free_notification;
51  vk_alloc.vulkan_callbacks.pfnReallocation = vk_reallocation_function;
52  return true;
53 }
54 
55 void vk_allocator_shutdown(void) {
56  vk_alloc.vulkan_callbacks.pUserData = KB_NULL;
57  vk_alloc.vulkan_callbacks.pfnAllocation = KB_NULL;
58  vk_alloc.vulkan_callbacks.pfnFree = KB_NULL;
59  vk_alloc.vulkan_callbacks.pfnInternalAllocation = KB_NULL;
60  vk_alloc.vulkan_callbacks.pfnInternalFree = KB_NULL;
61  vk_alloc.vulkan_callbacks.pfnReallocation = KB_NULL;
62  allocator_destroy(&vk_alloc.kiba_alloc);
63  memory_zero(&vk_alloc, sizeof(vk_alloc));
64 }
65 
66 void *vk_allocation_function(void *pUserData, size_t size, size_t alignment, VkSystemAllocationScope allocationScope) {
67  UNUSED(allocationScope);
68  KB_TRACE("vulkan allocating {usize} bytes aligned to {usize} with scope {raw_string}",
69  size,
70  alignment,
71  vk_allocation_scope_names[allocationScope]);
72  struct vk_alloc *alloc = pUserData; // could technically use global value
73  void *ret = allocator_allocate_aligned(&alloc->kiba_alloc, size, alignment);
74  uptr misalignment = (uptr) ret % alignment;
75  KB_ASSERT(misalignment == 0, "allcation must be aligned as requested");
76  return ret;
77 }
78 
79 void vk_free_function(void *pUserData, void *pMemory) {
80  KB_TRACE("vulkan freeing {pointer}", pMemory);
81  struct vk_alloc *alloc = pUserData;
82  if (pMemory != KB_NULL) {
83  allocator_free(&alloc->kiba_alloc, pMemory);
84  }
85 }
86 
87 void vk_internal_allocation_notification(void *pUserData,
88  size_t size,
89  VkInternalAllocationType allocationType,
90  VkSystemAllocationScope allocationScope) {
91  UNUSED(pUserData);
92  UNUSED(size);
93  UNUSED(allocationType);
94  UNUSED(allocationScope);
95  KB_DEBUG("vulkan allocating {usize} bytes of type {u32} with scope {raw_string}",
96  size,
97  allocationType,
98  vk_allocation_scope_names[allocationScope]);
99 }
100 
101 void vk_internal_free_notification(void *pUserData,
102  size_t size,
103  VkInternalAllocationType allocationType,
104  VkSystemAllocationScope allocationScope) {
105  UNUSED(pUserData);
106  UNUSED(size);
107  UNUSED(allocationType);
108  UNUSED(allocationScope);
109  KB_DEBUG("vulkan freeing {usize} bytes of type {u32} with scope {raw_string}",
110  size,
111  allocationType,
112  vk_allocation_scope_names[allocationScope]);
113 }
114 
115 void *vk_reallocation_function(void *pUserData,
116  void *pOriginal,
117  size_t size,
118  size_t alignment,
119  VkSystemAllocationScope allocationScope) {
120  UNUSED(allocationScope);
121  KB_TRACE("vulkan reallocating {pointer} to {usize} bytes aligned to {usize} with scope {raw_string}",
122  pOriginal,
123  size,
124  alignment,
125  vk_allocation_scope_names[allocationScope]);
126  struct vk_alloc *alloc = pUserData;
127 
128  if (pOriginal == KB_NULL) {
129  return vk_allocation_function(pUserData, size, alignment, allocationScope);
130  }
131  if (size == 0) {
132  vk_free_function(pUserData, pOriginal);
133  return 0;
134  }
135  void *ret = allocator_reallocate_aligned(&alloc->kiba_alloc, pOriginal, size, alignment);
136  uptr misalignment = (uptr) ret % alignment;
137  KB_ASSERT(misalignment == 0, "reallcation must be aligned as requested");
138  return ret;
139 }
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
void * memory_zero(void *mem, usize size)
Zero out memory.
Definition: memory.c:79
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