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@5
|
315 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@5
|
324 inf.imageFormat = VK_FORMAT_B8G8R8A8_UNORM; /* TODO enumerate and choose */
|
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@6
|
369 void vku_present(VkSwapchainKHR sc, int img_idx)
|
nuclear@6
|
370 {
|
nuclear@6
|
371 VkPresentInfoKHR inf;
|
nuclear@6
|
372 VkResult res;
|
nuclear@6
|
373 uint32_t index = img_idx;
|
nuclear@6
|
374
|
nuclear@6
|
375 memset(&inf, 0, sizeof inf);
|
nuclear@6
|
376 inf.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
nuclear@6
|
377 inf.swapchainCount = 1;
|
nuclear@6
|
378 inf.pSwapchains = ≻
|
nuclear@6
|
379 inf.pImageIndices = &index;
|
nuclear@6
|
380 inf.pResults = &res;
|
nuclear@6
|
381
|
nuclear@6
|
382 vkQueuePresentKHR(vkq, &inf);
|
nuclear@6
|
383 }
|
nuclear@6
|
384
|
nuclear@4
|
385 struct vku_buffer *vku_create_buffer(int sz, unsigned int usage)
|
nuclear@4
|
386 {
|
nuclear@4
|
387 struct vku_buffer *buf;
|
nuclear@3
|
388 VkBufferCreateInfo binfo;
|
nuclear@3
|
389
|
nuclear@3
|
390 if(!(buf = malloc(sizeof *buf))) {
|
nuclear@3
|
391 perror("failed to allocate vk_buffer structure");
|
nuclear@3
|
392 return 0;
|
nuclear@3
|
393 }
|
nuclear@3
|
394
|
nuclear@3
|
395 memset(&binfo, 0, sizeof binfo);
|
nuclear@3
|
396 binfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
nuclear@3
|
397 binfo.size = sz;
|
nuclear@3
|
398 binfo.usage = usage;
|
nuclear@3
|
399 binfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
nuclear@3
|
400
|
nuclear@3
|
401 if(vkCreateBuffer(vkdev, &binfo, 0, &buf->buf) != 0) {
|
nuclear@3
|
402 fprintf(stderr, "failed to create %d byte buffer (usage: %x)\n", sz, usage);
|
nuclear@3
|
403 return 0;
|
nuclear@3
|
404 }
|
nuclear@3
|
405 // TODO back with memory
|
nuclear@3
|
406 return buf;
|
nuclear@3
|
407 }
|
nuclear@3
|
408
|
nuclear@4
|
409 void vku_destroy_buffer(struct vku_buffer *buf)
|
nuclear@3
|
410 {
|
nuclear@3
|
411 if(buf) {
|
nuclear@3
|
412 vkDestroyBuffer(vkdev, buf->buf, 0);
|
nuclear@3
|
413 free(buf);
|
nuclear@3
|
414 }
|
nuclear@3
|
415 }
|
nuclear@3
|
416
|
nuclear@4
|
417 void vku_cmd_copybuf(VkCommandBuffer cmdbuf, VkBuffer dest, int doffs,
|
nuclear@4
|
418 VkBuffer src, int soffs, int size)
|
nuclear@4
|
419 {
|
nuclear@4
|
420 VkBufferCopy copy;
|
nuclear@4
|
421 copy.size = size;
|
nuclear@4
|
422 copy.srcOffset = soffs;
|
nuclear@4
|
423 copy.dstOffset = doffs;
|
nuclear@4
|
424
|
nuclear@4
|
425 vkCmdCopyBuffer(cmdbuf, src, dest, 1, ©);
|
nuclear@4
|
426 }
|
nuclear@4
|
427
|
nuclear@12
|
428
|
nuclear@13
|
429 VkRenderPass vku_create_renderpass(VkFormat cfmt, VkFormat dsfmt)
|
nuclear@13
|
430 {
|
nuclear@13
|
431 int count = 1; /* always assume we have a color attachment for now */
|
nuclear@13
|
432 VkAttachmentDescription at[2];
|
nuclear@13
|
433 VkAttachmentReference colref, dsref;
|
nuclear@13
|
434 VkSubpassDescription subpass;
|
nuclear@13
|
435 VkRenderPass pass;
|
nuclear@13
|
436 VkRenderPassCreateInfo rpinf;
|
nuclear@13
|
437
|
nuclear@13
|
438 colref.attachment = 0;
|
nuclear@13
|
439 colref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
nuclear@13
|
440 dsref.attachment = 1;
|
nuclear@13
|
441 dsref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
nuclear@13
|
442
|
nuclear@13
|
443 memset(&subpass, 0, sizeof subpass);
|
nuclear@13
|
444 subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
nuclear@13
|
445 subpass.colorAttachmentCount = 1;
|
nuclear@13
|
446 subpass.pColorAttachments = &colref;
|
nuclear@13
|
447
|
nuclear@13
|
448 at[0].format = cfmt;
|
nuclear@13
|
449 at[0].samples = VK_SAMPLE_COUNT_1_BIT; /* TODO multisampling */
|
nuclear@13
|
450 at[0].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
nuclear@13
|
451 at[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
nuclear@13
|
452 at[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
nuclear@13
|
453 at[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
nuclear@13
|
454 at[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
nuclear@13
|
455 at[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
nuclear@13
|
456
|
nuclear@13
|
457 if(dsfmt != VK_FORMAT_UNDEFINED) {
|
nuclear@13
|
458 at[1].format = dsfmt;
|
nuclear@13
|
459 at[1].samples = VK_SAMPLE_COUNT_1_BIT;
|
nuclear@13
|
460 at[1].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
nuclear@13
|
461 at[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
nuclear@13
|
462 at[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
nuclear@13
|
463 at[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
|
nuclear@13
|
464 at[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
nuclear@13
|
465 at[1].finalLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
nuclear@13
|
466
|
nuclear@13
|
467 subpass.pDepthStencilAttachment = &dsref;
|
nuclear@13
|
468 count++;
|
nuclear@13
|
469 }
|
nuclear@13
|
470
|
nuclear@13
|
471 memset(&rpinf, 0, sizeof rpinf);
|
nuclear@13
|
472 rpinf.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
nuclear@13
|
473 rpinf.attachmentCount = count;
|
nuclear@13
|
474 rpinf.pAttachments = at;
|
nuclear@13
|
475 rpinf.subpassCount = 1;
|
nuclear@13
|
476 rpinf.pSubpasses = &subpass;
|
nuclear@13
|
477
|
nuclear@13
|
478 if(vkCreateRenderPass(vkdev, &rpinf, 0, &pass) != 0) {
|
nuclear@13
|
479 fprintf(stderr, "vku_create_renderpass: failed to create renderpass\n");
|
nuclear@13
|
480 return 0;
|
nuclear@13
|
481 }
|
nuclear@13
|
482
|
nuclear@13
|
483 return pass;
|
nuclear@13
|
484 }
|
nuclear@13
|
485
|
nuclear@13
|
486 void vku_destroy_renderpass(VkRenderPass rpass)
|
nuclear@13
|
487 {
|
nuclear@13
|
488 vkDestroyRenderPass(vkdev, rpass, 0);
|
nuclear@13
|
489 }
|
nuclear@13
|
490
|
nuclear@13
|
491
|
nuclear@4
|
492 #ifdef VK_USE_PLATFORM_XLIB_KHR
|
nuclear@4
|
493 int vku_xlib_usable_visual(Display *dpy, VisualID vid)
|
nuclear@4
|
494 {
|
nuclear@4
|
495 return vkGetPhysicalDeviceXlibPresentationSupportKHR(phys_devices[sel_dev],
|
nuclear@4
|
496 sel_qfamily, dpy, vid);
|
nuclear@4
|
497 }
|
nuclear@5
|
498
|
nuclear@5
|
499 VkSurfaceKHR vku_xlib_create_surface(Display *dpy, Window win)
|
nuclear@5
|
500 {
|
nuclear@5
|
501 VkSurfaceKHR surf;
|
nuclear@5
|
502 VkXlibSurfaceCreateInfoKHR inf;
|
nuclear@5
|
503
|
nuclear@5
|
504 memset(&inf, 0, sizeof inf);
|
nuclear@5
|
505 inf.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
|
nuclear@5
|
506 inf.dpy = dpy;
|
nuclear@5
|
507 inf.window = win;
|
nuclear@5
|
508
|
nuclear@5
|
509 if(vkCreateXlibSurfaceKHR(vk, &inf, 0, &surf) != 0) {
|
nuclear@5
|
510 return 0;
|
nuclear@5
|
511 }
|
nuclear@5
|
512 return surf;
|
nuclear@5
|
513 }
|
nuclear@5
|
514
|
nuclear@4
|
515 #endif /* VK_USE_PLATFORM_XLIB_KHR */
|
nuclear@4
|
516
|
nuclear@3
|
517 static const char *get_device_name(VkPhysicalDeviceType type)
|
nuclear@3
|
518 {
|
nuclear@3
|
519 switch(type) {
|
nuclear@3
|
520 case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
|
nuclear@3
|
521 return "integrated GPU";
|
nuclear@3
|
522 case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
|
nuclear@3
|
523 return "discrete GPU";
|
nuclear@3
|
524 case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
|
nuclear@3
|
525 return "virtual GPU";
|
nuclear@3
|
526 case VK_PHYSICAL_DEVICE_TYPE_CPU:
|
nuclear@3
|
527 return "CPU";
|
nuclear@3
|
528 default:
|
nuclear@3
|
529 break;
|
nuclear@3
|
530 }
|
nuclear@3
|
531 return "unknown";
|
nuclear@3
|
532 }
|
nuclear@3
|
533
|
nuclear@3
|
534 static const char *get_mem_prop_flag_string(VkMemoryPropertyFlags flags)
|
nuclear@3
|
535 {
|
nuclear@3
|
536 static char str[128];
|
nuclear@3
|
537
|
nuclear@3
|
538 str[0] = 0;
|
nuclear@3
|
539 if(flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
|
nuclear@3
|
540 strcat(str, "device-local ");
|
nuclear@3
|
541 }
|
nuclear@3
|
542 if(flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
|
nuclear@3
|
543 strcat(str, "host-visible ");
|
nuclear@3
|
544 }
|
nuclear@3
|
545 if(flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) {
|
nuclear@3
|
546 strcat(str, "host-coherent ");
|
nuclear@3
|
547 }
|
nuclear@3
|
548 if(flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) {
|
nuclear@3
|
549 strcat(str, "host-cached ");
|
nuclear@3
|
550 }
|
nuclear@3
|
551 if(flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) {
|
nuclear@3
|
552 strcat(str, "lazily-allocated ");
|
nuclear@3
|
553 }
|
nuclear@3
|
554
|
nuclear@3
|
555 if(!*str) {
|
nuclear@3
|
556 strcat(str, "-");
|
nuclear@3
|
557 }
|
nuclear@3
|
558 return str;
|
nuclear@3
|
559 }
|
nuclear@3
|
560
|
nuclear@3
|
561 static const char *get_queue_flag_string(VkQueueFlagBits flags)
|
nuclear@3
|
562 {
|
nuclear@3
|
563 static char str[128];
|
nuclear@3
|
564
|
nuclear@3
|
565 str[0] = 0;
|
nuclear@3
|
566 if(flags & VK_QUEUE_GRAPHICS_BIT) {
|
nuclear@3
|
567 strcat(str, "graphics ");
|
nuclear@3
|
568 }
|
nuclear@3
|
569 if(flags & VK_QUEUE_COMPUTE_BIT) {
|
nuclear@3
|
570 strcat(str, "compute ");
|
nuclear@3
|
571 }
|
nuclear@3
|
572 if(flags & VK_QUEUE_TRANSFER_BIT) {
|
nuclear@3
|
573 strcat(str, "transfer ");
|
nuclear@3
|
574 }
|
nuclear@3
|
575 if(flags & VK_QUEUE_SPARSE_BINDING_BIT) {
|
nuclear@3
|
576 strcat(str, "sparse-binding ");
|
nuclear@3
|
577 }
|
nuclear@3
|
578 if(!*str) {
|
nuclear@3
|
579 strcat(str, "-");
|
nuclear@3
|
580 }
|
nuclear@3
|
581 return str;
|
nuclear@3
|
582 }
|
nuclear@3
|
583
|
nuclear@3
|
584 static int ver_major(uint32_t ver)
|
nuclear@3
|
585 {
|
nuclear@3
|
586 return (ver >> 22) & 0x3ff;
|
nuclear@3
|
587 }
|
nuclear@3
|
588
|
nuclear@3
|
589 static int ver_minor(uint32_t ver)
|
nuclear@3
|
590 {
|
nuclear@3
|
591 return (ver >> 12) & 0x3ff;
|
nuclear@3
|
592 }
|
nuclear@3
|
593
|
nuclear@3
|
594 static int ver_patch(uint32_t ver)
|
nuclear@3
|
595 {
|
nuclear@3
|
596 return ver & 0xfff;
|
nuclear@3
|
597 }
|
nuclear@3
|
598
|
nuclear@3
|
599 static const char *mem_size_str(long sz)
|
nuclear@3
|
600 {
|
nuclear@3
|
601 static char str[64];
|
nuclear@3
|
602 static const char *unitstr[] = { "bytes", "KB", "MB", "GB", "TB", "PB", 0 };
|
nuclear@3
|
603 int uidx = 0;
|
nuclear@3
|
604 sz *= 10;
|
nuclear@3
|
605
|
nuclear@3
|
606 while(sz >= 10240 && unitstr[uidx + 1]) {
|
nuclear@3
|
607 sz /= 1024;
|
nuclear@3
|
608 ++uidx;
|
nuclear@3
|
609 }
|
nuclear@3
|
610 sprintf(str, "%ld.%ld %s", sz / 10, sz % 10, unitstr[uidx]);
|
nuclear@3
|
611 return str;
|
nuclear@3
|
612 }
|