vulkan_test_simple
diff src/main.c @ 0:8de4fe926882
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 28 Jun 2018 13:57:28 +0300 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/main.c Thu Jun 28 13:57:28 2018 +0300 1.3 @@ -0,0 +1,748 @@ 1.4 +#include <stdio.h> 1.5 +#include <stdlib.h> 1.6 +#include <string.h> 1.7 +#include <stdint.h> 1.8 +#include <errno.h> 1.9 +#include <alloca.h> 1.10 +#include <GLFW/glfw3.h> 1.11 + 1.12 +void keyb(GLFWwindow *win, int key, int sc, int act, int mods); 1.13 +int init(void); 1.14 +void destroy(void); 1.15 +void draw(void); 1.16 + 1.17 +GLFWwindow *win; 1.18 +int win_width = 800; 1.19 +int win_height = 600; 1.20 +int redraw_pending; 1.21 + 1.22 +int main(void) 1.23 +{ 1.24 + if(!glfwInit()) { 1.25 + fprintf(stderr, "glfw init failed\n"); 1.26 + return 1; 1.27 + } 1.28 + 1.29 + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); 1.30 + win = glfwCreateWindow(win_width, win_height, "test", 0, 0); 1.31 + glfwSetKeyCallback(win, keyb); 1.32 + 1.33 + if(init() == -1) { 1.34 + glfwDestroyWindow(win); 1.35 + glfwTerminate(); 1.36 + return 1; 1.37 + } 1.38 + 1.39 + redraw_pending = 1; 1.40 + 1.41 + while(!glfwWindowShouldClose(win)) { 1.42 + glfwWaitEvents(); 1.43 + 1.44 + if(redraw_pending) { 1.45 + redraw_pending = 0; 1.46 + draw(); 1.47 + } 1.48 + } 1.49 + 1.50 + destroy(); 1.51 + glfwDestroyWindow(win); 1.52 + glfwTerminate(); 1.53 + return 0; 1.54 +} 1.55 + 1.56 +void keyb(GLFWwindow *win, int key, int sc, int act, int mods) 1.57 +{ 1.58 + if(act == GLFW_PRESS) { 1.59 + switch(key) { 1.60 + case GLFW_KEY_ESCAPE: 1.61 + glfwSetWindowShouldClose(win, 1); 1.62 + break; 1.63 + } 1.64 + } 1.65 +} 1.66 + 1.67 +/* -------------------------------------------------------------- */ 1.68 +int create_instance(void); 1.69 +int create_surface(void); 1.70 +int choose_phys_dev(void); 1.71 +int create_device(void); 1.72 +int create_swapchain(void); 1.73 +int create_imgviews(void); 1.74 +int create_rendpass(void); 1.75 +int create_pipeline(void); 1.76 +int create_framebuf(void); 1.77 +int create_cmdpool(void); 1.78 +int create_cmdbuf(void); 1.79 +int create_semaphores(void); 1.80 +VkShaderModule load_shader(const char *fname); 1.81 + 1.82 +VkInstance vk; 1.83 +VkPhysicalDevice vkpdev; 1.84 +int vkqfam_idx = -1; 1.85 +VkDevice vkdev; 1.86 +VkQueue vkq; 1.87 +VkSurfaceKHR vksurf; 1.88 +VkSurfaceCapabilitiesKHR vksurf_caps; 1.89 +int vksurf_numfmt, vksurf_selfmt; 1.90 +VkSurfaceFormatKHR *vksurf_fmt; 1.91 +VkSwapchainKHR vksc; 1.92 +int vksc_numimg; 1.93 +VkImage *vksc_img; 1.94 +VkExtent2D vksc_extent; 1.95 +VkImageView *vksc_view; 1.96 +VkRenderPass vkrpass; 1.97 +VkPipelineLayout vkpipe_layout; 1.98 +VkPipeline vkpipe; 1.99 +VkFramebuffer *vksc_fb; 1.100 +VkCommandPool vkcmdpool; 1.101 +VkCommandBuffer *vksc_cmdbuf; 1.102 +VkSemaphore sem_gotimg, sem_drawdone; 1.103 + 1.104 +int init(void) 1.105 +{ 1.106 + if(create_instance() == -1) return -1; 1.107 + if(create_surface() == -1) return -1; 1.108 + if(choose_phys_dev() == -1) return -1; 1.109 + if(create_device() == -1) return -1; 1.110 + if(create_swapchain() == -1) return -1; 1.111 + if(create_imgviews() == -1) return -1; 1.112 + if(create_rendpass() == -1) return -1; 1.113 + if(create_pipeline() == -1) return -1; 1.114 + if(create_framebuf() == -1) return -1; 1.115 + if(create_cmdpool() == -1) return -1; 1.116 + if(create_cmdbuf() == -1) return -1; 1.117 + if(create_semaphores() == -1) return -1; 1.118 + return 0; 1.119 +} 1.120 + 1.121 +void destroy(void) 1.122 +{ 1.123 + int i; 1.124 + 1.125 + if(sem_gotimg) vkDestroySemaphore(vkdev, sem_gotimg, 0); 1.126 + if(sem_drawdone) vkDestroySemaphore(vkdev, sem_drawdone, 0); 1.127 + if(vkcmdpool) vkDestroyCommandPool(vkdev, vkcmdpool, 0); 1.128 + if(vksc_fb) { 1.129 + for(i=0; i<vksc_numimg; i++) { 1.130 + vkDestroyFramebuffer(vkdev, vksc_fb[i], 0); 1.131 + } 1.132 + } 1.133 + if(vkpipe) vkDestroyPipeline(vkdev, vkpipe, 0); 1.134 + if(vkpipe_layout) vkDestroyPipelineLayout(vkdev, vkpipe_layout, 0); 1.135 + if(vkrpass) vkDestroyRenderPass(vkdev, vkrpass, 0); 1.136 + if(vksc_view) { 1.137 + for(i=0; i<vksc_numimg; i++) { 1.138 + vkDestroyImageView(vkdev, vksc_view[i], 0); 1.139 + } 1.140 + } 1.141 + if(vksc) vkDestroySwapchainKHR(vkdev, vksc, 0); 1.142 + if(vkdev) vkDestroyDevice(vkdev, 0); 1.143 + if(vksurf) vkDestroySurfaceKHR(vk, vksurf, 0); 1.144 + if(vk) vkDestroyInstance(vk, 0); 1.145 +} 1.146 + 1.147 +void draw(void) 1.148 +{ 1.149 + uint32_t img_idx; 1.150 + VkSubmitInfo submit; 1.151 + VkPipelineStageFlags wait_stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 1.152 + VkPresentInfoKHR pres; 1.153 + 1.154 + vkAcquireNextImageKHR(vkdev, vksc, UINT64_MAX, sem_gotimg, 0, &img_idx); 1.155 + 1.156 + memset(&submit, 0, sizeof submit); 1.157 + submit.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 1.158 + submit.waitSemaphoreCount = 1; 1.159 + submit.pWaitSemaphores = &sem_gotimg; 1.160 + submit.pWaitDstStageMask = &wait_stages; 1.161 + submit.commandBufferCount = 1; 1.162 + submit.pCommandBuffers = vksc_cmdbuf + img_idx; 1.163 + submit.signalSemaphoreCount = 1; 1.164 + submit.pSignalSemaphores = &sem_drawdone; 1.165 + 1.166 + if(vkQueueSubmit(vkq, 1, &submit, 0) != 0) { 1.167 + fprintf(stderr, "failed to submit draw commands\n"); 1.168 + abort(); 1.169 + } 1.170 + 1.171 + memset(&pres, 0, sizeof pres); 1.172 + pres.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; 1.173 + pres.waitSemaphoreCount = 1; 1.174 + pres.pWaitSemaphores = &sem_drawdone; 1.175 + pres.swapchainCount = 1; 1.176 + pres.pSwapchains = &vksc; 1.177 + pres.pImageIndices = &img_idx; 1.178 + 1.179 + vkQueuePresentKHR(vkq, &pres); 1.180 +} 1.181 + 1.182 +int create_instance(void) 1.183 +{ 1.184 + VkApplicationInfo appinf; 1.185 + VkInstanceCreateInfo iinf; 1.186 + uint32_t num_ext; 1.187 + const char **ext; 1.188 + 1.189 + ext = glfwGetRequiredInstanceExtensions(&num_ext); 1.190 + 1.191 + memset(&appinf, 0, sizeof appinf); 1.192 + appinf.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; 1.193 + appinf.pApplicationName = "test"; 1.194 + appinf.applicationVersion = VK_MAKE_VERSION(1, 0, 0); 1.195 + appinf.pEngineName = "fuckoff"; 1.196 + appinf.engineVersion = VK_MAKE_VERSION(1, 0, 0); 1.197 + appinf.apiVersion = VK_API_VERSION_1_0; 1.198 + 1.199 + memset(&iinf, 0, sizeof iinf); 1.200 + iinf.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; 1.201 + iinf.pApplicationInfo = &appinf; 1.202 + iinf.enabledExtensionCount = num_ext; 1.203 + iinf.ppEnabledExtensionNames = ext; 1.204 + 1.205 + if(vkCreateInstance(&iinf, 0, &vk) != 0) { 1.206 + fprintf(stderr, "failed to create instance\n"); 1.207 + return -1; 1.208 + } 1.209 + return 0; 1.210 +} 1.211 + 1.212 +int create_surface(void) 1.213 +{ 1.214 + if(glfwCreateWindowSurface(vk, win, 0, &vksurf) != 0) { 1.215 + fprintf(stderr, "failed to create window surface\n"); 1.216 + return -1; 1.217 + } 1.218 + return 0; 1.219 +} 1.220 + 1.221 +static int is_pdev_skookum(VkPhysicalDevice dev) 1.222 +{ 1.223 + uint32_t i, num_fmt, num_qfam, num_ext; 1.224 + VkQueueFamilyProperties *qfam; 1.225 + VkExtensionProperties *ext; 1.226 + VkPhysicalDeviceProperties prop; 1.227 + VkPhysicalDeviceFeatures feat; 1.228 + VkBool32 can_pres; 1.229 + int have_swap_ext; 1.230 + 1.231 + vkGetPhysicalDeviceProperties(dev, &prop); 1.232 + vkGetPhysicalDeviceFeatures(dev, &feat); 1.233 + 1.234 + /* check if we have the swapchain extension */ 1.235 + vkEnumerateDeviceExtensionProperties(dev, 0, &num_ext, 0); 1.236 + ext = alloca(num_ext * sizeof *ext); 1.237 + vkEnumerateDeviceExtensionProperties(dev, 0, &num_ext, ext); 1.238 + 1.239 + have_swap_ext = 0; 1.240 + for(i=0; i<num_ext; i++) { 1.241 + if(strcmp(ext[i].extensionName, "VK_KHR_swapchain") == 0) { 1.242 + have_swap_ext = 1; 1.243 + break; 1.244 + } 1.245 + } 1.246 + if(!have_swap_ext) { 1.247 + return 0; 1.248 + } 1.249 + 1.250 + /* populate format and present modes arrays, and make sure we have some of each */ 1.251 + vkGetPhysicalDeviceSurfaceFormatsKHR(dev, vksurf, &num_fmt, 0); 1.252 + if(!num_fmt || !(vksurf_fmt = malloc(num_fmt * sizeof *vksurf_fmt))) { 1.253 + return 0; 1.254 + } 1.255 + vksurf_numfmt = num_fmt; 1.256 + vkGetPhysicalDeviceSurfaceFormatsKHR(dev, vksurf, &num_fmt, vksurf_fmt); 1.257 + 1.258 + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(dev, vksurf, &vksurf_caps); 1.259 + 1.260 + /* find a queue family which can do graphics and can present */ 1.261 + vkGetPhysicalDeviceQueueFamilyProperties(dev, &num_qfam, 0); 1.262 + qfam = alloca(num_qfam * sizeof *qfam); 1.263 + vkGetPhysicalDeviceQueueFamilyProperties(dev, &num_qfam, qfam); 1.264 + 1.265 + vkqfam_idx = -1; 1.266 + for(i=0; i<num_qfam; i++) { 1.267 + vkGetPhysicalDeviceSurfaceSupportKHR(dev, i, vksurf, &can_pres); 1.268 + if(qfam[i].queueCount && (qfam[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) && can_pres) { 1.269 + vkqfam_idx = i; 1.270 + return 1; 1.271 + } 1.272 + } 1.273 + 1.274 + free(vksurf_fmt); 1.275 + vksurf_fmt = 0; 1.276 + vksurf_numfmt = 0; 1.277 + return 0; 1.278 +} 1.279 + 1.280 +static int choose_pixfmt(void) 1.281 +{ 1.282 + int i, j; 1.283 + static const VkFormat pref[] = { 1.284 + VK_FORMAT_B8G8R8_UNORM, 1.285 + VK_FORMAT_R8G8B8_UNORM, 1.286 + VK_FORMAT_B8G8R8A8_UNORM, 1.287 + VK_FORMAT_R8G8B8A8_UNORM 1.288 + }; 1.289 + 1.290 + vksurf_selfmt = 0; 1.291 + for(i=0; i<vksurf_numfmt; i++) { 1.292 + if(vksurf_fmt[i].colorSpace != VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { 1.293 + continue; 1.294 + } 1.295 + for(j=0; j<sizeof pref / sizeof *pref; j++) { 1.296 + if(vksurf_fmt[i].format == pref[j]) { 1.297 + vksurf_selfmt = i; 1.298 + return i; 1.299 + } 1.300 + } 1.301 + } 1.302 + return -1; 1.303 +} 1.304 + 1.305 +int choose_phys_dev(void) 1.306 +{ 1.307 + uint32_t i, num_pdev; 1.308 + VkPhysicalDevice *pdev; 1.309 + 1.310 + vkEnumeratePhysicalDevices(vk, &num_pdev, 0); 1.311 + if(!num_pdev) { 1.312 + fprintf(stderr, "no vulkan devices found\n"); 1.313 + return -1; 1.314 + } 1.315 + pdev = alloca(num_pdev * sizeof *pdev); 1.316 + vkEnumeratePhysicalDevices(vk, &num_pdev, pdev); 1.317 + 1.318 + for(i=0; i<num_pdev; i++) { 1.319 + if(is_pdev_skookum(pdev[i])) { 1.320 + vkpdev = pdev[i]; 1.321 + break; 1.322 + } 1.323 + } 1.324 + if(!vkpdev) { 1.325 + fprintf(stderr, "no skookum device found, vulkan can't chooch\n"); 1.326 + return -1; 1.327 + } 1.328 + 1.329 + choose_pixfmt(); 1.330 + return 0; 1.331 +} 1.332 + 1.333 +int create_device(void) 1.334 +{ 1.335 + static const float prio = 1.0f; 1.336 + VkDeviceQueueCreateInfo qinf; 1.337 + VkPhysicalDeviceFeatures feat; 1.338 + VkDeviceCreateInfo devinf; 1.339 + 1.340 + static const char *extensions[] = { 1.341 + "VK_KHR_swapchain" 1.342 + }; 1.343 + 1.344 + memset(&feat, 0, sizeof feat); 1.345 + 1.346 + memset(&qinf, 0, sizeof qinf); 1.347 + qinf.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; 1.348 + qinf.queueFamilyIndex = vkqfam_idx; 1.349 + qinf.queueCount = 1; 1.350 + qinf.pQueuePriorities = &prio; 1.351 + 1.352 + memset(&devinf, 0, sizeof devinf); 1.353 + devinf.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; 1.354 + devinf.pQueueCreateInfos = &qinf; 1.355 + devinf.queueCreateInfoCount = 1; 1.356 + devinf.pEnabledFeatures = &feat; 1.357 + devinf.enabledExtensionCount = sizeof extensions / sizeof *extensions; 1.358 + devinf.ppEnabledExtensionNames = extensions; 1.359 + 1.360 + if(vkCreateDevice(vkpdev, &devinf, 0, &vkdev) != 0) { 1.361 + fprintf(stderr, "failed to create vulkan device\n"); 1.362 + return -1; 1.363 + } 1.364 + 1.365 + vkGetDeviceQueue(vkdev, vkqfam_idx, 0, &vkq); 1.366 + return 0; 1.367 +} 1.368 + 1.369 +int create_swapchain(void) 1.370 +{ 1.371 + uint32_t num; 1.372 + VkSwapchainCreateInfoKHR scinf; 1.373 + 1.374 + vksc_extent.width = win_width; 1.375 + vksc_extent.height = win_height; 1.376 + 1.377 + memset(&scinf, 0, sizeof scinf); 1.378 + scinf.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; 1.379 + scinf.surface = vksurf; 1.380 + scinf.minImageCount = 2; 1.381 + scinf.imageFormat = vksurf_fmt[vksurf_selfmt].format; 1.382 + scinf.imageColorSpace = vksurf_fmt[vksurf_selfmt].colorSpace; 1.383 + scinf.imageExtent = vksc_extent; 1.384 + scinf.imageArrayLayers = 1; 1.385 + scinf.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 1.386 + scinf.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; 1.387 + scinf.preTransform = vksurf_caps.currentTransform; 1.388 + scinf.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; 1.389 + scinf.presentMode = VK_PRESENT_MODE_FIFO_KHR; 1.390 + scinf.clipped = VK_TRUE; 1.391 + 1.392 + if(vkCreateSwapchainKHR(vkdev, &scinf, 0, &vksc) != 0) { 1.393 + fprintf(stderr, "failed to create swapchain\n"); 1.394 + return -1; 1.395 + } 1.396 + 1.397 + vkGetSwapchainImagesKHR(vkdev, vksc, &num, 0); 1.398 + if(!num || !(vksc_img = malloc(num * sizeof *vksc_img))) { 1.399 + fprintf(stderr, "failed to allocate swapchain image array (%d images)\n", vksc_numimg); 1.400 + return -1; 1.401 + } 1.402 + vkGetSwapchainImagesKHR(vkdev, vksc, &num, vksc_img); 1.403 + vksc_numimg = num; 1.404 + 1.405 + return 0; 1.406 +} 1.407 + 1.408 +int create_imgviews(void) 1.409 +{ 1.410 + int i; 1.411 + VkImageViewCreateInfo ivinf; 1.412 + 1.413 + if(!(vksc_view = malloc(vksc_numimg * sizeof *vksc_view))) { 1.414 + fprintf(stderr, "failed to allocate image view array (%d images)\n", vksc_numimg); 1.415 + return -1; 1.416 + } 1.417 + 1.418 + for(i=0; i<vksc_numimg; i++) { 1.419 + memset(&ivinf, 0, sizeof ivinf); 1.420 + ivinf.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 1.421 + ivinf.image = vksc_img[i]; 1.422 + ivinf.format = vksurf_fmt[vksurf_selfmt].format; 1.423 + ivinf.components.r = ivinf.components.g = ivinf.components.b = 1.424 + ivinf.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; 1.425 + ivinf.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 1.426 + ivinf.subresourceRange.levelCount = 1; 1.427 + ivinf.subresourceRange.layerCount = 1; 1.428 + 1.429 + if(vkCreateImageView(vkdev, &ivinf, 0, vksc_view + i) != 0) { 1.430 + fprintf(stderr, "failed to create image view for image %d\n", i); 1.431 + return -1; 1.432 + } 1.433 + } 1.434 + return 0; 1.435 +} 1.436 + 1.437 +int create_rendpass(void) 1.438 +{ 1.439 + VkAttachmentDescription cat; 1.440 + VkAttachmentReference catref; 1.441 + VkSubpassDescription subpass; 1.442 + VkRenderPassCreateInfo pinf; 1.443 + VkSubpassDependency dep; 1.444 + 1.445 + memset(&cat, 0, sizeof cat); 1.446 + cat.format = vksurf_fmt[vksurf_selfmt].format; 1.447 + cat.samples = VK_SAMPLE_COUNT_1_BIT; 1.448 + cat.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; 1.449 + cat.storeOp = VK_ATTACHMENT_STORE_OP_STORE; 1.450 + cat.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 1.451 + cat.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 1.452 + cat.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 1.453 + cat.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; 1.454 + 1.455 + memset(&catref, 0, sizeof catref); 1.456 + catref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 1.457 + 1.458 + memset(&subpass, 0, sizeof subpass); 1.459 + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 1.460 + subpass.colorAttachmentCount = 1; 1.461 + subpass.pColorAttachments = &catref; 1.462 + 1.463 + memset(&dep, 0, sizeof dep); 1.464 + dep.srcSubpass = VK_SUBPASS_EXTERNAL; 1.465 + dep.dstSubpass = 0; 1.466 + dep.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 1.467 + dep.srcAccessMask = 0; 1.468 + dep.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 1.469 + dep.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 1.470 + 1.471 + memset(&pinf, 0, sizeof pinf); 1.472 + pinf.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; 1.473 + pinf.attachmentCount = 1; 1.474 + pinf.pAttachments = &cat; 1.475 + pinf.subpassCount = 1; 1.476 + pinf.pSubpasses = &subpass; 1.477 + pinf.dependencyCount = 1; 1.478 + pinf.pDependencies = &dep; 1.479 + 1.480 + if(vkCreateRenderPass(vkdev, &pinf, 0, &vkrpass) != 0) { 1.481 + fprintf(stderr, "failed to create render pass\n"); 1.482 + return -1; 1.483 + } 1.484 + return 0; 1.485 +} 1.486 + 1.487 +int create_pipeline(void) 1.488 +{ 1.489 + int i; 1.490 + VkShaderModule sdr[2]; 1.491 + VkPipelineShaderStageCreateInfo ssinf[2]; 1.492 + VkPipelineVertexInputStateCreateInfo vinp; 1.493 + VkPipelineInputAssemblyStateCreateInfo vasm; 1.494 + VkViewport vport; 1.495 + VkRect2D scissor; 1.496 + VkPipelineViewportStateCreateInfo vp; 1.497 + VkPipelineRasterizationStateCreateInfo rast; 1.498 + VkPipelineMultisampleStateCreateInfo msaa; 1.499 + VkPipelineColorBlendAttachmentState bat; 1.500 + VkPipelineColorBlendStateCreateInfo blend; 1.501 + VkPipelineLayoutCreateInfo lay; 1.502 + VkGraphicsPipelineCreateInfo pinf; 1.503 + 1.504 + if(!(sdr[0] = load_shader("vertex.glsl")) || !(sdr[1] = load_shader("pixel.glsl"))) { 1.505 + return -1; 1.506 + } 1.507 + memset(ssinf, 0, sizeof ssinf); 1.508 + for(i=0; i<2; i++) { 1.509 + ssinf[i].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 1.510 + ssinf[i].stage = i == 0 ? VK_SHADER_STAGE_VERTEX_BIT : VK_SHADER_STAGE_FRAGMENT_BIT; 1.511 + ssinf[i].module = sdr[i]; 1.512 + ssinf[i].pName = "main"; 1.513 + } 1.514 + 1.515 + memset(&vinp, 0, sizeof vinp); 1.516 + vinp.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; 1.517 + 1.518 + memset(&vasm, 0, sizeof vasm); 1.519 + vasm.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; 1.520 + vasm.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; 1.521 + 1.522 + vport.x = vport.y = 0; 1.523 + vport.width = vksc_extent.width; 1.524 + vport.height = vksc_extent.height; 1.525 + vport.minDepth = 0.0f; 1.526 + vport.maxDepth = 1.0f; 1.527 + 1.528 + scissor.offset.x = scissor.offset.y = 0; 1.529 + scissor.extent = vksc_extent; 1.530 + 1.531 + memset(&vp, 0, sizeof vp); 1.532 + vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; 1.533 + vp.viewportCount = 1; 1.534 + vp.pViewports = &vport; 1.535 + vp.scissorCount = 1; 1.536 + vp.pScissors = &scissor; 1.537 + 1.538 + memset(&rast, 0, sizeof rast); 1.539 + rast.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; 1.540 + rast.polygonMode = VK_POLYGON_MODE_FILL; 1.541 + rast.lineWidth = 1.0f; 1.542 + rast.cullMode = VK_CULL_MODE_BACK_BIT; 1.543 + rast.frontFace = VK_FRONT_FACE_CLOCKWISE; 1.544 + 1.545 + memset(&msaa, 0, sizeof msaa); 1.546 + msaa.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; 1.547 + msaa.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; 1.548 + msaa.minSampleShading = 1.0f; 1.549 + 1.550 + memset(&bat, 0, sizeof bat); 1.551 + bat.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | 1.552 + VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 1.553 + 1.554 + memset(&blend, 0, sizeof blend); 1.555 + blend.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; 1.556 + blend.attachmentCount = 1; 1.557 + blend.pAttachments = &bat; 1.558 + 1.559 + 1.560 + memset(&lay, 0, sizeof lay); 1.561 + lay.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 1.562 + 1.563 + if(vkCreatePipelineLayout(vkdev, &lay, 0, &vkpipe_layout) != 0) { 1.564 + fprintf(stderr, "failed to create a pipeline layout\n"); 1.565 + return -1; 1.566 + } 1.567 + 1.568 + memset(&pinf, 0, sizeof pinf); 1.569 + pinf.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; 1.570 + pinf.stageCount = 2; 1.571 + pinf.pStages = ssinf; 1.572 + pinf.pVertexInputState = &vinp; 1.573 + pinf.pInputAssemblyState = &vasm; 1.574 + pinf.pViewportState = &vp; 1.575 + pinf.pRasterizationState = &rast; 1.576 + pinf.pMultisampleState = &msaa; 1.577 + pinf.pColorBlendState = &blend; 1.578 + pinf.layout = vkpipe_layout; 1.579 + pinf.renderPass = vkrpass; 1.580 + pinf.basePipelineIndex = -1; 1.581 + 1.582 + if(vkCreateGraphicsPipelines(vkdev, 0, 1, &pinf, 0, &vkpipe) != 0) { 1.583 + fprintf(stderr, "failed to create graphics pipeline\n"); 1.584 + return -1; 1.585 + } 1.586 + 1.587 + for(i=0; i<2; i++) { 1.588 + vkDestroyShaderModule(vkdev, sdr[i], 0); 1.589 + } 1.590 + return 0; 1.591 +} 1.592 + 1.593 +int create_framebuf(void) 1.594 +{ 1.595 + int i; 1.596 + VkFramebufferCreateInfo fbinf; 1.597 + 1.598 + if(!(vksc_fb = malloc(vksc_numimg * sizeof *vksc_fb))) { 1.599 + fprintf(stderr, "failed to allocate array for swap chain framebuffers\n"); 1.600 + return -1; 1.601 + } 1.602 + 1.603 + for(i=0; i<vksc_numimg; i++) { 1.604 + memset(&fbinf, 0, sizeof fbinf); 1.605 + fbinf.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; 1.606 + fbinf.renderPass = vkrpass; 1.607 + fbinf.attachmentCount = 1; 1.608 + fbinf.pAttachments = vksc_view + i; 1.609 + fbinf.width = vksc_extent.width; 1.610 + fbinf.height = vksc_extent.height; 1.611 + fbinf.layers = 1; 1.612 + 1.613 + if(vkCreateFramebuffer(vkdev, &fbinf, 0, vksc_fb + i) != 0) { 1.614 + fprintf(stderr, "failed to create framebuffer\n"); 1.615 + return -1; 1.616 + } 1.617 + } 1.618 + 1.619 + return 0; 1.620 +} 1.621 + 1.622 +int create_cmdpool(void) 1.623 +{ 1.624 + VkCommandPoolCreateInfo cpinf; 1.625 + 1.626 + memset(&cpinf, 0, sizeof cpinf); 1.627 + cpinf.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; 1.628 + cpinf.queueFamilyIndex = vkqfam_idx; 1.629 + 1.630 + if(vkCreateCommandPool(vkdev, &cpinf, 0, &vkcmdpool) != 0) { 1.631 + fprintf(stderr, "failed to create command pool\n"); 1.632 + return -1; 1.633 + } 1.634 + return 0; 1.635 +} 1.636 + 1.637 +int create_cmdbuf(void) 1.638 +{ 1.639 + int i; 1.640 + VkCommandBufferAllocateInfo cbinf; 1.641 + 1.642 + if(!(vksc_cmdbuf = malloc(vksc_numimg * sizeof *vksc_cmdbuf))) { 1.643 + fprintf(stderr, "failed to allocate array of command buffers\n"); 1.644 + return -1; 1.645 + } 1.646 + 1.647 + memset(&cbinf, 0, sizeof cbinf); 1.648 + cbinf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; 1.649 + cbinf.commandPool = vkcmdpool; 1.650 + cbinf.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; 1.651 + cbinf.commandBufferCount = vksc_numimg; 1.652 + 1.653 + if(vkAllocateCommandBuffers(vkdev, &cbinf, vksc_cmdbuf) != 0) { 1.654 + fprintf(stderr, "failed to allocate command buffers\n"); 1.655 + return -1; 1.656 + } 1.657 + 1.658 + /* pre-record command buffers, because why the fuck not */ 1.659 + for(i=0; i<vksc_numimg; i++) { 1.660 + VkCommandBufferBeginInfo cbegin; 1.661 + VkRenderPassBeginInfo rbegin; 1.662 + VkClearValue clear; 1.663 + 1.664 + memset(&cbegin, 0, sizeof cbegin); 1.665 + cbegin.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 1.666 + cbegin.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; 1.667 + 1.668 + if(vkBeginCommandBuffer(vksc_cmdbuf[i], &cbegin) != 0) { 1.669 + fprintf(stderr, "failed to begin command buffer recording\n"); 1.670 + return -1; 1.671 + } 1.672 + 1.673 + clear.color.float32[0] = 0.2f; 1.674 + clear.color.float32[1] = 0.2f; 1.675 + clear.color.float32[2] = 0.2f; 1.676 + clear.color.float32[3] = 1.0f; 1.677 + 1.678 + memset(&rbegin, 0, sizeof rbegin); 1.679 + rbegin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 1.680 + rbegin.renderPass = vkrpass; 1.681 + rbegin.framebuffer = vksc_fb[i]; 1.682 + rbegin.renderArea.extent = vksc_extent; 1.683 + rbegin.clearValueCount = 1; 1.684 + rbegin.pClearValues = &clear; 1.685 + 1.686 + vkCmdBeginRenderPass(vksc_cmdbuf[i], &rbegin, VK_SUBPASS_CONTENTS_INLINE); 1.687 + vkCmdBindPipeline(vksc_cmdbuf[i], VK_PIPELINE_BIND_POINT_GRAPHICS, vkpipe); 1.688 + vkCmdDraw(vksc_cmdbuf[i], 3, 1, 0, 0); 1.689 + vkCmdEndRenderPass(vksc_cmdbuf[i]); 1.690 + 1.691 + if(vkEndCommandBuffer(vksc_cmdbuf[i]) != 0) { 1.692 + fprintf(stderr, "failed to record command buffer\n"); 1.693 + return -1; 1.694 + } 1.695 + } 1.696 + return 0; 1.697 +} 1.698 + 1.699 +int create_semaphores(void) 1.700 +{ 1.701 + VkSemaphoreCreateInfo sinf; 1.702 + 1.703 + memset(&sinf, 0, sizeof sinf); 1.704 + sinf.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; 1.705 + 1.706 + if(vkCreateSemaphore(vkdev, &sinf, 0, &sem_gotimg) != 0) { 1.707 + fprintf(stderr, "failed to create semaphore\n"); 1.708 + return -1; 1.709 + } 1.710 + if(vkCreateSemaphore(vkdev, &sinf, 0, &sem_drawdone) != 0) { 1.711 + fprintf(stderr, "failed to create semaphore\n"); 1.712 + return -1; 1.713 + } 1.714 + return 0; 1.715 +} 1.716 + 1.717 +VkShaderModule load_shader(const char *fname) 1.718 +{ 1.719 + FILE *fp; 1.720 + long sz; 1.721 + void *buf; 1.722 + VkShaderModuleCreateInfo sinf; 1.723 + VkShaderModule sdr; 1.724 + 1.725 + if(!(fp = fopen(fname, "rb"))) { 1.726 + fprintf(stderr, "failed to open shader: %s: %s\n", fname, strerror(errno)); 1.727 + return 0; 1.728 + } 1.729 + fseek(fp, 0, SEEK_END); 1.730 + sz = ftell(fp); 1.731 + fseek(fp, 0, SEEK_SET); 1.732 + 1.733 + buf = alloca(sz); 1.734 + if(fread(buf, 1, sz, fp) < sz) { 1.735 + fprintf(stderr, "unexpected EOF while reading shader: %s\n", fname); 1.736 + fclose(fp); 1.737 + return 0; 1.738 + } 1.739 + fclose(fp); 1.740 + 1.741 + memset(&sinf, 0, sizeof sinf); 1.742 + sinf.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 1.743 + sinf.codeSize = sz; 1.744 + sinf.pCode = buf; 1.745 + 1.746 + if(vkCreateShaderModule(vkdev, &sinf, 0, &sdr) != 0) { 1.747 + fprintf(stderr, "failed to create shader from %s\n", fname); 1.748 + return 0; 1.749 + } 1.750 + return sdr; 1.751 +}