vulkan_test2

view src/vku.c @ 17:f8bd29f124a8

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