rev |
line source |
nuclear@0
|
1 #include <stdio.h>
|
nuclear@0
|
2 #include <stdlib.h>
|
nuclear@0
|
3 #include <string.h>
|
nuclear@0
|
4 #include <stdint.h>
|
nuclear@0
|
5 #include <errno.h>
|
nuclear@0
|
6 #include <alloca.h>
|
nuclear@0
|
7 #include <GLFW/glfw3.h>
|
nuclear@0
|
8
|
nuclear@0
|
9 void keyb(GLFWwindow *win, int key, int sc, int act, int mods);
|
nuclear@0
|
10 int init(void);
|
nuclear@0
|
11 void destroy(void);
|
nuclear@0
|
12 void draw(void);
|
nuclear@0
|
13
|
nuclear@0
|
14 GLFWwindow *win;
|
nuclear@0
|
15 int win_width = 800;
|
nuclear@0
|
16 int win_height = 600;
|
nuclear@0
|
17 int redraw_pending;
|
nuclear@0
|
18
|
nuclear@0
|
19 int main(void)
|
nuclear@0
|
20 {
|
nuclear@0
|
21 if(!glfwInit()) {
|
nuclear@0
|
22 fprintf(stderr, "glfw init failed\n");
|
nuclear@0
|
23 return 1;
|
nuclear@0
|
24 }
|
nuclear@0
|
25
|
nuclear@0
|
26 glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
nuclear@0
|
27 win = glfwCreateWindow(win_width, win_height, "test", 0, 0);
|
nuclear@0
|
28 glfwSetKeyCallback(win, keyb);
|
nuclear@0
|
29
|
nuclear@0
|
30 if(init() == -1) {
|
nuclear@0
|
31 glfwDestroyWindow(win);
|
nuclear@0
|
32 glfwTerminate();
|
nuclear@0
|
33 return 1;
|
nuclear@0
|
34 }
|
nuclear@0
|
35
|
nuclear@0
|
36 redraw_pending = 1;
|
nuclear@0
|
37
|
nuclear@0
|
38 while(!glfwWindowShouldClose(win)) {
|
nuclear@0
|
39 glfwWaitEvents();
|
nuclear@0
|
40
|
nuclear@0
|
41 if(redraw_pending) {
|
nuclear@0
|
42 redraw_pending = 0;
|
nuclear@0
|
43 draw();
|
nuclear@0
|
44 }
|
nuclear@0
|
45 }
|
nuclear@0
|
46
|
nuclear@0
|
47 destroy();
|
nuclear@0
|
48 glfwDestroyWindow(win);
|
nuclear@0
|
49 glfwTerminate();
|
nuclear@0
|
50 return 0;
|
nuclear@0
|
51 }
|
nuclear@0
|
52
|
nuclear@0
|
53 void keyb(GLFWwindow *win, int key, int sc, int act, int mods)
|
nuclear@0
|
54 {
|
nuclear@0
|
55 if(act == GLFW_PRESS) {
|
nuclear@0
|
56 switch(key) {
|
nuclear@0
|
57 case GLFW_KEY_ESCAPE:
|
nuclear@0
|
58 glfwSetWindowShouldClose(win, 1);
|
nuclear@0
|
59 break;
|
nuclear@0
|
60 }
|
nuclear@0
|
61 }
|
nuclear@0
|
62 }
|
nuclear@0
|
63
|
nuclear@0
|
64 /* -------------------------------------------------------------- */
|
nuclear@0
|
65 int create_instance(void);
|
nuclear@0
|
66 int create_surface(void);
|
nuclear@0
|
67 int choose_phys_dev(void);
|
nuclear@0
|
68 int create_device(void);
|
nuclear@0
|
69 int create_swapchain(void);
|
nuclear@0
|
70 int create_imgviews(void);
|
nuclear@0
|
71 int create_rendpass(void);
|
nuclear@0
|
72 int create_pipeline(void);
|
nuclear@0
|
73 int create_framebuf(void);
|
nuclear@0
|
74 int create_cmdpool(void);
|
nuclear@0
|
75 int create_cmdbuf(void);
|
nuclear@0
|
76 int create_semaphores(void);
|
nuclear@0
|
77 VkShaderModule load_shader(const char *fname);
|
nuclear@0
|
78
|
nuclear@0
|
79 VkInstance vk;
|
nuclear@0
|
80 VkPhysicalDevice vkpdev;
|
nuclear@0
|
81 int vkqfam_idx = -1;
|
nuclear@0
|
82 VkDevice vkdev;
|
nuclear@0
|
83 VkQueue vkq;
|
nuclear@0
|
84 VkSurfaceKHR vksurf;
|
nuclear@0
|
85 VkSurfaceCapabilitiesKHR vksurf_caps;
|
nuclear@0
|
86 int vksurf_numfmt, vksurf_selfmt;
|
nuclear@0
|
87 VkSurfaceFormatKHR *vksurf_fmt;
|
nuclear@0
|
88 VkSwapchainKHR vksc;
|
nuclear@0
|
89 int vksc_numimg;
|
nuclear@0
|
90 VkImage *vksc_img;
|
nuclear@0
|
91 VkExtent2D vksc_extent;
|
nuclear@0
|
92 VkImageView *vksc_view;
|
nuclear@0
|
93 VkRenderPass vkrpass;
|
nuclear@0
|
94 VkPipelineLayout vkpipe_layout;
|
nuclear@0
|
95 VkPipeline vkpipe;
|
nuclear@0
|
96 VkFramebuffer *vksc_fb;
|
nuclear@0
|
97 VkCommandPool vkcmdpool;
|
nuclear@0
|
98 VkCommandBuffer *vksc_cmdbuf;
|
nuclear@0
|
99 VkSemaphore sem_gotimg, sem_drawdone;
|
nuclear@0
|
100
|
nuclear@0
|
101 int init(void)
|
nuclear@0
|
102 {
|
nuclear@0
|
103 if(create_instance() == -1) return -1;
|
nuclear@0
|
104 if(create_surface() == -1) return -1;
|
nuclear@0
|
105 if(choose_phys_dev() == -1) return -1;
|
nuclear@0
|
106 if(create_device() == -1) return -1;
|
nuclear@0
|
107 if(create_swapchain() == -1) return -1;
|
nuclear@0
|
108 if(create_imgviews() == -1) return -1;
|
nuclear@0
|
109 if(create_rendpass() == -1) return -1;
|
nuclear@0
|
110 if(create_pipeline() == -1) return -1;
|
nuclear@0
|
111 if(create_framebuf() == -1) return -1;
|
nuclear@0
|
112 if(create_cmdpool() == -1) return -1;
|
nuclear@0
|
113 if(create_cmdbuf() == -1) return -1;
|
nuclear@0
|
114 if(create_semaphores() == -1) return -1;
|
nuclear@0
|
115 return 0;
|
nuclear@0
|
116 }
|
nuclear@0
|
117
|
nuclear@0
|
118 void destroy(void)
|
nuclear@0
|
119 {
|
nuclear@0
|
120 int i;
|
nuclear@0
|
121
|
nuclear@0
|
122 if(sem_gotimg) vkDestroySemaphore(vkdev, sem_gotimg, 0);
|
nuclear@0
|
123 if(sem_drawdone) vkDestroySemaphore(vkdev, sem_drawdone, 0);
|
nuclear@0
|
124 if(vkcmdpool) vkDestroyCommandPool(vkdev, vkcmdpool, 0);
|
nuclear@0
|
125 if(vksc_fb) {
|
nuclear@0
|
126 for(i=0; i<vksc_numimg; i++) {
|
nuclear@0
|
127 vkDestroyFramebuffer(vkdev, vksc_fb[i], 0);
|
nuclear@0
|
128 }
|
nuclear@0
|
129 }
|
nuclear@0
|
130 if(vkpipe) vkDestroyPipeline(vkdev, vkpipe, 0);
|
nuclear@0
|
131 if(vkpipe_layout) vkDestroyPipelineLayout(vkdev, vkpipe_layout, 0);
|
nuclear@0
|
132 if(vkrpass) vkDestroyRenderPass(vkdev, vkrpass, 0);
|
nuclear@0
|
133 if(vksc_view) {
|
nuclear@0
|
134 for(i=0; i<vksc_numimg; i++) {
|
nuclear@0
|
135 vkDestroyImageView(vkdev, vksc_view[i], 0);
|
nuclear@0
|
136 }
|
nuclear@0
|
137 }
|
nuclear@0
|
138 if(vksc) vkDestroySwapchainKHR(vkdev, vksc, 0);
|
nuclear@0
|
139 if(vkdev) vkDestroyDevice(vkdev, 0);
|
nuclear@0
|
140 if(vksurf) vkDestroySurfaceKHR(vk, vksurf, 0);
|
nuclear@0
|
141 if(vk) vkDestroyInstance(vk, 0);
|
nuclear@0
|
142 }
|
nuclear@0
|
143
|
nuclear@0
|
144 void draw(void)
|
nuclear@0
|
145 {
|
nuclear@0
|
146 uint32_t img_idx;
|
nuclear@0
|
147 VkSubmitInfo submit;
|
nuclear@0
|
148 VkPipelineStageFlags wait_stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
nuclear@0
|
149 VkPresentInfoKHR pres;
|
nuclear@0
|
150
|
nuclear@0
|
151 vkAcquireNextImageKHR(vkdev, vksc, UINT64_MAX, sem_gotimg, 0, &img_idx);
|
nuclear@0
|
152
|
nuclear@0
|
153 memset(&submit, 0, sizeof submit);
|
nuclear@0
|
154 submit.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
nuclear@0
|
155 submit.waitSemaphoreCount = 1;
|
nuclear@0
|
156 submit.pWaitSemaphores = &sem_gotimg;
|
nuclear@0
|
157 submit.pWaitDstStageMask = &wait_stages;
|
nuclear@0
|
158 submit.commandBufferCount = 1;
|
nuclear@0
|
159 submit.pCommandBuffers = vksc_cmdbuf + img_idx;
|
nuclear@0
|
160 submit.signalSemaphoreCount = 1;
|
nuclear@0
|
161 submit.pSignalSemaphores = &sem_drawdone;
|
nuclear@0
|
162
|
nuclear@0
|
163 if(vkQueueSubmit(vkq, 1, &submit, 0) != 0) {
|
nuclear@0
|
164 fprintf(stderr, "failed to submit draw commands\n");
|
nuclear@0
|
165 abort();
|
nuclear@0
|
166 }
|
nuclear@0
|
167
|
nuclear@0
|
168 memset(&pres, 0, sizeof pres);
|
nuclear@0
|
169 pres.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
nuclear@0
|
170 pres.waitSemaphoreCount = 1;
|
nuclear@0
|
171 pres.pWaitSemaphores = &sem_drawdone;
|
nuclear@0
|
172 pres.swapchainCount = 1;
|
nuclear@0
|
173 pres.pSwapchains = &vksc;
|
nuclear@0
|
174 pres.pImageIndices = &img_idx;
|
nuclear@0
|
175
|
nuclear@0
|
176 vkQueuePresentKHR(vkq, &pres);
|
nuclear@0
|
177 }
|
nuclear@0
|
178
|
nuclear@0
|
179 int create_instance(void)
|
nuclear@0
|
180 {
|
nuclear@0
|
181 VkApplicationInfo appinf;
|
nuclear@0
|
182 VkInstanceCreateInfo iinf;
|
nuclear@0
|
183 uint32_t num_ext;
|
nuclear@0
|
184 const char **ext;
|
nuclear@0
|
185
|
nuclear@0
|
186 ext = glfwGetRequiredInstanceExtensions(&num_ext);
|
nuclear@0
|
187
|
nuclear@0
|
188 memset(&appinf, 0, sizeof appinf);
|
nuclear@0
|
189 appinf.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
nuclear@0
|
190 appinf.pApplicationName = "test";
|
nuclear@0
|
191 appinf.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
|
nuclear@0
|
192 appinf.pEngineName = "fuckoff";
|
nuclear@0
|
193 appinf.engineVersion = VK_MAKE_VERSION(1, 0, 0);
|
nuclear@0
|
194 appinf.apiVersion = VK_API_VERSION_1_0;
|
nuclear@0
|
195
|
nuclear@0
|
196 memset(&iinf, 0, sizeof iinf);
|
nuclear@0
|
197 iinf.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
nuclear@0
|
198 iinf.pApplicationInfo = &appinf;
|
nuclear@0
|
199 iinf.enabledExtensionCount = num_ext;
|
nuclear@0
|
200 iinf.ppEnabledExtensionNames = ext;
|
nuclear@0
|
201
|
nuclear@0
|
202 if(vkCreateInstance(&iinf, 0, &vk) != 0) {
|
nuclear@0
|
203 fprintf(stderr, "failed to create instance\n");
|
nuclear@0
|
204 return -1;
|
nuclear@0
|
205 }
|
nuclear@0
|
206 return 0;
|
nuclear@0
|
207 }
|
nuclear@0
|
208
|
nuclear@0
|
209 int create_surface(void)
|
nuclear@0
|
210 {
|
nuclear@0
|
211 if(glfwCreateWindowSurface(vk, win, 0, &vksurf) != 0) {
|
nuclear@0
|
212 fprintf(stderr, "failed to create window surface\n");
|
nuclear@0
|
213 return -1;
|
nuclear@0
|
214 }
|
nuclear@0
|
215 return 0;
|
nuclear@0
|
216 }
|
nuclear@0
|
217
|
nuclear@0
|
218 static int is_pdev_skookum(VkPhysicalDevice dev)
|
nuclear@0
|
219 {
|
nuclear@0
|
220 uint32_t i, num_fmt, num_qfam, num_ext;
|
nuclear@0
|
221 VkQueueFamilyProperties *qfam;
|
nuclear@0
|
222 VkExtensionProperties *ext;
|
nuclear@0
|
223 VkPhysicalDeviceProperties prop;
|
nuclear@0
|
224 VkPhysicalDeviceFeatures feat;
|
nuclear@0
|
225 VkBool32 can_pres;
|
nuclear@0
|
226 int have_swap_ext;
|
nuclear@0
|
227
|
nuclear@0
|
228 vkGetPhysicalDeviceProperties(dev, &prop);
|
nuclear@0
|
229 vkGetPhysicalDeviceFeatures(dev, &feat);
|
nuclear@0
|
230
|
nuclear@0
|
231 /* check if we have the swapchain extension */
|
nuclear@0
|
232 vkEnumerateDeviceExtensionProperties(dev, 0, &num_ext, 0);
|
nuclear@0
|
233 ext = alloca(num_ext * sizeof *ext);
|
nuclear@0
|
234 vkEnumerateDeviceExtensionProperties(dev, 0, &num_ext, ext);
|
nuclear@0
|
235
|
nuclear@0
|
236 have_swap_ext = 0;
|
nuclear@0
|
237 for(i=0; i<num_ext; i++) {
|
nuclear@0
|
238 if(strcmp(ext[i].extensionName, "VK_KHR_swapchain") == 0) {
|
nuclear@0
|
239 have_swap_ext = 1;
|
nuclear@0
|
240 break;
|
nuclear@0
|
241 }
|
nuclear@0
|
242 }
|
nuclear@0
|
243 if(!have_swap_ext) {
|
nuclear@0
|
244 return 0;
|
nuclear@0
|
245 }
|
nuclear@0
|
246
|
nuclear@0
|
247 /* populate format and present modes arrays, and make sure we have some of each */
|
nuclear@0
|
248 vkGetPhysicalDeviceSurfaceFormatsKHR(dev, vksurf, &num_fmt, 0);
|
nuclear@0
|
249 if(!num_fmt || !(vksurf_fmt = malloc(num_fmt * sizeof *vksurf_fmt))) {
|
nuclear@0
|
250 return 0;
|
nuclear@0
|
251 }
|
nuclear@0
|
252 vksurf_numfmt = num_fmt;
|
nuclear@0
|
253 vkGetPhysicalDeviceSurfaceFormatsKHR(dev, vksurf, &num_fmt, vksurf_fmt);
|
nuclear@0
|
254
|
nuclear@0
|
255 vkGetPhysicalDeviceSurfaceCapabilitiesKHR(dev, vksurf, &vksurf_caps);
|
nuclear@0
|
256
|
nuclear@0
|
257 /* find a queue family which can do graphics and can present */
|
nuclear@0
|
258 vkGetPhysicalDeviceQueueFamilyProperties(dev, &num_qfam, 0);
|
nuclear@0
|
259 qfam = alloca(num_qfam * sizeof *qfam);
|
nuclear@0
|
260 vkGetPhysicalDeviceQueueFamilyProperties(dev, &num_qfam, qfam);
|
nuclear@0
|
261
|
nuclear@0
|
262 vkqfam_idx = -1;
|
nuclear@0
|
263 for(i=0; i<num_qfam; i++) {
|
nuclear@0
|
264 vkGetPhysicalDeviceSurfaceSupportKHR(dev, i, vksurf, &can_pres);
|
nuclear@0
|
265 if(qfam[i].queueCount && (qfam[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) && can_pres) {
|
nuclear@0
|
266 vkqfam_idx = i;
|
nuclear@0
|
267 return 1;
|
nuclear@0
|
268 }
|
nuclear@0
|
269 }
|
nuclear@0
|
270
|
nuclear@0
|
271 free(vksurf_fmt);
|
nuclear@0
|
272 vksurf_fmt = 0;
|
nuclear@0
|
273 vksurf_numfmt = 0;
|
nuclear@0
|
274 return 0;
|
nuclear@0
|
275 }
|
nuclear@0
|
276
|
nuclear@0
|
277 static int choose_pixfmt(void)
|
nuclear@0
|
278 {
|
nuclear@0
|
279 int i, j;
|
nuclear@0
|
280 static const VkFormat pref[] = {
|
nuclear@0
|
281 VK_FORMAT_B8G8R8_UNORM,
|
nuclear@0
|
282 VK_FORMAT_R8G8B8_UNORM,
|
nuclear@0
|
283 VK_FORMAT_B8G8R8A8_UNORM,
|
nuclear@0
|
284 VK_FORMAT_R8G8B8A8_UNORM
|
nuclear@0
|
285 };
|
nuclear@0
|
286
|
nuclear@0
|
287 vksurf_selfmt = 0;
|
nuclear@0
|
288 for(i=0; i<vksurf_numfmt; i++) {
|
nuclear@0
|
289 if(vksurf_fmt[i].colorSpace != VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
|
nuclear@0
|
290 continue;
|
nuclear@0
|
291 }
|
nuclear@0
|
292 for(j=0; j<sizeof pref / sizeof *pref; j++) {
|
nuclear@0
|
293 if(vksurf_fmt[i].format == pref[j]) {
|
nuclear@0
|
294 vksurf_selfmt = i;
|
nuclear@0
|
295 return i;
|
nuclear@0
|
296 }
|
nuclear@0
|
297 }
|
nuclear@0
|
298 }
|
nuclear@0
|
299 return -1;
|
nuclear@0
|
300 }
|
nuclear@0
|
301
|
nuclear@0
|
302 int choose_phys_dev(void)
|
nuclear@0
|
303 {
|
nuclear@0
|
304 uint32_t i, num_pdev;
|
nuclear@0
|
305 VkPhysicalDevice *pdev;
|
nuclear@0
|
306
|
nuclear@0
|
307 vkEnumeratePhysicalDevices(vk, &num_pdev, 0);
|
nuclear@0
|
308 if(!num_pdev) {
|
nuclear@0
|
309 fprintf(stderr, "no vulkan devices found\n");
|
nuclear@0
|
310 return -1;
|
nuclear@0
|
311 }
|
nuclear@0
|
312 pdev = alloca(num_pdev * sizeof *pdev);
|
nuclear@0
|
313 vkEnumeratePhysicalDevices(vk, &num_pdev, pdev);
|
nuclear@0
|
314
|
nuclear@0
|
315 for(i=0; i<num_pdev; i++) {
|
nuclear@0
|
316 if(is_pdev_skookum(pdev[i])) {
|
nuclear@0
|
317 vkpdev = pdev[i];
|
nuclear@0
|
318 break;
|
nuclear@0
|
319 }
|
nuclear@0
|
320 }
|
nuclear@0
|
321 if(!vkpdev) {
|
nuclear@0
|
322 fprintf(stderr, "no skookum device found, vulkan can't chooch\n");
|
nuclear@0
|
323 return -1;
|
nuclear@0
|
324 }
|
nuclear@0
|
325
|
nuclear@0
|
326 choose_pixfmt();
|
nuclear@0
|
327 return 0;
|
nuclear@0
|
328 }
|
nuclear@0
|
329
|
nuclear@0
|
330 int create_device(void)
|
nuclear@0
|
331 {
|
nuclear@0
|
332 static const float prio = 1.0f;
|
nuclear@0
|
333 VkDeviceQueueCreateInfo qinf;
|
nuclear@0
|
334 VkPhysicalDeviceFeatures feat;
|
nuclear@0
|
335 VkDeviceCreateInfo devinf;
|
nuclear@0
|
336
|
nuclear@0
|
337 static const char *extensions[] = {
|
nuclear@0
|
338 "VK_KHR_swapchain"
|
nuclear@0
|
339 };
|
nuclear@0
|
340
|
nuclear@0
|
341 memset(&feat, 0, sizeof feat);
|
nuclear@0
|
342
|
nuclear@0
|
343 memset(&qinf, 0, sizeof qinf);
|
nuclear@0
|
344 qinf.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
nuclear@0
|
345 qinf.queueFamilyIndex = vkqfam_idx;
|
nuclear@0
|
346 qinf.queueCount = 1;
|
nuclear@0
|
347 qinf.pQueuePriorities = &prio;
|
nuclear@0
|
348
|
nuclear@0
|
349 memset(&devinf, 0, sizeof devinf);
|
nuclear@0
|
350 devinf.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
nuclear@0
|
351 devinf.pQueueCreateInfos = &qinf;
|
nuclear@0
|
352 devinf.queueCreateInfoCount = 1;
|
nuclear@0
|
353 devinf.pEnabledFeatures = &feat;
|
nuclear@0
|
354 devinf.enabledExtensionCount = sizeof extensions / sizeof *extensions;
|
nuclear@0
|
355 devinf.ppEnabledExtensionNames = extensions;
|
nuclear@0
|
356
|
nuclear@0
|
357 if(vkCreateDevice(vkpdev, &devinf, 0, &vkdev) != 0) {
|
nuclear@0
|
358 fprintf(stderr, "failed to create vulkan device\n");
|
nuclear@0
|
359 return -1;
|
nuclear@0
|
360 }
|
nuclear@0
|
361
|
nuclear@0
|
362 vkGetDeviceQueue(vkdev, vkqfam_idx, 0, &vkq);
|
nuclear@0
|
363 return 0;
|
nuclear@0
|
364 }
|
nuclear@0
|
365
|
nuclear@0
|
366 int create_swapchain(void)
|
nuclear@0
|
367 {
|
nuclear@0
|
368 uint32_t num;
|
nuclear@0
|
369 VkSwapchainCreateInfoKHR scinf;
|
nuclear@0
|
370
|
nuclear@0
|
371 vksc_extent.width = win_width;
|
nuclear@0
|
372 vksc_extent.height = win_height;
|
nuclear@0
|
373
|
nuclear@0
|
374 memset(&scinf, 0, sizeof scinf);
|
nuclear@0
|
375 scinf.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
nuclear@0
|
376 scinf.surface = vksurf;
|
nuclear@0
|
377 scinf.minImageCount = 2;
|
nuclear@0
|
378 scinf.imageFormat = vksurf_fmt[vksurf_selfmt].format;
|
nuclear@0
|
379 scinf.imageColorSpace = vksurf_fmt[vksurf_selfmt].colorSpace;
|
nuclear@0
|
380 scinf.imageExtent = vksc_extent;
|
nuclear@0
|
381 scinf.imageArrayLayers = 1;
|
nuclear@0
|
382 scinf.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
nuclear@0
|
383 scinf.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
nuclear@0
|
384 scinf.preTransform = vksurf_caps.currentTransform;
|
nuclear@0
|
385 scinf.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
nuclear@0
|
386 scinf.presentMode = VK_PRESENT_MODE_FIFO_KHR;
|
nuclear@0
|
387 scinf.clipped = VK_TRUE;
|
nuclear@0
|
388
|
nuclear@0
|
389 if(vkCreateSwapchainKHR(vkdev, &scinf, 0, &vksc) != 0) {
|
nuclear@0
|
390 fprintf(stderr, "failed to create swapchain\n");
|
nuclear@0
|
391 return -1;
|
nuclear@0
|
392 }
|
nuclear@0
|
393
|
nuclear@0
|
394 vkGetSwapchainImagesKHR(vkdev, vksc, &num, 0);
|
nuclear@0
|
395 if(!num || !(vksc_img = malloc(num * sizeof *vksc_img))) {
|
nuclear@0
|
396 fprintf(stderr, "failed to allocate swapchain image array (%d images)\n", vksc_numimg);
|
nuclear@0
|
397 return -1;
|
nuclear@0
|
398 }
|
nuclear@0
|
399 vkGetSwapchainImagesKHR(vkdev, vksc, &num, vksc_img);
|
nuclear@0
|
400 vksc_numimg = num;
|
nuclear@0
|
401
|
nuclear@0
|
402 return 0;
|
nuclear@0
|
403 }
|
nuclear@0
|
404
|
nuclear@0
|
405 int create_imgviews(void)
|
nuclear@0
|
406 {
|
nuclear@0
|
407 int i;
|
nuclear@0
|
408 VkImageViewCreateInfo ivinf;
|
nuclear@0
|
409
|
nuclear@0
|
410 if(!(vksc_view = malloc(vksc_numimg * sizeof *vksc_view))) {
|
nuclear@0
|
411 fprintf(stderr, "failed to allocate image view array (%d images)\n", vksc_numimg);
|
nuclear@0
|
412 return -1;
|
nuclear@0
|
413 }
|
nuclear@0
|
414
|
nuclear@0
|
415 for(i=0; i<vksc_numimg; i++) {
|
nuclear@0
|
416 memset(&ivinf, 0, sizeof ivinf);
|
nuclear@0
|
417 ivinf.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
nuclear@0
|
418 ivinf.image = vksc_img[i];
|
nuclear@0
|
419 ivinf.format = vksurf_fmt[vksurf_selfmt].format;
|
nuclear@0
|
420 ivinf.components.r = ivinf.components.g = ivinf.components.b =
|
nuclear@0
|
421 ivinf.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
|
nuclear@0
|
422 ivinf.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
nuclear@0
|
423 ivinf.subresourceRange.levelCount = 1;
|
nuclear@0
|
424 ivinf.subresourceRange.layerCount = 1;
|
nuclear@0
|
425
|
nuclear@0
|
426 if(vkCreateImageView(vkdev, &ivinf, 0, vksc_view + i) != 0) {
|
nuclear@0
|
427 fprintf(stderr, "failed to create image view for image %d\n", i);
|
nuclear@0
|
428 return -1;
|
nuclear@0
|
429 }
|
nuclear@0
|
430 }
|
nuclear@0
|
431 return 0;
|
nuclear@0
|
432 }
|
nuclear@0
|
433
|
nuclear@0
|
434 int create_rendpass(void)
|
nuclear@0
|
435 {
|
nuclear@0
|
436 VkAttachmentDescription cat;
|
nuclear@0
|
437 VkAttachmentReference catref;
|
nuclear@0
|
438 VkSubpassDescription subpass;
|
nuclear@0
|
439 VkRenderPassCreateInfo pinf;
|
nuclear@0
|
440 VkSubpassDependency dep;
|
nuclear@0
|
441
|
nuclear@0
|
442 memset(&cat, 0, sizeof cat);
|
nuclear@0
|
443 cat.format = vksurf_fmt[vksurf_selfmt].format;
|
nuclear@0
|
444 cat.samples = VK_SAMPLE_COUNT_1_BIT;
|
nuclear@0
|
445 cat.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
nuclear@0
|
446 cat.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
nuclear@0
|
447 cat.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
nuclear@0
|
448 cat.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
nuclear@0
|
449 cat.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
nuclear@0
|
450 cat.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
nuclear@0
|
451
|
nuclear@0
|
452 memset(&catref, 0, sizeof catref);
|
nuclear@0
|
453 catref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
nuclear@0
|
454
|
nuclear@0
|
455 memset(&subpass, 0, sizeof subpass);
|
nuclear@0
|
456 subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
nuclear@0
|
457 subpass.colorAttachmentCount = 1;
|
nuclear@0
|
458 subpass.pColorAttachments = &catref;
|
nuclear@0
|
459
|
nuclear@0
|
460 memset(&dep, 0, sizeof dep);
|
nuclear@0
|
461 dep.srcSubpass = VK_SUBPASS_EXTERNAL;
|
nuclear@0
|
462 dep.dstSubpass = 0;
|
nuclear@0
|
463 dep.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
nuclear@0
|
464 dep.srcAccessMask = 0;
|
nuclear@0
|
465 dep.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
nuclear@0
|
466 dep.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
nuclear@0
|
467
|
nuclear@0
|
468 memset(&pinf, 0, sizeof pinf);
|
nuclear@0
|
469 pinf.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
nuclear@0
|
470 pinf.attachmentCount = 1;
|
nuclear@0
|
471 pinf.pAttachments = &cat;
|
nuclear@0
|
472 pinf.subpassCount = 1;
|
nuclear@0
|
473 pinf.pSubpasses = &subpass;
|
nuclear@0
|
474 pinf.dependencyCount = 1;
|
nuclear@0
|
475 pinf.pDependencies = &dep;
|
nuclear@0
|
476
|
nuclear@0
|
477 if(vkCreateRenderPass(vkdev, &pinf, 0, &vkrpass) != 0) {
|
nuclear@0
|
478 fprintf(stderr, "failed to create render pass\n");
|
nuclear@0
|
479 return -1;
|
nuclear@0
|
480 }
|
nuclear@0
|
481 return 0;
|
nuclear@0
|
482 }
|
nuclear@0
|
483
|
nuclear@0
|
484 int create_pipeline(void)
|
nuclear@0
|
485 {
|
nuclear@0
|
486 int i;
|
nuclear@0
|
487 VkShaderModule sdr[2];
|
nuclear@0
|
488 VkPipelineShaderStageCreateInfo ssinf[2];
|
nuclear@0
|
489 VkPipelineVertexInputStateCreateInfo vinp;
|
nuclear@0
|
490 VkPipelineInputAssemblyStateCreateInfo vasm;
|
nuclear@0
|
491 VkViewport vport;
|
nuclear@0
|
492 VkRect2D scissor;
|
nuclear@0
|
493 VkPipelineViewportStateCreateInfo vp;
|
nuclear@0
|
494 VkPipelineRasterizationStateCreateInfo rast;
|
nuclear@0
|
495 VkPipelineMultisampleStateCreateInfo msaa;
|
nuclear@0
|
496 VkPipelineColorBlendAttachmentState bat;
|
nuclear@0
|
497 VkPipelineColorBlendStateCreateInfo blend;
|
nuclear@0
|
498 VkPipelineLayoutCreateInfo lay;
|
nuclear@0
|
499 VkGraphicsPipelineCreateInfo pinf;
|
nuclear@0
|
500
|
nuclear@0
|
501 if(!(sdr[0] = load_shader("vertex.glsl")) || !(sdr[1] = load_shader("pixel.glsl"))) {
|
nuclear@0
|
502 return -1;
|
nuclear@0
|
503 }
|
nuclear@0
|
504 memset(ssinf, 0, sizeof ssinf);
|
nuclear@0
|
505 for(i=0; i<2; i++) {
|
nuclear@0
|
506 ssinf[i].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
nuclear@0
|
507 ssinf[i].stage = i == 0 ? VK_SHADER_STAGE_VERTEX_BIT : VK_SHADER_STAGE_FRAGMENT_BIT;
|
nuclear@0
|
508 ssinf[i].module = sdr[i];
|
nuclear@0
|
509 ssinf[i].pName = "main";
|
nuclear@0
|
510 }
|
nuclear@0
|
511
|
nuclear@0
|
512 memset(&vinp, 0, sizeof vinp);
|
nuclear@0
|
513 vinp.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
nuclear@0
|
514
|
nuclear@0
|
515 memset(&vasm, 0, sizeof vasm);
|
nuclear@0
|
516 vasm.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
nuclear@0
|
517 vasm.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
nuclear@0
|
518
|
nuclear@0
|
519 vport.x = vport.y = 0;
|
nuclear@0
|
520 vport.width = vksc_extent.width;
|
nuclear@0
|
521 vport.height = vksc_extent.height;
|
nuclear@0
|
522 vport.minDepth = 0.0f;
|
nuclear@0
|
523 vport.maxDepth = 1.0f;
|
nuclear@0
|
524
|
nuclear@0
|
525 scissor.offset.x = scissor.offset.y = 0;
|
nuclear@0
|
526 scissor.extent = vksc_extent;
|
nuclear@0
|
527
|
nuclear@0
|
528 memset(&vp, 0, sizeof vp);
|
nuclear@0
|
529 vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
nuclear@0
|
530 vp.viewportCount = 1;
|
nuclear@0
|
531 vp.pViewports = &vport;
|
nuclear@0
|
532 vp.scissorCount = 1;
|
nuclear@0
|
533 vp.pScissors = &scissor;
|
nuclear@0
|
534
|
nuclear@0
|
535 memset(&rast, 0, sizeof rast);
|
nuclear@0
|
536 rast.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
nuclear@0
|
537 rast.polygonMode = VK_POLYGON_MODE_FILL;
|
nuclear@0
|
538 rast.lineWidth = 1.0f;
|
nuclear@0
|
539 rast.cullMode = VK_CULL_MODE_BACK_BIT;
|
nuclear@0
|
540 rast.frontFace = VK_FRONT_FACE_CLOCKWISE;
|
nuclear@0
|
541
|
nuclear@0
|
542 memset(&msaa, 0, sizeof msaa);
|
nuclear@0
|
543 msaa.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
nuclear@0
|
544 msaa.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
nuclear@0
|
545 msaa.minSampleShading = 1.0f;
|
nuclear@0
|
546
|
nuclear@0
|
547 memset(&bat, 0, sizeof bat);
|
nuclear@0
|
548 bat.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
|
nuclear@0
|
549 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
nuclear@0
|
550
|
nuclear@0
|
551 memset(&blend, 0, sizeof blend);
|
nuclear@0
|
552 blend.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
|
nuclear@0
|
553 blend.attachmentCount = 1;
|
nuclear@0
|
554 blend.pAttachments = &bat;
|
nuclear@0
|
555
|
nuclear@0
|
556
|
nuclear@0
|
557 memset(&lay, 0, sizeof lay);
|
nuclear@0
|
558 lay.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
nuclear@0
|
559
|
nuclear@0
|
560 if(vkCreatePipelineLayout(vkdev, &lay, 0, &vkpipe_layout) != 0) {
|
nuclear@0
|
561 fprintf(stderr, "failed to create a pipeline layout\n");
|
nuclear@0
|
562 return -1;
|
nuclear@0
|
563 }
|
nuclear@0
|
564
|
nuclear@0
|
565 memset(&pinf, 0, sizeof pinf);
|
nuclear@0
|
566 pinf.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
nuclear@0
|
567 pinf.stageCount = 2;
|
nuclear@0
|
568 pinf.pStages = ssinf;
|
nuclear@0
|
569 pinf.pVertexInputState = &vinp;
|
nuclear@0
|
570 pinf.pInputAssemblyState = &vasm;
|
nuclear@0
|
571 pinf.pViewportState = &vp;
|
nuclear@0
|
572 pinf.pRasterizationState = &rast;
|
nuclear@0
|
573 pinf.pMultisampleState = &msaa;
|
nuclear@0
|
574 pinf.pColorBlendState = &blend;
|
nuclear@0
|
575 pinf.layout = vkpipe_layout;
|
nuclear@0
|
576 pinf.renderPass = vkrpass;
|
nuclear@0
|
577 pinf.basePipelineIndex = -1;
|
nuclear@0
|
578
|
nuclear@0
|
579 if(vkCreateGraphicsPipelines(vkdev, 0, 1, &pinf, 0, &vkpipe) != 0) {
|
nuclear@0
|
580 fprintf(stderr, "failed to create graphics pipeline\n");
|
nuclear@0
|
581 return -1;
|
nuclear@0
|
582 }
|
nuclear@0
|
583
|
nuclear@0
|
584 for(i=0; i<2; i++) {
|
nuclear@0
|
585 vkDestroyShaderModule(vkdev, sdr[i], 0);
|
nuclear@0
|
586 }
|
nuclear@0
|
587 return 0;
|
nuclear@0
|
588 }
|
nuclear@0
|
589
|
nuclear@0
|
590 int create_framebuf(void)
|
nuclear@0
|
591 {
|
nuclear@0
|
592 int i;
|
nuclear@0
|
593 VkFramebufferCreateInfo fbinf;
|
nuclear@0
|
594
|
nuclear@0
|
595 if(!(vksc_fb = malloc(vksc_numimg * sizeof *vksc_fb))) {
|
nuclear@0
|
596 fprintf(stderr, "failed to allocate array for swap chain framebuffers\n");
|
nuclear@0
|
597 return -1;
|
nuclear@0
|
598 }
|
nuclear@0
|
599
|
nuclear@0
|
600 for(i=0; i<vksc_numimg; i++) {
|
nuclear@0
|
601 memset(&fbinf, 0, sizeof fbinf);
|
nuclear@0
|
602 fbinf.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
nuclear@0
|
603 fbinf.renderPass = vkrpass;
|
nuclear@0
|
604 fbinf.attachmentCount = 1;
|
nuclear@0
|
605 fbinf.pAttachments = vksc_view + i;
|
nuclear@0
|
606 fbinf.width = vksc_extent.width;
|
nuclear@0
|
607 fbinf.height = vksc_extent.height;
|
nuclear@0
|
608 fbinf.layers = 1;
|
nuclear@0
|
609
|
nuclear@0
|
610 if(vkCreateFramebuffer(vkdev, &fbinf, 0, vksc_fb + i) != 0) {
|
nuclear@0
|
611 fprintf(stderr, "failed to create framebuffer\n");
|
nuclear@0
|
612 return -1;
|
nuclear@0
|
613 }
|
nuclear@0
|
614 }
|
nuclear@0
|
615
|
nuclear@0
|
616 return 0;
|
nuclear@0
|
617 }
|
nuclear@0
|
618
|
nuclear@0
|
619 int create_cmdpool(void)
|
nuclear@0
|
620 {
|
nuclear@0
|
621 VkCommandPoolCreateInfo cpinf;
|
nuclear@0
|
622
|
nuclear@0
|
623 memset(&cpinf, 0, sizeof cpinf);
|
nuclear@0
|
624 cpinf.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
nuclear@0
|
625 cpinf.queueFamilyIndex = vkqfam_idx;
|
nuclear@0
|
626
|
nuclear@0
|
627 if(vkCreateCommandPool(vkdev, &cpinf, 0, &vkcmdpool) != 0) {
|
nuclear@0
|
628 fprintf(stderr, "failed to create command pool\n");
|
nuclear@0
|
629 return -1;
|
nuclear@0
|
630 }
|
nuclear@0
|
631 return 0;
|
nuclear@0
|
632 }
|
nuclear@0
|
633
|
nuclear@0
|
634 int create_cmdbuf(void)
|
nuclear@0
|
635 {
|
nuclear@0
|
636 int i;
|
nuclear@0
|
637 VkCommandBufferAllocateInfo cbinf;
|
nuclear@0
|
638
|
nuclear@0
|
639 if(!(vksc_cmdbuf = malloc(vksc_numimg * sizeof *vksc_cmdbuf))) {
|
nuclear@0
|
640 fprintf(stderr, "failed to allocate array of command buffers\n");
|
nuclear@0
|
641 return -1;
|
nuclear@0
|
642 }
|
nuclear@0
|
643
|
nuclear@0
|
644 memset(&cbinf, 0, sizeof cbinf);
|
nuclear@0
|
645 cbinf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
nuclear@0
|
646 cbinf.commandPool = vkcmdpool;
|
nuclear@0
|
647 cbinf.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
nuclear@0
|
648 cbinf.commandBufferCount = vksc_numimg;
|
nuclear@0
|
649
|
nuclear@0
|
650 if(vkAllocateCommandBuffers(vkdev, &cbinf, vksc_cmdbuf) != 0) {
|
nuclear@0
|
651 fprintf(stderr, "failed to allocate command buffers\n");
|
nuclear@0
|
652 return -1;
|
nuclear@0
|
653 }
|
nuclear@0
|
654
|
nuclear@0
|
655 /* pre-record command buffers, because why the fuck not */
|
nuclear@0
|
656 for(i=0; i<vksc_numimg; i++) {
|
nuclear@0
|
657 VkCommandBufferBeginInfo cbegin;
|
nuclear@0
|
658 VkRenderPassBeginInfo rbegin;
|
nuclear@0
|
659 VkClearValue clear;
|
nuclear@0
|
660
|
nuclear@0
|
661 memset(&cbegin, 0, sizeof cbegin);
|
nuclear@0
|
662 cbegin.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
nuclear@0
|
663 cbegin.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
|
nuclear@0
|
664
|
nuclear@0
|
665 if(vkBeginCommandBuffer(vksc_cmdbuf[i], &cbegin) != 0) {
|
nuclear@0
|
666 fprintf(stderr, "failed to begin command buffer recording\n");
|
nuclear@0
|
667 return -1;
|
nuclear@0
|
668 }
|
nuclear@0
|
669
|
nuclear@0
|
670 clear.color.float32[0] = 0.2f;
|
nuclear@0
|
671 clear.color.float32[1] = 0.2f;
|
nuclear@0
|
672 clear.color.float32[2] = 0.2f;
|
nuclear@0
|
673 clear.color.float32[3] = 1.0f;
|
nuclear@0
|
674
|
nuclear@0
|
675 memset(&rbegin, 0, sizeof rbegin);
|
nuclear@0
|
676 rbegin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
nuclear@0
|
677 rbegin.renderPass = vkrpass;
|
nuclear@0
|
678 rbegin.framebuffer = vksc_fb[i];
|
nuclear@0
|
679 rbegin.renderArea.extent = vksc_extent;
|
nuclear@0
|
680 rbegin.clearValueCount = 1;
|
nuclear@0
|
681 rbegin.pClearValues = &clear;
|
nuclear@0
|
682
|
nuclear@0
|
683 vkCmdBeginRenderPass(vksc_cmdbuf[i], &rbegin, VK_SUBPASS_CONTENTS_INLINE);
|
nuclear@0
|
684 vkCmdBindPipeline(vksc_cmdbuf[i], VK_PIPELINE_BIND_POINT_GRAPHICS, vkpipe);
|
nuclear@0
|
685 vkCmdDraw(vksc_cmdbuf[i], 3, 1, 0, 0);
|
nuclear@0
|
686 vkCmdEndRenderPass(vksc_cmdbuf[i]);
|
nuclear@0
|
687
|
nuclear@0
|
688 if(vkEndCommandBuffer(vksc_cmdbuf[i]) != 0) {
|
nuclear@0
|
689 fprintf(stderr, "failed to record command buffer\n");
|
nuclear@0
|
690 return -1;
|
nuclear@0
|
691 }
|
nuclear@0
|
692 }
|
nuclear@0
|
693 return 0;
|
nuclear@0
|
694 }
|
nuclear@0
|
695
|
nuclear@0
|
696 int create_semaphores(void)
|
nuclear@0
|
697 {
|
nuclear@0
|
698 VkSemaphoreCreateInfo sinf;
|
nuclear@0
|
699
|
nuclear@0
|
700 memset(&sinf, 0, sizeof sinf);
|
nuclear@0
|
701 sinf.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
nuclear@0
|
702
|
nuclear@0
|
703 if(vkCreateSemaphore(vkdev, &sinf, 0, &sem_gotimg) != 0) {
|
nuclear@0
|
704 fprintf(stderr, "failed to create semaphore\n");
|
nuclear@0
|
705 return -1;
|
nuclear@0
|
706 }
|
nuclear@0
|
707 if(vkCreateSemaphore(vkdev, &sinf, 0, &sem_drawdone) != 0) {
|
nuclear@0
|
708 fprintf(stderr, "failed to create semaphore\n");
|
nuclear@0
|
709 return -1;
|
nuclear@0
|
710 }
|
nuclear@0
|
711 return 0;
|
nuclear@0
|
712 }
|
nuclear@0
|
713
|
nuclear@0
|
714 VkShaderModule load_shader(const char *fname)
|
nuclear@0
|
715 {
|
nuclear@0
|
716 FILE *fp;
|
nuclear@0
|
717 long sz;
|
nuclear@0
|
718 void *buf;
|
nuclear@0
|
719 VkShaderModuleCreateInfo sinf;
|
nuclear@0
|
720 VkShaderModule sdr;
|
nuclear@0
|
721
|
nuclear@0
|
722 if(!(fp = fopen(fname, "rb"))) {
|
nuclear@0
|
723 fprintf(stderr, "failed to open shader: %s: %s\n", fname, strerror(errno));
|
nuclear@0
|
724 return 0;
|
nuclear@0
|
725 }
|
nuclear@0
|
726 fseek(fp, 0, SEEK_END);
|
nuclear@0
|
727 sz = ftell(fp);
|
nuclear@0
|
728 fseek(fp, 0, SEEK_SET);
|
nuclear@0
|
729
|
nuclear@0
|
730 buf = alloca(sz);
|
nuclear@0
|
731 if(fread(buf, 1, sz, fp) < sz) {
|
nuclear@0
|
732 fprintf(stderr, "unexpected EOF while reading shader: %s\n", fname);
|
nuclear@0
|
733 fclose(fp);
|
nuclear@0
|
734 return 0;
|
nuclear@0
|
735 }
|
nuclear@0
|
736 fclose(fp);
|
nuclear@0
|
737
|
nuclear@0
|
738 memset(&sinf, 0, sizeof sinf);
|
nuclear@0
|
739 sinf.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
nuclear@0
|
740 sinf.codeSize = sz;
|
nuclear@0
|
741 sinf.pCode = buf;
|
nuclear@0
|
742
|
nuclear@0
|
743 if(vkCreateShaderModule(vkdev, &sinf, 0, &sdr) != 0) {
|
nuclear@0
|
744 fprintf(stderr, "failed to create shader from %s\n", fname);
|
nuclear@0
|
745 return 0;
|
nuclear@0
|
746 }
|
nuclear@0
|
747 return sdr;
|
nuclear@0
|
748 }
|