1 #include <vulkan/vulkan.h>
11 /* global variables */
13 VkSwapchainKHR vkswapchain;
14 VkImage *vkswapchain_images;
15 int vknext_swapchain_image;
16 VkSurfaceKHR vksurface;
18 VkPhysicalDevice vkpdev;
21 VkCommandPool vkcmdpool;
22 VkCommandBuffer vkcmdbuf; /* primary command buffer */
25 /* static functions */
26 static const char *get_device_name_str(VkPhysicalDeviceType type);
27 static const char *get_memtype_flags_str(VkMemoryPropertyFlags flags);
28 static const char *get_queue_flags_str(VkQueueFlags flags);
29 static const char *get_mem_size_str(long sz);
30 static int ver_major(uint32_t ver);
31 static int ver_minor(uint32_t ver);
32 static int ver_patch(uint32_t ver);
34 /* static variables */
35 static VkPhysicalDevice *phys_devices;
38 static int sel_qfamily;
40 static VkExtensionProperties *vkext, *vkdevext;
41 static uint32_t vkext_count, vkdevext_count;
43 bool vku_have_extension(const char *name)
47 vkEnumerateInstanceExtensionProperties(0, &vkext_count, 0);
49 if(!(vkext = (VkExtensionProperties *)malloc(vkext_count * sizeof *vkext))) {
50 perror("failed to allocate instance extension list");
53 vkEnumerateInstanceExtensionProperties(0, &vkext_count, vkext);
55 printf("instance extensions:\n");
56 for(int i=0; i<(int)vkext_count; i++) {
57 printf(" %s (ver: %u)\n", vkext[i].extensionName, (unsigned int)vkext[i].specVersion);
62 for(int i=0; i<(int)vkext_count; i++) {
63 if(strcmp(vkext[i].extensionName, name) == 0) {
70 bool vku_have_device_extension(const char *name)
72 if(sel_dev < 0) return false;
76 vkEnumerateDeviceExtensionProperties(phys_devices[sel_dev], 0, &vkdevext_count, 0);
78 if(!(vkdevext = (VkExtensionProperties *)malloc(vkdevext_count * sizeof *vkdevext))) {
79 perror("failed to allocate device extension list");
82 vkEnumerateDeviceExtensionProperties(phys_devices[sel_dev], 0, &vkdevext_count, vkdevext);
84 printf("selected device extensions:\n");
85 for(int i=0; i<(int)vkdevext_count; i++) {
86 printf(" %s (ver: %u)\n", vkdevext[i].extensionName, (unsigned int)vkdevext[i].specVersion);
91 for(int i=0; i<(int)vkdevext_count; i++) {
92 if(strcmp(vkdevext[i].extensionName, name) == 0) {
99 bool vku_create_device()
101 VkInstanceCreateInfo inst_info;
102 VkDeviceCreateInfo dev_info;
103 VkDeviceQueueCreateInfo queue_info;
104 VkCommandPoolCreateInfo cmdpool_info;
105 uint32_t num_devices;
108 static const char *ext_names[] = {
109 "VK_KHR_xcb_surface",
113 static const char *devext_names[] = {
120 for(unsigned int i=0; i<sizeof ext_names / sizeof *ext_names; i++) {
121 if(!vku_have_extension(ext_names[i])) {
122 fprintf(stderr, "required extension (%s) not found\n", ext_names[i]);
126 memset(&inst_info, 0, sizeof inst_info);
127 inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
128 inst_info.ppEnabledExtensionNames = ext_names;
129 inst_info.enabledExtensionCount = sizeof ext_names / sizeof *ext_names;
131 if(vkCreateInstance(&inst_info, 0, &vkinst) != 0) {
132 fprintf(stderr, "failed to create vulkan instance\n");
135 printf("created vulkan instance\n");
136 if(vkEnumeratePhysicalDevices(vkinst, &num_devices, 0) != 0) {
137 fprintf(stderr, "failed to enumerate vulkan physical devices\n");
140 phys_devices = (VkPhysicalDevice *)malloc(num_devices * sizeof *phys_devices);
141 if(vkEnumeratePhysicalDevices(vkinst, &num_devices, phys_devices) != 0) {
142 fprintf(stderr, "failed to enumerate vulkan physical devices\n");
145 printf("found %u physical device(s)\n", (unsigned int)num_devices);
147 for(int i=0; i<(int)num_devices; i++) {
148 VkPhysicalDeviceProperties dev_prop;
149 VkPhysicalDeviceMemoryProperties mem_prop;
150 VkQueueFamilyProperties *qprop;
151 uint32_t qprop_count;
153 vkGetPhysicalDeviceProperties(phys_devices[i], &dev_prop);
155 printf("Device %d: %s\n", i, dev_prop.deviceName);
156 printf(" type: %s\n", get_device_name_str(dev_prop.deviceType));
157 printf(" API version: %d.%d.%d\n", ver_major(dev_prop.apiVersion), ver_minor(dev_prop.apiVersion),
158 ver_patch(dev_prop.apiVersion));
159 printf(" driver version: %d.%d.%d\n", ver_major(dev_prop.driverVersion), ver_minor(dev_prop.driverVersion),
160 ver_patch(dev_prop.driverVersion));
161 printf(" vendor id: %x device id: %x\n", dev_prop.vendorID, dev_prop.deviceID);
164 vkGetPhysicalDeviceMemoryProperties(phys_devices[i], &mem_prop);
165 printf(" %d memory heaps:\n", mem_prop.memoryHeapCount);
166 for(unsigned int j=0; j<mem_prop.memoryHeapCount; j++) {
167 VkMemoryHeap heap = mem_prop.memoryHeaps[j];
168 printf(" Heap %d - size: %s, flags: %s\n", j, get_mem_size_str(heap.size),
169 heap.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT ? "device-local" : "-");
171 printf(" %d memory types:\n", mem_prop.memoryTypeCount);
172 for(unsigned int j=0; j<mem_prop.memoryTypeCount; j++) {
173 VkMemoryType type = mem_prop.memoryTypes[j];
174 printf(" Type %d - heap: %d, flags: %s\n", j, type.heapIndex,
175 get_memtype_flags_str(type.propertyFlags));
178 vkGetPhysicalDeviceQueueFamilyProperties(phys_devices[i], &qprop_count, 0);
179 if(qprop_count <= 0) {
182 qprop = (VkQueueFamilyProperties *)malloc(qprop_count * sizeof *qprop);
183 vkGetPhysicalDeviceQueueFamilyProperties(phys_devices[i], &qprop_count, qprop);
185 for(unsigned int j=0; j<qprop_count; j++) {
186 printf(" Queue family %d:\n", j);
187 printf(" flags: %s\n", get_queue_flags_str(qprop[j].queueFlags));
188 printf(" num queues: %u\n", qprop[j].queueCount);
190 if(qprop[j].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
198 if(sel_dev < 0 || sel_qfamily < 0) {
199 fprintf(stderr, "failed to find any device with a graphics-capable command queue\n");
200 vkDestroyDevice(vkdev, 0);
204 for(unsigned int i=0; i<sizeof devext_names / sizeof *devext_names; i++) {
205 if(!vku_have_device_extension(devext_names[i])) {
206 fprintf(stderr, "required extension (%s) not found on the selected device (%d)\n",
207 ext_names[i], sel_dev);
212 /* create device & command queue */
213 memset(&queue_info, 0, sizeof queue_info);
214 queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
215 queue_info.queueFamilyIndex = sel_qfamily;
216 queue_info.queueCount = 1;
217 queue_info.pQueuePriorities = &qprio;
219 memset(&dev_info, 0, sizeof dev_info);
220 dev_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
221 dev_info.queueCreateInfoCount = 1;
222 dev_info.pQueueCreateInfos = &queue_info;
223 dev_info.enabledExtensionCount = sizeof devext_names / sizeof *devext_names;
224 dev_info.ppEnabledExtensionNames = devext_names;
226 if(vkCreateDevice(phys_devices[sel_dev], &dev_info, 0, &vkdev) != 0) {
227 fprintf(stderr, "failed to create device %d\n", sel_dev);
230 printf("created device %d\n", sel_dev);
232 vkpdev = phys_devices[sel_dev];
233 vkqfamily = sel_qfamily;
235 vkGetDeviceQueue(vkdev, sel_qfamily, 0, &vkq);
237 /* create command buffer pool */
238 memset(&cmdpool_info, 0, sizeof cmdpool_info);
239 cmdpool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
240 cmdpool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
241 cmdpool_info.queueFamilyIndex = sel_qfamily;
243 if(vkCreateCommandPool(vkdev, &cmdpool_info, 0, &vkcmdpool) != 0) {
244 fprintf(stderr, "failed to get command quque!\n");
248 if(!(vkcmdbuf = vku_alloc_cmdbuf(vkcmdpool, VK_COMMAND_BUFFER_LEVEL_PRIMARY))) {
249 fprintf(stderr, "failed to create primary command buffer\n");
259 vkDeviceWaitIdle(vkdev);
260 vkDestroyCommandPool(vkdev, vkcmdpool, 0);
261 vkDestroyDevice(vkdev, 0);
262 vkDestroyInstance(vkinst, 0);
270 VkCommandBuffer vku_alloc_cmdbuf(VkCommandPool pool, VkCommandBufferLevel level)
272 VkCommandBuffer cmdbuf;
273 VkCommandBufferAllocateInfo inf;
275 memset(&inf, 0, sizeof inf);
276 inf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
277 inf.commandPool = pool;
279 inf.commandBufferCount = 1;
281 if(vkAllocateCommandBuffers(vkdev, &inf, &cmdbuf) != 0) {
287 void vku_free_cmdbuf(VkCommandPool pool, VkCommandBuffer buf)
289 vkFreeCommandBuffers(vkdev, pool, 1, &buf);
292 void vku_begin_cmdbuf(VkCommandBuffer buf, unsigned int flags)
294 VkCommandBufferBeginInfo inf;
296 memset(&inf, 0, sizeof inf);
297 inf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
300 vkBeginCommandBuffer(buf, &inf);
304 void vku_end_cmdbuf(VkCommandBuffer buf)
306 vkEndCommandBuffer(buf);
309 void vku_reset_cmdbuf(VkCommandBuffer buf)
311 vkResetCommandBuffer(buf, 0);
314 void vku_submit_cmdbuf(VkQueue q, VkCommandBuffer buf, VkFence done_fence)
318 memset(&info, 0, sizeof info);
319 info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
320 info.commandBufferCount = 1;
321 info.pCommandBuffers = &buf;
323 vkQueueSubmit(q, 1, &info, done_fence);
326 VkSwapchainKHR vku_create_swapchain(VkSurfaceKHR surf, int xsz, int ysz, int n,
327 VkPresentModeKHR pmode, VkSwapchainKHR prev)
330 VkSwapchainCreateInfoKHR inf;
332 memset(&inf, 0, sizeof inf);
333 inf.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
335 inf.minImageCount = n;
336 inf.imageFormat = VK_FORMAT_B8G8R8A8_UNORM; /* TODO enumerate and choose */
337 inf.imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
338 inf.imageExtent.width = xsz;
339 inf.imageExtent.height = ysz;
340 inf.imageArrayLayers = 1;
341 inf.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
342 inf.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; /* XXX make this an option? */
343 inf.preTransform = VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR;
344 inf.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
345 inf.presentMode = pmode;
346 inf.oldSwapchain = prev;
348 if(vkCreateSwapchainKHR(vkdev, &inf, 0, &sc) != 0) {
354 VkImage *vku_get_swapchain_images(VkSwapchainKHR sc, int *count)
359 if(vkGetSwapchainImagesKHR(vkdev, sc, &nimg, 0) != 0) {
362 if(!(images = (VkImage *)malloc(nimg * sizeof *images))) {
365 vkGetSwapchainImagesKHR(vkdev, sc, &nimg, images);
367 if(count) *count = (int)nimg;
371 int vku_get_next_image(VkSwapchainKHR sc)
375 if(vkAcquireNextImageKHR(vkdev, sc, UINT64_MAX, 0, 0, &next) != 0) {
381 void vku_present(VkSwapchainKHR sc, int img_idx)
383 VkPresentInfoKHR inf;
385 uint32_t index = img_idx;
387 memset(&inf, 0, sizeof inf);
388 inf.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
389 inf.swapchainCount = 1;
390 inf.pSwapchains = ≻
391 inf.pImageIndices = &index;
394 vkQueuePresentKHR(vkq, &inf);
397 struct vku_buffer *vku_create_buffer(int sz, unsigned int usage)
399 struct vku_buffer *buf;
400 VkBufferCreateInfo binfo;
402 if(!(buf = (vku_buffer *)malloc(sizeof *buf))) {
403 perror("failed to allocate vk_buffer structure");
407 memset(&binfo, 0, sizeof binfo);
408 binfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
411 binfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
413 if(vkCreateBuffer(vkdev, &binfo, 0, &buf->buf) != 0) {
414 fprintf(stderr, "failed to create %d byte buffer (usage: %x)\n", sz, usage);
417 // TODO back with memory
421 void vku_destroy_buffer(struct vku_buffer *buf)
424 vkDestroyBuffer(vkdev, buf->buf, 0);
429 void vku_cmd_copybuf(VkCommandBuffer cmdbuf, VkBuffer dest, int doffs,
430 VkBuffer src, int soffs, int size)
434 copy.srcOffset = soffs;
435 copy.dstOffset = doffs;
437 vkCmdCopyBuffer(cmdbuf, src, dest, 1, ©);
442 static bool create_instance()
444 uint32_t layer_count = 0;
445 std::vector<const char *> enabled_layers;
447 if(vkEnumerateInstanceLayerProperties(&layer_count, 0) != VK_SUCCESS) {
448 fprintf(stderr, "Failed to query layer properties.\n");
452 if(layer_count > 0) {
453 VkLayerProperties *layers = (VkLayerProperties *)alloca(layer_count * sizeof *layers);
454 vkEnumerateInstanceLayerProperties(&layer_count, layers);
455 for(uint32_t i=0; i<layer_count; i++) {
456 if(strcmp(layers[i].layerName, "VK_LAYER_LUNARG_standard_validation")) {
457 enabled_layers.push_back(layers[i].layerName);
462 uint32_t extensions_count = 0;
463 std::vector<const char *> enabled_extensions;
465 if(vkEnumerateInstanceExtensionProperties(0, &extensions_count, 0) != VK_SUCCESS) {
466 fprintf(stderr, "Failed to enumerate instance extension properties\n");
470 if(extensions_count > 0) {
471 VkExtensionProperties *extensions = (VkExtensionProperties *)alloca(extensions_count * sizeof *extensions);
472 vkEnumerateInstanceExtensionProperties(0, &extensions_count, extensions);
474 for(uint32_t i=0; i<extensions_count; i++) {
475 printf("Extension %u: %s %u.\n", i, extensions[i].extensionName, extensions[i].specVersion);
476 //enable all the available extensions
477 enabled_extensions.push_back(extensions[i].extensionName);
478 enabled_extension_names.push_back(std::string(extensions[i].extensionName));
482 VkInstanceCreateInfo create_info;
483 memset(&create_info, 0, sizeof create_info);
484 create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
486 if(!enabled_layers.empty()) {
487 create_info.enabledLayerCount = enabled_layers.size();
488 create_info.ppEnabledLayerNames = enabled_layers.data();
491 if(!enabled_extensions.empty()) {
492 create_info.enabledExtensionCount = enabled_extensions.size();
493 create_info.ppEnabledExtensionNames = enabled_extensions.data();
496 if(vkCreateInstance(&create_info, 0, &inst) != VK_SUCCESS) {
497 fprintf(stderr, "Failed to create instance.\n");
507 static bool create_device()
513 if(vkEnumeratePhysicalDevices(inst, &dev_count, 0) != VK_SUCCESS) {
514 fprintf(stderr, "Failed to enumerate physical devices.\n");
517 printf("%u devices found.\n", (unsigned int)dev_count);
519 VkPhysicalDevice *phys_dev = (VkPhysicalDevice *)alloca(dev_count * sizeof *phys_dev);
520 vkEnumeratePhysicalDevices(inst, &dev_count, phys_dev);
521 VkPhysicalDeviceMemoryProperties memprop;
523 for(uint32_t i=0; i<dev_count; i++) {
524 VkPhysicalDeviceProperties dev_props;
525 vkGetPhysicalDeviceProperties(phys_dev[i], &dev_props);
528 vkGetPhysicalDeviceMemoryProperties(phys_dev[i], &memprop);
529 printf("\tNumber of heaps: %u\n", memprop.memoryHeapCount);
530 for(uint32_t j=0; j<memprop.memoryHeapCount; j++) {
531 printf("\t\tHeap %u size: %lu\n", j, (unsigned long)memprop.memoryHeaps[j].size);
532 printf("\t\tHeap %u flags: %s\n", j, heap_flags_str(memprop.memoryHeaps[j].flags));
535 printf("\tMemory types: %u\n", memprop.memoryTypeCount);
536 for(uint32_t j=0; j<memprop.memoryTypeCount; j++) {
537 printf("\t\tType %u heap index: %u\n", j, memprop.memoryTypes[j].heapIndex);
538 printf("\t\tType %u flags: %s\n", j, memtype_flags_str(memprop.memoryTypes[j].propertyFlags));
542 VkPhysicalDeviceFeatures features;
543 vkGetPhysicalDeviceFeatures(phys_dev[i], &features);
547 vkGetPhysicalDeviceQueueFamilyProperties(phys_dev[i], &qfam_count, 0);
548 printf("\tQueue Families: %u\n", qfam_count);
549 VkQueueFamilyProperties *qfam_props = new VkQueueFamilyProperties[qfam_count];
550 vkGetPhysicalDeviceQueueFamilyProperties(phys_dev[i], &qfam_count, qfam_props);
551 for(uint32_t j=0; j<qfam_count; j++) {
552 printf("\t\tFamily %u flags: %s\n", j, queue_flags_str(qfam_props[j].queueFlags));
553 printf("\t\tFamily %u number of queues: %u\n", j, qfam_props[j].queueCount);
555 if((qfam_props[j].queueFlags & VK_QUEUE_GRAPHICS_BIT) && (pdev_idx == -1)) {
558 num_queues = qfam_props[j].queueCount;
561 delete [] qfam_props;
565 fprintf(stderr, "No suitable devices found.\n");
569 pdev = *(phys_dev + pdev_idx);
570 qfamily_idx = qfam_idx;
572 uint32_t layer_count;
573 if(vkEnumerateDeviceLayerProperties(pdev, &layer_count, 0) != VK_SUCCESS) {
574 fprintf(stderr, "Failed to enumerate device layers.\n");
577 if(layer_count > 0) {
578 VkLayerProperties *layers = (VkLayerProperties*)alloca(layer_count * sizeof *layers);
579 vkEnumerateDeviceLayerProperties(pdev, &layer_count, layers);
580 printf("%u layers found.\n", layer_count);
581 for(uint32_t i=0; i<layer_count; i++) {
582 printf("Layer %u: %s (%u, %u)\n", i, layers[i].layerName,
583 layers[i].specVersion, layers[i].implementationVersion);
584 printf("\tDesc: %s\n", layers[i].description);
588 VkDeviceCreateInfo dev_info;
589 memset(&dev_info, 0, sizeof dev_info);
590 dev_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
592 VkDeviceQueueCreateInfo dev_qinfo;
593 memset(&dev_qinfo, 0, sizeof dev_qinfo);
594 dev_qinfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
595 dev_qinfo.queueFamilyIndex = qfam_idx;
596 dev_qinfo.queueCount = 1;
598 dev_info.queueCreateInfoCount = 1;
599 dev_info.pQueueCreateInfos = &dev_qinfo;
601 if(vkCreateDevice(pdev, &dev_info, 0, &device) != VK_SUCCESS) {
602 fprintf(stderr, "Failed to create logical device.\n");
606 vkGetPhysicalDeviceMemoryProperties(pdev, &memprop);
607 for(uint32_t j=0; j<memprop.memoryTypeCount; j++) {
608 if(memprop.memoryTypes[j].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
610 printf("Selected device memory index: %u\n", device_mem_idx);
618 static const char *dev_type_str(VkPhysicalDeviceType type)
621 case VK_PHYSICAL_DEVICE_TYPE_OTHER:
623 case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
624 return "integrated GPU";
625 case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
626 return "discrete GPU";
627 case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
628 return "virtual GPU";
629 case VK_PHYSICAL_DEVICE_TYPE_CPU:
637 static const char *heap_flags_str(VkMemoryHeapFlags flags)
639 static std::string str;
641 if(flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) {
642 str += "device-local ";
649 static const char *memtype_flags_str(VkMemoryPropertyFlags flags)
651 static std::string str;
653 if(flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
654 str += "device-local ";
656 if(flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
657 str += "host-visible ";
659 if(flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) {
660 str += "host-coherent ";
662 if(flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) {
663 str += "host-cached ";
665 if(flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) {
666 str += "lazily-allocated ";
673 static const char *queue_flags_str(VkQueueFlags flags)
675 static std::string str;
677 if(flags & VK_QUEUE_GRAPHICS_BIT)
679 if(flags & VK_QUEUE_COMPUTE_BIT)
681 if(flags & VK_QUEUE_TRANSFER_BIT)
683 if(flags & VK_QUEUE_SPARSE_BINDING_BIT)
684 str += "sparse-binding ";
691 const char *vku_get_vulkan_error_str(VkResult error)
696 errmsg = std::string("VK_SUCCESS");
699 errmsg = std::string("VK_NOT_READY");
702 errmsg = std::string("VK_TIMEOUT");
705 errmsg = std::string("VK_EVENT_SET");
708 errmsg = std::string("VK_EVENT_RESET");
711 errmsg = std::string("VK_EVENT");
713 case VK_ERROR_OUT_OF_HOST_MEMORY:
714 errmsg = std::string("VK_ERROR_OUT_OF_HOST_MEMORY");
716 case VK_ERROR_OUT_OF_DEVICE_MEMORY:
717 errmsg = std::string("VK_ERROR_OUT_OF_DEVICE_MEMORY");
719 case VK_ERROR_INITIALIZATION_FAILED:
720 errmsg = std::string("VK_ERROR_INITIALIZATION_FAILED");
722 case VK_ERROR_DEVICE_LOST:
723 errmsg = std::string("VK_ERROR_DEVICE_LOST");
725 case VK_ERROR_MEMORY_MAP_FAILED:
726 errmsg = std::string("VK_ERROR_MEMORY_MAP_FAILED");
728 case VK_ERROR_LAYER_NOT_PRESENT:
729 errmsg = std::string("VK_ERROR_LAYER_NOT_PRESENT");
731 case VK_ERROR_EXTENSION_NOT_PRESENT:
732 errmsg = std::string("VK_ERROR_EXTENSION_NOT_PRESENT");
734 case VK_ERROR_FEATURE_NOT_PRESENT:
735 errmsg = std::string("VK_ERROR_FEATURE_NOT_PRESENT");
737 case VK_ERROR_INCOMPATIBLE_DRIVER:
738 errmsg = std::string("VK_ERROR_INCOMPATIBLE_DRIVER");
740 case VK_ERROR_TOO_MANY_OBJECTS:
741 errmsg = std::string("VK_ERROR_TOO_MANY_OBJECTS");
743 case VK_ERROR_FORMAT_NOT_SUPPORTED:
744 errmsg = std::string("VK_ERROR_FORMAT_NOT_SUPPORTED");
746 case VK_ERROR_FRAGMENTED_POOL:
747 errmsg = std::string("VK_ERROR_FRAGMENTED_POOL");
750 errmsg = std::string("UNKNOWN");
754 return errmsg.c_str();
757 static const char *get_device_name_str(VkPhysicalDeviceType type)
760 case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
761 return "integrated GPU";
762 case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
763 return "discrete GPU";
764 case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
765 return "virtual GPU";
766 case VK_PHYSICAL_DEVICE_TYPE_CPU:
774 static const char *get_memtype_flags_str(VkMemoryPropertyFlags flags)
776 static char str[128];
779 if(flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
780 strcat(str, "device-local ");
782 if(flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
783 strcat(str, "host-visible ");
785 if(flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) {
786 strcat(str, "host-coherent ");
788 if(flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) {
789 strcat(str, "host-cached ");
791 if(flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) {
792 strcat(str, "lazily-allocated ");
801 static const char *get_queue_flags_str(VkQueueFlags flags)
803 static char str[128];
806 if(flags & VK_QUEUE_GRAPHICS_BIT) {
807 strcat(str, "graphics ");
809 if(flags & VK_QUEUE_COMPUTE_BIT) {
810 strcat(str, "compute ");
812 if(flags & VK_QUEUE_TRANSFER_BIT) {
813 strcat(str, "transfer ");
815 if(flags & VK_QUEUE_SPARSE_BINDING_BIT) {
816 strcat(str, "sparse-binding ");
824 static int ver_major(uint32_t ver)
826 return (ver >> 22) & 0x3ff;
829 static int ver_minor(uint32_t ver)
831 return (ver >> 12) & 0x3ff;
834 static int ver_patch(uint32_t ver)
839 static const char *get_mem_size_str(long sz)
842 static const char *unitstr[] = { "bytes", "KB", "MB", "GB", "TB", "PB", 0 };
846 while(sz >= 10240 && unitstr[uidx + 1]) {
850 sprintf(str, "%ld.%ld %s", sz / 10, sz % 10, unitstr[uidx]);