vulkan_test2

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