vulkan_test2
view src/vku.c @ 4:c31c4115d44a
test 2, open window, create queue, etc ...
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Fri, 22 Sep 2017 15:26:29 +0300 |
parents | 68e1c437343f |
children | cec4b0e7fce8 |
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 };
103 sel_dev = -1;
104 sel_qfamily = -1;
106 for(i=0; i<sizeof ext_names / sizeof *ext_names; i++) {
107 if(!vku_have_extension(ext_names[i])) {
108 fprintf(stderr, "required extension (%s) not found\n", ext_names[i]);
109 return -1;
110 }
111 }
113 memset(&inst_info, 0, sizeof inst_info);
114 inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
115 inst_info.ppEnabledExtensionNames = ext_names;
116 inst_info.enabledExtensionCount = sizeof ext_names / sizeof *ext_names;
118 if(vkCreateInstance(&inst_info, 0, &vk) != 0) {
119 fprintf(stderr, "failed to create vulkan instance\n");
120 return -1;
121 }
122 printf("created vulkan instance\n");
124 if(vkEnumeratePhysicalDevices(vk, &num_devices, 0) != 0) {
125 fprintf(stderr, "failed to enumerate vulkan physical devices\n");
126 return -1;
127 }
128 phys_devices = malloc(num_devices * sizeof *phys_devices);
129 if(vkEnumeratePhysicalDevices(vk, &num_devices, phys_devices) != 0) {
130 fprintf(stderr, "failed to enumerate vulkan physical devices\n");
131 return -1;
132 }
133 printf("found %u physical device(s)\n", (unsigned int)num_devices);
135 for(i=0; i<(int)num_devices; i++) {
136 VkPhysicalDeviceProperties dev_prop;
137 VkPhysicalDeviceMemoryProperties mem_prop;
138 VkQueueFamilyProperties *qprop;
139 uint32_t qprop_count;
141 vkGetPhysicalDeviceProperties(phys_devices[i], &dev_prop);
143 printf("Device %d: %s\n", i, dev_prop.deviceName);
144 printf(" type: %s\n", get_device_name(dev_prop.deviceType));
145 printf(" API version: %d.%d.%d\n", ver_major(dev_prop.apiVersion), ver_minor(dev_prop.apiVersion),
146 ver_patch(dev_prop.apiVersion));
147 printf(" driver version: %d.%d.%d\n", ver_major(dev_prop.driverVersion), ver_minor(dev_prop.driverVersion),
148 ver_patch(dev_prop.driverVersion));
149 printf(" vendor id: %x device id: %x\n", dev_prop.vendorID, dev_prop.deviceID);
152 vkGetPhysicalDeviceMemoryProperties(phys_devices[i], &mem_prop);
153 printf(" %d memory heaps:\n", mem_prop.memoryHeapCount);
154 for(j=0; j<mem_prop.memoryHeapCount; j++) {
155 VkMemoryHeap heap = mem_prop.memoryHeaps[j];
156 printf(" Heap %d - size: %s, flags: %s\n", j, mem_size_str(heap.size),
157 heap.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT ? "device-local" : "-");
158 }
159 printf(" %d memory types:\n", mem_prop.memoryTypeCount);
160 for(j=0; j<mem_prop.memoryTypeCount; j++) {
161 VkMemoryType type = mem_prop.memoryTypes[j];
162 printf(" Type %d - heap: %d, flags: %s\n", j, type.heapIndex,
163 get_mem_prop_flag_string(type.propertyFlags));
164 }
166 vkGetPhysicalDeviceQueueFamilyProperties(phys_devices[i], &qprop_count, 0);
167 if(qprop_count <= 0) {
168 continue;
169 }
170 qprop = malloc(qprop_count * sizeof *qprop);
171 vkGetPhysicalDeviceQueueFamilyProperties(phys_devices[i], &qprop_count, qprop);
173 for(j=0; j<qprop_count; j++) {
174 printf(" Queue family %d:\n", j);
175 printf(" flags: %s\n", get_queue_flag_string(qprop[j].queueFlags));
176 printf(" num queues: %u\n", qprop[j].queueCount);
178 if(qprop[j].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
179 sel_dev = i;
180 sel_qfamily = j;
181 }
182 }
183 free(qprop);
184 }
186 if(sel_dev < 0 || sel_qfamily < 0) {
187 fprintf(stderr, "failed to find any device with a graphics-capable command queue\n");
188 vkDestroyDevice(vkdev, 0);
189 return -1;
190 }
192 /* create device & command queue */
193 memset(&queue_info, 0, sizeof queue_info);
194 queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
195 queue_info.queueFamilyIndex = sel_qfamily;
196 queue_info.queueCount = 1;
197 queue_info.pQueuePriorities = &qprio;
199 memset(&dev_info, 0, sizeof dev_info);
200 dev_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
201 dev_info.queueCreateInfoCount = 1;
202 dev_info.pQueueCreateInfos = &queue_info;
204 if(vkCreateDevice(phys_devices[sel_dev], &dev_info, 0, &vkdev) != 0) {
205 fprintf(stderr, "failed to create device %d\n", sel_dev);
206 return -1;
207 }
208 printf("created device %d\n", sel_dev);
210 vkGetDeviceQueue(vkdev, sel_qfamily, 0, &vkq);
212 /* create command buffer pool */
213 memset(&cmdpool_info, 0, sizeof cmdpool_info);
214 cmdpool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
215 cmdpool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
216 cmdpool_info.queueFamilyIndex = sel_qfamily;
218 if(vkCreateCommandPool(vkdev, &cmdpool_info, 0, &vkcmdpool) != 0) {
219 fprintf(stderr, "failed to get command quque!\n");
220 return -1;
221 }
223 if(!(vkcmdbuf = vku_alloc_cmdbuf(vkcmdpool, VK_COMMAND_BUFFER_LEVEL_PRIMARY))) {
224 fprintf(stderr, "failed to create primary command buffer\n");
225 return -1;
226 }
228 return 0;
229 }
231 void vku_cleanup(void)
232 {
233 if(vk) {
234 vkDeviceWaitIdle(vkdev);
235 vkDestroyCommandPool(vkdev, vkcmdpool, 0);
236 vkDestroyDevice(vkdev, 0);
237 vkDestroyInstance(vk, 0);
238 vk = 0;
239 }
241 free(phys_devices);
242 phys_devices = 0;
243 }
245 VkCommandBuffer vku_alloc_cmdbuf(VkCommandPool pool, VkCommandBufferLevel level)
246 {
247 VkCommandBuffer cmdbuf;
248 VkCommandBufferAllocateInfo inf;
250 memset(&inf, 0, sizeof inf);
251 inf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
252 inf.commandPool = pool;
253 inf.level = level;
254 inf.commandBufferCount = 1;
256 if(vkAllocateCommandBuffers(vkdev, &inf, &cmdbuf) != 0) {
257 return 0;
258 }
259 return cmdbuf;
260 }
262 void vku_free_cmdbuf(VkCommandPool pool, VkCommandBuffer buf)
263 {
264 vkFreeCommandBuffers(vkdev, pool, 1, &buf);
265 }
267 void vku_begin_cmdbuf(VkCommandBuffer buf, unsigned int flags)
268 {
269 VkCommandBufferBeginInfo inf;
271 memset(&inf, 0, sizeof inf);
272 inf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
273 inf.flags = flags;
275 vkBeginCommandBuffer(buf, &inf);
276 }
279 void vku_end_cmdbuf(VkCommandBuffer buf)
280 {
281 vkEndCommandBuffer(buf);
282 }
284 void vku_reset_cmdbuf(VkCommandBuffer buf)
285 {
286 vkResetCommandBuffer(buf, 0);
287 }
289 void vku_submit_cmdbuf(VkQueue q, VkCommandBuffer buf, VkFence done_fence)
290 {
291 VkSubmitInfo info;
293 memset(&info, 0, sizeof info);
294 info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
295 info.commandBufferCount = 1;
296 info.pCommandBuffers = &buf;
298 vkQueueSubmit(q, 1, &info, done_fence);
299 }
301 struct vku_buffer *vku_create_buffer(int sz, unsigned int usage)
302 {
303 struct vku_buffer *buf;
304 VkBufferCreateInfo binfo;
306 if(!(buf = malloc(sizeof *buf))) {
307 perror("failed to allocate vk_buffer structure");
308 return 0;
309 }
311 memset(&binfo, 0, sizeof binfo);
312 binfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
313 binfo.size = sz;
314 binfo.usage = usage;
315 binfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
317 if(vkCreateBuffer(vkdev, &binfo, 0, &buf->buf) != 0) {
318 fprintf(stderr, "failed to create %d byte buffer (usage: %x)\n", sz, usage);
319 return 0;
320 }
321 // TODO back with memory
322 return buf;
323 }
325 void vku_destroy_buffer(struct vku_buffer *buf)
326 {
327 if(buf) {
328 vkDestroyBuffer(vkdev, buf->buf, 0);
329 free(buf);
330 }
331 }
333 void vku_cmd_copybuf(VkCommandBuffer cmdbuf, VkBuffer dest, int doffs,
334 VkBuffer src, int soffs, int size)
335 {
336 VkBufferCopy copy;
337 copy.size = size;
338 copy.srcOffset = soffs;
339 copy.dstOffset = doffs;
341 vkCmdCopyBuffer(cmdbuf, src, dest, 1, ©);
342 }
344 #ifdef VK_USE_PLATFORM_XLIB_KHR
345 int vku_xlib_usable_visual(Display *dpy, VisualID vid)
346 {
347 return vkGetPhysicalDeviceXlibPresentationSupportKHR(phys_devices[sel_dev],
348 sel_qfamily, dpy, vid);
349 }
350 #endif /* VK_USE_PLATFORM_XLIB_KHR */
352 static const char *get_device_name(VkPhysicalDeviceType type)
353 {
354 switch(type) {
355 case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
356 return "integrated GPU";
357 case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
358 return "discrete GPU";
359 case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
360 return "virtual GPU";
361 case VK_PHYSICAL_DEVICE_TYPE_CPU:
362 return "CPU";
363 default:
364 break;
365 }
366 return "unknown";
367 }
369 static const char *get_mem_prop_flag_string(VkMemoryPropertyFlags flags)
370 {
371 static char str[128];
373 str[0] = 0;
374 if(flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
375 strcat(str, "device-local ");
376 }
377 if(flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
378 strcat(str, "host-visible ");
379 }
380 if(flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) {
381 strcat(str, "host-coherent ");
382 }
383 if(flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) {
384 strcat(str, "host-cached ");
385 }
386 if(flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) {
387 strcat(str, "lazily-allocated ");
388 }
390 if(!*str) {
391 strcat(str, "-");
392 }
393 return str;
394 }
396 static const char *get_queue_flag_string(VkQueueFlagBits flags)
397 {
398 static char str[128];
400 str[0] = 0;
401 if(flags & VK_QUEUE_GRAPHICS_BIT) {
402 strcat(str, "graphics ");
403 }
404 if(flags & VK_QUEUE_COMPUTE_BIT) {
405 strcat(str, "compute ");
406 }
407 if(flags & VK_QUEUE_TRANSFER_BIT) {
408 strcat(str, "transfer ");
409 }
410 if(flags & VK_QUEUE_SPARSE_BINDING_BIT) {
411 strcat(str, "sparse-binding ");
412 }
413 if(!*str) {
414 strcat(str, "-");
415 }
416 return str;
417 }
419 static int ver_major(uint32_t ver)
420 {
421 return (ver >> 22) & 0x3ff;
422 }
424 static int ver_minor(uint32_t ver)
425 {
426 return (ver >> 12) & 0x3ff;
427 }
429 static int ver_patch(uint32_t ver)
430 {
431 return ver & 0xfff;
432 }
434 static const char *mem_size_str(long sz)
435 {
436 static char str[64];
437 static const char *unitstr[] = { "bytes", "KB", "MB", "GB", "TB", "PB", 0 };
438 int uidx = 0;
439 sz *= 10;
441 while(sz >= 10240 && unitstr[uidx + 1]) {
442 sz /= 1024;
443 ++uidx;
444 }
445 sprintf(str, "%ld.%ld %s", sz / 10, sz % 10, unitstr[uidx]);
446 return str;
447 }