vulkan_test_simple
changeset 0:8de4fe926882
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 28 Jun 2018 13:57:28 +0300 |
parents | |
children | d5a3f6912f4d |
files | .hgignore Makefile pixel.glsl src/main.c vertex.glsl |
diffstat | 5 files changed, 810 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/.hgignore Thu Jun 28 13:57:28 2018 +0300 1.3 @@ -0,0 +1,5 @@ 1.4 +\.o$ 1.5 +\.swp$ 1.6 +\.d$ 1.7 +\.spv$ 1.8 +^test$
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/Makefile Thu Jun 28 13:57:28 2018 +0300 2.3 @@ -0,0 +1,21 @@ 2.4 +src = $(wildcard src/*.c) 2.5 +obj = $(src:.c=.o) 2.6 +bin = test 2.7 + 2.8 +def = -DGLFW_INCLUDE_VULKAN 2.9 + 2.10 +CFLAGS = -pedantic -Wall -g $(def) 2.11 +LDFLAGS = -lvulkan -lglfw 2.12 + 2.13 +$(bin): $(obj) vertex.spv pixel.spv 2.14 + $(CC) -o $@ $(obj) $(LDFLAGS) 2.15 + 2.16 +vertex.spv: vertex.glsl 2.17 + glslangValidator -o $@ -S vert -V $< 2.18 + 2.19 +pixel.spv: pixel.glsl 2.20 + glslangValidator -o $@ -S frag -V $< 2.21 + 2.22 +.PHONY: clean 2.23 +clean: 2.24 + rm -f $(obj) $(bin) *.spv
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/pixel.glsl Thu Jun 28 13:57:28 2018 +0300 3.3 @@ -0,0 +1,10 @@ 3.4 +#version 450 3.5 +#extension GL_ARB_separate_shader_objects : enable 3.6 + 3.7 +layout(location = 0) in vec3 incol; 3.8 +layout(location = 0) out vec4 outcol; 3.9 + 3.10 +void main() 3.11 +{ 3.12 + outcol = vec4(incol, 1.0); 3.13 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/main.c Thu Jun 28 13:57:28 2018 +0300 4.3 @@ -0,0 +1,748 @@ 4.4 +#include <stdio.h> 4.5 +#include <stdlib.h> 4.6 +#include <string.h> 4.7 +#include <stdint.h> 4.8 +#include <errno.h> 4.9 +#include <alloca.h> 4.10 +#include <GLFW/glfw3.h> 4.11 + 4.12 +void keyb(GLFWwindow *win, int key, int sc, int act, int mods); 4.13 +int init(void); 4.14 +void destroy(void); 4.15 +void draw(void); 4.16 + 4.17 +GLFWwindow *win; 4.18 +int win_width = 800; 4.19 +int win_height = 600; 4.20 +int redraw_pending; 4.21 + 4.22 +int main(void) 4.23 +{ 4.24 + if(!glfwInit()) { 4.25 + fprintf(stderr, "glfw init failed\n"); 4.26 + return 1; 4.27 + } 4.28 + 4.29 + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); 4.30 + win = glfwCreateWindow(win_width, win_height, "test", 0, 0); 4.31 + glfwSetKeyCallback(win, keyb); 4.32 + 4.33 + if(init() == -1) { 4.34 + glfwDestroyWindow(win); 4.35 + glfwTerminate(); 4.36 + return 1; 4.37 + } 4.38 + 4.39 + redraw_pending = 1; 4.40 + 4.41 + while(!glfwWindowShouldClose(win)) { 4.42 + glfwWaitEvents(); 4.43 + 4.44 + if(redraw_pending) { 4.45 + redraw_pending = 0; 4.46 + draw(); 4.47 + } 4.48 + } 4.49 + 4.50 + destroy(); 4.51 + glfwDestroyWindow(win); 4.52 + glfwTerminate(); 4.53 + return 0; 4.54 +} 4.55 + 4.56 +void keyb(GLFWwindow *win, int key, int sc, int act, int mods) 4.57 +{ 4.58 + if(act == GLFW_PRESS) { 4.59 + switch(key) { 4.60 + case GLFW_KEY_ESCAPE: 4.61 + glfwSetWindowShouldClose(win, 1); 4.62 + break; 4.63 + } 4.64 + } 4.65 +} 4.66 + 4.67 +/* -------------------------------------------------------------- */ 4.68 +int create_instance(void); 4.69 +int create_surface(void); 4.70 +int choose_phys_dev(void); 4.71 +int create_device(void); 4.72 +int create_swapchain(void); 4.73 +int create_imgviews(void); 4.74 +int create_rendpass(void); 4.75 +int create_pipeline(void); 4.76 +int create_framebuf(void); 4.77 +int create_cmdpool(void); 4.78 +int create_cmdbuf(void); 4.79 +int create_semaphores(void); 4.80 +VkShaderModule load_shader(const char *fname); 4.81 + 4.82 +VkInstance vk; 4.83 +VkPhysicalDevice vkpdev; 4.84 +int vkqfam_idx = -1; 4.85 +VkDevice vkdev; 4.86 +VkQueue vkq; 4.87 +VkSurfaceKHR vksurf; 4.88 +VkSurfaceCapabilitiesKHR vksurf_caps; 4.89 +int vksurf_numfmt, vksurf_selfmt; 4.90 +VkSurfaceFormatKHR *vksurf_fmt; 4.91 +VkSwapchainKHR vksc; 4.92 +int vksc_numimg; 4.93 +VkImage *vksc_img; 4.94 +VkExtent2D vksc_extent; 4.95 +VkImageView *vksc_view; 4.96 +VkRenderPass vkrpass; 4.97 +VkPipelineLayout vkpipe_layout; 4.98 +VkPipeline vkpipe; 4.99 +VkFramebuffer *vksc_fb; 4.100 +VkCommandPool vkcmdpool; 4.101 +VkCommandBuffer *vksc_cmdbuf; 4.102 +VkSemaphore sem_gotimg, sem_drawdone; 4.103 + 4.104 +int init(void) 4.105 +{ 4.106 + if(create_instance() == -1) return -1; 4.107 + if(create_surface() == -1) return -1; 4.108 + if(choose_phys_dev() == -1) return -1; 4.109 + if(create_device() == -1) return -1; 4.110 + if(create_swapchain() == -1) return -1; 4.111 + if(create_imgviews() == -1) return -1; 4.112 + if(create_rendpass() == -1) return -1; 4.113 + if(create_pipeline() == -1) return -1; 4.114 + if(create_framebuf() == -1) return -1; 4.115 + if(create_cmdpool() == -1) return -1; 4.116 + if(create_cmdbuf() == -1) return -1; 4.117 + if(create_semaphores() == -1) return -1; 4.118 + return 0; 4.119 +} 4.120 + 4.121 +void destroy(void) 4.122 +{ 4.123 + int i; 4.124 + 4.125 + if(sem_gotimg) vkDestroySemaphore(vkdev, sem_gotimg, 0); 4.126 + if(sem_drawdone) vkDestroySemaphore(vkdev, sem_drawdone, 0); 4.127 + if(vkcmdpool) vkDestroyCommandPool(vkdev, vkcmdpool, 0); 4.128 + if(vksc_fb) { 4.129 + for(i=0; i<vksc_numimg; i++) { 4.130 + vkDestroyFramebuffer(vkdev, vksc_fb[i], 0); 4.131 + } 4.132 + } 4.133 + if(vkpipe) vkDestroyPipeline(vkdev, vkpipe, 0); 4.134 + if(vkpipe_layout) vkDestroyPipelineLayout(vkdev, vkpipe_layout, 0); 4.135 + if(vkrpass) vkDestroyRenderPass(vkdev, vkrpass, 0); 4.136 + if(vksc_view) { 4.137 + for(i=0; i<vksc_numimg; i++) { 4.138 + vkDestroyImageView(vkdev, vksc_view[i], 0); 4.139 + } 4.140 + } 4.141 + if(vksc) vkDestroySwapchainKHR(vkdev, vksc, 0); 4.142 + if(vkdev) vkDestroyDevice(vkdev, 0); 4.143 + if(vksurf) vkDestroySurfaceKHR(vk, vksurf, 0); 4.144 + if(vk) vkDestroyInstance(vk, 0); 4.145 +} 4.146 + 4.147 +void draw(void) 4.148 +{ 4.149 + uint32_t img_idx; 4.150 + VkSubmitInfo submit; 4.151 + VkPipelineStageFlags wait_stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 4.152 + VkPresentInfoKHR pres; 4.153 + 4.154 + vkAcquireNextImageKHR(vkdev, vksc, UINT64_MAX, sem_gotimg, 0, &img_idx); 4.155 + 4.156 + memset(&submit, 0, sizeof submit); 4.157 + submit.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 4.158 + submit.waitSemaphoreCount = 1; 4.159 + submit.pWaitSemaphores = &sem_gotimg; 4.160 + submit.pWaitDstStageMask = &wait_stages; 4.161 + submit.commandBufferCount = 1; 4.162 + submit.pCommandBuffers = vksc_cmdbuf + img_idx; 4.163 + submit.signalSemaphoreCount = 1; 4.164 + submit.pSignalSemaphores = &sem_drawdone; 4.165 + 4.166 + if(vkQueueSubmit(vkq, 1, &submit, 0) != 0) { 4.167 + fprintf(stderr, "failed to submit draw commands\n"); 4.168 + abort(); 4.169 + } 4.170 + 4.171 + memset(&pres, 0, sizeof pres); 4.172 + pres.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; 4.173 + pres.waitSemaphoreCount = 1; 4.174 + pres.pWaitSemaphores = &sem_drawdone; 4.175 + pres.swapchainCount = 1; 4.176 + pres.pSwapchains = &vksc; 4.177 + pres.pImageIndices = &img_idx; 4.178 + 4.179 + vkQueuePresentKHR(vkq, &pres); 4.180 +} 4.181 + 4.182 +int create_instance(void) 4.183 +{ 4.184 + VkApplicationInfo appinf; 4.185 + VkInstanceCreateInfo iinf; 4.186 + uint32_t num_ext; 4.187 + const char **ext; 4.188 + 4.189 + ext = glfwGetRequiredInstanceExtensions(&num_ext); 4.190 + 4.191 + memset(&appinf, 0, sizeof appinf); 4.192 + appinf.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; 4.193 + appinf.pApplicationName = "test"; 4.194 + appinf.applicationVersion = VK_MAKE_VERSION(1, 0, 0); 4.195 + appinf.pEngineName = "fuckoff"; 4.196 + appinf.engineVersion = VK_MAKE_VERSION(1, 0, 0); 4.197 + appinf.apiVersion = VK_API_VERSION_1_0; 4.198 + 4.199 + memset(&iinf, 0, sizeof iinf); 4.200 + iinf.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; 4.201 + iinf.pApplicationInfo = &appinf; 4.202 + iinf.enabledExtensionCount = num_ext; 4.203 + iinf.ppEnabledExtensionNames = ext; 4.204 + 4.205 + if(vkCreateInstance(&iinf, 0, &vk) != 0) { 4.206 + fprintf(stderr, "failed to create instance\n"); 4.207 + return -1; 4.208 + } 4.209 + return 0; 4.210 +} 4.211 + 4.212 +int create_surface(void) 4.213 +{ 4.214 + if(glfwCreateWindowSurface(vk, win, 0, &vksurf) != 0) { 4.215 + fprintf(stderr, "failed to create window surface\n"); 4.216 + return -1; 4.217 + } 4.218 + return 0; 4.219 +} 4.220 + 4.221 +static int is_pdev_skookum(VkPhysicalDevice dev) 4.222 +{ 4.223 + uint32_t i, num_fmt, num_qfam, num_ext; 4.224 + VkQueueFamilyProperties *qfam; 4.225 + VkExtensionProperties *ext; 4.226 + VkPhysicalDeviceProperties prop; 4.227 + VkPhysicalDeviceFeatures feat; 4.228 + VkBool32 can_pres; 4.229 + int have_swap_ext; 4.230 + 4.231 + vkGetPhysicalDeviceProperties(dev, &prop); 4.232 + vkGetPhysicalDeviceFeatures(dev, &feat); 4.233 + 4.234 + /* check if we have the swapchain extension */ 4.235 + vkEnumerateDeviceExtensionProperties(dev, 0, &num_ext, 0); 4.236 + ext = alloca(num_ext * sizeof *ext); 4.237 + vkEnumerateDeviceExtensionProperties(dev, 0, &num_ext, ext); 4.238 + 4.239 + have_swap_ext = 0; 4.240 + for(i=0; i<num_ext; i++) { 4.241 + if(strcmp(ext[i].extensionName, "VK_KHR_swapchain") == 0) { 4.242 + have_swap_ext = 1; 4.243 + break; 4.244 + } 4.245 + } 4.246 + if(!have_swap_ext) { 4.247 + return 0; 4.248 + } 4.249 + 4.250 + /* populate format and present modes arrays, and make sure we have some of each */ 4.251 + vkGetPhysicalDeviceSurfaceFormatsKHR(dev, vksurf, &num_fmt, 0); 4.252 + if(!num_fmt || !(vksurf_fmt = malloc(num_fmt * sizeof *vksurf_fmt))) { 4.253 + return 0; 4.254 + } 4.255 + vksurf_numfmt = num_fmt; 4.256 + vkGetPhysicalDeviceSurfaceFormatsKHR(dev, vksurf, &num_fmt, vksurf_fmt); 4.257 + 4.258 + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(dev, vksurf, &vksurf_caps); 4.259 + 4.260 + /* find a queue family which can do graphics and can present */ 4.261 + vkGetPhysicalDeviceQueueFamilyProperties(dev, &num_qfam, 0); 4.262 + qfam = alloca(num_qfam * sizeof *qfam); 4.263 + vkGetPhysicalDeviceQueueFamilyProperties(dev, &num_qfam, qfam); 4.264 + 4.265 + vkqfam_idx = -1; 4.266 + for(i=0; i<num_qfam; i++) { 4.267 + vkGetPhysicalDeviceSurfaceSupportKHR(dev, i, vksurf, &can_pres); 4.268 + if(qfam[i].queueCount && (qfam[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) && can_pres) { 4.269 + vkqfam_idx = i; 4.270 + return 1; 4.271 + } 4.272 + } 4.273 + 4.274 + free(vksurf_fmt); 4.275 + vksurf_fmt = 0; 4.276 + vksurf_numfmt = 0; 4.277 + return 0; 4.278 +} 4.279 + 4.280 +static int choose_pixfmt(void) 4.281 +{ 4.282 + int i, j; 4.283 + static const VkFormat pref[] = { 4.284 + VK_FORMAT_B8G8R8_UNORM, 4.285 + VK_FORMAT_R8G8B8_UNORM, 4.286 + VK_FORMAT_B8G8R8A8_UNORM, 4.287 + VK_FORMAT_R8G8B8A8_UNORM 4.288 + }; 4.289 + 4.290 + vksurf_selfmt = 0; 4.291 + for(i=0; i<vksurf_numfmt; i++) { 4.292 + if(vksurf_fmt[i].colorSpace != VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { 4.293 + continue; 4.294 + } 4.295 + for(j=0; j<sizeof pref / sizeof *pref; j++) { 4.296 + if(vksurf_fmt[i].format == pref[j]) { 4.297 + vksurf_selfmt = i; 4.298 + return i; 4.299 + } 4.300 + } 4.301 + } 4.302 + return -1; 4.303 +} 4.304 + 4.305 +int choose_phys_dev(void) 4.306 +{ 4.307 + uint32_t i, num_pdev; 4.308 + VkPhysicalDevice *pdev; 4.309 + 4.310 + vkEnumeratePhysicalDevices(vk, &num_pdev, 0); 4.311 + if(!num_pdev) { 4.312 + fprintf(stderr, "no vulkan devices found\n"); 4.313 + return -1; 4.314 + } 4.315 + pdev = alloca(num_pdev * sizeof *pdev); 4.316 + vkEnumeratePhysicalDevices(vk, &num_pdev, pdev); 4.317 + 4.318 + for(i=0; i<num_pdev; i++) { 4.319 + if(is_pdev_skookum(pdev[i])) { 4.320 + vkpdev = pdev[i]; 4.321 + break; 4.322 + } 4.323 + } 4.324 + if(!vkpdev) { 4.325 + fprintf(stderr, "no skookum device found, vulkan can't chooch\n"); 4.326 + return -1; 4.327 + } 4.328 + 4.329 + choose_pixfmt(); 4.330 + return 0; 4.331 +} 4.332 + 4.333 +int create_device(void) 4.334 +{ 4.335 + static const float prio = 1.0f; 4.336 + VkDeviceQueueCreateInfo qinf; 4.337 + VkPhysicalDeviceFeatures feat; 4.338 + VkDeviceCreateInfo devinf; 4.339 + 4.340 + static const char *extensions[] = { 4.341 + "VK_KHR_swapchain" 4.342 + }; 4.343 + 4.344 + memset(&feat, 0, sizeof feat); 4.345 + 4.346 + memset(&qinf, 0, sizeof qinf); 4.347 + qinf.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; 4.348 + qinf.queueFamilyIndex = vkqfam_idx; 4.349 + qinf.queueCount = 1; 4.350 + qinf.pQueuePriorities = &prio; 4.351 + 4.352 + memset(&devinf, 0, sizeof devinf); 4.353 + devinf.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; 4.354 + devinf.pQueueCreateInfos = &qinf; 4.355 + devinf.queueCreateInfoCount = 1; 4.356 + devinf.pEnabledFeatures = &feat; 4.357 + devinf.enabledExtensionCount = sizeof extensions / sizeof *extensions; 4.358 + devinf.ppEnabledExtensionNames = extensions; 4.359 + 4.360 + if(vkCreateDevice(vkpdev, &devinf, 0, &vkdev) != 0) { 4.361 + fprintf(stderr, "failed to create vulkan device\n"); 4.362 + return -1; 4.363 + } 4.364 + 4.365 + vkGetDeviceQueue(vkdev, vkqfam_idx, 0, &vkq); 4.366 + return 0; 4.367 +} 4.368 + 4.369 +int create_swapchain(void) 4.370 +{ 4.371 + uint32_t num; 4.372 + VkSwapchainCreateInfoKHR scinf; 4.373 + 4.374 + vksc_extent.width = win_width; 4.375 + vksc_extent.height = win_height; 4.376 + 4.377 + memset(&scinf, 0, sizeof scinf); 4.378 + scinf.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; 4.379 + scinf.surface = vksurf; 4.380 + scinf.minImageCount = 2; 4.381 + scinf.imageFormat = vksurf_fmt[vksurf_selfmt].format; 4.382 + scinf.imageColorSpace = vksurf_fmt[vksurf_selfmt].colorSpace; 4.383 + scinf.imageExtent = vksc_extent; 4.384 + scinf.imageArrayLayers = 1; 4.385 + scinf.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 4.386 + scinf.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; 4.387 + scinf.preTransform = vksurf_caps.currentTransform; 4.388 + scinf.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; 4.389 + scinf.presentMode = VK_PRESENT_MODE_FIFO_KHR; 4.390 + scinf.clipped = VK_TRUE; 4.391 + 4.392 + if(vkCreateSwapchainKHR(vkdev, &scinf, 0, &vksc) != 0) { 4.393 + fprintf(stderr, "failed to create swapchain\n"); 4.394 + return -1; 4.395 + } 4.396 + 4.397 + vkGetSwapchainImagesKHR(vkdev, vksc, &num, 0); 4.398 + if(!num || !(vksc_img = malloc(num * sizeof *vksc_img))) { 4.399 + fprintf(stderr, "failed to allocate swapchain image array (%d images)\n", vksc_numimg); 4.400 + return -1; 4.401 + } 4.402 + vkGetSwapchainImagesKHR(vkdev, vksc, &num, vksc_img); 4.403 + vksc_numimg = num; 4.404 + 4.405 + return 0; 4.406 +} 4.407 + 4.408 +int create_imgviews(void) 4.409 +{ 4.410 + int i; 4.411 + VkImageViewCreateInfo ivinf; 4.412 + 4.413 + if(!(vksc_view = malloc(vksc_numimg * sizeof *vksc_view))) { 4.414 + fprintf(stderr, "failed to allocate image view array (%d images)\n", vksc_numimg); 4.415 + return -1; 4.416 + } 4.417 + 4.418 + for(i=0; i<vksc_numimg; i++) { 4.419 + memset(&ivinf, 0, sizeof ivinf); 4.420 + ivinf.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 4.421 + ivinf.image = vksc_img[i]; 4.422 + ivinf.format = vksurf_fmt[vksurf_selfmt].format; 4.423 + ivinf.components.r = ivinf.components.g = ivinf.components.b = 4.424 + ivinf.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; 4.425 + ivinf.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 4.426 + ivinf.subresourceRange.levelCount = 1; 4.427 + ivinf.subresourceRange.layerCount = 1; 4.428 + 4.429 + if(vkCreateImageView(vkdev, &ivinf, 0, vksc_view + i) != 0) { 4.430 + fprintf(stderr, "failed to create image view for image %d\n", i); 4.431 + return -1; 4.432 + } 4.433 + } 4.434 + return 0; 4.435 +} 4.436 + 4.437 +int create_rendpass(void) 4.438 +{ 4.439 + VkAttachmentDescription cat; 4.440 + VkAttachmentReference catref; 4.441 + VkSubpassDescription subpass; 4.442 + VkRenderPassCreateInfo pinf; 4.443 + VkSubpassDependency dep; 4.444 + 4.445 + memset(&cat, 0, sizeof cat); 4.446 + cat.format = vksurf_fmt[vksurf_selfmt].format; 4.447 + cat.samples = VK_SAMPLE_COUNT_1_BIT; 4.448 + cat.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; 4.449 + cat.storeOp = VK_ATTACHMENT_STORE_OP_STORE; 4.450 + cat.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 4.451 + cat.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 4.452 + cat.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 4.453 + cat.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; 4.454 + 4.455 + memset(&catref, 0, sizeof catref); 4.456 + catref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 4.457 + 4.458 + memset(&subpass, 0, sizeof subpass); 4.459 + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 4.460 + subpass.colorAttachmentCount = 1; 4.461 + subpass.pColorAttachments = &catref; 4.462 + 4.463 + memset(&dep, 0, sizeof dep); 4.464 + dep.srcSubpass = VK_SUBPASS_EXTERNAL; 4.465 + dep.dstSubpass = 0; 4.466 + dep.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 4.467 + dep.srcAccessMask = 0; 4.468 + dep.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 4.469 + dep.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 4.470 + 4.471 + memset(&pinf, 0, sizeof pinf); 4.472 + pinf.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; 4.473 + pinf.attachmentCount = 1; 4.474 + pinf.pAttachments = &cat; 4.475 + pinf.subpassCount = 1; 4.476 + pinf.pSubpasses = &subpass; 4.477 + pinf.dependencyCount = 1; 4.478 + pinf.pDependencies = &dep; 4.479 + 4.480 + if(vkCreateRenderPass(vkdev, &pinf, 0, &vkrpass) != 0) { 4.481 + fprintf(stderr, "failed to create render pass\n"); 4.482 + return -1; 4.483 + } 4.484 + return 0; 4.485 +} 4.486 + 4.487 +int create_pipeline(void) 4.488 +{ 4.489 + int i; 4.490 + VkShaderModule sdr[2]; 4.491 + VkPipelineShaderStageCreateInfo ssinf[2]; 4.492 + VkPipelineVertexInputStateCreateInfo vinp; 4.493 + VkPipelineInputAssemblyStateCreateInfo vasm; 4.494 + VkViewport vport; 4.495 + VkRect2D scissor; 4.496 + VkPipelineViewportStateCreateInfo vp; 4.497 + VkPipelineRasterizationStateCreateInfo rast; 4.498 + VkPipelineMultisampleStateCreateInfo msaa; 4.499 + VkPipelineColorBlendAttachmentState bat; 4.500 + VkPipelineColorBlendStateCreateInfo blend; 4.501 + VkPipelineLayoutCreateInfo lay; 4.502 + VkGraphicsPipelineCreateInfo pinf; 4.503 + 4.504 + if(!(sdr[0] = load_shader("vertex.glsl")) || !(sdr[1] = load_shader("pixel.glsl"))) { 4.505 + return -1; 4.506 + } 4.507 + memset(ssinf, 0, sizeof ssinf); 4.508 + for(i=0; i<2; i++) { 4.509 + ssinf[i].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 4.510 + ssinf[i].stage = i == 0 ? VK_SHADER_STAGE_VERTEX_BIT : VK_SHADER_STAGE_FRAGMENT_BIT; 4.511 + ssinf[i].module = sdr[i]; 4.512 + ssinf[i].pName = "main"; 4.513 + } 4.514 + 4.515 + memset(&vinp, 0, sizeof vinp); 4.516 + vinp.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; 4.517 + 4.518 + memset(&vasm, 0, sizeof vasm); 4.519 + vasm.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; 4.520 + vasm.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; 4.521 + 4.522 + vport.x = vport.y = 0; 4.523 + vport.width = vksc_extent.width; 4.524 + vport.height = vksc_extent.height; 4.525 + vport.minDepth = 0.0f; 4.526 + vport.maxDepth = 1.0f; 4.527 + 4.528 + scissor.offset.x = scissor.offset.y = 0; 4.529 + scissor.extent = vksc_extent; 4.530 + 4.531 + memset(&vp, 0, sizeof vp); 4.532 + vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; 4.533 + vp.viewportCount = 1; 4.534 + vp.pViewports = &vport; 4.535 + vp.scissorCount = 1; 4.536 + vp.pScissors = &scissor; 4.537 + 4.538 + memset(&rast, 0, sizeof rast); 4.539 + rast.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; 4.540 + rast.polygonMode = VK_POLYGON_MODE_FILL; 4.541 + rast.lineWidth = 1.0f; 4.542 + rast.cullMode = VK_CULL_MODE_BACK_BIT; 4.543 + rast.frontFace = VK_FRONT_FACE_CLOCKWISE; 4.544 + 4.545 + memset(&msaa, 0, sizeof msaa); 4.546 + msaa.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; 4.547 + msaa.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; 4.548 + msaa.minSampleShading = 1.0f; 4.549 + 4.550 + memset(&bat, 0, sizeof bat); 4.551 + bat.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | 4.552 + VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 4.553 + 4.554 + memset(&blend, 0, sizeof blend); 4.555 + blend.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; 4.556 + blend.attachmentCount = 1; 4.557 + blend.pAttachments = &bat; 4.558 + 4.559 + 4.560 + memset(&lay, 0, sizeof lay); 4.561 + lay.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 4.562 + 4.563 + if(vkCreatePipelineLayout(vkdev, &lay, 0, &vkpipe_layout) != 0) { 4.564 + fprintf(stderr, "failed to create a pipeline layout\n"); 4.565 + return -1; 4.566 + } 4.567 + 4.568 + memset(&pinf, 0, sizeof pinf); 4.569 + pinf.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; 4.570 + pinf.stageCount = 2; 4.571 + pinf.pStages = ssinf; 4.572 + pinf.pVertexInputState = &vinp; 4.573 + pinf.pInputAssemblyState = &vasm; 4.574 + pinf.pViewportState = &vp; 4.575 + pinf.pRasterizationState = &rast; 4.576 + pinf.pMultisampleState = &msaa; 4.577 + pinf.pColorBlendState = &blend; 4.578 + pinf.layout = vkpipe_layout; 4.579 + pinf.renderPass = vkrpass; 4.580 + pinf.basePipelineIndex = -1; 4.581 + 4.582 + if(vkCreateGraphicsPipelines(vkdev, 0, 1, &pinf, 0, &vkpipe) != 0) { 4.583 + fprintf(stderr, "failed to create graphics pipeline\n"); 4.584 + return -1; 4.585 + } 4.586 + 4.587 + for(i=0; i<2; i++) { 4.588 + vkDestroyShaderModule(vkdev, sdr[i], 0); 4.589 + } 4.590 + return 0; 4.591 +} 4.592 + 4.593 +int create_framebuf(void) 4.594 +{ 4.595 + int i; 4.596 + VkFramebufferCreateInfo fbinf; 4.597 + 4.598 + if(!(vksc_fb = malloc(vksc_numimg * sizeof *vksc_fb))) { 4.599 + fprintf(stderr, "failed to allocate array for swap chain framebuffers\n"); 4.600 + return -1; 4.601 + } 4.602 + 4.603 + for(i=0; i<vksc_numimg; i++) { 4.604 + memset(&fbinf, 0, sizeof fbinf); 4.605 + fbinf.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; 4.606 + fbinf.renderPass = vkrpass; 4.607 + fbinf.attachmentCount = 1; 4.608 + fbinf.pAttachments = vksc_view + i; 4.609 + fbinf.width = vksc_extent.width; 4.610 + fbinf.height = vksc_extent.height; 4.611 + fbinf.layers = 1; 4.612 + 4.613 + if(vkCreateFramebuffer(vkdev, &fbinf, 0, vksc_fb + i) != 0) { 4.614 + fprintf(stderr, "failed to create framebuffer\n"); 4.615 + return -1; 4.616 + } 4.617 + } 4.618 + 4.619 + return 0; 4.620 +} 4.621 + 4.622 +int create_cmdpool(void) 4.623 +{ 4.624 + VkCommandPoolCreateInfo cpinf; 4.625 + 4.626 + memset(&cpinf, 0, sizeof cpinf); 4.627 + cpinf.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; 4.628 + cpinf.queueFamilyIndex = vkqfam_idx; 4.629 + 4.630 + if(vkCreateCommandPool(vkdev, &cpinf, 0, &vkcmdpool) != 0) { 4.631 + fprintf(stderr, "failed to create command pool\n"); 4.632 + return -1; 4.633 + } 4.634 + return 0; 4.635 +} 4.636 + 4.637 +int create_cmdbuf(void) 4.638 +{ 4.639 + int i; 4.640 + VkCommandBufferAllocateInfo cbinf; 4.641 + 4.642 + if(!(vksc_cmdbuf = malloc(vksc_numimg * sizeof *vksc_cmdbuf))) { 4.643 + fprintf(stderr, "failed to allocate array of command buffers\n"); 4.644 + return -1; 4.645 + } 4.646 + 4.647 + memset(&cbinf, 0, sizeof cbinf); 4.648 + cbinf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; 4.649 + cbinf.commandPool = vkcmdpool; 4.650 + cbinf.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; 4.651 + cbinf.commandBufferCount = vksc_numimg; 4.652 + 4.653 + if(vkAllocateCommandBuffers(vkdev, &cbinf, vksc_cmdbuf) != 0) { 4.654 + fprintf(stderr, "failed to allocate command buffers\n"); 4.655 + return -1; 4.656 + } 4.657 + 4.658 + /* pre-record command buffers, because why the fuck not */ 4.659 + for(i=0; i<vksc_numimg; i++) { 4.660 + VkCommandBufferBeginInfo cbegin; 4.661 + VkRenderPassBeginInfo rbegin; 4.662 + VkClearValue clear; 4.663 + 4.664 + memset(&cbegin, 0, sizeof cbegin); 4.665 + cbegin.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 4.666 + cbegin.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; 4.667 + 4.668 + if(vkBeginCommandBuffer(vksc_cmdbuf[i], &cbegin) != 0) { 4.669 + fprintf(stderr, "failed to begin command buffer recording\n"); 4.670 + return -1; 4.671 + } 4.672 + 4.673 + clear.color.float32[0] = 0.2f; 4.674 + clear.color.float32[1] = 0.2f; 4.675 + clear.color.float32[2] = 0.2f; 4.676 + clear.color.float32[3] = 1.0f; 4.677 + 4.678 + memset(&rbegin, 0, sizeof rbegin); 4.679 + rbegin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 4.680 + rbegin.renderPass = vkrpass; 4.681 + rbegin.framebuffer = vksc_fb[i]; 4.682 + rbegin.renderArea.extent = vksc_extent; 4.683 + rbegin.clearValueCount = 1; 4.684 + rbegin.pClearValues = &clear; 4.685 + 4.686 + vkCmdBeginRenderPass(vksc_cmdbuf[i], &rbegin, VK_SUBPASS_CONTENTS_INLINE); 4.687 + vkCmdBindPipeline(vksc_cmdbuf[i], VK_PIPELINE_BIND_POINT_GRAPHICS, vkpipe); 4.688 + vkCmdDraw(vksc_cmdbuf[i], 3, 1, 0, 0); 4.689 + vkCmdEndRenderPass(vksc_cmdbuf[i]); 4.690 + 4.691 + if(vkEndCommandBuffer(vksc_cmdbuf[i]) != 0) { 4.692 + fprintf(stderr, "failed to record command buffer\n"); 4.693 + return -1; 4.694 + } 4.695 + } 4.696 + return 0; 4.697 +} 4.698 + 4.699 +int create_semaphores(void) 4.700 +{ 4.701 + VkSemaphoreCreateInfo sinf; 4.702 + 4.703 + memset(&sinf, 0, sizeof sinf); 4.704 + sinf.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; 4.705 + 4.706 + if(vkCreateSemaphore(vkdev, &sinf, 0, &sem_gotimg) != 0) { 4.707 + fprintf(stderr, "failed to create semaphore\n"); 4.708 + return -1; 4.709 + } 4.710 + if(vkCreateSemaphore(vkdev, &sinf, 0, &sem_drawdone) != 0) { 4.711 + fprintf(stderr, "failed to create semaphore\n"); 4.712 + return -1; 4.713 + } 4.714 + return 0; 4.715 +} 4.716 + 4.717 +VkShaderModule load_shader(const char *fname) 4.718 +{ 4.719 + FILE *fp; 4.720 + long sz; 4.721 + void *buf; 4.722 + VkShaderModuleCreateInfo sinf; 4.723 + VkShaderModule sdr; 4.724 + 4.725 + if(!(fp = fopen(fname, "rb"))) { 4.726 + fprintf(stderr, "failed to open shader: %s: %s\n", fname, strerror(errno)); 4.727 + return 0; 4.728 + } 4.729 + fseek(fp, 0, SEEK_END); 4.730 + sz = ftell(fp); 4.731 + fseek(fp, 0, SEEK_SET); 4.732 + 4.733 + buf = alloca(sz); 4.734 + if(fread(buf, 1, sz, fp) < sz) { 4.735 + fprintf(stderr, "unexpected EOF while reading shader: %s\n", fname); 4.736 + fclose(fp); 4.737 + return 0; 4.738 + } 4.739 + fclose(fp); 4.740 + 4.741 + memset(&sinf, 0, sizeof sinf); 4.742 + sinf.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 4.743 + sinf.codeSize = sz; 4.744 + sinf.pCode = buf; 4.745 + 4.746 + if(vkCreateShaderModule(vkdev, &sinf, 0, &sdr) != 0) { 4.747 + fprintf(stderr, "failed to create shader from %s\n", fname); 4.748 + return 0; 4.749 + } 4.750 + return sdr; 4.751 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/vertex.glsl Thu Jun 28 13:57:28 2018 +0300 5.3 @@ -0,0 +1,26 @@ 5.4 +#version 450 5.5 +#extension GL_ARB_separate_shader_objects : enable 5.6 + 5.7 +out gl_PerVertex { 5.8 + vec4 gl_Position; 5.9 +}; 5.10 + 5.11 +layout(location = 0) out vec3 color; 5.12 + 5.13 +vec2 vpos[3] = vec2[]( 5.14 + vec2(0.0, -0.5), 5.15 + vec2(0.5, 0.5), 5.16 + vec2(-0.5, 0.5) 5.17 +); 5.18 + 5.19 +vec3 vcol[3] = vec3[]( 5.20 + vec3(1.0, 0.0, 0.0), 5.21 + vec3(0.0, 1.0, 0.0), 5.22 + vec3(0.0, 0.0, 1.0) 5.23 +); 5.24 + 5.25 +void main() 5.26 +{ 5.27 + gl_Position = vec4(vpos[gl_VertexIndex], 0.0, 1.0); 5.28 + color = vcol[gl_VertexIndex]; 5.29 +}