Quake II RTX doxygen  1.0 dev
device_memory_allocator.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 2019, NVIDIA CORPORATION. All rights reserved.
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18 
19 #include "shared/shared.h"
20 
21 #include <vulkan/vulkan.h>
22 #include <assert.h>
23 
25 #include "buddy_allocator.h"
26 
27 #include "vkpt.h"
28 
29 #define ALLOCATOR_CAPACITY 33554432 // 32MiB
30 #define ALLOCATOR_BLOCK_SIZE 1024 // 1024B
31 
32 typedef struct SubAllocator
33 {
34  VkDeviceMemory memory;
36  struct SubAllocator* next;
37 } SubAllocator;
38 
39 typedef struct DeviceMemoryAllocator
40 {
41  SubAllocator* sub_allocators[VK_MAX_MEMORY_TYPES];
42  VkDevice device;
43  void* memory;
45 
46 int create_sub_allocator(DeviceMemoryAllocator* allocator, uint32_t memory_type);
47 
49 {
50  char* memory = malloc(sizeof(DeviceMemoryAllocator));
51 
52  DeviceMemoryAllocator* allocator = (DeviceMemoryAllocator*)memory;
53  memset(allocator, 0, sizeof(DeviceMemoryAllocator));
54  allocator->memory = memory;
55  allocator->device = device;
56 
57  return allocator;
58 }
59 
61 {
62  const uint32_t memory_type = device_memory->memory_type;
63  if (allocator->sub_allocators[memory_type] == NULL)
64  {
65  if (!create_sub_allocator(allocator, memory_type))
66  return DMA_NOT_ENOUGH_MEMORY;
67  }
68 
69  assert(device_memory->size <= ALLOCATOR_CAPACITY);
70 
72  SubAllocator* sub_allocator = allocator->sub_allocators[memory_type];
73 
74  while (result != BA_SUCCESS)
75  {
76  device_memory->memory = sub_allocator->memory;
77 
78  result = buddy_allocator_allocate(sub_allocator->buddy_allocator, device_memory->size,
79  device_memory->alignment, &device_memory->memory_offset);
80 
81  assert(result <= BA_NOT_ENOUGH_MEMORY);
82  if (result == BA_NOT_ENOUGH_MEMORY)
83  {
84  if (sub_allocator->next != NULL)
85  {
86  sub_allocator = sub_allocator->next;
87  }
88  else
89  {
90  if (!create_sub_allocator(allocator, memory_type))
91  return DMA_NOT_ENOUGH_MEMORY;
92  sub_allocator = allocator->sub_allocators[memory_type];
93  }
94  }
95  }
96 
97  return DMA_SUCCESS;
98 }
99 
100 void free_device_memory(DeviceMemoryAllocator* allocator, const DeviceMemory* device_memory)
101 {
102  SubAllocator* sub_allocator = allocator->sub_allocators[device_memory->memory_type];
103 
104  while (sub_allocator->memory != device_memory->memory)
105  sub_allocator = sub_allocator->next;
106 
107  buddy_allocator_free(sub_allocator->buddy_allocator, device_memory->memory_offset, device_memory->size);
108 }
109 
111 {
112  for (uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; i++)
113  {
114  SubAllocator* sub_allocator = allocator->sub_allocators[i];
115  while (sub_allocator != NULL)
116  {
117  vkFreeMemory(allocator->device, sub_allocator->memory, NULL);
118  sub_allocator = sub_allocator->next;
119  }
120  }
121 
122  free(allocator->memory);
123 }
124 
125 int create_sub_allocator(DeviceMemoryAllocator* allocator, uint32_t memory_type)
126 {
127  SubAllocator* sub_allocator = (SubAllocator*)malloc(sizeof(SubAllocator));
128 
129  VkMemoryAllocateInfo memory_allocate_info = {
130  .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
131  .allocationSize = ALLOCATOR_CAPACITY,
132  .memoryTypeIndex = memory_type
133  };
134 
135 #ifdef VKPT_DEVICE_GROUPS
136  VkMemoryAllocateFlagsInfoKHR mem_alloc_flags = {
137  .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR,
138  .flags = VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT_KHR,
139  .deviceMask = (1 << qvk.device_count) - 1
140  };
141 
142  if (qvk.device_count > 1) {
143  memory_allocate_info.pNext = &mem_alloc_flags;
144  }
145 #endif
146 
147  const VkResult result = vkAllocateMemory(allocator->device, &memory_allocate_info, NULL, &sub_allocator->memory);
148  if (result != VK_SUCCESS)
149  return 0;
150 
152  sub_allocator->next = allocator->sub_allocators[memory_type];
153  allocator->sub_allocators[memory_type] = sub_allocator;
154 
155  return 1;
156 }
157 
SubAllocator
Definition: device_memory_allocator.c:32
DeviceMemoryAllocator
struct DeviceMemoryAllocator DeviceMemoryAllocator
DMAResult
DMAResult
Definition: device_memory_allocator.h:22
buddy_allocator_free
void buddy_allocator_free(BuddyAllocator *allocator, uint64_t offset, uint64_t size)
Definition: buddy_allocator.c:136
DeviceMemoryAllocator::device
VkDevice device
Definition: device_memory_allocator.c:42
create_device_memory_allocator
DeviceMemoryAllocator * create_device_memory_allocator(VkDevice device)
Definition: device_memory_allocator.c:48
SubAllocator::buddy_allocator
BuddyAllocator * buddy_allocator
Definition: device_memory_allocator.c:35
allocate_device_memory
DMAResult allocate_device_memory(DeviceMemoryAllocator *allocator, DeviceMemory *device_memory)
Definition: device_memory_allocator.c:60
vkpt.h
SubAllocator
struct SubAllocator SubAllocator
buddy_allocator_allocate
BAResult buddy_allocator_allocate(BuddyAllocator *allocator, uint64_t size, uint64_t alignment, uint64_t *offset)
Definition: buddy_allocator.c:97
DeviceMemoryAllocator
Definition: device_memory_allocator.c:39
DeviceMemoryAllocator::sub_allocators
SubAllocator * sub_allocators[VK_MAX_MEMORY_TYPES]
Definition: device_memory_allocator.c:41
device
static ALCdevice * device
Definition: dynamic.c:53
SubAllocator::next
struct SubAllocator * next
Definition: device_memory_allocator.c:36
BA_SUCCESS
@ BA_SUCCESS
Definition: buddy_allocator.h:24
free_device_memory
void free_device_memory(DeviceMemoryAllocator *allocator, const DeviceMemory *device_memory)
Definition: device_memory_allocator.c:100
DeviceMemory::alignment
uint64_t alignment
Definition: device_memory_allocator.h:33
DeviceMemoryAllocator::memory
void * memory
Definition: device_memory_allocator.c:43
DeviceMemory
Definition: device_memory_allocator.h:28
create_sub_allocator
int create_sub_allocator(DeviceMemoryAllocator *allocator, uint32_t memory_type)
Definition: device_memory_allocator.c:125
SubAllocator::memory
VkDeviceMemory memory
Definition: device_memory_allocator.c:34
BuddyAllocator
Definition: buddy_allocator.c:37
BAResult
BAResult
Definition: buddy_allocator.h:22
ALLOCATOR_BLOCK_SIZE
#define ALLOCATOR_BLOCK_SIZE
Definition: device_memory_allocator.c:30
DeviceMemory::memory
VkDeviceMemory memory
Definition: device_memory_allocator.h:30
DMA_SUCCESS
@ DMA_SUCCESS
Definition: device_memory_allocator.h:24
DeviceMemory::memory_offset
uint64_t memory_offset
Definition: device_memory_allocator.h:31
device_memory_allocator.h
qvk
QVK_t qvk
Definition: main.c:377
destroy_device_memory_allocator
void destroy_device_memory_allocator(DeviceMemoryAllocator *allocator)
Definition: device_memory_allocator.c:110
DeviceMemory::size
uint64_t size
Definition: device_memory_allocator.h:32
buddy_allocator.h
BA_NOT_ENOUGH_MEMORY
@ BA_NOT_ENOUGH_MEMORY
Definition: buddy_allocator.h:25
create_buddy_allocator
BuddyAllocator * create_buddy_allocator(uint64_t capacity, uint64_t block_size)
Definition: buddy_allocator.c:59
DeviceMemory::memory_type
uint32_t memory_type
Definition: device_memory_allocator.h:34
ALLOCATOR_CAPACITY
#define ALLOCATOR_CAPACITY
Definition: device_memory_allocator.c:29
QVK_s::device_count
int device_count
Definition: vkpt.h:167
DMA_NOT_ENOUGH_MEMORY
@ DMA_NOT_ENOUGH_MEMORY
Definition: device_memory_allocator.h:25