vulkan_test2

view src/vku.c @ 14:9fb6c24691ea

this shit never ends...
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 26 Jun 2018 07:20:03 +0300
parents d34f84bede17
children 196122a2b8c2
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <stdint.h>
5 #include "vku.h"
7 static const char *get_device_name(VkPhysicalDeviceType type);
8 static const char *get_mem_prop_flag_string(VkMemoryPropertyFlags flags);
9 static const char *get_queue_flag_string(VkQueueFlagBits flags);
10 static int ver_major(uint32_t ver);
11 static int ver_minor(uint32_t ver);
12 static int ver_patch(uint32_t ver);
13 static const char *mem_size_str(long sz);
15 VkInstance vk;
16 VkDevice vkdev;
17 VkQueue vkq;
19 static VkPhysicalDevice *phys_devices;
20 static int sel_dev, sel_qfamily;
22 static VkExtensionProperties *vkext, *vkdevext;
23 static uint32_t vkext_count, vkdevext_count;
26 int vku_have_extension(const char *name)
27 {
28 int i;
30 if(!vkext) {
31 vkext_count = 0;
32 vkEnumerateInstanceExtensionProperties(0, &vkext_count, 0);
33 if(vkext_count) {
34 if(!(vkext = malloc(vkext_count * sizeof *vkext))) {
35 perror("failed to allocate instance extension list");
36 return 0;
37 }
38 vkEnumerateInstanceExtensionProperties(0, &vkext_count, vkext);
40 printf("instance extensions:\n");
41 for(i=0; i<(int)vkext_count; i++) {
42 printf(" %s (ver: %u)\n", vkext[i].extensionName, (unsigned int)vkext[i].specVersion);
43 }
44 }
45 }
47 for(i=0; i<(int)vkext_count; i++) {
48 if(strcmp(vkext[i].extensionName, name) == 0) {
49 return 1;
50 }
51 }
52 return 0;
53 }
55 int vku_have_device_extension(const char *name)
56 {
57 int i;
59 if(sel_dev < 0) return 0;
61 if(!vkdevext) {
62 vkdevext_count = 0;
63 vkEnumerateDeviceExtensionProperties(phys_devices[sel_dev], 0, &vkdevext_count, 0);
64 if(vkdevext_count) {
65 if(!(vkdevext = malloc(vkdevext_count * sizeof *vkdevext))) {
66 perror("failed to allocate device extension list");
67 return 0;
68 }
69 vkEnumerateDeviceExtensionProperties(phys_devices[sel_dev], 0, &vkdevext_count, vkdevext);
71 printf("selected device extensions:\n");
72 for(i=0; i<(int)vkdevext_count; i++) {
73 printf(" %s (ver: %u)\n", vkdevext[i].extensionName, (unsigned int)vkdevext[i].specVersion);
74 }
75 }
76 }
78 for(i=0; i<(int)vkdevext_count; i++) {
79 if(strcmp(vkdevext[i].extensionName, name) == 0) {
80 return 1;
81 }
82 }
83 return 0;
84 }
86 int vku_create_dev(void)
87 {
88 int i, j;
89 VkInstanceCreateInfo inst_info;
90 VkDeviceCreateInfo dev_info;
91 VkDeviceQueueCreateInfo queue_info;
92 VkCommandPoolCreateInfo cmdpool_info;
93 uint32_t num_devices;
94 float qprio = 0.0f;
96 static const char *ext_names[] = {
97 #ifdef VK_USE_PLATFORM_XLIB_KHR
98 "VK_KHR_xlib_surface",
99 #endif
100 "VK_KHR_surface"
101 };
102 static const char *devext_names[] = {
103 "VK_KHR_swapchain"
104 };
106 sel_dev = -1;
107 sel_qfamily = -1;
109 for(i=0; i<sizeof ext_names / sizeof *ext_names; i++) {
110 if(!vku_have_extension(ext_names[i])) {
111 fprintf(stderr, "required extension (%s) not found\n", ext_names[i]);
112 return -1;
113 }
114 }
116 memset(&inst_info, 0, sizeof inst_info);
117 inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
118 inst_info.ppEnabledExtensionNames = ext_names;
119 inst_info.enabledExtensionCount = sizeof ext_names / sizeof *ext_names;
121 if(vkCreateInstance(&inst_info, 0, &vk) != 0) {
122 fprintf(stderr, "failed to create vulkan instance\n");
123 return -1;
124 }
125 printf("created vulkan instance\n");
127 if(vkEnumeratePhysicalDevices(vk, &num_devices, 0) != 0) {
128 fprintf(stderr, "failed to enumerate vulkan physical devices\n");
129 return -1;
130 }
131 phys_devices = malloc(num_devices * sizeof *phys_devices);
132 if(vkEnumeratePhysicalDevices(vk, &num_devices, phys_devices) != 0) {
133 fprintf(stderr, "failed to enumerate vulkan physical devices\n");
134 return -1;
135 }
136 printf("found %u physical device(s)\n", (unsigned int)num_devices);
138 for(i=0; i<(int)num_devices; i++) {
139 VkPhysicalDeviceProperties dev_prop;
140 VkPhysicalDeviceMemoryProperties mem_prop;
141 VkQueueFamilyProperties *qprop;
142 uint32_t qprop_count;
144 vkGetPhysicalDeviceProperties(phys_devices[i], &dev_prop);
146 printf("Device %d: %s\n", i, dev_prop.deviceName);
147 printf(" type: %s\n", get_device_name(dev_prop.deviceType));
148 printf(" API version: %d.%d.%d\n", ver_major(dev_prop.apiVersion), ver_minor(dev_prop.apiVersion),
149 ver_patch(dev_prop.apiVersion));
150 printf(" driver version: %d.%d.%d\n", ver_major(dev_prop.driverVersion), ver_minor(dev_prop.driverVersion),
151 ver_patch(dev_prop.driverVersion));
152 printf(" vendor id: %x device id: %x\n", dev_prop.vendorID, dev_prop.deviceID);
155 vkGetPhysicalDeviceMemoryProperties(phys_devices[i], &mem_prop);
156 printf(" %d memory heaps:\n", mem_prop.memoryHeapCount);
157 for(j=0; j<mem_prop.memoryHeapCount; j++) {
158 VkMemoryHeap heap = mem_prop.memoryHeaps[j];
159 printf(" Heap %d - size: %s, flags: %s\n", j, mem_size_str(heap.size),
160 heap.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT ? "device-local" : "-");
161 }
162 printf(" %d memory types:\n", mem_prop.memoryTypeCount);
163 for(j=0; j<mem_prop.memoryTypeCount; j++) {
164 VkMemoryType type = mem_prop.memoryTypes[j];
165 printf(" Type %d - heap: %d, flags: %s\n", j, type.heapIndex,
166 get_mem_prop_flag_string(type.propertyFlags));
167 }
169 vkGetPhysicalDeviceQueueFamilyProperties(phys_devices[i], &qprop_count, 0);
170 if(qprop_count <= 0) {
171 continue;
172 }
173 qprop = malloc(qprop_count * sizeof *qprop);
174 vkGetPhysicalDeviceQueueFamilyProperties(phys_devices[i], &qprop_count, qprop);
176 for(j=0; j<qprop_count; j++) {
177 printf(" Queue family %d:\n", j);
178 printf(" flags: %s\n", get_queue_flag_string(qprop[j].queueFlags));
179 printf(" num queues: %u\n", qprop[j].queueCount);
181 if(qprop[j].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
182 sel_dev = i;
183 sel_qfamily = j;
184 }
185 }
186 free(qprop);
187 }
189 if(sel_dev < 0 || sel_qfamily < 0) {
190 fprintf(stderr, "failed to find any device with a graphics-capable command queue\n");
191 vkDestroyDevice(vkdev, 0);
192 return -1;
193 }
195 for(i=0; i<sizeof devext_names / sizeof *devext_names; i++) {
196 if(!vku_have_device_extension(devext_names[i])) {
197 fprintf(stderr, "required extension (%s) not found on the selected device (%d)\n",
198 ext_names[i], sel_dev);
199 return -1;
200 }
201 }
203 /* create device & command queue */
204 memset(&queue_info, 0, sizeof queue_info);
205 queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
206 queue_info.queueFamilyIndex = sel_qfamily;
207 queue_info.queueCount = 1;
208 queue_info.pQueuePriorities = &qprio;
210 memset(&dev_info, 0, sizeof dev_info);
211 dev_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
212 dev_info.queueCreateInfoCount = 1;
213 dev_info.pQueueCreateInfos = &queue_info;
214 dev_info.enabledExtensionCount = sizeof devext_names / sizeof *devext_names;
215 dev_info.ppEnabledExtensionNames = devext_names;
217 if(vkCreateDevice(phys_devices[sel_dev], &dev_info, 0, &vkdev) != 0) {
218 fprintf(stderr, "failed to create device %d\n", sel_dev);
219 return -1;
220 }
221 printf("created device %d\n", sel_dev);
223 vkGetDeviceQueue(vkdev, sel_qfamily, 0, &vkq);
225 /* create command buffer pool */
226 memset(&cmdpool_info, 0, sizeof cmdpool_info);
227 cmdpool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
228 cmdpool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
229 cmdpool_info.queueFamilyIndex = sel_qfamily;
231 if(vkCreateCommandPool(vkdev, &cmdpool_info, 0, &vkcmdpool) != 0) {
232 fprintf(stderr, "failed to get command quque!\n");
233 return -1;
234 }
236 if(!(vkcmdbuf = vku_alloc_cmdbuf(vkcmdpool, VK_COMMAND_BUFFER_LEVEL_PRIMARY))) {
237 fprintf(stderr, "failed to create primary command buffer\n");
238 return -1;
239 }
241 return 0;
242 }
244 void vku_cleanup(void)
245 {
246 if(vk) {
247 vkDeviceWaitIdle(vkdev);
248 vkDestroyCommandPool(vkdev, vkcmdpool, 0);
249 vkDestroyDevice(vkdev, 0);
250 vkDestroyInstance(vk, 0);
251 vk = 0;
252 }
254 free(phys_devices);
255 phys_devices = 0;
256 }
258 VkCommandBuffer vku_alloc_cmdbuf(VkCommandPool pool, VkCommandBufferLevel level)
259 {
260 VkCommandBuffer cmdbuf;
261 VkCommandBufferAllocateInfo inf;
263 memset(&inf, 0, sizeof inf);
264 inf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
265 inf.commandPool = pool;
266 inf.level = level;
267 inf.commandBufferCount = 1;
269 if(vkAllocateCommandBuffers(vkdev, &inf, &cmdbuf) != 0) {
270 return 0;
271 }
272 return cmdbuf;
273 }
275 void vku_free_cmdbuf(VkCommandPool pool, VkCommandBuffer buf)
276 {
277 vkFreeCommandBuffers(vkdev, pool, 1, &buf);
278 }
280 void vku_begin_cmdbuf(VkCommandBuffer buf, unsigned int flags)
281 {
282 VkCommandBufferBeginInfo inf;
284 memset(&inf, 0, sizeof inf);
285 inf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
286 inf.flags = flags;
288 vkBeginCommandBuffer(buf, &inf);
289 }
292 void vku_end_cmdbuf(VkCommandBuffer buf)
293 {
294 vkEndCommandBuffer(buf);
295 }
297 void vku_reset_cmdbuf(VkCommandBuffer buf)
298 {
299 vkResetCommandBuffer(buf, 0);
300 }
302 void vku_submit_cmdbuf(VkQueue q, VkCommandBuffer buf, VkFence done_fence)
303 {
304 VkSubmitInfo info;
306 memset(&info, 0, sizeof info);
307 info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
308 info.commandBufferCount = 1;
309 info.pCommandBuffers = &buf;
311 vkQueueSubmit(q, 1, &info, done_fence);
312 }
314 VkSwapchainKHR vku_create_swapchain(VkSurfaceKHR surf, int xsz, int ysz, int n,
315 VkFormat fmt, VkPresentModeKHR pmode, VkSwapchainKHR prev)
316 {
317 VkSwapchainKHR sc;
318 VkSwapchainCreateInfoKHR inf;
320 memset(&inf, 0, sizeof inf);
321 inf.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
322 inf.surface = surf;
323 inf.minImageCount = n;
324 inf.imageFormat = fmt;
325 inf.imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
326 inf.imageExtent.width = xsz;
327 inf.imageExtent.height = ysz;
328 inf.imageArrayLayers = 1;
329 inf.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
330 inf.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; /* XXX make this an option? */
331 inf.preTransform = VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR;
332 inf.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
333 inf.presentMode = pmode;
334 inf.oldSwapchain = prev;
336 if(vkCreateSwapchainKHR(vkdev, &inf, 0, &sc) != 0) {
337 return 0;
338 }
339 return sc;
340 }
342 VkImage *vku_get_swapchain_images(VkSwapchainKHR sc, int *count)
343 {
344 uint32_t nimg;
345 VkImage *images;
347 if(vkGetSwapchainImagesKHR(vkdev, sc, &nimg, 0) != 0) {
348 return 0;
349 }
350 if(!(images = malloc(nimg * sizeof *images))) {
351 return 0;
352 }
353 vkGetSwapchainImagesKHR(vkdev, sc, &nimg, images);
355 if(count) *count = (int)nimg;
356 return images;
357 }
359 int vku_get_next_image(VkSwapchainKHR sc)
360 {
361 uint32_t next;
363 if(vkAcquireNextImageKHR(vkdev, sc, UINT64_MAX, 0, 0, &next) != 0) {
364 return -1;
365 }
366 return (int)next;
367 }
369 VkImageView vku_create_view(VkImage img, VkFormat fmt)
370 {
371 VkImageView view;
372 VkImageViewCreateInfo iv;
374 memset(&iv, 0, sizeof iv);
375 iv.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
376 iv.image = img;
377 iv.viewType = VK_IMAGE_VIEW_TYPE_2D;
378 iv.format = fmt;
379 iv.components.r = iv.components.g = iv.components.b = iv.components.a =
380 VK_COMPONENT_SWIZZLE_IDENTITY;
381 iv.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
382 iv.subresourceRange.baseMipLevel = 0;
383 iv.subresourceRange.levelCount = 1;
384 iv.subresourceRange.baseArrayLayer = 0;
385 iv.subresourceRange.layerCount = 1;
387 if(vkCreateImageView(vkdev, &iv, 0, &view) != 0) {
388 fprintf(stderr, "vku_create_view failed\n");
389 return 0;
390 }
391 return view;
392 }
394 void vku_destroy_view(VkImageView view)
395 {
396 vkDestroyImageView(vkdev, view, 0);
397 }
399 VkFramebuffer vku_create_framebuffer(VkImageView view, int width, int height, VkRenderPass rpass)
400 {
401 VkFramebuffer fb;
402 VkFramebufferCreateInfo fbinf;
404 memset(&fbinf, 0, sizeof fbinf);
405 fbinf.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
406 fbinf.renderPass = rpass;
407 fbinf.attachmentCount = 1;
408 fbinf.pAttachments = &view;
409 fbinf.width = width;
410 fbinf.height = height;
411 fbinf.layers = 1;
413 if(vkCreateFramebuffer(vkdev, &fbinf, 0, &fb) != 0) {
414 fprintf(stderr, "vku_create_framebuffer failed\n");
415 return 0;
416 }
417 return fb;
418 }
420 void vku_destroy_framebuffer(VkFramebuffer fb)
421 {
422 vkDestroyFramebuffer(vkdev, fb, 0);
423 }
425 void vku_present(VkSwapchainKHR sc, int img_idx)
426 {
427 VkPresentInfoKHR inf;
428 VkResult res;
429 uint32_t index = img_idx;
431 memset(&inf, 0, sizeof inf);
432 inf.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
433 inf.swapchainCount = 1;
434 inf.pSwapchains = &sc;
435 inf.pImageIndices = &index;
436 inf.pResults = &res;
438 vkQueuePresentKHR(vkq, &inf);
439 }
441 struct vku_buffer *vku_create_buffer(int sz, unsigned int usage)
442 {
443 struct vku_buffer *buf;
444 VkBufferCreateInfo binfo;
446 if(!(buf = malloc(sizeof *buf))) {
447 perror("failed to allocate vk_buffer structure");
448 return 0;
449 }
451 memset(&binfo, 0, sizeof binfo);
452 binfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
453 binfo.size = sz;
454 binfo.usage = usage;
455 binfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
457 if(vkCreateBuffer(vkdev, &binfo, 0, &buf->buf) != 0) {
458 fprintf(stderr, "failed to create %d byte buffer (usage: %x)\n", sz, usage);
459 return 0;
460 }
461 // TODO back with memory
462 return buf;
463 }
465 void vku_destroy_buffer(struct vku_buffer *buf)
466 {
467 if(buf) {
468 vkDestroyBuffer(vkdev, buf->buf, 0);
469 free(buf);
470 }
471 }
473 void vku_cmd_copybuf(VkCommandBuffer cmdbuf, VkBuffer dest, int doffs,
474 VkBuffer src, int soffs, int size)
475 {
476 VkBufferCopy copy;
477 copy.size = size;
478 copy.srcOffset = soffs;
479 copy.dstOffset = doffs;
481 vkCmdCopyBuffer(cmdbuf, src, dest, 1, &copy);
482 }
485 VkRenderPass vku_create_renderpass(VkFormat cfmt, VkFormat dsfmt)
486 {
487 int count = 1; /* always assume we have a color attachment for now */
488 VkAttachmentDescription at[2];
489 VkAttachmentReference colref, dsref;
490 VkSubpassDescription subpass;
491 VkRenderPass pass;
492 VkRenderPassCreateInfo rpinf;
494 colref.attachment = 0;
495 colref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
496 dsref.attachment = 1;
497 dsref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
499 memset(&subpass, 0, sizeof subpass);
500 subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
501 subpass.colorAttachmentCount = 1;
502 subpass.pColorAttachments = &colref;
504 at[0].format = cfmt;
505 at[0].samples = VK_SAMPLE_COUNT_1_BIT; /* TODO multisampling */
506 at[0].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
507 at[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
508 at[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
509 at[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
510 at[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
511 at[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
513 if(dsfmt != VK_FORMAT_UNDEFINED) {
514 at[1].format = dsfmt;
515 at[1].samples = VK_SAMPLE_COUNT_1_BIT;
516 at[1].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
517 at[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
518 at[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
519 at[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
520 at[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
521 at[1].finalLayout = VK_IMAGE_LAYOUT_UNDEFINED;
523 subpass.pDepthStencilAttachment = &dsref;
524 count++;
525 }
527 memset(&rpinf, 0, sizeof rpinf);
528 rpinf.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
529 rpinf.attachmentCount = count;
530 rpinf.pAttachments = at;
531 rpinf.subpassCount = 1;
532 rpinf.pSubpasses = &subpass;
534 if(vkCreateRenderPass(vkdev, &rpinf, 0, &pass) != 0) {
535 fprintf(stderr, "vku_create_renderpass: failed to create renderpass\n");
536 return 0;
537 }
539 return pass;
540 }
542 void vku_destroy_renderpass(VkRenderPass rpass)
543 {
544 vkDestroyRenderPass(vkdev, rpass, 0);
545 }
548 #ifdef VK_USE_PLATFORM_XLIB_KHR
549 int vku_xlib_usable_visual(Display *dpy, VisualID vid)
550 {
551 return vkGetPhysicalDeviceXlibPresentationSupportKHR(phys_devices[sel_dev],
552 sel_qfamily, dpy, vid);
553 }
555 VkSurfaceKHR vku_xlib_create_surface(Display *dpy, Window win)
556 {
557 VkSurfaceKHR surf;
558 VkXlibSurfaceCreateInfoKHR inf;
560 memset(&inf, 0, sizeof inf);
561 inf.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
562 inf.dpy = dpy;
563 inf.window = win;
565 if(vkCreateXlibSurfaceKHR(vk, &inf, 0, &surf) != 0) {
566 return 0;
567 }
568 return surf;
569 }
571 #endif /* VK_USE_PLATFORM_XLIB_KHR */
573 static const char *get_device_name(VkPhysicalDeviceType type)
574 {
575 switch(type) {
576 case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
577 return "integrated GPU";
578 case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
579 return "discrete GPU";
580 case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
581 return "virtual GPU";
582 case VK_PHYSICAL_DEVICE_TYPE_CPU:
583 return "CPU";
584 default:
585 break;
586 }
587 return "unknown";
588 }
590 static const char *get_mem_prop_flag_string(VkMemoryPropertyFlags flags)
591 {
592 static char str[128];
594 str[0] = 0;
595 if(flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
596 strcat(str, "device-local ");
597 }
598 if(flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
599 strcat(str, "host-visible ");
600 }
601 if(flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) {
602 strcat(str, "host-coherent ");
603 }
604 if(flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) {
605 strcat(str, "host-cached ");
606 }
607 if(flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) {
608 strcat(str, "lazily-allocated ");
609 }
611 if(!*str) {
612 strcat(str, "-");
613 }
614 return str;
615 }
617 static const char *get_queue_flag_string(VkQueueFlagBits flags)
618 {
619 static char str[128];
621 str[0] = 0;
622 if(flags & VK_QUEUE_GRAPHICS_BIT) {
623 strcat(str, "graphics ");
624 }
625 if(flags & VK_QUEUE_COMPUTE_BIT) {
626 strcat(str, "compute ");
627 }
628 if(flags & VK_QUEUE_TRANSFER_BIT) {
629 strcat(str, "transfer ");
630 }
631 if(flags & VK_QUEUE_SPARSE_BINDING_BIT) {
632 strcat(str, "sparse-binding ");
633 }
634 if(!*str) {
635 strcat(str, "-");
636 }
637 return str;
638 }
640 static int ver_major(uint32_t ver)
641 {
642 return (ver >> 22) & 0x3ff;
643 }
645 static int ver_minor(uint32_t ver)
646 {
647 return (ver >> 12) & 0x3ff;
648 }
650 static int ver_patch(uint32_t ver)
651 {
652 return ver & 0xfff;
653 }
655 static const char *mem_size_str(long sz)
656 {
657 static char str[64];
658 static const char *unitstr[] = { "bytes", "KB", "MB", "GB", "TB", "PB", 0 };
659 int uidx = 0;
660 sz *= 10;
662 while(sz >= 10240 && unitstr[uidx + 1]) {
663 sz /= 1024;
664 ++uidx;
665 }
666 sprintf(str, "%ld.%ld %s", sz / 10, sz % 10, unitstr[uidx]);
667 return str;
668 }