Advertisement
Guest User

Triangle

a guest
Apr 23rd, 2024
143
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 47.67 KB | Source Code | 0 0
  1. #define GLFW_INCLUDE_VULKAN
  2. #include <GLFW/glfw3.h>
  3. #include <inttypes.h>
  4. #include <stdio.h>
  5. #include <stdbool.h>
  6. #include <string.h>
  7. #include <stddef.h>
  8. #include "cglm/cglm.h"
  9.  
  10. typedef struct
  11. {
  12.     vec2 pos;
  13.     vec3 color;
  14. }   _vertex;
  15.  
  16. typedef struct
  17. {
  18.     GLFWwindow *window;
  19.     VkInstance instance;
  20.     VkDebugUtilsMessengerEXT debug_messenger;
  21.     VkSurfaceKHR surface;
  22.     VkPhysicalDevice gpu;
  23.     VkDevice gpu_interface;
  24.     VkQueue queue;
  25.     uint32_t queue_index;
  26.     VkSwapchainKHR swapchain;
  27.     VkImage images[256];
  28.     uint32_t image_count;
  29.     VkImageView image_data[256];
  30.     VkFormat format;
  31.     VkExtent2D extent;
  32.     VkRenderPass render_pass;
  33.     VkPipelineLayout pipeline_layout;
  34.     VkPipeline graphics_pipeline;
  35.     VkFramebuffer framebuffers[256];
  36.     VkCommandPool command_pool;
  37.     VkCommandBuffer command_buffers[8];
  38.     VkSemaphore image_available[8];
  39.     VkSemaphore render_finished[8];
  40.     VkFence in_flight[8];
  41.     uint32_t current_frame;
  42.     bool framebuffer_resized;
  43.     VkBuffer vertex_buffer;
  44.     VkDeviceMemory vertex_buffer_memory;
  45. }   _vk;
  46.  
  47. bool vk_init(_vk *vk, bool debugging);
  48. bool vk_instance_init(_vk *vk, bool debugging);
  49. bool vk_debug_messenger_init(_vk *vk);
  50. bool vk_surface_init(_vk *vk);
  51. bool vk_gpu_init(_vk *vk);
  52. bool vk_gpu_interface_init(_vk *vk, bool debugging);
  53. bool vk_swapchain_init(_vk *vk);
  54. bool vk_image_data_init(_vk *vk);
  55. bool vk_render_pass_init(_vk *vk);
  56. bool vk_graphics_pipeline_init(_vk *vk);
  57. bool vk_framebuffers_init(_vk *vk);
  58. bool vk_command_pool_init(_vk *vk);
  59. bool vk_vertex_buffer_init(_vk *vk);
  60. bool vk_command_buffers_init(_vk *vk);
  61. bool vk_sync_objects_init(_vk *vk);
  62. GLFWwindow *vk_window_init(const char *title);
  63. bool vk_validation_layer_support(void);
  64. void vk_required_extensions(const char **required_extensions, uint32_t *required_extension_count, bool debugging);
  65. void vk_populate_debug_messenger_create_info(VkDebugUtilsMessengerCreateInfoEXT *debug_info);
  66. VKAPI_ATTR VkResult VKAPI_CALL vk_create_debug_utils_messenger_ext(_vk *vk, const VkDebugUtilsMessengerCreateInfoEXT debug_info, const VkAllocationCallbacks *allocator);
  67. VKAPI_ATTR void VKAPI_CALL vk_destroy_debug_utils_messenger_ext(_vk *vk, const VkAllocationCallbacks *allocator);
  68. const char *vk_debug_severity(VkDebugUtilsMessageSeverityFlagBitsEXT severity);
  69. const char *vk_debug_type(VkDebugUtilsMessageTypeFlagBitsEXT type);
  70. bool vk_queue_families(_vk *vk);
  71. VkSurfaceFormatKHR vk_surface_format(VkSurfaceFormatKHR *formats, uint32_t format_count);
  72. VkPresentModeKHR vk_present_mode(const VkPresentModeKHR *present_modes, uint32_t present_mode_count);
  73. VkExtent2D vk_swap_extent(_vk *vk, const VkSurfaceCapabilitiesKHR extent);
  74. VkShaderModule vk_shader_module_init(_vk *vk, const uint32_t *shader, const size_t shader_size);
  75. void vk_swapchain_recreation(_vk *vk);
  76. void vk_swapchain_destruction(_vk *vk);
  77. VkVertexInputBindingDescription vk_get_binding_description(void);
  78. VkVertexInputAttributeDescription vk_get_attribute_description(void);
  79. VkVertexInputAttributeDescription vk_get_color_data(void);
  80. uint32_t vk_find_memory_type(_vk *vk, uint32_t type_filter, VkMemoryPropertyFlags properties);
  81. void vk_mainloop(_vk *vk);
  82. void vk_cleanup(_vk *vk, bool debugging);
  83. void vk_draw_frame(_vk *vk);
  84. bool vk_command_buffer_write(_vk *vk, uint32_t current_frame, uint32_t image_index);
  85.  
  86. typedef struct
  87. {
  88.     _vk vk;
  89. } _app;
  90.  
  91. bool app_init(_app *app, bool debugging);
  92. void app_mainloop(_app *app);
  93. void app_cleanup(_app *app, bool debugging);
  94.  
  95. const _vertex VERTICES[] =
  96. {
  97.     { {0.0f, -0.5f}, {1.0f, 0.0f, 0.0f}},
  98.     {{ 0.5f,  0.5f}, {0.0f, 1.0f, 0.0f}},
  99.     {{-0.5f,  0.5f}, {0.0f, 0.0f, 1.0f}}
  100. };
  101.  
  102. const uint32_t VALIDATION_LAYER_COUNT = 1;
  103. const char *VALIDATION_LAYERS[] =
  104. {
  105.     "VK_LAYER_KHRONOS_validation"
  106. };
  107.  
  108. const uint32_t DEVICE_EXTENSION_COUNT = 1;
  109. const char *DEVICE_EXTENSIONS[] =
  110. {
  111.     VK_KHR_SWAPCHAIN_EXTENSION_NAME
  112. };
  113.  
  114. const uint32_t MAX_FRAMES_IN_FLIGHT = 2;
  115.  
  116. static void glfw_error_callback(int code, const char *description)
  117. {
  118.     fprintf(stderr, "GLFW Error %d: %s\n", code, description);
  119. }
  120.  
  121. static void glfw_framebuffer_resize_callback(GLFWwindow *window, int width, int height)
  122. {
  123.     _vk *vk = (_vk *) glfwGetWindowUserPointer(window);
  124.     vk->framebuffer_resized = true;
  125.     fprintf(stdout, "Current size of window: %d x %d\n", width, height);
  126. }
  127.  
  128. VkVertexInputBindingDescription vk_get_binding_description(void)
  129. {
  130.     VkVertexInputBindingDescription binding_description =
  131.     {
  132.         .binding = 0,
  133.         .stride = sizeof(_vertex),
  134.         .inputRate = VK_VERTEX_INPUT_RATE_VERTEX
  135.     };
  136.    
  137.     return binding_description;
  138. }
  139.  
  140. VkVertexInputAttributeDescription vk_get_attribute_description(void)
  141. {
  142.     VkVertexInputAttributeDescription attribute_description =
  143.     {
  144.         .binding = 0,
  145.         .location = 0,
  146.         .format = VK_FORMAT_R32G32_SFLOAT,
  147.         .offset = offsetof(_vertex, color)
  148.     };
  149.    
  150.     return attribute_description;
  151. }
  152.  
  153. VkVertexInputAttributeDescription vk_get_color_data(void)
  154. {
  155.     VkVertexInputAttributeDescription color_data =
  156.     {
  157.         .binding = 0,
  158.         .location = 1,
  159.         .format = VK_FORMAT_R32G32B32_SFLOAT,
  160.         .offset = offsetof(_vertex, color)
  161.     };
  162.    
  163.     return color_data;
  164. }
  165.  
  166. GLFWwindow *vk_window_init(const char *title)
  167. {
  168.     const uint32_t WINDOW_WIDTH = 800;
  169.     const uint32_t WINDOW_HEIGHT = 600;
  170.    
  171.     glfwInit();
  172.    
  173.     glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
  174.    
  175.     glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
  176.    
  177.     glfwSetErrorCallback(glfw_error_callback);
  178.    
  179.     GLFWwindow *window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, title, NULL, NULL);
  180.     glfwSetFramebufferSizeCallback(window, glfw_framebuffer_resize_callback);
  181.    
  182.     if (window == NULL)
  183.     {
  184.         fprintf(stderr, "Failed to create window!\n");
  185.     }
  186.  
  187.     return window;
  188. }
  189.  
  190. bool vk_init(_vk *vk, bool debugging)
  191. {
  192.     vk->window = vk_window_init("Vulkan Game");
  193.     vk->gpu = VK_NULL_HANDLE;
  194.     bool success = vk_instance_init(vk, debugging);
  195.    
  196.     if (debugging && success)
  197.     {
  198.         vk_debug_messenger_init(vk);
  199.     }
  200.  
  201.     success &= vk_surface_init(vk);
  202.     success &= vk_gpu_init(vk);
  203.     success &= vk_gpu_interface_init(vk, debugging);
  204.     success &= vk_swapchain_init(vk);
  205.     success &= vk_image_data_init(vk);
  206.     success &= vk_render_pass_init(vk);
  207.     success &= vk_graphics_pipeline_init(vk);
  208.     success &= vk_framebuffers_init(vk);
  209.     success &= vk_command_pool_init(vk);
  210.     success &= vk_command_buffers_init(vk);
  211.     success &= vk_sync_objects_init(vk);
  212.    
  213.     return success;
  214. }
  215.  
  216. void vk_mainloop(_vk *vk)
  217. {
  218.     while (!glfwWindowShouldClose(vk->window))
  219.     {
  220.         glfwPollEvents();
  221.         vk_draw_frame(vk);
  222.     }
  223.    
  224.     vkDeviceWaitIdle(vk->gpu_interface);
  225. }
  226.  
  227. void vk_cleanup(_vk *vk, bool debugging)
  228. {
  229.     vk_swapchain_destruction(vk);
  230.    
  231.     vkDestroyBuffer(vk->gpu_interface, vk->vertex_buffer, NULL);
  232.     vkFreeMemory(vk->gpu_interface, vk->vertex_buffer_memory, NULL);
  233.     vkDestroyPipeline(vk->gpu_interface, vk->graphics_pipeline, NULL);
  234.     vkDestroyPipelineLayout(vk->gpu_interface, vk->pipeline_layout, NULL);
  235.     vkDestroyRenderPass(vk->gpu_interface, vk->render_pass, NULL);
  236.    
  237.     for (uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
  238.     {
  239.         vkDestroySemaphore(vk->gpu_interface, vk->image_available[i], NULL);
  240.         vkDestroySemaphore(vk->gpu_interface, vk->render_finished[i], NULL);
  241.         vkDestroyFence(vk->gpu_interface, vk->in_flight[i], NULL);
  242.     }
  243.    
  244.     vkDestroyCommandPool(vk->gpu_interface, vk->command_pool, NULL);
  245.    
  246.     vkDestroyDevice(vk->gpu_interface, NULL);
  247.    
  248.     if (debugging)
  249.     {
  250.         vk_destroy_debug_utils_messenger_ext(vk, NULL);
  251.     }
  252.    
  253.     vkDestroySurfaceKHR(vk->instance, vk->surface, NULL);
  254.     vkDestroyInstance(vk->instance, NULL);
  255.    
  256.     glfwDestroyWindow(vk->window);
  257.    
  258.     vk->window = NULL;
  259.    
  260.     glfwTerminate();
  261. }
  262.  
  263. bool vk_instance_init(_vk *vk, bool debugging)
  264. {
  265.     if (debugging && !vk_validation_layer_support())
  266.     {
  267.         fprintf(stderr, "Validation layers requested, but are not available!\n");
  268.     }
  269.    
  270.     VkApplicationInfo app_info =
  271.     {
  272.         .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
  273.         .pApplicationName = "Vulkan App",
  274.         .applicationVersion = VK_MAKE_API_VERSION(0, 1, 3, 239),
  275.         .pEngineName = "No Engine",
  276.         .engineVersion = VK_MAKE_API_VERSION(0, 1, 3, 239),
  277.         .apiVersion = VK_API_VERSION_1_3
  278.     };
  279.    
  280.     uint32_t required_extension_count = 0;
  281.     vk_required_extensions(NULL, &required_extension_count, debugging);
  282.    
  283.     const char *required_extensions[required_extension_count];
  284.     vk_required_extensions(required_extensions, &required_extension_count, debugging);
  285.    
  286.     if (required_extension_count == 0)
  287.     {
  288.         fprintf(stderr, "Failed to find required instance extensions!\n");
  289.     }
  290.  
  291.     uint32_t available_extension_count = 0;
  292.     vkEnumerateInstanceExtensionProperties(NULL, &available_extension_count, NULL);
  293.    
  294.     VkExtensionProperties available_extensions[available_extension_count];
  295.    
  296.     vkEnumerateInstanceExtensionProperties(NULL, &available_extension_count, available_extensions);
  297.    
  298.     if (available_extension_count == 0)
  299.     {
  300.         fprintf(stderr, "Failed to find any Vulkan extensions!\n");
  301.     }
  302.    
  303.     fprintf(stdout, "%u available extensions:\n", available_extension_count);
  304.    
  305.     for (uint32_t i = 0; i < available_extension_count; i++)
  306.     {
  307.         fprintf(stdout, "\t %s (spec version %u)\n", available_extensions[i].extensionName, available_extensions[i].specVersion);
  308.     }
  309.    
  310.     VkInstanceCreateInfo instance_info =
  311.     {
  312.         .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
  313.         .pNext = NULL,
  314.         .flags = 0,
  315.         .pApplicationInfo = &app_info,
  316.         .enabledExtensionCount = required_extension_count,
  317.         .ppEnabledExtensionNames = required_extensions,
  318.     };
  319.    
  320.     VkDebugUtilsMessengerCreateInfoEXT debug_info = {0};
  321.     if (debugging)
  322.     {
  323.         instance_info.enabledLayerCount = VALIDATION_LAYER_COUNT;
  324.         instance_info.ppEnabledLayerNames = VALIDATION_LAYERS;
  325.        
  326.         vk_populate_debug_messenger_create_info(&debug_info);
  327.         instance_info.pNext = (VkDebugUtilsMessengerCreateInfoEXT *) &debug_info;
  328.     }
  329.    
  330.     instance_info.enabledLayerCount = 0;
  331.     instance_info.pNext = NULL;
  332.  
  333.     VkResult result = vkCreateInstance(&instance_info, NULL, &vk->instance);
  334.    
  335.     if (result != VK_SUCCESS)
  336.     {
  337.         fprintf(stderr, "Failed to create instance!\n");
  338.         return false;
  339.     }
  340.    
  341.     return true;
  342. }
  343.  
  344. bool vk_debug_messenger_init(_vk *vk)
  345. {  
  346.     VkDebugUtilsMessengerCreateInfoEXT debug_info = {0};
  347.     vk_populate_debug_messenger_create_info(&debug_info);
  348.    
  349.     VkResult result = vk_create_debug_utils_messenger_ext(vk, debug_info, NULL);
  350.     if (result != VK_SUCCESS)
  351.     {
  352.         fprintf(stderr, "Failed to create debug messenger!\n");
  353.         return false;
  354.     }
  355.    
  356.     return true;
  357. }
  358.  
  359. static VKAPI_ATTR VkBool32 VKAPI_CALL vk_debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagBitsEXT type, const VkDebugUtilsMessengerCallbackDataEXT *callback_data, void *user_data)
  360. {
  361.     fprintf(stdout, "Validation Layers: %s\n", callback_data->pMessage);
  362.     fprintf(stdout, "\t Severity: %s\n", vk_debug_severity(severity));
  363.     fprintf(stdout, "\t Type: %s\n", vk_debug_type(type));
  364.     fprintf(stdout, "\t Objects: ");
  365.    
  366.     for (uint32_t i = 0; i < callback_data->objectCount; i++)
  367.     {
  368.         fprintf(stdout, "%lx \n", callback_data->pObjects[i].objectHandle);
  369.     }
  370.    
  371.     _vk *vk = (_vk *) user_data;
  372.     fprintf(stdout, "Optional user data: %p\n", (void *) vk);
  373.    
  374.     return VK_FALSE;
  375. }
  376.  
  377. void vk_populate_debug_messenger_create_info(VkDebugUtilsMessengerCreateInfoEXT *debug_info)
  378. {
  379.     debug_info->sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
  380.     debug_info->pNext = NULL;
  381.     debug_info->flags = 0;
  382.     debug_info->messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
  383.     debug_info->messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
  384.     debug_info->pfnUserCallback = vk_debug_callback;
  385.     debug_info->pUserData = NULL;
  386. }
  387.  
  388. VKAPI_ATTR VkResult VKAPI_CALL vk_create_debug_utils_messenger_ext(_vk *vk, const VkDebugUtilsMessengerCreateInfoEXT debug_info, const VkAllocationCallbacks *allocator)
  389. {
  390.     PFN_vkCreateDebugUtilsMessengerEXT func = (PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(vk->instance, "vkCreateDebugUtilsMessengerEXT");
  391.    
  392.     if (func != NULL)
  393.     {
  394.         return func(vk->instance, &debug_info, allocator, &vk->debug_messenger);
  395.     }
  396.    
  397.     return VK_ERROR_EXTENSION_NOT_PRESENT;
  398. }
  399.  
  400. VKAPI_ATTR void VKAPI_CALL vk_destroy_debug_utils_messenger_ext(_vk *vk, const VkAllocationCallbacks *allocator)
  401. {
  402.     PFN_vkDestroyDebugUtilsMessengerEXT func = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(vk->instance, "vkDestroyDebugUtilsMessengerEXT");
  403.    
  404.     if (func != NULL)
  405.     {
  406.         func(vk->instance, vk->debug_messenger, allocator);
  407.     }
  408. }
  409.  
  410. bool vk_validation_layer_support(void)
  411. {
  412.     uint32_t layer_count = 0;
  413.     vkEnumerateInstanceLayerProperties(&layer_count, NULL);
  414.    
  415.     if (layer_count == 0)
  416.     {
  417.         fprintf(stderr, "Failed to find validation layers!\n");
  418.         return false;
  419.     }
  420.    
  421.     VkLayerProperties available_layers[layer_count];
  422.     vkEnumerateInstanceLayerProperties(&layer_count, available_layers);
  423.    
  424.     for (uint32_t i = 0; i < VALIDATION_LAYER_COUNT; i++)
  425.     {
  426.         bool layer_found = false;
  427.         for (uint32_t j = 0; j < layer_count; j++)
  428.         {
  429.             if (strcmp(VALIDATION_LAYERS[i], available_layers[j].layerName) == 0)
  430.             {
  431.                 layer_found = true;
  432.                 break;
  433.             }
  434.         }
  435.         if (!layer_found)
  436.         {
  437.             return false;
  438.         }
  439.     }
  440.    
  441.     return true;
  442. }
  443.  
  444. void vk_required_extensions(const char **required_extensions, uint32_t *required_extension_count, bool debugging)
  445. {
  446.     uint32_t glfw_extension_count = 0;
  447.     const char **glfw_extensions = glfwGetRequiredInstanceExtensions(&glfw_extension_count);
  448.    
  449.     if (glfw_extensions == NULL)
  450.     {
  451.         fprintf(stderr, "Failed to find required instance extensions!\n");
  452.         return;
  453.     }
  454.  
  455.     if (required_extensions == NULL)
  456.     {
  457.         *required_extension_count = glfw_extension_count + debugging;      
  458.         return;
  459.     }
  460.    
  461.     for (uint32_t i = 0; i < glfw_extension_count; i++)
  462.     {
  463.         required_extensions[i] = glfw_extensions[i];
  464.     }
  465.    
  466.     if (debugging)
  467.     {
  468.         required_extensions[glfw_extension_count] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
  469.     }
  470. }
  471.  
  472. const char *vk_debug_severity(VkDebugUtilsMessageSeverityFlagBitsEXT severity)
  473. {
  474.     switch (severity)
  475.     {
  476.         case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
  477.             return "Verbose";
  478.         case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
  479.             return "Info";
  480.         case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
  481.             return "Warning";
  482.         case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
  483.             return "Error";
  484.         default:
  485.             fprintf(stdout, "Invalid severity code: %d\n", severity);
  486.     }
  487.    
  488.     return "No such severity\n";
  489. }
  490.  
  491. const char *vk_debug_type(VkDebugUtilsMessageTypeFlagBitsEXT type)
  492. {
  493.     switch (type)
  494.     {
  495.         case VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT:
  496.             return "General";
  497.         case VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT:
  498.             return "Validation";
  499.         case VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT:
  500.             return "Performance";
  501.         default:
  502.             fprintf(stdout, "Invalid type code: %d\n", type);
  503.     }
  504.    
  505.     return "No such type\n";
  506. }
  507.  
  508. bool vk_gpu_init(_vk *vk)
  509. {
  510.     uint32_t gpu_count = 0;
  511.     vkEnumeratePhysicalDevices(vk->instance, &gpu_count, NULL);
  512.    
  513.     if (gpu_count == 0)
  514.     {
  515.         fprintf(stderr, "Failed to find GPUs with Vulkan support!\n");
  516.         return false;
  517.     }
  518.    
  519.     VkPhysicalDevice gpus[gpu_count];
  520.     vkEnumeratePhysicalDevices(vk->instance, &gpu_count, gpus);
  521.    
  522.     vk->gpu = gpus[0];
  523.    
  524.     if (vk->gpu == VK_NULL_HANDLE)
  525.     {
  526.         fprintf(stderr, "Failed to find a suitable GPU!\n");
  527.         return false;
  528.     }
  529.    
  530.     return true;
  531. }
  532.  
  533. bool vk_queue_families(_vk *vk)
  534. {
  535.     uint32_t queue_family_count = 0;
  536.     vkGetPhysicalDeviceQueueFamilyProperties(vk->gpu, &queue_family_count, NULL);
  537.    
  538.     if (queue_family_count == 0)
  539.     {
  540.         fprintf(stderr, "Failed to find queue families!\n");
  541.     }
  542.    
  543.     VkQueueFamilyProperties queue_families[queue_family_count];
  544.     vkGetPhysicalDeviceQueueFamilyProperties(vk->gpu, &queue_family_count, queue_families);
  545.    
  546.     for (uint32_t i = 0; i < queue_family_count; i++)
  547.     {
  548.         VkBool32 graphics_support = queue_families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT;
  549.         VkBool32 present_support = false;
  550.         vkGetPhysicalDeviceSurfaceSupportKHR(vk->gpu, i, vk->surface, &present_support);
  551.        
  552.         if (!graphics_support && !present_support)
  553.         {
  554.             fprintf(stderr, "Failed to find queue families with render support!\n");
  555.             return false;
  556.         }
  557.        
  558.         vk->queue_index = i;
  559.     }
  560.    
  561.     return true;
  562. }
  563.  
  564. bool vk_gpu_interface_init(_vk *vk, bool debugging)
  565. {
  566.     if (!vk_queue_families(vk))
  567.     {
  568.         return false;
  569.     }
  570.    
  571.     float queue_priority = 1.0f;
  572.    
  573.     VkDeviceQueueCreateInfo queue_create_info =
  574.     {
  575.         .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
  576.         .pNext = NULL,
  577.         .flags = 0,
  578.         .queueFamilyIndex = vk->queue_index,
  579.         .queueCount = 1,
  580.         .pQueuePriorities = &queue_priority
  581.     };
  582.    
  583.     VkPhysicalDeviceFeatures gpu_features = {0};
  584.    
  585.     VkDeviceCreateInfo gpu_interface_info =
  586.     {
  587.         .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
  588.         .pNext = NULL,
  589.         .flags = 0,
  590.         .pQueueCreateInfos = &queue_create_info,
  591.         .queueCreateInfoCount = 1,
  592.         .pEnabledFeatures = &gpu_features,
  593.         .ppEnabledExtensionNames = DEVICE_EXTENSIONS,
  594.         .enabledExtensionCount = DEVICE_EXTENSION_COUNT,
  595.         .enabledLayerCount = 0
  596.     };
  597.    
  598.     if (debugging)
  599.     {
  600.         gpu_interface_info.enabledLayerCount = VALIDATION_LAYER_COUNT;
  601.         gpu_interface_info.ppEnabledLayerNames = VALIDATION_LAYERS;
  602.     }
  603.    
  604.     VkResult result = vkCreateDevice(vk->gpu, &gpu_interface_info, NULL, &vk->gpu_interface);
  605.     if (result != VK_SUCCESS)
  606.     {
  607.         fprintf(stderr, "Failed to create GPU interface!\n");
  608.         return false;
  609.     }
  610.    
  611.     vkGetDeviceQueue(vk->gpu_interface, vk->queue_index, 0, &vk->queue);
  612.    
  613.     return true;
  614. }
  615.  
  616. bool vk_surface_init(_vk *vk)
  617. {
  618.     VkResult result = glfwCreateWindowSurface(vk->instance, vk->window, NULL, &vk->surface);
  619.     if (result != VK_SUCCESS)
  620.     {
  621.         fprintf(stderr, "Failed to create window interface!\n");
  622.         return false;
  623.     }
  624.     return true;
  625. }
  626.  
  627. VkSurfaceFormatKHR vk_surface_format(VkSurfaceFormatKHR *formats, uint32_t format_count)
  628. {
  629.     for (uint32_t i = 0; i < format_count; i++)
  630.     {
  631.         if (formats[i].format == VK_FORMAT_B8G8R8A8_SRGB && formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
  632.         {
  633.             return formats[i];
  634.         }
  635.     }
  636.    
  637.     return formats[0];
  638. }
  639.  
  640. VkPresentModeKHR vk_present_mode(const VkPresentModeKHR *present_modes, uint32_t present_mode_count)
  641. {
  642.     for (uint32_t i = 0; i < present_mode_count; i++)
  643.     {
  644.         if (present_modes[i] == VK_PRESENT_MODE_MAILBOX_KHR)
  645.         {
  646.             return present_modes[i];
  647.         }
  648.     }
  649.    
  650.     return VK_PRESENT_MODE_FIFO_KHR;
  651. }
  652.  
  653. VkExtent2D vk_swap_extent(_vk *vk, const VkSurfaceCapabilitiesKHR extent)
  654. {
  655.     VkExtent2D extents;
  656.     if (extent.currentExtent.width == UINT32_MAX)
  657.     {
  658.         int width, height;
  659.         glfwGetFramebufferSize(vk->window, &width, &height);
  660.        
  661.         extents.width = width;
  662.         extents.height = height;
  663.     }
  664.     else
  665.     {
  666.         extents = extent.currentExtent;
  667.     }
  668.    
  669.     return extents;
  670. }
  671.  
  672. bool vk_swapchain_init(_vk *vk)
  673. {
  674.     VkSurfaceCapabilitiesKHR capabilities;
  675.     vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vk->gpu, vk->surface, &capabilities);
  676.    
  677.     uint32_t format_count = 0;
  678.     vkGetPhysicalDeviceSurfaceFormatsKHR(vk->gpu, vk->surface, &format_count, NULL);
  679.     VkSurfaceFormatKHR formats[format_count];
  680.     vkGetPhysicalDeviceSurfaceFormatsKHR(vk->gpu, vk->surface, &format_count, formats);
  681.    
  682.     uint32_t present_mode_count = 0;
  683.     vkGetPhysicalDeviceSurfacePresentModesKHR(vk->gpu, vk->surface, &present_mode_count, NULL);
  684.     VkPresentModeKHR present_modes[present_mode_count];
  685.     vkGetPhysicalDeviceSurfacePresentModesKHR(vk->gpu, vk->surface, &present_mode_count, present_modes);
  686.    
  687.     VkSurfaceFormatKHR format = vk_surface_format(formats, format_count);
  688.     VkPresentModeKHR present_mode = vk_present_mode(present_modes, present_mode_count);
  689.     VkExtent2D extent = vk_swap_extent(vk, capabilities);
  690.    
  691.     uint32_t image_count = capabilities.minImageCount + 1;
  692.    
  693.     if (capabilities.maxImageCount > 0 && image_count > capabilities.maxImageCount)
  694.     {
  695.         image_count = capabilities.maxImageCount;
  696.     }
  697.    
  698.     VkSwapchainCreateInfoKHR swapchain_info =
  699.     {
  700.         .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
  701.         .pNext = NULL,
  702.         .flags = 0,
  703.         .surface = vk->surface,
  704.         .minImageCount = image_count,
  705.         .imageFormat = format.format,
  706.         .imageColorSpace = format.colorSpace,
  707.         .imageExtent = extent,
  708.         .imageArrayLayers = 1,
  709.         .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
  710.         .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
  711.         .queueFamilyIndexCount = 0,
  712.         .pQueueFamilyIndices = NULL,
  713.         .preTransform = capabilities.currentTransform,
  714.         .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
  715.         .presentMode = present_mode,
  716.         .clipped = VK_TRUE,
  717.         .oldSwapchain = VK_NULL_HANDLE
  718.     };
  719.    
  720.     VkResult result = vkCreateSwapchainKHR(vk->gpu_interface, &swapchain_info, NULL, &vk->swapchain);
  721.     if (result != VK_SUCCESS)
  722.     {
  723.         fprintf(stderr, "Failed to create swapchain!\n");
  724.         return false;
  725.     }
  726.    
  727.     vkGetSwapchainImagesKHR(vk->gpu_interface, vk->swapchain, &image_count, NULL);
  728.     VkImage image[image_count];
  729.     vkGetSwapchainImagesKHR(vk->gpu_interface, vk->swapchain, &image_count, image);
  730.    
  731.     for (uint32_t i = 0; i < image_count; i++)
  732.     {
  733.         vk->images[i] = image[i];
  734.     }
  735.    
  736.     vk->format = format.format;
  737.     vk->extent = extent;
  738.     vk->image_count = image_count;
  739.     return true;
  740. }
  741.  
  742. bool vk_image_data_init(_vk *vk)
  743. {
  744.     for (uint32_t i = 0; i < vk->image_count; i++)
  745.     {
  746.         VkImageViewCreateInfo image_info =
  747.         {
  748.             .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
  749.             .pNext = NULL,
  750.             .flags = 0,
  751.             .image = vk->images[i],
  752.             .viewType = VK_IMAGE_VIEW_TYPE_2D,
  753.             .format = vk->format,
  754.             .components.r = VK_COMPONENT_SWIZZLE_IDENTITY,
  755.             .components.g = VK_COMPONENT_SWIZZLE_IDENTITY,
  756.             .components.b = VK_COMPONENT_SWIZZLE_IDENTITY,
  757.             .components.a = VK_COMPONENT_SWIZZLE_IDENTITY,
  758.             .subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
  759.             .subresourceRange.baseMipLevel = 0,
  760.             .subresourceRange.levelCount = 1,
  761.             .subresourceRange.baseArrayLayer = 0,
  762.             .subresourceRange.layerCount = 1
  763.         };
  764.        
  765.         VkResult result = vkCreateImageView(vk->gpu_interface, &image_info, NULL, &vk->image_data[i]);
  766.         if (result != VK_SUCCESS)
  767.         {
  768.             fprintf(stderr, "Failed to create image views!\n");
  769.             return false;
  770.         }
  771.     }
  772.    
  773.     return true;
  774. }
  775.  
  776. static void get_file_size(const char *filename, size_t *length)
  777. {
  778.     FILE* fptr = fopen(filename, "rb");
  779.    
  780.     if (fptr == NULL)
  781.     {
  782.         fprintf(stderr, "Failed to query for file size: %s!\n", filename);
  783.         return;
  784.     }
  785.    
  786.     fseek(fptr, 0L, SEEK_END);
  787.     long len = ftell(fptr);
  788.     *length = (size_t) len;
  789.     if (len < 0)
  790.     {
  791.         fprintf(stderr, "Failed to determine the size of the file!\n");
  792.         return;
  793.     }
  794.     else if (*length != (size_t) len)
  795.     {
  796.         fprintf(stderr, "An conversion overflow has occurred!\n");
  797.         return;
  798.     }
  799.    
  800.     fseek(fptr, 0L, SEEK_SET);
  801.     fclose(fptr);
  802. }
  803.  
  804. static uint32_t *load_spirv_shaders(const char *filename, size_t length, char *contents)
  805. {
  806.     FILE* fptr = fopen(filename, "rb");
  807.    
  808.     if (fptr == NULL)
  809.     {
  810.         fprintf(stderr, "Failed to open file: %s!\n", filename);
  811.     }
  812.  
  813.     fseek(fptr, 0L, SEEK_END);
  814.     length = ftell(fptr);
  815.     fseek(fptr, 0L, SEEK_SET);
  816.    
  817.     size_t read_count = fread(contents, length, 1, fptr);
  818.    
  819.     if (read_count == 0)
  820.     {
  821.         fprintf(stderr, "Failed to read SPIR-V files!\n");
  822.     }
  823.    
  824.     fclose(fptr);
  825.     return (uint32_t *) contents;
  826. }
  827.  
  828. VkShaderModule vk_shader_module_init(_vk *vk, const uint32_t *shader, const size_t shader_size)
  829. {
  830.     VkShaderModuleCreateInfo module_info =
  831.     {
  832.         .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
  833.         .pNext = NULL,
  834.         .flags = 0,
  835.         .codeSize = shader_size,
  836.         .pCode = shader
  837.     };
  838.    
  839.     VkShaderModule shader_module = {0};
  840.    
  841.     VkResult result = vkCreateShaderModule(vk->gpu_interface, &module_info, NULL, &shader_module);
  842.     if (result != VK_SUCCESS)
  843.     {
  844.         fprintf(stderr, "Failed to create shader module!\n");
  845.     }
  846.    
  847.     return shader_module;
  848. }
  849.  
  850. bool vk_render_pass_init(_vk *vk)
  851. {
  852.     VkAttachmentDescription color_attachment =
  853.     {
  854.         .format = vk->format,
  855.         .samples = VK_SAMPLE_COUNT_1_BIT,
  856.         .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
  857.         .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
  858.         .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
  859.         .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
  860.         .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
  861.         .finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
  862.     };
  863.    
  864.     VkAttachmentReference color_attachment_ref =
  865.     {
  866.         .attachment = 0,
  867.         .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
  868.     };
  869.    
  870.     VkSubpassDescription subpass =
  871.     {
  872.         .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
  873.         .colorAttachmentCount = 1,
  874.         .pColorAttachments = &color_attachment_ref
  875.     };
  876.    
  877.     VkSubpassDependency dependency =
  878.     {
  879.         .srcSubpass = VK_SUBPASS_EXTERNAL,
  880.         .dstSubpass = 0,
  881.         .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
  882.         .srcAccessMask = 0,
  883.         .dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
  884.         .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
  885.     };
  886.    
  887.     VkRenderPassCreateInfo render_pass_info =
  888.     {
  889.         .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
  890.         .pNext = NULL,
  891.         .flags = 0,
  892.         .attachmentCount = 1,
  893.         .pAttachments = &color_attachment,
  894.         .subpassCount = 1,
  895.         .pSubpasses = &subpass,
  896.         .dependencyCount = 1,
  897.         .pDependencies = &dependency
  898.     };
  899.    
  900.     VkResult result = vkCreateRenderPass(vk->gpu_interface, &render_pass_info, NULL, &vk->render_pass);
  901.     if (result != VK_SUCCESS)
  902.     {
  903.         fprintf(stderr, "Failed to create render pass!\n");
  904.         return false;
  905.     }
  906.    
  907.     return true;
  908. }
  909.  
  910. bool vk_vertex_buffer_init(_vk *vk)
  911. {
  912.     VkResult result = VK_SUCCESS;
  913.    
  914.     VkBufferCreateInfo buffer_info =
  915.     {
  916.         .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
  917.         .pNext = NULL,
  918.         .flags = 0,
  919.         .size = sizeof(VERTICES[0]) * 3,
  920.         .usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
  921.         .sharingMode = VK_SHARING_MODE_EXCLUSIVE
  922.     };
  923.    
  924.     result = vkCreateBuffer(vk->gpu_interface, &buffer_info, NULL, &vk->vertex_buffer);
  925.     if (result != VK_SUCCESS)
  926.     {
  927.         fprintf(stderr, "Failed to create vertex buffer!\n");
  928.         return false;
  929.     }
  930.    
  931.     VkMemoryRequirements memory_requirements = {0};
  932.     vkGetBufferMemoryRequirements(vk->gpu_interface, vk->vertex_buffer, &memory_requirements);
  933.    
  934.     VkMemoryAllocateInfo alloc_info =
  935.     {
  936.         .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
  937.         .allocationSize = memory_requirements.size,
  938.         .memoryTypeIndex = vk_find_memory_type(vk, memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
  939.     };
  940.    
  941.     result = vkAllocateMemory(vk->gpu_interface, &alloc_info, NULL, &vk->vertex_buffer_memory);
  942.     if (result != VK_SUCCESS)
  943.     {
  944.         fprintf(stderr, "Failed to allocate vertex buffer memory!\n");
  945.         return false;
  946.     }
  947.    
  948.     vkBindBufferMemory(vk->gpu_interface, vk->vertex_buffer, vk->vertex_buffer_memory, 0);
  949.    
  950.     void *data = 0;
  951.     vkMapMemory(vk->gpu_interface, vk->vertex_buffer_memory, 0, buffer_info.size, 0, &data);
  952.     memcpy(data, VERTICES, (size_t) buffer_info.size);
  953.     vkUnmapMemory(vk->gpu_interface, vk->vertex_buffer_memory);
  954.    
  955.     return true;
  956. }
  957.  
  958. uint32_t vk_find_memory_type(_vk *vk, uint32_t type_filter, VkMemoryPropertyFlags properties)
  959. {
  960.     VkPhysicalDeviceMemoryProperties memory_properties = {0};
  961.     vkGetPhysicalDeviceMemoryProperties(vk->gpu, &memory_properties);
  962.    
  963.     for (uint32_t i = 0; i < memory_properties.memoryTypeCount; i++)
  964.     {
  965.         if ((type_filter & (1 << i)) && (memory_properties.memoryTypes[i].propertyFlags & properties) == properties)
  966.         {
  967.             return i;
  968.         }
  969.     }
  970.    
  971.     fprintf(stderr, "Failed to find suitable memory type!\n");
  972.    
  973.     return 0;
  974. }
  975.  
  976. bool vk_graphics_pipeline_init(_vk *vk)
  977. {
  978.     VkResult result = VK_SUCCESS;
  979.    
  980.     size_t vert_spirv_size = 0;
  981.     get_file_size("vkapp/shaders/vertex.vert.spv", &vert_spirv_size);
  982.     char vert_contents[vert_spirv_size + 1];
  983.     uint32_t *vert_spirv = load_spirv_shaders("vkapp/shaders/vertex.vert.spv", vert_spirv_size, vert_contents);
  984.    
  985.     if (vert_spirv == NULL)
  986.     {
  987.         fprintf(stderr, "Failed to load SPIR-V vertex shader!\n");
  988.         return false;
  989.     }
  990.    
  991.     fprintf(stdout, "Size of SPIR-V vertex shader: %lu\n", vert_spirv_size);
  992.    
  993.     size_t frag_spirv_size = 0;
  994.     get_file_size("vkapp/shaders/fragment.frag.spv", &frag_spirv_size);
  995.     char frag_contents[frag_spirv_size + 1];
  996.     uint32_t *frag_spirv = load_spirv_shaders("vkapp/shaders/fragment.frag.spv", frag_spirv_size, frag_contents);
  997.    
  998.     if (frag_spirv == NULL)
  999.     {
  1000.         fprintf(stderr, "Failed to load SPIR-V fragment shader!\n");
  1001.         return false;
  1002.     }
  1003.    
  1004.     fprintf(stdout, "Size of SPIR-V fragment shader: %lu\n", frag_spirv_size);
  1005.    
  1006.     VkShaderModule vert_spirv_module = vk_shader_module_init(vk, vert_spirv, vert_spirv_size);
  1007.     VkShaderModule frag_spirv_module = vk_shader_module_init(vk, frag_spirv, frag_spirv_size);
  1008.  
  1009.     VkVertexInputBindingDescription binding_description = vk_get_binding_description();
  1010.     VkVertexInputAttributeDescription vertex_description = vk_get_attribute_description();
  1011.     VkVertexInputAttributeDescription color_data = vk_get_color_data();
  1012.    
  1013.     VkVertexInputAttributeDescription attribute_descriptions[] = {vertex_description, color_data};
  1014.    
  1015.     VkPipelineShaderStageCreateInfo vert_stage_info =
  1016.     {
  1017.         .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
  1018.         .pNext = NULL,
  1019.         .flags = 0,
  1020.         .stage = VK_SHADER_STAGE_VERTEX_BIT,
  1021.         .module = vert_spirv_module,
  1022.         .pName = "main",
  1023.         .pSpecializationInfo = NULL
  1024.     };
  1025.    
  1026.     VkPipelineShaderStageCreateInfo frag_stage_info =
  1027.     {
  1028.         .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
  1029.         .pNext = NULL,
  1030.         .flags = 0,
  1031.         .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
  1032.         .module = frag_spirv_module,
  1033.         .pName = "main",
  1034.         .pSpecializationInfo = NULL
  1035.     };
  1036.    
  1037.     VkDynamicState dynamic_states[] = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR};
  1038.     const uint32_t DYNAMIC_STATES_COUNT = 2;
  1039.    
  1040.     VkPipelineDynamicStateCreateInfo dynamic_state =
  1041.     {
  1042.         .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
  1043.         .pNext = NULL,
  1044.         .flags = 0,
  1045.         .dynamicStateCount = DYNAMIC_STATES_COUNT,
  1046.         .pDynamicStates = dynamic_states
  1047.     };
  1048.      
  1049.     VkPipelineShaderStageCreateInfo shader_stages[] = {vert_stage_info, frag_stage_info};
  1050.    
  1051.     VkPipelineVertexInputStateCreateInfo vertex_input_info =
  1052.     {
  1053.         .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
  1054.         .pNext = NULL,
  1055.         .flags = 0,
  1056.         .vertexBindingDescriptionCount = 1,
  1057.         .vertexAttributeDescriptionCount = 2,
  1058.         .pVertexBindingDescriptions = &binding_description,
  1059.         .pVertexAttributeDescriptions = attribute_descriptions
  1060.     };
  1061.    
  1062.     VkViewport viewport =
  1063.     {
  1064.         .x = 0.0f,
  1065.         .y = 0.0f,
  1066.         .width = (float) vk->extent.width,
  1067.         .height = (float) vk->extent.height,
  1068.         .minDepth = 0.0f,
  1069.         .maxDepth = 1.0f
  1070.     };
  1071.    
  1072.     VkRect2D scissor =
  1073.     {
  1074.         .offset = {0, 0},
  1075.         .extent = vk->extent
  1076.     };
  1077.    
  1078.     VkPipelineInputAssemblyStateCreateInfo input_assembly_info =
  1079.     {
  1080.         .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
  1081.         .pNext = NULL,
  1082.         .flags = 0,
  1083.         .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
  1084.         .primitiveRestartEnable = VK_FALSE
  1085.     };
  1086.    
  1087.     VkPipelineViewportStateCreateInfo viewport_state_info =
  1088.     {
  1089.         .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
  1090.         .pNext = NULL,
  1091.         .flags = 0,
  1092.         .viewportCount = 1,
  1093.         .pViewports = &viewport,
  1094.         .scissorCount = 1,
  1095.         .pScissors = &scissor
  1096.     };
  1097.    
  1098.     VkPipelineRasterizationStateCreateInfo rasterizer_info =
  1099.     {
  1100.         .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
  1101.         .pNext = NULL,
  1102.         .flags = 0,
  1103.         .depthClampEnable = VK_FALSE,
  1104.         .rasterizerDiscardEnable = VK_FALSE,
  1105.         .polygonMode = VK_POLYGON_MODE_FILL,
  1106.         .lineWidth = 1.0f,
  1107.         .cullMode = VK_CULL_MODE_BACK_BIT,
  1108.         .frontFace = VK_FRONT_FACE_CLOCKWISE,
  1109.         .depthBiasEnable = VK_FALSE,
  1110.         .depthBiasConstantFactor = 0.0f,
  1111.         .depthBiasClamp = 0.0f,
  1112.         .depthBiasSlopeFactor = 0.0f
  1113.     };
  1114.    
  1115.     VkPipelineMultisampleStateCreateInfo multisampling_info =
  1116.     {
  1117.         .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
  1118.         .pNext = NULL,
  1119.         .flags = 0,
  1120.         .sampleShadingEnable = VK_FALSE,
  1121.         .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
  1122.         .minSampleShading = 1.0f,
  1123.         .pSampleMask = NULL,
  1124.         .alphaToCoverageEnable = VK_FALSE,
  1125.         .alphaToOneEnable = VK_FALSE
  1126.     };
  1127.    
  1128.     VkPipelineColorBlendAttachmentState color_blend_attachment =
  1129.     {
  1130.         .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
  1131.         .blendEnable = VK_FALSE,
  1132.         .srcColorBlendFactor = VK_BLEND_FACTOR_ONE,
  1133.         .dstColorBlendFactor = VK_BLEND_FACTOR_ZERO,
  1134.         .colorBlendOp = VK_BLEND_OP_ADD,
  1135.         .srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
  1136.         .dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
  1137.         .alphaBlendOp = VK_BLEND_OP_ADD
  1138.     };
  1139.    
  1140.     VkPipelineColorBlendStateCreateInfo color_blending_info =
  1141.     {
  1142.         .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
  1143.         .pNext = NULL,
  1144.         .flags = 0,
  1145.         .logicOpEnable = VK_FALSE,
  1146.         .logicOp = VK_LOGIC_OP_COPY,
  1147.         .attachmentCount = 1,
  1148.         .pAttachments = &color_blend_attachment,
  1149.         .blendConstants[0] = 0.0f,
  1150.         .blendConstants[1] = 0.0f,
  1151.         .blendConstants[2] = 0.0f,
  1152.         .blendConstants[3] = 0.0f
  1153.     };
  1154.    
  1155.     VkPipelineLayoutCreateInfo pipeline_layout_info =
  1156.     {
  1157.         .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
  1158.         .pNext = NULL,
  1159.         .flags = 0,
  1160.         .setLayoutCount = 0,
  1161.         .pSetLayouts = NULL,
  1162.         .pushConstantRangeCount = 0,
  1163.         .pPushConstantRanges = NULL
  1164.     };
  1165.    
  1166.     result = vkCreatePipelineLayout(vk->gpu_interface, &pipeline_layout_info, NULL, &vk->pipeline_layout);
  1167.     if (result != VK_SUCCESS)
  1168.     {
  1169.         fprintf(stderr, "Failed to create pipeline layout!\n");
  1170.         return false;
  1171.     }
  1172.    
  1173.     VkGraphicsPipelineCreateInfo pipeline_info =
  1174.     {
  1175.         .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
  1176.         .pNext = NULL,
  1177.         .flags = 0,
  1178.         .stageCount = 2,
  1179.         .pStages = shader_stages,
  1180.         .pVertexInputState = &vertex_input_info,
  1181.         .pInputAssemblyState = &input_assembly_info,
  1182.         .pViewportState = &viewport_state_info,
  1183.         .pRasterizationState = &rasterizer_info,
  1184.         .pMultisampleState = &multisampling_info,
  1185.         .pDepthStencilState = NULL,
  1186.         .pColorBlendState = &color_blending_info,
  1187.         .pDynamicState = &dynamic_state,
  1188.         .layout = vk->pipeline_layout,
  1189.         .renderPass = vk->render_pass,
  1190.         .subpass = 0,
  1191.         .basePipelineHandle = VK_NULL_HANDLE,
  1192.         .basePipelineIndex = -1
  1193.     };
  1194.    
  1195.     result = vkCreateGraphicsPipelines(vk->gpu_interface, VK_NULL_HANDLE, 1, &pipeline_info, NULL, &vk->graphics_pipeline);
  1196.     if (result != VK_SUCCESS)
  1197.     {
  1198.         fprintf(stderr, "Failed to create graphics pipeline!\n");
  1199.         return false;
  1200.     }
  1201.    
  1202.     vkDestroyShaderModule(vk->gpu_interface, vert_spirv_module, NULL);
  1203.     vkDestroyShaderModule(vk->gpu_interface, frag_spirv_module, NULL);
  1204.    
  1205.     return true;    
  1206. }
  1207.  
  1208. bool vk_framebuffers_init(_vk *vk)
  1209. {
  1210.     for (uint32_t i = 0; i < vk->image_count; i++)
  1211.     {
  1212.         VkImageView attachments[] =
  1213.         {
  1214.             vk->image_data[i]
  1215.         };
  1216.        
  1217.         VkFramebufferCreateInfo framebuffer_info =
  1218.         {
  1219.             .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
  1220.             .pNext = NULL,
  1221.             .flags = 0,
  1222.             .renderPass = vk->render_pass,
  1223.             .attachmentCount = 1,
  1224.             .pAttachments = attachments,
  1225.             .width = vk->extent.width,
  1226.             .height = vk->extent.height,
  1227.             .layers = 1
  1228.         };
  1229.        
  1230.         VkResult result = vkCreateFramebuffer(vk->gpu_interface, &framebuffer_info, NULL, &vk->framebuffers[i]);
  1231.         if (result != VK_SUCCESS)
  1232.         {
  1233.             fprintf(stderr, "Failed to create frame buffers!\n");
  1234.             return false;
  1235.         }
  1236.     }
  1237.    
  1238.     return true;
  1239. }
  1240.  
  1241. bool vk_command_pool_init(_vk *vk)
  1242. {
  1243.     VkCommandPoolCreateInfo pool_info =
  1244.     {
  1245.         .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
  1246.         .pNext = NULL,
  1247.         .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
  1248.         .queueFamilyIndex = vk->queue_index
  1249.      };
  1250.      
  1251.      VkResult result = vkCreateCommandPool(vk->gpu_interface, &pool_info, NULL, &vk->command_pool);
  1252.      if (result != VK_SUCCESS)
  1253.      {
  1254.         fprintf(stderr, "Failed to create command pool!\n");
  1255.         return false;
  1256.     }
  1257.    
  1258.     return true;
  1259. }
  1260.  
  1261. bool vk_command_buffers_init(_vk *vk)
  1262. {
  1263.     VkCommandBufferAllocateInfo alloc_info =
  1264.     {
  1265.         .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
  1266.         .pNext = NULL,
  1267.         .commandPool = vk->command_pool,
  1268.         .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
  1269.         .commandBufferCount = MAX_FRAMES_IN_FLIGHT
  1270.     };
  1271.    
  1272.     VkResult result = vkAllocateCommandBuffers(vk->gpu_interface, &alloc_info, vk->command_buffers);
  1273.     if (result != VK_SUCCESS)
  1274.     {
  1275.         fprintf(stderr, "Failed to allocate command buffers!\n");
  1276.         return false;
  1277.     }
  1278.    
  1279.     return true;
  1280. }
  1281.  
  1282. bool vk_command_buffer_write(_vk *vk, uint32_t current_frame, uint32_t image_index)
  1283. {
  1284.     VkResult result = VK_SUCCESS;
  1285.    
  1286.     VkCommandBufferBeginInfo begin_info =
  1287.     {
  1288.         .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
  1289.         .pNext = NULL,
  1290.         .flags = 0,
  1291.         .pInheritanceInfo = NULL
  1292.     };
  1293.    
  1294.     result = vkBeginCommandBuffer(vk->command_buffers[current_frame], &begin_info);
  1295.     if (result != VK_SUCCESS)
  1296.     {
  1297.         fprintf(stderr, "Failed to begin writing to command buffer!\n");
  1298.         return false;
  1299.     }
  1300.    
  1301.     VkClearValue clear_color = {{{0.0f, 0.0f, 0.0f, 1.0f}}};
  1302.    
  1303.     VkRenderPassBeginInfo render_pass_info =
  1304.     {
  1305.         .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
  1306.         .pNext = NULL,
  1307.         .renderPass = vk->render_pass,
  1308.         .framebuffer = vk->framebuffers[image_index],
  1309.         .renderArea.offset = {0, 0},
  1310.         .renderArea.extent = vk->extent,
  1311.         .clearValueCount = 1,
  1312.         .pClearValues = &clear_color
  1313.     };
  1314.    
  1315.     vkCmdBeginRenderPass(vk->command_buffers[current_frame], &render_pass_info, VK_SUBPASS_CONTENTS_INLINE);
  1316.    
  1317.     vkCmdBindPipeline(vk->command_buffers[current_frame], VK_PIPELINE_BIND_POINT_GRAPHICS, vk->graphics_pipeline);
  1318.    
  1319.     VkDeviceSize offsets[] = {0};
  1320.    
  1321.     vkCmdBindVertexBuffers(vk->command_buffers[current_frame], 0, 1, &vk->vertex_buffer, offsets);
  1322.    
  1323.     VkViewport viewport =
  1324.     {
  1325.         .x = 0.0f,
  1326.         .y = 0.0f,
  1327.         .width = (float) vk->extent.width,
  1328.         .height = (float) vk->extent.height,
  1329.         .minDepth = 0.0f,
  1330.         .maxDepth = 1.0f
  1331.     };
  1332.    
  1333.     vkCmdSetViewport(vk->command_buffers[current_frame], 0, 1, &viewport);
  1334.    
  1335.     VkRect2D scissor =
  1336.     {
  1337.         .offset = {0, 0},
  1338.         .extent = vk->extent
  1339.     };
  1340.    
  1341.     vkCmdSetScissor(vk->command_buffers[current_frame], 0, 1, &scissor);
  1342.    
  1343.     vkCmdDraw(vk->command_buffers[current_frame], 3, 1, 0, 0);
  1344.    
  1345.     vkCmdEndRenderPass(vk->command_buffers[current_frame]);
  1346.    
  1347.     result = vkEndCommandBuffer(vk->command_buffers[current_frame]);
  1348.     if (result != VK_SUCCESS)
  1349.     {
  1350.         fprintf(stderr, "Failed to write to command buffer!\n");
  1351.         return false;
  1352.     }
  1353.    
  1354.     return true;
  1355. }
  1356.  
  1357. bool vk_sync_objects_init(_vk *vk)
  1358. {
  1359.     VkResult result = VK_SUCCESS;
  1360.    
  1361.     VkSemaphoreCreateInfo semaphore_info =
  1362.     {
  1363.         .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
  1364.         .pNext = NULL,
  1365.         .flags = VK_FENCE_CREATE_SIGNALED_BIT
  1366.     };
  1367.    
  1368.     VkFenceCreateInfo fence_info =
  1369.     {
  1370.         .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
  1371.         .pNext = NULL,
  1372.         .flags = 0
  1373.     };
  1374.    
  1375.     for (uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
  1376.     {
  1377.         result = vkCreateSemaphore(vk->gpu_interface, &semaphore_info, NULL, &vk->image_available[i]);
  1378.         if (result != VK_SUCCESS)
  1379.         {
  1380.             fprintf(stderr, "Failed to create image semaphore!\n");
  1381.             return false;
  1382.         }
  1383.        
  1384.         result = vkCreateSemaphore(vk->gpu_interface, &semaphore_info, NULL, &vk->render_finished[i]);
  1385.         if (result != VK_SUCCESS)
  1386.         {
  1387.             fprintf(stderr, "Failed to create presentation semaphore!\n");
  1388.             return false;
  1389.         }
  1390.        
  1391.         result = vkCreateFence(vk->gpu_interface, &fence_info, NULL, &vk->in_flight[i]);
  1392.         if (result != VK_SUCCESS)
  1393.         {
  1394.             fprintf(stderr, "Failed to create fence!\n");
  1395.             return false;
  1396.         }
  1397.     }
  1398.    
  1399.     return true;
  1400. }
  1401.  
  1402. void vk_swapchain_recreation(_vk *vk)
  1403. {
  1404.     int width = 0, height = 0;
  1405.     glfwGetFramebufferSize(vk->window, &width, &height);
  1406.    
  1407.     while (width == 0 || height == 0)
  1408.     {
  1409.         glfwGetFramebufferSize(vk->window, &width, &height);
  1410.         glfwWaitEvents();
  1411.     }
  1412.    
  1413.     vkDeviceWaitIdle(vk->gpu_interface);
  1414.    
  1415.     vk_swapchain_init(vk);
  1416.    
  1417.     vk_image_data_init(vk);
  1418.    
  1419.     vk_framebuffers_init(vk);
  1420. }
  1421.  
  1422. void vk_swapchain_destruction(_vk *vk)
  1423. {
  1424.     for (uint32_t i = 0; i < vk->image_count; i++)
  1425.     {
  1426.         vkDestroyFramebuffer(vk->gpu_interface, vk->framebuffers[i], NULL);
  1427.     }
  1428.    
  1429.     for (uint32_t i = 0; i < vk->image_count; i++)
  1430.     {
  1431.         vkDestroyImageView(vk->gpu_interface, vk->image_data[i], NULL);
  1432.     }
  1433.    
  1434.     vkDestroySwapchainKHR(vk->gpu_interface, vk->swapchain, NULL);
  1435. }
  1436.  
  1437. void vk_draw_frame(_vk *vk)
  1438. {
  1439.     VkResult result = VK_SUCCESS;
  1440.     vk->current_frame = 0;
  1441.     vkWaitForFences(vk->gpu_interface, 1, &vk->in_flight[vk->current_frame], VK_TRUE, UINT64_MAX);
  1442.    
  1443.     uint32_t image_index = 0;
  1444.     result = vkAcquireNextImageKHR(vk->gpu_interface, vk->swapchain, UINT64_MAX, vk->image_available[vk->current_frame], VK_NULL_HANDLE, &image_index);
  1445.     if (result == VK_ERROR_OUT_OF_DATE_KHR)
  1446.     {
  1447.         vk_swapchain_recreation(vk);
  1448.         return;
  1449.     }
  1450.     else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)
  1451.     {
  1452.         fprintf(stderr, "Failed to acquire swap chain images!\n");
  1453.     }
  1454.    
  1455.     vkResetFences(vk->gpu_interface, 1, &vk->in_flight[vk->current_frame]);
  1456.    
  1457.     vkResetCommandBuffer(vk->command_buffers[vk->current_frame], 0);
  1458.     vk_command_buffer_write(vk, vk->current_frame, image_index);
  1459.    
  1460.     VkPipelineStageFlags wait_stages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
  1461.    
  1462.     VkSubmitInfo submit_info =
  1463.     {
  1464.         .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
  1465.         .waitSemaphoreCount = 1,
  1466.         .pWaitSemaphores = &vk->image_available[vk->current_frame],
  1467.         .signalSemaphoreCount = 1,
  1468.         .pSignalSemaphores = &vk->render_finished[vk->current_frame],
  1469.         .pWaitDstStageMask = wait_stages,
  1470.         .commandBufferCount = 1,
  1471.         .pCommandBuffers = &vk->command_buffers[vk->current_frame]
  1472.     };
  1473.    
  1474.     result = vkQueueSubmit(vk->queue, 1, &submit_info, vk->in_flight[vk->current_frame]);
  1475.     if (result != VK_SUCCESS)
  1476.     {
  1477.         fprintf(stderr, "Failed to submit draw command buffer!\n");
  1478.     }
  1479.     else if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || vk->framebuffer_resized)
  1480.     {
  1481.         vk->framebuffer_resized = false;
  1482.         vk_swapchain_recreation(vk);
  1483.     }
  1484.    
  1485.     VkPresentInfoKHR present_info =
  1486.     {
  1487.         .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
  1488.         .waitSemaphoreCount = 1,
  1489.         .pWaitSemaphores = &vk->render_finished[vk->current_frame],
  1490.         .swapchainCount = 1,
  1491.         .pSwapchains = &vk->swapchain,
  1492.         .pImageIndices = &image_index,
  1493.         .pResults = NULL
  1494.     };
  1495.    
  1496.     vkQueuePresentKHR(vk->queue, &present_info);
  1497.    
  1498.     vk->current_frame = vk->current_frame + 1;
  1499.     vk->current_frame *= vk->current_frame < MAX_FRAMES_IN_FLIGHT;
  1500. }
  1501.    
  1502. bool app_init(_app *app, bool debugging)
  1503. {
  1504.     bool success = vk_init(&app->vk, debugging);
  1505.    
  1506.     return success;
  1507. }
  1508.  
  1509. void app_mainloop(_app *app)
  1510. {
  1511.     vk_mainloop(&app->vk);
  1512. }
  1513.  
  1514. void app_cleanup(_app *app, bool debugging)
  1515. {
  1516.     vk_cleanup(&app->vk, debugging);
  1517. }
  1518.  
  1519. bool check_build_type(int argc, char **argv)
  1520. {
  1521.     if ((argc > 1) && (strcmp(argv[1], "-Debugging") == 0))
  1522.     {
  1523.         return true;
  1524.     }
  1525.    
  1526.     return false;
  1527. }
  1528.  
  1529. int main(int argc, char **argv)
  1530. {  
  1531.     bool debugging = check_build_type(argc, argv);
  1532.    
  1533.     _app app = {0};
  1534.    
  1535.     bool success = app_init(&app, debugging);
  1536.    
  1537.     if (success)
  1538.     {
  1539.         app_mainloop(&app);
  1540.         app_cleanup(&app, debugging);
  1541.     }
  1542.     else
  1543.     {
  1544.         fprintf(stderr, "Failed to launch app!\n");
  1545.     }
  1546.    
  1547.     return 0;
  1548. }
Tags: vulkan
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement