vulkan_test2

annotate src/vku.c @ 3:68e1c437343f

more vulkan
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 22 Sep 2017 01:01:10 +0300
parents
children c31c4115d44a
rev   line source
nuclear@3 1 #include <stdio.h>
nuclear@3 2 #include <stdlib.h>
nuclear@3 3 #include <string.h>
nuclear@3 4 #include <alloca.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
nuclear@3 16 VkInstance vk;
nuclear@3 17 VkDevice vkdev;
nuclear@3 18 VkQueue vkq;
nuclear@3 19
nuclear@3 20 int vku_create_dev(void)
nuclear@3 21 {
nuclear@3 22 int i, j;
nuclear@3 23 VkInstanceCreateInfo inst_info;
nuclear@3 24 VkPhysicalDevice *devices;
nuclear@3 25 VkDeviceCreateInfo dev_info;
nuclear@3 26 VkDeviceQueueCreateInfo queue_info;
nuclear@3 27 VkCommandPoolCreateInfo cmdpool_info;
nuclear@3 28 uint32_t num_devices;
nuclear@3 29 int sel_dev = -1;
nuclear@3 30 int sel_qfamily = -1;
nuclear@3 31 float qprio = 0.0f;
nuclear@3 32
nuclear@3 33 memset(&inst_info, 0, sizeof inst_info);
nuclear@3 34 inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
nuclear@3 35
nuclear@3 36 if(vkCreateInstance(&inst_info, 0, &vk) != 0) {
nuclear@3 37 fprintf(stderr, "failed to create vulkan instance\n");
nuclear@3 38 return -1;
nuclear@3 39 }
nuclear@3 40 printf("created vulkan instance\n");
nuclear@3 41
nuclear@3 42 if(vkEnumeratePhysicalDevices(vk, &num_devices, 0) != 0) {
nuclear@3 43 fprintf(stderr, "failed to enumerate vulkan physical devices\n");
nuclear@3 44 return -1;
nuclear@3 45 }
nuclear@3 46 devices = alloca(num_devices * sizeof *devices);
nuclear@3 47 if(vkEnumeratePhysicalDevices(vk, &num_devices, devices) != 0) {
nuclear@3 48 fprintf(stderr, "failed to enumerate vulkan physical devices\n");
nuclear@3 49 return -1;
nuclear@3 50 }
nuclear@3 51 printf("found %u physical device(s)\n", (unsigned int)num_devices);
nuclear@3 52
nuclear@3 53 for(i=0; i<(int)num_devices; i++) {
nuclear@3 54 VkPhysicalDeviceProperties dev_prop;
nuclear@3 55 VkPhysicalDeviceMemoryProperties mem_prop;
nuclear@3 56 VkQueueFamilyProperties *qprop;
nuclear@3 57 uint32_t qprop_count;
nuclear@3 58
nuclear@3 59 vkGetPhysicalDeviceProperties(devices[i], &dev_prop);
nuclear@3 60
nuclear@3 61 printf("Device %d: %s\n", i, dev_prop.deviceName);
nuclear@3 62 printf(" type: %s\n", get_device_name(dev_prop.deviceType));
nuclear@3 63 printf(" API version: %d.%d.%d\n", ver_major(dev_prop.apiVersion), ver_minor(dev_prop.apiVersion),
nuclear@3 64 ver_patch(dev_prop.apiVersion));
nuclear@3 65 printf(" driver version: %d.%d.%d\n", ver_major(dev_prop.driverVersion), ver_minor(dev_prop.driverVersion),
nuclear@3 66 ver_patch(dev_prop.driverVersion));
nuclear@3 67 printf(" vendor id: %x device id: %x\n", dev_prop.vendorID, dev_prop.deviceID);
nuclear@3 68
nuclear@3 69
nuclear@3 70 vkGetPhysicalDeviceMemoryProperties(devices[i], &mem_prop);
nuclear@3 71 printf(" %d memory heaps:\n", mem_prop.memoryHeapCount);
nuclear@3 72 for(j=0; j<mem_prop.memoryHeapCount; j++) {
nuclear@3 73 VkMemoryHeap heap = mem_prop.memoryHeaps[j];
nuclear@3 74 printf(" Heap %d - size: %s, flags: %s\n", j, mem_size_str(heap.size),
nuclear@3 75 heap.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT ? "device-local" : "-");
nuclear@3 76 }
nuclear@3 77 printf(" %d memory types:\n", mem_prop.memoryTypeCount);
nuclear@3 78 for(j=0; j<mem_prop.memoryTypeCount; j++) {
nuclear@3 79 VkMemoryType type = mem_prop.memoryTypes[j];
nuclear@3 80 printf(" Type %d - heap: %d, flags: %s\n", j, type.heapIndex,
nuclear@3 81 get_mem_prop_flag_string(type.propertyFlags));
nuclear@3 82 }
nuclear@3 83
nuclear@3 84 vkGetPhysicalDeviceQueueFamilyProperties(devices[i], &qprop_count, 0);
nuclear@3 85 if(qprop_count <= 0) {
nuclear@3 86 continue;
nuclear@3 87 }
nuclear@3 88 qprop = malloc(qprop_count * sizeof *qprop);
nuclear@3 89 vkGetPhysicalDeviceQueueFamilyProperties(devices[i], &qprop_count, qprop);
nuclear@3 90
nuclear@3 91 for(j=0; j<qprop_count; j++) {
nuclear@3 92 printf(" Queue family %d:\n", j);
nuclear@3 93 printf(" flags: %s\n", get_queue_flag_string(qprop[j].queueFlags));
nuclear@3 94 printf(" num queues: %u\n", qprop[j].queueCount);
nuclear@3 95
nuclear@3 96 if(qprop[j].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
nuclear@3 97 sel_dev = i;
nuclear@3 98 sel_qfamily = j;
nuclear@3 99 }
nuclear@3 100 }
nuclear@3 101 free(qprop);
nuclear@3 102 }
nuclear@3 103
nuclear@3 104 if(sel_dev < 0 || sel_qfamily < 0) {
nuclear@3 105 fprintf(stderr, "failed to find any device with a graphics-capable command queue\n");
nuclear@3 106 vkDestroyDevice(vkdev, 0);
nuclear@3 107 return -1;
nuclear@3 108 }
nuclear@3 109
nuclear@3 110 /* create device & command queue */
nuclear@3 111 memset(&queue_info, 0, sizeof queue_info);
nuclear@3 112 queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
nuclear@3 113 queue_info.queueFamilyIndex = sel_qfamily;
nuclear@3 114 queue_info.queueCount = 1;
nuclear@3 115 queue_info.pQueuePriorities = &qprio;
nuclear@3 116
nuclear@3 117 memset(&dev_info, 0, sizeof dev_info);
nuclear@3 118 dev_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
nuclear@3 119 dev_info.queueCreateInfoCount = 1;
nuclear@3 120 dev_info.pQueueCreateInfos = &queue_info;
nuclear@3 121
nuclear@3 122 if(vkCreateDevice(devices[sel_dev], &dev_info, 0, &vkdev) != 0) {
nuclear@3 123 fprintf(stderr, "failed to create device %d\n", sel_dev);
nuclear@3 124 return -1;
nuclear@3 125 }
nuclear@3 126 printf("created device %d\n", sel_dev);
nuclear@3 127
nuclear@3 128 vkGetDeviceQueue(vkdev, sel_qfamily, 0, &vkq);
nuclear@3 129
nuclear@3 130 /* create command buffer pool */
nuclear@3 131 memset(&cmdpool_info, 0, sizeof cmdpool_info);
nuclear@3 132 cmdpool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
nuclear@3 133 cmdpool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
nuclear@3 134 cmdpool_info.queueFamilyIndex = sel_qfamily;
nuclear@3 135
nuclear@3 136 if(vkCreateCommandPool(vkdev, &cmdpool_info, 0, &vkcmdpool) != 0) {
nuclear@3 137 fprintf(stderr, "failed to get command quque!\n");
nuclear@3 138 return -1;
nuclear@3 139 }
nuclear@3 140
nuclear@3 141 return 0;
nuclear@3 142 }
nuclear@3 143
nuclear@3 144 void vku_cleanup(void)
nuclear@3 145 {
nuclear@3 146 if(vk) {
nuclear@3 147 vkDeviceWaitIdle(vkdev);
nuclear@3 148 vkDestroyDevice(vkdev, 0);
nuclear@3 149 vkDestroyInstance(vk, 0);
nuclear@3 150 vk = 0;
nuclear@3 151 }
nuclear@3 152 }
nuclear@3 153
nuclear@3 154 struct vk_buffer *vku_create_buffer(int sz, unsigned int usage)
nuclear@3 155 {
nuclear@3 156 struct vk_buffer *buf;
nuclear@3 157 VkBufferCreateInfo binfo;
nuclear@3 158
nuclear@3 159 if(!(buf = malloc(sizeof *buf))) {
nuclear@3 160 perror("failed to allocate vk_buffer structure");
nuclear@3 161 return 0;
nuclear@3 162 }
nuclear@3 163
nuclear@3 164 memset(&binfo, 0, sizeof binfo);
nuclear@3 165 binfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
nuclear@3 166 binfo.size = sz;
nuclear@3 167 binfo.usage = usage;
nuclear@3 168 binfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
nuclear@3 169
nuclear@3 170 if(vkCreateBuffer(vkdev, &binfo, 0, &buf->buf) != 0) {
nuclear@3 171 fprintf(stderr, "failed to create %d byte buffer (usage: %x)\n", sz, usage);
nuclear@3 172 return 0;
nuclear@3 173 }
nuclear@3 174 // TODO back with memory
nuclear@3 175 return buf;
nuclear@3 176 }
nuclear@3 177
nuclear@3 178 void vku_destroy_buffer(struct vk_buffer *buf)
nuclear@3 179 {
nuclear@3 180 if(buf) {
nuclear@3 181 vkDestroyBuffer(vkdev, buf->buf, 0);
nuclear@3 182 free(buf);
nuclear@3 183 }
nuclear@3 184 }
nuclear@3 185
nuclear@3 186 static const char *get_device_name(VkPhysicalDeviceType type)
nuclear@3 187 {
nuclear@3 188 switch(type) {
nuclear@3 189 case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
nuclear@3 190 return "integrated GPU";
nuclear@3 191 case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
nuclear@3 192 return "discrete GPU";
nuclear@3 193 case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
nuclear@3 194 return "virtual GPU";
nuclear@3 195 case VK_PHYSICAL_DEVICE_TYPE_CPU:
nuclear@3 196 return "CPU";
nuclear@3 197 default:
nuclear@3 198 break;
nuclear@3 199 }
nuclear@3 200 return "unknown";
nuclear@3 201 }
nuclear@3 202
nuclear@3 203 static const char *get_mem_prop_flag_string(VkMemoryPropertyFlags flags)
nuclear@3 204 {
nuclear@3 205 static char str[128];
nuclear@3 206
nuclear@3 207 str[0] = 0;
nuclear@3 208 if(flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
nuclear@3 209 strcat(str, "device-local ");
nuclear@3 210 }
nuclear@3 211 if(flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
nuclear@3 212 strcat(str, "host-visible ");
nuclear@3 213 }
nuclear@3 214 if(flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) {
nuclear@3 215 strcat(str, "host-coherent ");
nuclear@3 216 }
nuclear@3 217 if(flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) {
nuclear@3 218 strcat(str, "host-cached ");
nuclear@3 219 }
nuclear@3 220 if(flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) {
nuclear@3 221 strcat(str, "lazily-allocated ");
nuclear@3 222 }
nuclear@3 223
nuclear@3 224 if(!*str) {
nuclear@3 225 strcat(str, "-");
nuclear@3 226 }
nuclear@3 227 return str;
nuclear@3 228 }
nuclear@3 229
nuclear@3 230 static const char *get_queue_flag_string(VkQueueFlagBits flags)
nuclear@3 231 {
nuclear@3 232 static char str[128];
nuclear@3 233
nuclear@3 234 str[0] = 0;
nuclear@3 235 if(flags & VK_QUEUE_GRAPHICS_BIT) {
nuclear@3 236 strcat(str, "graphics ");
nuclear@3 237 }
nuclear@3 238 if(flags & VK_QUEUE_COMPUTE_BIT) {
nuclear@3 239 strcat(str, "compute ");
nuclear@3 240 }
nuclear@3 241 if(flags & VK_QUEUE_TRANSFER_BIT) {
nuclear@3 242 strcat(str, "transfer ");
nuclear@3 243 }
nuclear@3 244 if(flags & VK_QUEUE_SPARSE_BINDING_BIT) {
nuclear@3 245 strcat(str, "sparse-binding ");
nuclear@3 246 }
nuclear@3 247 if(!*str) {
nuclear@3 248 strcat(str, "-");
nuclear@3 249 }
nuclear@3 250 return str;
nuclear@3 251 }
nuclear@3 252
nuclear@3 253 static int ver_major(uint32_t ver)
nuclear@3 254 {
nuclear@3 255 return (ver >> 22) & 0x3ff;
nuclear@3 256 }
nuclear@3 257
nuclear@3 258 static int ver_minor(uint32_t ver)
nuclear@3 259 {
nuclear@3 260 return (ver >> 12) & 0x3ff;
nuclear@3 261 }
nuclear@3 262
nuclear@3 263 static int ver_patch(uint32_t ver)
nuclear@3 264 {
nuclear@3 265 return ver & 0xfff;
nuclear@3 266 }
nuclear@3 267
nuclear@3 268 static const char *mem_size_str(long sz)
nuclear@3 269 {
nuclear@3 270 static char str[64];
nuclear@3 271 static const char *unitstr[] = { "bytes", "KB", "MB", "GB", "TB", "PB", 0 };
nuclear@3 272 int uidx = 0;
nuclear@3 273 sz *= 10;
nuclear@3 274
nuclear@3 275 while(sz >= 10240 && unitstr[uidx + 1]) {
nuclear@3 276 sz /= 1024;
nuclear@3 277 ++uidx;
nuclear@3 278 }
nuclear@3 279 sprintf(str, "%ld.%ld %s", sz / 10, sz % 10, unitstr[uidx]);
nuclear@3 280 return str;
nuclear@3 281 }