rev |
line source |
nuclear@3
|
1 #include <stdio.h>
|
nuclear@3
|
2 #include <stdlib.h>
|
nuclear@3
|
3 #include <string.h>
|
nuclear@4
|
4 #include <stdint.h>
|
nuclear@3
|
5 #include "vku.h"
|
nuclear@3
|
6
|
nuclear@3
|
7 static const char *get_device_name(VkPhysicalDeviceType type);
|
nuclear@3
|
8 static const char *get_mem_prop_flag_string(VkMemoryPropertyFlags flags);
|
nuclear@3
|
9 static const char *get_queue_flag_string(VkQueueFlagBits flags);
|
nuclear@3
|
10 static int ver_major(uint32_t ver);
|
nuclear@3
|
11 static int ver_minor(uint32_t ver);
|
nuclear@3
|
12 static int ver_patch(uint32_t ver);
|
nuclear@3
|
13 static const char *mem_size_str(long sz);
|
nuclear@3
|
14
|
nuclear@15
|
15 static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback_thunk(VkDebugReportFlagsEXT flags,
|
nuclear@15
|
16 VkDebugReportObjectTypeEXT otype, uint64_t obj, size_t loc, int32_t code,
|
nuclear@15
|
17 const char *layer_prefix, const char *msg, void *udata);
|
nuclear@15
|
18
|
nuclear@3
|
19 VkInstance vk;
|
nuclear@3
|
20 VkDevice vkdev;
|
nuclear@3
|
21 VkQueue vkq;
|
nuclear@3
|
22
|
nuclear@4
|
23 static VkPhysicalDevice *phys_devices;
|
nuclear@4
|
24 static int sel_dev, sel_qfamily;
|
nuclear@4
|
25
|
nuclear@4
|
26 static VkExtensionProperties *vkext, *vkdevext;
|
nuclear@4
|
27 static uint32_t vkext_count, vkdevext_count;
|
nuclear@4
|
28
|
nuclear@15
|
29 static VkDebugReportCallbackEXT debug_callback_obj;
|
nuclear@15
|
30 static VkResult (*vk_create_debug_report_callback)(VkInstance,
|
nuclear@15
|
31 const VkDebugReportCallbackCreateInfoEXT*, const VkAllocationCallbacks*,
|
nuclear@15
|
32 VkDebugReportCallbackEXT*);
|
nuclear@15
|
33 static void (*user_dbg_callback)(const char*, void*);
|
nuclear@15
|
34 static void *user_dbg_callback_data;
|
nuclear@15
|
35
|
nuclear@4
|
36
|
nuclear@4
|
37 int vku_have_extension(const char *name)
|
nuclear@4
|
38 {
|
nuclear@4
|
39 int i;
|
nuclear@4
|
40
|
nuclear@4
|
41 if(!vkext) {
|
nuclear@4
|
42 vkext_count = 0;
|
nuclear@4
|
43 vkEnumerateInstanceExtensionProperties(0, &vkext_count, 0);
|
nuclear@4
|
44 if(vkext_count) {
|
nuclear@4
|
45 if(!(vkext = malloc(vkext_count * sizeof *vkext))) {
|
nuclear@4
|
46 perror("failed to allocate instance extension list");
|
nuclear@4
|
47 return 0;
|
nuclear@4
|
48 }
|
nuclear@4
|
49 vkEnumerateInstanceExtensionProperties(0, &vkext_count, vkext);
|
nuclear@4
|
50
|
nuclear@4
|
51 printf("instance extensions:\n");
|
nuclear@4
|
52 for(i=0; i<(int)vkext_count; i++) {
|
nuclear@4
|
53 printf(" %s (ver: %u)\n", vkext[i].extensionName, (unsigned int)vkext[i].specVersion);
|
nuclear@4
|
54 }
|
nuclear@4
|
55 }
|
nuclear@4
|
56 }
|
nuclear@4
|
57
|
nuclear@4
|
58 for(i=0; i<(int)vkext_count; i++) {
|
nuclear@4
|
59 if(strcmp(vkext[i].extensionName, name) == 0) {
|
nuclear@4
|
60 return 1;
|
nuclear@4
|
61 }
|
nuclear@4
|
62 }
|
nuclear@4
|
63 return 0;
|
nuclear@4
|
64 }
|
nuclear@4
|
65
|
nuclear@4
|
66 int vku_have_device_extension(const char *name)
|
nuclear@4
|
67 {
|
nuclear@4
|
68 int i;
|
nuclear@4
|
69
|
nuclear@4
|
70 if(sel_dev < 0) return 0;
|
nuclear@4
|
71
|
nuclear@4
|
72 if(!vkdevext) {
|
nuclear@4
|
73 vkdevext_count = 0;
|
nuclear@4
|
74 vkEnumerateDeviceExtensionProperties(phys_devices[sel_dev], 0, &vkdevext_count, 0);
|
nuclear@4
|
75 if(vkdevext_count) {
|
nuclear@4
|
76 if(!(vkdevext = malloc(vkdevext_count * sizeof *vkdevext))) {
|
nuclear@4
|
77 perror("failed to allocate device extension list");
|
nuclear@4
|
78 return 0;
|
nuclear@4
|
79 }
|
nuclear@4
|
80 vkEnumerateDeviceExtensionProperties(phys_devices[sel_dev], 0, &vkdevext_count, vkdevext);
|
nuclear@4
|
81
|
nuclear@4
|
82 printf("selected device extensions:\n");
|
nuclear@4
|
83 for(i=0; i<(int)vkdevext_count; i++) {
|
nuclear@4
|
84 printf(" %s (ver: %u)\n", vkdevext[i].extensionName, (unsigned int)vkdevext[i].specVersion);
|
nuclear@4
|
85 }
|
nuclear@4
|
86 }
|
nuclear@4
|
87 }
|
nuclear@4
|
88
|
nuclear@4
|
89 for(i=0; i<(int)vkdevext_count; i++) {
|
nuclear@4
|
90 if(strcmp(vkdevext[i].extensionName, name) == 0) {
|
nuclear@4
|
91 return 1;
|
nuclear@4
|
92 }
|
nuclear@4
|
93 }
|
nuclear@4
|
94 return 0;
|
nuclear@4
|
95 }
|
nuclear@4
|
96
|
nuclear@15
|
97 void vku_set_debug_callback(void (*func)(const char*, void*), void *cls)
|
nuclear@15
|
98 {
|
nuclear@15
|
99 if(!debug_callback_obj && vk_create_debug_report_callback) {
|
nuclear@15
|
100 VkDebugReportCallbackCreateInfoEXT foo;
|
nuclear@15
|
101
|
nuclear@15
|
102 memset(&foo, 0, sizeof foo);
|
nuclear@15
|
103 foo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
|
nuclear@15
|
104 foo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
|
nuclear@15
|
105 foo.pfnCallback = debug_callback_thunk;
|
nuclear@15
|
106
|
nuclear@15
|
107 vk_create_debug_report_callback(vk, &foo, 0, &debug_callback_obj);
|
nuclear@15
|
108 }
|
nuclear@15
|
109
|
nuclear@15
|
110 user_dbg_callback = func;
|
nuclear@15
|
111 user_dbg_callback_data = cls;
|
nuclear@15
|
112 }
|
nuclear@15
|
113
|
nuclear@15
|
114
|
nuclear@3
|
115 int vku_create_dev(void)
|
nuclear@3
|
116 {
|
nuclear@3
|
117 int i, j;
|
nuclear@15
|
118 uint32_t nlayers;
|
nuclear@3
|
119 VkInstanceCreateInfo inst_info;
|
nuclear@15
|
120 VkLayerProperties *layers;
|
nuclear@3
|
121 VkDeviceCreateInfo dev_info;
|
nuclear@3
|
122 VkDeviceQueueCreateInfo queue_info;
|
nuclear@3
|
123 VkCommandPoolCreateInfo cmdpool_info;
|
nuclear@3
|
124 uint32_t num_devices;
|
nuclear@3
|
125 float qprio = 0.0f;
|
nuclear@3
|
126
|
nuclear@4
|
127 static const char *ext_names[] = {
|
nuclear@4
|
128 #ifdef VK_USE_PLATFORM_XLIB_KHR
|
nuclear@4
|
129 "VK_KHR_xlib_surface",
|
nuclear@4
|
130 #endif
|
nuclear@15
|
131 "VK_KHR_surface",
|
nuclear@15
|
132 "VK_EXT_debug_report"
|
nuclear@4
|
133 };
|
nuclear@5
|
134 static const char *devext_names[] = {
|
nuclear@5
|
135 "VK_KHR_swapchain"
|
nuclear@5
|
136 };
|
nuclear@15
|
137 static const char *layer_names[] = {
|
nuclear@16
|
138 "VK_LAYER_LUNARG_standard_validation",
|
nuclear@16
|
139 "VK_LAYER_LUNARG_parameter_validation",
|
nuclear@16
|
140 "VK_LAYER_LUNARG_core_validation"
|
nuclear@15
|
141 };
|
nuclear@4
|
142
|
nuclear@4
|
143 sel_dev = -1;
|
nuclear@4
|
144 sel_qfamily = -1;
|
nuclear@4
|
145
|
nuclear@4
|
146 for(i=0; i<sizeof ext_names / sizeof *ext_names; i++) {
|
nuclear@4
|
147 if(!vku_have_extension(ext_names[i])) {
|
nuclear@4
|
148 fprintf(stderr, "required extension (%s) not found\n", ext_names[i]);
|
nuclear@4
|
149 return -1;
|
nuclear@4
|
150 }
|
nuclear@4
|
151 }
|
nuclear@4
|
152
|
nuclear@15
|
153 /* enumerate available validation layers */
|
nuclear@15
|
154 vkEnumerateInstanceLayerProperties(&nlayers, 0);
|
nuclear@15
|
155 layers = alloca(nlayers * sizeof *layers);
|
nuclear@15
|
156 vkEnumerateInstanceLayerProperties(&nlayers, layers);
|
nuclear@15
|
157
|
nuclear@15
|
158 printf("Available validation layers:\n");
|
nuclear@15
|
159 for(i=0; i<(int)nlayers; i++) {
|
nuclear@15
|
160 printf(" %s\n", layers[i].layerName);
|
nuclear@15
|
161 }
|
nuclear@15
|
162
|
nuclear@3
|
163 memset(&inst_info, 0, sizeof inst_info);
|
nuclear@3
|
164 inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
nuclear@4
|
165 inst_info.ppEnabledExtensionNames = ext_names;
|
nuclear@4
|
166 inst_info.enabledExtensionCount = sizeof ext_names / sizeof *ext_names;
|
nuclear@15
|
167 inst_info.ppEnabledLayerNames = layer_names;
|
nuclear@15
|
168 inst_info.enabledLayerCount = sizeof layer_names / sizeof *layer_names;
|
nuclear@3
|
169
|
nuclear@3
|
170 if(vkCreateInstance(&inst_info, 0, &vk) != 0) {
|
nuclear@3
|
171 fprintf(stderr, "failed to create vulkan instance\n");
|
nuclear@3
|
172 return -1;
|
nuclear@3
|
173 }
|
nuclear@3
|
174 printf("created vulkan instance\n");
|
nuclear@3
|
175
|
nuclear@15
|
176 if(!(vk_create_debug_report_callback = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(vk, "vkCreateDebugReportCallbackEXT"))) {
|
nuclear@15
|
177 fprintf(stderr, "FUCK EVERYTHING\n");
|
nuclear@15
|
178 return -1;
|
nuclear@15
|
179 }
|
nuclear@15
|
180 vku_set_debug_callback(user_dbg_callback, user_dbg_callback_data); /* set debug callback */
|
nuclear@15
|
181
|
nuclear@15
|
182
|
nuclear@3
|
183 if(vkEnumeratePhysicalDevices(vk, &num_devices, 0) != 0) {
|
nuclear@3
|
184 fprintf(stderr, "failed to enumerate vulkan physical devices\n");
|
nuclear@3
|
185 return -1;
|
nuclear@3
|
186 }
|
nuclear@4
|
187 phys_devices = malloc(num_devices * sizeof *phys_devices);
|
nuclear@4
|
188 if(vkEnumeratePhysicalDevices(vk, &num_devices, phys_devices) != 0) {
|
nuclear@3
|
189 fprintf(stderr, "failed to enumerate vulkan physical devices\n");
|
nuclear@3
|
190 return -1;
|
nuclear@3
|
191 }
|
nuclear@3
|
192 printf("found %u physical device(s)\n", (unsigned int)num_devices);
|
nuclear@3
|
193
|
nuclear@3
|
194 for(i=0; i<(int)num_devices; i++) {
|
nuclear@3
|
195 VkPhysicalDeviceProperties dev_prop;
|
nuclear@3
|
196 VkPhysicalDeviceMemoryProperties mem_prop;
|
nuclear@3
|
197 VkQueueFamilyProperties *qprop;
|
nuclear@3
|
198 uint32_t qprop_count;
|
nuclear@3
|
199
|
nuclear@4
|
200 vkGetPhysicalDeviceProperties(phys_devices[i], &dev_prop);
|
nuclear@3
|
201
|
nuclear@3
|
202 printf("Device %d: %s\n", i, dev_prop.deviceName);
|
nuclear@3
|
203 printf(" type: %s\n", get_device_name(dev_prop.deviceType));
|
nuclear@3
|
204 printf(" API version: %d.%d.%d\n", ver_major(dev_prop.apiVersion), ver_minor(dev_prop.apiVersion),
|
nuclear@3
|
205 ver_patch(dev_prop.apiVersion));
|
nuclear@3
|
206 printf(" driver version: %d.%d.%d\n", ver_major(dev_prop.driverVersion), ver_minor(dev_prop.driverVersion),
|
nuclear@3
|
207 ver_patch(dev_prop.driverVersion));
|
nuclear@3
|
208 printf(" vendor id: %x device id: %x\n", dev_prop.vendorID, dev_prop.deviceID);
|
nuclear@3
|
209
|
nuclear@3
|
210
|
nuclear@4
|
211 vkGetPhysicalDeviceMemoryProperties(phys_devices[i], &mem_prop);
|
nuclear@3
|
212 printf(" %d memory heaps:\n", mem_prop.memoryHeapCount);
|
nuclear@3
|
213 for(j=0; j<mem_prop.memoryHeapCount; j++) {
|
nuclear@3
|
214 VkMemoryHeap heap = mem_prop.memoryHeaps[j];
|
nuclear@3
|
215 printf(" Heap %d - size: %s, flags: %s\n", j, mem_size_str(heap.size),
|
nuclear@3
|
216 heap.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT ? "device-local" : "-");
|
nuclear@3
|
217 }
|
nuclear@3
|
218 printf(" %d memory types:\n", mem_prop.memoryTypeCount);
|
nuclear@3
|
219 for(j=0; j<mem_prop.memoryTypeCount; j++) {
|
nuclear@3
|
220 VkMemoryType type = mem_prop.memoryTypes[j];
|
nuclear@3
|
221 printf(" Type %d - heap: %d, flags: %s\n", j, type.heapIndex,
|
nuclear@3
|
222 get_mem_prop_flag_string(type.propertyFlags));
|
nuclear@3
|
223 }
|
nuclear@3
|
224
|
nuclear@4
|
225 vkGetPhysicalDeviceQueueFamilyProperties(phys_devices[i], &qprop_count, 0);
|
nuclear@3
|
226 if(qprop_count <= 0) {
|
nuclear@3
|
227 continue;
|
nuclear@3
|
228 }
|
nuclear@3
|
229 qprop = malloc(qprop_count * sizeof *qprop);
|
nuclear@4
|
230 vkGetPhysicalDeviceQueueFamilyProperties(phys_devices[i], &qprop_count, qprop);
|
nuclear@3
|
231
|
nuclear@3
|
232 for(j=0; j<qprop_count; j++) {
|
nuclear@3
|
233 printf(" Queue family %d:\n", j);
|
nuclear@3
|
234 printf(" flags: %s\n", get_queue_flag_string(qprop[j].queueFlags));
|
nuclear@3
|
235 printf(" num queues: %u\n", qprop[j].queueCount);
|
nuclear@3
|
236
|
nuclear@3
|
237 if(qprop[j].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
|
nuclear@3
|
238 sel_dev = i;
|
nuclear@3
|
239 sel_qfamily = j;
|
nuclear@3
|
240 }
|
nuclear@3
|
241 }
|
nuclear@3
|
242 free(qprop);
|
nuclear@3
|
243 }
|
nuclear@3
|
244
|
nuclear@3
|
245 if(sel_dev < 0 || sel_qfamily < 0) {
|
nuclear@3
|
246 fprintf(stderr, "failed to find any device with a graphics-capable command queue\n");
|
nuclear@3
|
247 vkDestroyDevice(vkdev, 0);
|
nuclear@3
|
248 return -1;
|
nuclear@3
|
249 }
|
nuclear@3
|
250
|
nuclear@5
|
251 for(i=0; i<sizeof devext_names / sizeof *devext_names; i++) {
|
nuclear@5
|
252 if(!vku_have_device_extension(devext_names[i])) {
|
nuclear@5
|
253 fprintf(stderr, "required extension (%s) not found on the selected device (%d)\n",
|
nuclear@5
|
254 ext_names[i], sel_dev);
|
nuclear@5
|
255 return -1;
|
nuclear@5
|
256 }
|
nuclear@5
|
257 }
|
nuclear@5
|
258
|
nuclear@3
|
259 /* create device & command queue */
|
nuclear@3
|
260 memset(&queue_info, 0, sizeof queue_info);
|
nuclear@3
|
261 queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
nuclear@3
|
262 queue_info.queueFamilyIndex = sel_qfamily;
|
nuclear@3
|
263 queue_info.queueCount = 1;
|
nuclear@3
|
264 queue_info.pQueuePriorities = &qprio;
|
nuclear@3
|
265
|
nuclear@3
|
266 memset(&dev_info, 0, sizeof dev_info);
|
nuclear@3
|
267 dev_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
nuclear@3
|
268 dev_info.queueCreateInfoCount = 1;
|
nuclear@3
|
269 dev_info.pQueueCreateInfos = &queue_info;
|
nuclear@5
|
270 dev_info.enabledExtensionCount = sizeof devext_names / sizeof *devext_names;
|
nuclear@5
|
271 dev_info.ppEnabledExtensionNames = devext_names;
|
nuclear@3
|
272
|
nuclear@4
|
273 if(vkCreateDevice(phys_devices[sel_dev], &dev_info, 0, &vkdev) != 0) {
|
nuclear@3
|
274 fprintf(stderr, "failed to create device %d\n", sel_dev);
|
nuclear@3
|
275 return -1;
|
nuclear@3
|
276 }
|
nuclear@3
|
277 printf("created device %d\n", sel_dev);
|
nuclear@3
|
278
|
nuclear@3
|
279 vkGetDeviceQueue(vkdev, sel_qfamily, 0, &vkq);
|
nuclear@3
|
280
|
nuclear@3
|
281 /* create command buffer pool */
|
nuclear@3
|
282 memset(&cmdpool_info, 0, sizeof cmdpool_info);
|
nuclear@3
|
283 cmdpool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
nuclear@3
|
284 cmdpool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
nuclear@3
|
285 cmdpool_info.queueFamilyIndex = sel_qfamily;
|
nuclear@3
|
286
|
nuclear@3
|
287 if(vkCreateCommandPool(vkdev, &cmdpool_info, 0, &vkcmdpool) != 0) {
|
nuclear@3
|
288 fprintf(stderr, "failed to get command quque!\n");
|
nuclear@3
|
289 return -1;
|
nuclear@3
|
290 }
|
nuclear@3
|
291
|
nuclear@4
|
292 if(!(vkcmdbuf = vku_alloc_cmdbuf(vkcmdpool, VK_COMMAND_BUFFER_LEVEL_PRIMARY))) {
|
nuclear@4
|
293 fprintf(stderr, "failed to create primary command buffer\n");
|
nuclear@4
|
294 return -1;
|
nuclear@4
|
295 }
|
nuclear@4
|
296
|
nuclear@3
|
297 return 0;
|
nuclear@3
|
298 }
|
nuclear@3
|
299
|
nuclear@3
|
300 void vku_cleanup(void)
|
nuclear@3
|
301 {
|
nuclear@3
|
302 if(vk) {
|
nuclear@3
|
303 vkDeviceWaitIdle(vkdev);
|
nuclear@4
|
304 vkDestroyCommandPool(vkdev, vkcmdpool, 0);
|
nuclear@3
|
305 vkDestroyDevice(vkdev, 0);
|
nuclear@3
|
306 vkDestroyInstance(vk, 0);
|
nuclear@3
|
307 vk = 0;
|
nuclear@3
|
308 }
|
nuclear@4
|
309
|
nuclear@4
|
310 free(phys_devices);
|
nuclear@4
|
311 phys_devices = 0;
|
nuclear@3
|
312 }
|
nuclear@3
|
313
|
nuclear@4
|
314 VkCommandBuffer vku_alloc_cmdbuf(VkCommandPool pool, VkCommandBufferLevel level)
|
nuclear@3
|
315 {
|
nuclear@4
|
316 VkCommandBuffer cmdbuf;
|
nuclear@4
|
317 VkCommandBufferAllocateInfo inf;
|
nuclear@4
|
318
|
nuclear@4
|
319 memset(&inf, 0, sizeof inf);
|
nuclear@4
|
320 inf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
nuclear@4
|
321 inf.commandPool = pool;
|
nuclear@4
|
322 inf.level = level;
|
nuclear@4
|
323 inf.commandBufferCount = 1;
|
nuclear@4
|
324
|
nuclear@4
|
325 if(vkAllocateCommandBuffers(vkdev, &inf, &cmdbuf) != 0) {
|
nuclear@4
|
326 return 0;
|
nuclear@4
|
327 }
|
nuclear@4
|
328 return cmdbuf;
|
nuclear@4
|
329 }
|
nuclear@4
|
330
|
nuclear@4
|
331 void vku_free_cmdbuf(VkCommandPool pool, VkCommandBuffer buf)
|
nuclear@4
|
332 {
|
nuclear@4
|
333 vkFreeCommandBuffers(vkdev, pool, 1, &buf);
|
nuclear@4
|
334 }
|
nuclear@4
|
335
|
nuclear@4
|
336 void vku_begin_cmdbuf(VkCommandBuffer buf, unsigned int flags)
|
nuclear@4
|
337 {
|
nuclear@4
|
338 VkCommandBufferBeginInfo inf;
|
nuclear@4
|
339
|
nuclear@4
|
340 memset(&inf, 0, sizeof inf);
|
nuclear@4
|
341 inf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
nuclear@4
|
342 inf.flags = flags;
|
nuclear@4
|
343
|
nuclear@4
|
344 vkBeginCommandBuffer(buf, &inf);
|
nuclear@4
|
345 }
|
nuclear@4
|
346
|
nuclear@4
|
347
|
nuclear@4
|
348 void vku_end_cmdbuf(VkCommandBuffer buf)
|
nuclear@4
|
349 {
|
nuclear@4
|
350 vkEndCommandBuffer(buf);
|
nuclear@4
|
351 }
|
nuclear@4
|
352
|
nuclear@4
|
353 void vku_reset_cmdbuf(VkCommandBuffer buf)
|
nuclear@4
|
354 {
|
nuclear@4
|
355 vkResetCommandBuffer(buf, 0);
|
nuclear@4
|
356 }
|
nuclear@4
|
357
|
nuclear@4
|
358 void vku_submit_cmdbuf(VkQueue q, VkCommandBuffer buf, VkFence done_fence)
|
nuclear@4
|
359 {
|
nuclear@4
|
360 VkSubmitInfo info;
|
nuclear@4
|
361
|
nuclear@4
|
362 memset(&info, 0, sizeof info);
|
nuclear@4
|
363 info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
nuclear@4
|
364 info.commandBufferCount = 1;
|
nuclear@4
|
365 info.pCommandBuffers = &buf;
|
nuclear@4
|
366
|
nuclear@4
|
367 vkQueueSubmit(q, 1, &info, done_fence);
|
nuclear@4
|
368 }
|
nuclear@4
|
369
|
nuclear@5
|
370 VkSwapchainKHR vku_create_swapchain(VkSurfaceKHR surf, int xsz, int ysz, int n,
|
nuclear@14
|
371 VkFormat fmt, VkPresentModeKHR pmode, VkSwapchainKHR prev)
|
nuclear@5
|
372 {
|
nuclear@5
|
373 VkSwapchainKHR sc;
|
nuclear@5
|
374 VkSwapchainCreateInfoKHR inf;
|
nuclear@5
|
375
|
nuclear@5
|
376 memset(&inf, 0, sizeof inf);
|
nuclear@5
|
377 inf.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
nuclear@5
|
378 inf.surface = surf;
|
nuclear@5
|
379 inf.minImageCount = n;
|
nuclear@14
|
380 inf.imageFormat = fmt;
|
nuclear@5
|
381 inf.imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
|
nuclear@5
|
382 inf.imageExtent.width = xsz;
|
nuclear@5
|
383 inf.imageExtent.height = ysz;
|
nuclear@5
|
384 inf.imageArrayLayers = 1;
|
nuclear@5
|
385 inf.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
nuclear@5
|
386 inf.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; /* XXX make this an option? */
|
nuclear@5
|
387 inf.preTransform = VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR;
|
nuclear@5
|
388 inf.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
nuclear@5
|
389 inf.presentMode = pmode;
|
nuclear@5
|
390 inf.oldSwapchain = prev;
|
nuclear@5
|
391
|
nuclear@5
|
392 if(vkCreateSwapchainKHR(vkdev, &inf, 0, &sc) != 0) {
|
nuclear@5
|
393 return 0;
|
nuclear@5
|
394 }
|
nuclear@5
|
395 return sc;
|
nuclear@5
|
396 }
|
nuclear@5
|
397
|
nuclear@6
|
398 VkImage *vku_get_swapchain_images(VkSwapchainKHR sc, int *count)
|
nuclear@6
|
399 {
|
nuclear@6
|
400 uint32_t nimg;
|
nuclear@6
|
401 VkImage *images;
|
nuclear@6
|
402
|
nuclear@6
|
403 if(vkGetSwapchainImagesKHR(vkdev, sc, &nimg, 0) != 0) {
|
nuclear@6
|
404 return 0;
|
nuclear@6
|
405 }
|
nuclear@6
|
406 if(!(images = malloc(nimg * sizeof *images))) {
|
nuclear@6
|
407 return 0;
|
nuclear@6
|
408 }
|
nuclear@6
|
409 vkGetSwapchainImagesKHR(vkdev, sc, &nimg, images);
|
nuclear@6
|
410
|
nuclear@6
|
411 if(count) *count = (int)nimg;
|
nuclear@6
|
412 return images;
|
nuclear@6
|
413 }
|
nuclear@6
|
414
|
nuclear@6
|
415 int vku_get_next_image(VkSwapchainKHR sc)
|
nuclear@6
|
416 {
|
nuclear@6
|
417 uint32_t next;
|
nuclear@6
|
418
|
nuclear@6
|
419 if(vkAcquireNextImageKHR(vkdev, sc, UINT64_MAX, 0, 0, &next) != 0) {
|
nuclear@6
|
420 return -1;
|
nuclear@6
|
421 }
|
nuclear@6
|
422 return (int)next;
|
nuclear@6
|
423 }
|
nuclear@6
|
424
|
nuclear@14
|
425 VkImageView vku_create_view(VkImage img, VkFormat fmt)
|
nuclear@14
|
426 {
|
nuclear@14
|
427 VkImageView view;
|
nuclear@14
|
428 VkImageViewCreateInfo iv;
|
nuclear@14
|
429
|
nuclear@14
|
430 memset(&iv, 0, sizeof iv);
|
nuclear@14
|
431 iv.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
nuclear@14
|
432 iv.image = img;
|
nuclear@14
|
433 iv.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
nuclear@14
|
434 iv.format = fmt;
|
nuclear@14
|
435 iv.components.r = iv.components.g = iv.components.b = iv.components.a =
|
nuclear@14
|
436 VK_COMPONENT_SWIZZLE_IDENTITY;
|
nuclear@14
|
437 iv.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
nuclear@14
|
438 iv.subresourceRange.baseMipLevel = 0;
|
nuclear@14
|
439 iv.subresourceRange.levelCount = 1;
|
nuclear@14
|
440 iv.subresourceRange.baseArrayLayer = 0;
|
nuclear@14
|
441 iv.subresourceRange.layerCount = 1;
|
nuclear@14
|
442
|
nuclear@14
|
443 if(vkCreateImageView(vkdev, &iv, 0, &view) != 0) {
|
nuclear@14
|
444 fprintf(stderr, "vku_create_view failed\n");
|
nuclear@14
|
445 return 0;
|
nuclear@14
|
446 }
|
nuclear@14
|
447 return view;
|
nuclear@14
|
448 }
|
nuclear@14
|
449
|
nuclear@14
|
450 void vku_destroy_view(VkImageView view)
|
nuclear@14
|
451 {
|
nuclear@14
|
452 vkDestroyImageView(vkdev, view, 0);
|
nuclear@14
|
453 }
|
nuclear@14
|
454
|
nuclear@14
|
455 VkFramebuffer vku_create_framebuffer(VkImageView view, int width, int height, VkRenderPass rpass)
|
nuclear@14
|
456 {
|
nuclear@14
|
457 VkFramebuffer fb;
|
nuclear@14
|
458 VkFramebufferCreateInfo fbinf;
|
nuclear@14
|
459
|
nuclear@14
|
460 memset(&fbinf, 0, sizeof fbinf);
|
nuclear@14
|
461 fbinf.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
nuclear@14
|
462 fbinf.renderPass = rpass;
|
nuclear@14
|
463 fbinf.attachmentCount = 1;
|
nuclear@14
|
464 fbinf.pAttachments = &view;
|
nuclear@14
|
465 fbinf.width = width;
|
nuclear@14
|
466 fbinf.height = height;
|
nuclear@14
|
467 fbinf.layers = 1;
|
nuclear@14
|
468
|
nuclear@14
|
469 if(vkCreateFramebuffer(vkdev, &fbinf, 0, &fb) != 0) {
|
nuclear@14
|
470 fprintf(stderr, "vku_create_framebuffer failed\n");
|
nuclear@14
|
471 return 0;
|
nuclear@14
|
472 }
|
nuclear@14
|
473 return fb;
|
nuclear@14
|
474 }
|
nuclear@14
|
475
|
nuclear@14
|
476 void vku_destroy_framebuffer(VkFramebuffer fb)
|
nuclear@14
|
477 {
|
nuclear@14
|
478 vkDestroyFramebuffer(vkdev, fb, 0);
|
nuclear@14
|
479 }
|
nuclear@14
|
480
|
nuclear@6
|
481 void vku_present(VkSwapchainKHR sc, int img_idx)
|
nuclear@6
|
482 {
|
nuclear@6
|
483 VkPresentInfoKHR inf;
|
nuclear@6
|
484 VkResult res;
|
nuclear@6
|
485 uint32_t index = img_idx;
|
nuclear@6
|
486
|
nuclear@6
|
487 memset(&inf, 0, sizeof inf);
|
nuclear@6
|
488 inf.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
nuclear@6
|
489 inf.swapchainCount = 1;
|
nuclear@6
|
490 inf.pSwapchains = ≻
|
nuclear@6
|
491 inf.pImageIndices = &index;
|
nuclear@6
|
492 inf.pResults = &res;
|
nuclear@6
|
493
|
nuclear@6
|
494 vkQueuePresentKHR(vkq, &inf);
|
nuclear@6
|
495 }
|
nuclear@6
|
496
|
nuclear@4
|
497 struct vku_buffer *vku_create_buffer(int sz, unsigned int usage)
|
nuclear@4
|
498 {
|
nuclear@4
|
499 struct vku_buffer *buf;
|
nuclear@3
|
500 VkBufferCreateInfo binfo;
|
nuclear@3
|
501
|
nuclear@3
|
502 if(!(buf = malloc(sizeof *buf))) {
|
nuclear@3
|
503 perror("failed to allocate vk_buffer structure");
|
nuclear@3
|
504 return 0;
|
nuclear@3
|
505 }
|
nuclear@3
|
506
|
nuclear@3
|
507 memset(&binfo, 0, sizeof binfo);
|
nuclear@3
|
508 binfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
nuclear@3
|
509 binfo.size = sz;
|
nuclear@3
|
510 binfo.usage = usage;
|
nuclear@3
|
511 binfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
nuclear@3
|
512
|
nuclear@3
|
513 if(vkCreateBuffer(vkdev, &binfo, 0, &buf->buf) != 0) {
|
nuclear@3
|
514 fprintf(stderr, "failed to create %d byte buffer (usage: %x)\n", sz, usage);
|
nuclear@3
|
515 return 0;
|
nuclear@3
|
516 }
|
nuclear@3
|
517 // TODO back with memory
|
nuclear@3
|
518 return buf;
|
nuclear@3
|
519 }
|
nuclear@3
|
520
|
nuclear@4
|
521 void vku_destroy_buffer(struct vku_buffer *buf)
|
nuclear@3
|
522 {
|
nuclear@3
|
523 if(buf) {
|
nuclear@3
|
524 vkDestroyBuffer(vkdev, buf->buf, 0);
|
nuclear@3
|
525 free(buf);
|
nuclear@3
|
526 }
|
nuclear@3
|
527 }
|
nuclear@3
|
528
|
nuclear@4
|
529 void vku_cmd_copybuf(VkCommandBuffer cmdbuf, VkBuffer dest, int doffs,
|
nuclear@4
|
530 VkBuffer src, int soffs, int size)
|
nuclear@4
|
531 {
|
nuclear@4
|
532 VkBufferCopy copy;
|
nuclear@4
|
533 copy.size = size;
|
nuclear@4
|
534 copy.srcOffset = soffs;
|
nuclear@4
|
535 copy.dstOffset = doffs;
|
nuclear@4
|
536
|
nuclear@4
|
537 vkCmdCopyBuffer(cmdbuf, src, dest, 1, ©);
|
nuclear@4
|
538 }
|
nuclear@4
|
539
|
nuclear@12
|
540
|
nuclear@13
|
541 VkRenderPass vku_create_renderpass(VkFormat cfmt, VkFormat dsfmt)
|
nuclear@13
|
542 {
|
nuclear@13
|
543 int count = 1; /* always assume we have a color attachment for now */
|
nuclear@13
|
544 VkAttachmentDescription at[2];
|
nuclear@13
|
545 VkAttachmentReference colref, dsref;
|
nuclear@13
|
546 VkSubpassDescription subpass;
|
nuclear@13
|
547 VkRenderPass pass;
|
nuclear@13
|
548 VkRenderPassCreateInfo rpinf;
|
nuclear@13
|
549
|
nuclear@13
|
550 colref.attachment = 0;
|
nuclear@13
|
551 colref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
nuclear@13
|
552 dsref.attachment = 1;
|
nuclear@13
|
553 dsref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
nuclear@13
|
554
|
nuclear@13
|
555 memset(&subpass, 0, sizeof subpass);
|
nuclear@13
|
556 subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
nuclear@13
|
557 subpass.colorAttachmentCount = 1;
|
nuclear@13
|
558 subpass.pColorAttachments = &colref;
|
nuclear@13
|
559
|
nuclear@13
|
560 at[0].format = cfmt;
|
nuclear@13
|
561 at[0].samples = VK_SAMPLE_COUNT_1_BIT; /* TODO multisampling */
|
nuclear@13
|
562 at[0].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
nuclear@13
|
563 at[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
nuclear@13
|
564 at[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
nuclear@13
|
565 at[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
nuclear@13
|
566 at[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
nuclear@13
|
567 at[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
nuclear@13
|
568
|
nuclear@13
|
569 if(dsfmt != VK_FORMAT_UNDEFINED) {
|
nuclear@13
|
570 at[1].format = dsfmt;
|
nuclear@13
|
571 at[1].samples = VK_SAMPLE_COUNT_1_BIT;
|
nuclear@13
|
572 at[1].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
nuclear@13
|
573 at[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
nuclear@13
|
574 at[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
nuclear@13
|
575 at[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
|
nuclear@13
|
576 at[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
nuclear@13
|
577 at[1].finalLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
nuclear@13
|
578
|
nuclear@13
|
579 subpass.pDepthStencilAttachment = &dsref;
|
nuclear@13
|
580 count++;
|
nuclear@13
|
581 }
|
nuclear@13
|
582
|
nuclear@13
|
583 memset(&rpinf, 0, sizeof rpinf);
|
nuclear@13
|
584 rpinf.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
nuclear@13
|
585 rpinf.attachmentCount = count;
|
nuclear@13
|
586 rpinf.pAttachments = at;
|
nuclear@13
|
587 rpinf.subpassCount = 1;
|
nuclear@13
|
588 rpinf.pSubpasses = &subpass;
|
nuclear@13
|
589
|
nuclear@13
|
590 if(vkCreateRenderPass(vkdev, &rpinf, 0, &pass) != 0) {
|
nuclear@13
|
591 fprintf(stderr, "vku_create_renderpass: failed to create renderpass\n");
|
nuclear@13
|
592 return 0;
|
nuclear@13
|
593 }
|
nuclear@13
|
594
|
nuclear@13
|
595 return pass;
|
nuclear@13
|
596 }
|
nuclear@13
|
597
|
nuclear@13
|
598 void vku_destroy_renderpass(VkRenderPass rpass)
|
nuclear@13
|
599 {
|
nuclear@13
|
600 vkDestroyRenderPass(vkdev, rpass, 0);
|
nuclear@13
|
601 }
|
nuclear@13
|
602
|
nuclear@15
|
603 void vku_begin_renderpass(VkCommandBuffer cmdbuf, VkRenderPass rpass, VkFramebuffer fb,
|
nuclear@15
|
604 VkSubpassContents cont)
|
nuclear@15
|
605 {
|
nuclear@15
|
606 VkRenderPassBeginInfo rpinf;
|
nuclear@15
|
607
|
nuclear@15
|
608 memset(&rpinf, 0, sizeof rpinf);
|
nuclear@15
|
609 rpinf.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
nuclear@15
|
610 rpinf.renderPass = rpass;
|
nuclear@15
|
611 rpinf.framebuffer = fb;
|
nuclear@15
|
612 rpinf.renderArea.offset.x = vkvport.x;
|
nuclear@15
|
613 rpinf.renderArea.offset.y = vkvport.y;
|
nuclear@15
|
614 rpinf.renderArea.extent.width = vkvport.width;
|
nuclear@15
|
615 rpinf.renderArea.extent.height = vkvport.height;
|
nuclear@15
|
616
|
nuclear@15
|
617 vkCmdBeginRenderPass(cmdbuf, &rpinf, cont);
|
nuclear@15
|
618 }
|
nuclear@15
|
619
|
nuclear@15
|
620 void vku_end_renderpass(VkCommandBuffer cmdbuf)
|
nuclear@15
|
621 {
|
nuclear@15
|
622 vkCmdEndRenderPass(cmdbuf);
|
nuclear@15
|
623 }
|
nuclear@13
|
624
|
nuclear@4
|
625 #ifdef VK_USE_PLATFORM_XLIB_KHR
|
nuclear@4
|
626 int vku_xlib_usable_visual(Display *dpy, VisualID vid)
|
nuclear@4
|
627 {
|
nuclear@4
|
628 return vkGetPhysicalDeviceXlibPresentationSupportKHR(phys_devices[sel_dev],
|
nuclear@4
|
629 sel_qfamily, dpy, vid);
|
nuclear@4
|
630 }
|
nuclear@5
|
631
|
nuclear@5
|
632 VkSurfaceKHR vku_xlib_create_surface(Display *dpy, Window win)
|
nuclear@5
|
633 {
|
nuclear@5
|
634 VkSurfaceKHR surf;
|
nuclear@5
|
635 VkXlibSurfaceCreateInfoKHR inf;
|
nuclear@5
|
636
|
nuclear@5
|
637 memset(&inf, 0, sizeof inf);
|
nuclear@5
|
638 inf.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
|
nuclear@5
|
639 inf.dpy = dpy;
|
nuclear@5
|
640 inf.window = win;
|
nuclear@5
|
641
|
nuclear@5
|
642 if(vkCreateXlibSurfaceKHR(vk, &inf, 0, &surf) != 0) {
|
nuclear@5
|
643 return 0;
|
nuclear@5
|
644 }
|
nuclear@5
|
645 return surf;
|
nuclear@5
|
646 }
|
nuclear@5
|
647
|
nuclear@4
|
648 #endif /* VK_USE_PLATFORM_XLIB_KHR */
|
nuclear@4
|
649
|
nuclear@3
|
650 static const char *get_device_name(VkPhysicalDeviceType type)
|
nuclear@3
|
651 {
|
nuclear@3
|
652 switch(type) {
|
nuclear@3
|
653 case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
|
nuclear@3
|
654 return "integrated GPU";
|
nuclear@3
|
655 case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
|
nuclear@3
|
656 return "discrete GPU";
|
nuclear@3
|
657 case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
|
nuclear@3
|
658 return "virtual GPU";
|
nuclear@3
|
659 case VK_PHYSICAL_DEVICE_TYPE_CPU:
|
nuclear@3
|
660 return "CPU";
|
nuclear@3
|
661 default:
|
nuclear@3
|
662 break;
|
nuclear@3
|
663 }
|
nuclear@3
|
664 return "unknown";
|
nuclear@3
|
665 }
|
nuclear@3
|
666
|
nuclear@3
|
667 static const char *get_mem_prop_flag_string(VkMemoryPropertyFlags flags)
|
nuclear@3
|
668 {
|
nuclear@3
|
669 static char str[128];
|
nuclear@3
|
670
|
nuclear@3
|
671 str[0] = 0;
|
nuclear@3
|
672 if(flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
|
nuclear@3
|
673 strcat(str, "device-local ");
|
nuclear@3
|
674 }
|
nuclear@3
|
675 if(flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
|
nuclear@3
|
676 strcat(str, "host-visible ");
|
nuclear@3
|
677 }
|
nuclear@3
|
678 if(flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) {
|
nuclear@3
|
679 strcat(str, "host-coherent ");
|
nuclear@3
|
680 }
|
nuclear@3
|
681 if(flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) {
|
nuclear@3
|
682 strcat(str, "host-cached ");
|
nuclear@3
|
683 }
|
nuclear@3
|
684 if(flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) {
|
nuclear@3
|
685 strcat(str, "lazily-allocated ");
|
nuclear@3
|
686 }
|
nuclear@3
|
687
|
nuclear@3
|
688 if(!*str) {
|
nuclear@3
|
689 strcat(str, "-");
|
nuclear@3
|
690 }
|
nuclear@3
|
691 return str;
|
nuclear@3
|
692 }
|
nuclear@3
|
693
|
nuclear@3
|
694 static const char *get_queue_flag_string(VkQueueFlagBits flags)
|
nuclear@3
|
695 {
|
nuclear@3
|
696 static char str[128];
|
nuclear@3
|
697
|
nuclear@3
|
698 str[0] = 0;
|
nuclear@3
|
699 if(flags & VK_QUEUE_GRAPHICS_BIT) {
|
nuclear@3
|
700 strcat(str, "graphics ");
|
nuclear@3
|
701 }
|
nuclear@3
|
702 if(flags & VK_QUEUE_COMPUTE_BIT) {
|
nuclear@3
|
703 strcat(str, "compute ");
|
nuclear@3
|
704 }
|
nuclear@3
|
705 if(flags & VK_QUEUE_TRANSFER_BIT) {
|
nuclear@3
|
706 strcat(str, "transfer ");
|
nuclear@3
|
707 }
|
nuclear@3
|
708 if(flags & VK_QUEUE_SPARSE_BINDING_BIT) {
|
nuclear@3
|
709 strcat(str, "sparse-binding ");
|
nuclear@3
|
710 }
|
nuclear@3
|
711 if(!*str) {
|
nuclear@3
|
712 strcat(str, "-");
|
nuclear@3
|
713 }
|
nuclear@3
|
714 return str;
|
nuclear@3
|
715 }
|
nuclear@3
|
716
|
nuclear@3
|
717 static int ver_major(uint32_t ver)
|
nuclear@3
|
718 {
|
nuclear@3
|
719 return (ver >> 22) & 0x3ff;
|
nuclear@3
|
720 }
|
nuclear@3
|
721
|
nuclear@3
|
722 static int ver_minor(uint32_t ver)
|
nuclear@3
|
723 {
|
nuclear@3
|
724 return (ver >> 12) & 0x3ff;
|
nuclear@3
|
725 }
|
nuclear@3
|
726
|
nuclear@3
|
727 static int ver_patch(uint32_t ver)
|
nuclear@3
|
728 {
|
nuclear@3
|
729 return ver & 0xfff;
|
nuclear@3
|
730 }
|
nuclear@3
|
731
|
nuclear@3
|
732 static const char *mem_size_str(long sz)
|
nuclear@3
|
733 {
|
nuclear@3
|
734 static char str[64];
|
nuclear@3
|
735 static const char *unitstr[] = { "bytes", "KB", "MB", "GB", "TB", "PB", 0 };
|
nuclear@3
|
736 int uidx = 0;
|
nuclear@3
|
737 sz *= 10;
|
nuclear@3
|
738
|
nuclear@3
|
739 while(sz >= 10240 && unitstr[uidx + 1]) {
|
nuclear@3
|
740 sz /= 1024;
|
nuclear@3
|
741 ++uidx;
|
nuclear@3
|
742 }
|
nuclear@3
|
743 sprintf(str, "%ld.%ld %s", sz / 10, sz % 10, unitstr[uidx]);
|
nuclear@3
|
744 return str;
|
nuclear@3
|
745 }
|
nuclear@15
|
746
|
nuclear@15
|
747 static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback_thunk(VkDebugReportFlagsEXT flags,
|
nuclear@15
|
748 VkDebugReportObjectTypeEXT otype, uint64_t obj, size_t loc, int32_t code,
|
nuclear@15
|
749 const char *layer_prefix, const char *msg, void *udata)
|
nuclear@15
|
750 {
|
nuclear@15
|
751 if(user_dbg_callback) {
|
nuclear@15
|
752 user_dbg_callback(msg, user_dbg_callback_data);
|
nuclear@15
|
753 } else {
|
nuclear@15
|
754 fprintf(stderr, "VK DEBUG (%s): %s\n", layer_prefix, msg);
|
nuclear@15
|
755 }
|
nuclear@15
|
756
|
nuclear@15
|
757 return VK_TRUE;
|
nuclear@15
|
758 }
|