|  | @@ -2,220 +2,139 @@
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #include <core/Logger.h>
 | 
	
		
			
				|  |  |  #include <core/Utility.h>
 | 
	
		
			
				|  |  | -#include <stdio.h>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#include "core/internal/GLFW.h"
 | 
	
		
			
				|  |  | +#include "GLFW.h"
 | 
	
		
			
				|  |  | +#include "VulkanUtils.h"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -typedef struct {
 | 
	
		
			
				|  |  | -    VkPhysicalDevice physical;
 | 
	
		
			
				|  |  | -    VkDevice logical;
 | 
	
		
			
				|  |  | -    u32 graphicsFamily;
 | 
	
		
			
				|  |  | -    VkQueue graphicsQueue;
 | 
	
		
			
				|  |  | -} Device;
 | 
	
		
			
				|  |  | +// VkCommandPool commandPool;
 | 
	
		
			
				|  |  | +// VkCommandBuffer* commandsBuffers;
 | 
	
		
			
				|  |  | +// VkFramebuffer* framebuffers;
 | 
	
		
			
				|  |  | +// VkSemaphore semaphore;
 | 
	
		
			
				|  |  | +// VkSemaphore renderSemaphore;
 | 
	
		
			
				|  |  | +// VkRenderPass renderPass;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -typedef struct {
 | 
	
		
			
				|  |  | -    VkFormat format;
 | 
	
		
			
				|  |  | -    VkSwapchainKHR handle;
 | 
	
		
			
				|  |  | -    u32 amount;
 | 
	
		
			
				|  |  | -    VkImage* images;
 | 
	
		
			
				|  |  | -    VkImageView* imageViews;
 | 
	
		
			
				|  |  | -    VkCommandPool commandPool;
 | 
	
		
			
				|  |  | -    VkCommandBuffer* commandsBuffers;
 | 
	
		
			
				|  |  | -    VkFramebuffer* framebuffers;
 | 
	
		
			
				|  |  | -} Swapchain;
 | 
	
		
			
				|  |  | +static VkPhysicalDevice physicalDevice;
 | 
	
		
			
				|  |  | +static u32 graphicsFamily = 0;
 | 
	
		
			
				|  |  | +static u32 presentFamily = 0;
 | 
	
		
			
				|  |  | +static VkDevice device;
 | 
	
		
			
				|  |  | +static VkQueue graphicsQueue;
 | 
	
		
			
				|  |  | +static VkQueue presentQueue;
 | 
	
		
			
				|  |  | +static VkSurfaceFormatKHR surfaceFormat;
 | 
	
		
			
				|  |  | +static VkSurfaceKHR surface;
 | 
	
		
			
				|  |  | +static VkSwapchainKHR swapchain;
 | 
	
		
			
				|  |  | +static VulkanSwapchainImages images;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -typedef struct {
 | 
	
		
			
				|  |  | -    // basic setup
 | 
	
		
			
				|  |  | -    VkInstance instance;
 | 
	
		
			
				|  |  | -    VkSurfaceKHR surface;
 | 
	
		
			
				|  |  | -#ifdef DEBUG_VULKAN
 | 
	
		
			
				|  |  | -    VkDebugUtilsMessengerEXT debugMessenger;
 | 
	
		
			
				|  |  | -    VkDebugReportCallbackEXT debugReportCallback;
 | 
	
		
			
				|  |  | -#endif
 | 
	
		
			
				|  |  | -    // render setup
 | 
	
		
			
				|  |  | -    Device device;
 | 
	
		
			
				|  |  | -    VkSemaphore semaphore;
 | 
	
		
			
				|  |  | -    VkSemaphore renderSemaphore;
 | 
	
		
			
				|  |  | -    Swapchain swapchain;
 | 
	
		
			
				|  |  | -    VkRenderPass renderPass;
 | 
	
		
			
				|  |  | -    u32 width;
 | 
	
		
			
				|  |  | -    u32 height;
 | 
	
		
			
				|  |  | -} VulkanData;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static VulkanData vk = {0};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -#define VK_ERROR_CASE(error)  \
 | 
	
		
			
				|  |  | -    case error: return #error
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static const char* getVulkanErrorString(VkResult r) {
 | 
	
		
			
				|  |  | -    switch(r) {
 | 
	
		
			
				|  |  | -        VK_ERROR_CASE(VK_ERROR_OUT_OF_HOST_MEMORY);
 | 
	
		
			
				|  |  | -        VK_ERROR_CASE(VK_ERROR_OUT_OF_DEVICE_MEMORY);
 | 
	
		
			
				|  |  | -        VK_ERROR_CASE(VK_ERROR_INITIALIZATION_FAILED);
 | 
	
		
			
				|  |  | -        VK_ERROR_CASE(VK_ERROR_LAYER_NOT_PRESENT);
 | 
	
		
			
				|  |  | -        VK_ERROR_CASE(VK_ERROR_EXTENSION_NOT_PRESENT);
 | 
	
		
			
				|  |  | -        VK_ERROR_CASE(VK_ERROR_INCOMPATIBLE_DRIVER);
 | 
	
		
			
				|  |  | -        default: return "unknown";
 | 
	
		
			
				|  |  | +static int getSurfaceFormatPoints(const VkSurfaceFormatKHR* sf) {
 | 
	
		
			
				|  |  | +    if(sf->format == VK_FORMAT_B8G8R8A8_UNORM &&
 | 
	
		
			
				|  |  | +       sf->colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
 | 
	
		
			
				|  |  | +        return 10;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +    return 1;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#define VK_ASSERT(a)                                                         \
 | 
	
		
			
				|  |  | -    do {                                                                     \
 | 
	
		
			
				|  |  | -        VkResult vkResult = (a);                                             \
 | 
	
		
			
				|  |  | -        if(vkResult != VK_SUCCESS) {                                         \
 | 
	
		
			
				|  |  | -            LOG_ERROR("Vulkan error: %s\n", getVulkanErrorString(vkResult)); \
 | 
	
		
			
				|  |  | -            return true;                                                     \
 | 
	
		
			
				|  |  | -        }                                                                    \
 | 
	
		
			
				|  |  | -    } while(false)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static PFN_vkVoidFunction getVulkanFunction(const char* name) {
 | 
	
		
			
				|  |  | -    return vkGetInstanceProcAddr(vk.instance, name);
 | 
	
		
			
				|  |  | +static int getSurfacePresentModePoints(VkPresentModeKHR m) {
 | 
	
		
			
				|  |  | +    if(m == VK_PRESENT_MODE_MAILBOX_KHR) {
 | 
	
		
			
				|  |  | +        return 5;
 | 
	
		
			
				|  |  | +    } else if(m == VK_PRESENT_MODE_FIFO_KHR) {
 | 
	
		
			
				|  |  | +        return 2;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    return 0;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#define GET_VULKAN_FUNCTION(name) ((PFN_##name)getVulkanFunction(#name))
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static bool initInstance() {
 | 
	
		
			
				|  |  | -    u32 baseCount = 0;
 | 
	
		
			
				|  |  | -    const char** baseExtensions = glfwGetRequiredInstanceExtensions(&baseCount);
 | 
	
		
			
				|  |  | -    if(baseExtensions == nullptr) {
 | 
	
		
			
				|  |  | -        LOG_ERROR("Could not get required extensions from GLFW");
 | 
	
		
			
				|  |  | -        return true;
 | 
	
		
			
				|  |  | +static bool getSwapchainSize(VkExtent2D* size) {
 | 
	
		
			
				|  |  | +    VkSurfaceCapabilitiesKHR c = {0};
 | 
	
		
			
				|  |  | +    VK_ASSERT(
 | 
	
		
			
				|  |  | +        vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &c));
 | 
	
		
			
				|  |  | +    if(c.currentExtent.width != 0xFFFF'FFFFu &&
 | 
	
		
			
				|  |  | +       c.currentExtent.height != 0xFFFF'FFFFu) {
 | 
	
		
			
				|  |  | +        *size = c.currentExtent;
 | 
	
		
			
				|  |  | +        LOG_INFO("Swapchain size: %ux%u", size->width, size->height);
 | 
	
		
			
				|  |  | +        return false;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -#ifdef DEBUG_VULKAN
 | 
	
		
			
				|  |  | -    u32 count = baseCount + 2;
 | 
	
		
			
				|  |  | -    const char* extensions[32];
 | 
	
		
			
				|  |  | -    if(count > ARRAY_LENGTH(extensions)) {
 | 
	
		
			
				|  |  | -        LOG_ERROR("Extension buffer is too small");
 | 
	
		
			
				|  |  | +    int w = 0;
 | 
	
		
			
				|  |  | +    int h = 0;
 | 
	
		
			
				|  |  | +    glfwGetFramebufferSize(getWindow(), &w, &h);
 | 
	
		
			
				|  |  | +    if(w <= 0 || h <= 0) {
 | 
	
		
			
				|  |  | +        LOG_ERROR("Could not get framebuffer size");
 | 
	
		
			
				|  |  |          return true;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    for(u32 i = 0; i < baseCount; i++) {
 | 
	
		
			
				|  |  | -        extensions[i] = baseExtensions[i];
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    extensions[baseCount] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
 | 
	
		
			
				|  |  | -    extensions[baseCount + 1] = VK_EXT_DEBUG_REPORT_EXTENSION_NAME;
 | 
	
		
			
				|  |  | -#else
 | 
	
		
			
				|  |  | -    u32 count = baseCount;
 | 
	
		
			
				|  |  | -    const char** extensions = baseExtensions;
 | 
	
		
			
				|  |  | -#endif
 | 
	
		
			
				|  |  | -    VkApplicationInfo appInfo = {
 | 
	
		
			
				|  |  | -        .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
 | 
	
		
			
				|  |  | -        .pApplicationName = "Vulkan",
 | 
	
		
			
				|  |  | -        .applicationVersion = VK_MAKE_VERSION(1, 0, 0),
 | 
	
		
			
				|  |  | -        .pEngineName = "Kajetan",
 | 
	
		
			
				|  |  | -        .engineVersion = VK_MAKE_VERSION(0, 0, 1),
 | 
	
		
			
				|  |  | -        .apiVersion = VK_API_VERSION_1_1};
 | 
	
		
			
				|  |  | -    VkInstanceCreateInfo info = {
 | 
	
		
			
				|  |  | -        .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
 | 
	
		
			
				|  |  | -        .pApplicationInfo = &appInfo,
 | 
	
		
			
				|  |  | -#ifdef DEBUG_VULKAN
 | 
	
		
			
				|  |  | -        .enabledLayerCount = 1,
 | 
	
		
			
				|  |  | -        .ppEnabledLayerNames = (const char*[]){"VK_LAYER_KHRONOS_validation"},
 | 
	
		
			
				|  |  | -#endif
 | 
	
		
			
				|  |  | -        .enabledExtensionCount = count,
 | 
	
		
			
				|  |  | -        .ppEnabledExtensionNames = extensions};
 | 
	
		
			
				|  |  | -    VK_ASSERT(vkCreateInstance(&info, nullptr, &vk.instance));
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -#ifdef DEBUG_VULKAN
 | 
	
		
			
				|  |  | -static VKAPI_ATTR VkBool32 onVulkanDebugMessenger VKAPI_CALL(
 | 
	
		
			
				|  |  | -    VkDebugUtilsMessageSeverityFlagBitsEXT, VkDebugUtilsMessageTypeFlagsEXT,
 | 
	
		
			
				|  |  | -    const VkDebugUtilsMessengerCallbackDataEXT* data, void*) {
 | 
	
		
			
				|  |  | -    LOG_WARNING("Vulkan validation layer message: %s", data->pMessage);
 | 
	
		
			
				|  |  | +    LOG_INFO("Framebuffer size: %dx%d", w, h);
 | 
	
		
			
				|  |  | +    size->width =
 | 
	
		
			
				|  |  | +        clampU32((u32)w, c.minImageExtent.width, c.maxImageExtent.width);
 | 
	
		
			
				|  |  | +    size->height =
 | 
	
		
			
				|  |  | +        clampU32((u32)h, c.minImageExtent.height, c.maxImageExtent.height);
 | 
	
		
			
				|  |  | +    LOG_INFO("Swapchain size: %ux%u", size->width, size->height);
 | 
	
		
			
				|  |  |      return false;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static bool initDebugMessenger() {
 | 
	
		
			
				|  |  | -    VkDebugUtilsMessengerCreateInfoEXT info = {
 | 
	
		
			
				|  |  | -        .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
 | 
	
		
			
				|  |  | -        .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
 | 
	
		
			
				|  |  | -                           VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
 | 
	
		
			
				|  |  | -        .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,
 | 
	
		
			
				|  |  | -        .pfnUserCallback = onVulkanDebugMessenger};
 | 
	
		
			
				|  |  | -    auto f = GET_VULKAN_FUNCTION(vkCreateDebugUtilsMessengerEXT);
 | 
	
		
			
				|  |  | -    if(f == nullptr) {
 | 
	
		
			
				|  |  | -        LOG_WARNING("Could not find debug util messenger function");
 | 
	
		
			
				|  |  | -        return false;
 | 
	
		
			
				|  |  | +static bool initSwapchain() {
 | 
	
		
			
				|  |  | +    VulkanSwapchainData d = {
 | 
	
		
			
				|  |  | +        .physicalDevice = physicalDevice, .device = device, .surface = surface};
 | 
	
		
			
				|  |  | +    if(getSwapchainSize(&d.size)) {
 | 
	
		
			
				|  |  | +        LOG_ERROR("Could not retrieve any swapchain size");
 | 
	
		
			
				|  |  | +        return true;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    VK_ASSERT(f(vk.instance, &info, nullptr, &vk.debugMessenger));
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static VKAPI_ATTR VkBool32 onVulkanDebugReport VKAPI_CALL(
 | 
	
		
			
				|  |  | -    VkDebugReportFlagsEXT, VkDebugReportObjectTypeEXT, uint64_t, size_t,
 | 
	
		
			
				|  |  | -    int32_t, const char* pLayerPrefix, const char* pMessage, void*) {
 | 
	
		
			
				|  |  | -    LOG_WARNING("Vulkan debug message '%s': %s", pLayerPrefix, pMessage);
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static bool initDebugReportCallback() {
 | 
	
		
			
				|  |  | -    VkDebugReportCallbackCreateInfoEXT info = {
 | 
	
		
			
				|  |  | -        .sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT,
 | 
	
		
			
				|  |  | -        .flags = VK_DEBUG_REPORT_WARNING_BIT_EXT |
 | 
	
		
			
				|  |  | -                 VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT |
 | 
	
		
			
				|  |  | -                 VK_DEBUG_REPORT_ERROR_BIT_EXT,
 | 
	
		
			
				|  |  | -        .pfnCallback = onVulkanDebugReport};
 | 
	
		
			
				|  |  | -    auto f = GET_VULKAN_FUNCTION(vkCreateDebugReportCallbackEXT);
 | 
	
		
			
				|  |  | -    if(f == nullptr) {
 | 
	
		
			
				|  |  | -        LOG_WARNING("Could not find debug report function");
 | 
	
		
			
				|  |  | -        return false;
 | 
	
		
			
				|  |  | +    if(findVulkanSurfaceFormat(
 | 
	
		
			
				|  |  | +           &d.surfaceFormat, physicalDevice, surface, getSurfaceFormatPoints)) {
 | 
	
		
			
				|  |  | +        LOG_ERROR("Could not find surface format");
 | 
	
		
			
				|  |  | +        return true;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    VK_ASSERT(f(vk.instance, &info, nullptr, &vk.debugReportCallback));
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static bool initDebugging() {
 | 
	
		
			
				|  |  | -    return initDebugMessenger() || initDebugReportCallback();
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static void destroyDebugMessenger() {
 | 
	
		
			
				|  |  | -    auto f = GET_VULKAN_FUNCTION(vkDestroyDebugUtilsMessengerEXT);
 | 
	
		
			
				|  |  | -    if(f == nullptr) {
 | 
	
		
			
				|  |  | -        LOG_WARNING("Could not find debug util messenger destroy function");
 | 
	
		
			
				|  |  | -        return;
 | 
	
		
			
				|  |  | +    surfaceFormat = d.surfaceFormat;
 | 
	
		
			
				|  |  | +    if(findVulkanSurfacePresentMode(
 | 
	
		
			
				|  |  | +           &d.presentMode, physicalDevice, surface,
 | 
	
		
			
				|  |  | +           getSurfacePresentModePoints)) {
 | 
	
		
			
				|  |  | +        LOG_ERROR("Could not find present mode");
 | 
	
		
			
				|  |  | +        return true;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    f(vk.instance, vk.debugMessenger, nullptr);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static void destroyDebugReportCallback() {
 | 
	
		
			
				|  |  | -    auto f = GET_VULKAN_FUNCTION(vkDestroyDebugReportCallbackEXT);
 | 
	
		
			
				|  |  | -    if(f == nullptr) {
 | 
	
		
			
				|  |  | -        LOG_WARNING("Could not find debug report destroy function");
 | 
	
		
			
				|  |  | -        return;
 | 
	
		
			
				|  |  | +    u32 queueFamilyIndices[] = {graphicsFamily, presentFamily};
 | 
	
		
			
				|  |  | +    if(graphicsFamily != presentFamily) {
 | 
	
		
			
				|  |  | +        d.sharingMode = VK_SHARING_MODE_CONCURRENT;
 | 
	
		
			
				|  |  | +        d.queueFamilyIndexCount = 2;
 | 
	
		
			
				|  |  | +        d.queueFamilyIndices = queueFamilyIndices;
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +        d.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    f(vk.instance, vk.debugReportCallback, nullptr);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -#else
 | 
	
		
			
				|  |  | -static bool initDebugging() {
 | 
	
		
			
				|  |  | -    (void)getVulkanFunction;
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static void destroyDebugMessenger() {
 | 
	
		
			
				|  |  | +    return initVulkanSwapchain(&swapchain, &d);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static void destroyDebugReportCallback() {
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -#endif
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static u32 findQueueFamilies(VkPhysicalDevice pd, VkQueueFlags flags) {
 | 
	
		
			
				|  |  | -    VkQueueFamilyProperties properties[32];
 | 
	
		
			
				|  |  | -    u32 count = ARRAY_LENGTH(properties);
 | 
	
		
			
				|  |  | -    vkGetPhysicalDeviceQueueFamilyProperties(pd, &count, properties);
 | 
	
		
			
				|  |  | -    for(u32 i = 0; i < count; i++) {
 | 
	
		
			
				|  |  | -        if((properties[i].queueFlags & flags) == flags) {
 | 
	
		
			
				|  |  | -            return i;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +static bool initDevice() {
 | 
	
		
			
				|  |  | +    graphicsFamily =
 | 
	
		
			
				|  |  | +        findVulkanQueueFamily(physicalDevice, VK_QUEUE_GRAPHICS_BIT);
 | 
	
		
			
				|  |  | +    presentFamily = findVulkanSurfaceQueueFamily(physicalDevice, surface);
 | 
	
		
			
				|  |  | +    if(graphicsFamily == INVALID_VULKAN_QUEUE_FAMILY ||
 | 
	
		
			
				|  |  | +       presentFamily == INVALID_VULKAN_QUEUE_FAMILY) {
 | 
	
		
			
				|  |  | +        return true;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    bool same = graphicsFamily == presentFamily;
 | 
	
		
			
				|  |  | +    VulkanDeviceQueueData data[] = {
 | 
	
		
			
				|  |  | +        {graphicsFamily, 1.0f}, {presentFamily, 1.0f}};
 | 
	
		
			
				|  |  | +    const char* extensions[] = {VK_KHR_SWAPCHAIN_EXTENSION_NAME};
 | 
	
		
			
				|  |  | +    if(initVulkanDevice(
 | 
	
		
			
				|  |  | +           &device, physicalDevice, data, same ? 1 : 2, extensions,
 | 
	
		
			
				|  |  | +           ARRAY_LENGTH(extensions))) {
 | 
	
		
			
				|  |  | +        return true;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    vkGetDeviceQueue(device, graphicsFamily, 0, &graphicsQueue);
 | 
	
		
			
				|  |  | +    if(graphicsQueue == VK_NULL_HANDLE) {
 | 
	
		
			
				|  |  | +        LOG_ERROR("Cannot get device graphics queue");
 | 
	
		
			
				|  |  | +        return true;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if(same) {
 | 
	
		
			
				|  |  | +        presentQueue = graphicsQueue;
 | 
	
		
			
				|  |  | +        return false;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    vkGetDeviceQueue(device, presentFamily, 0, &presentQueue);
 | 
	
		
			
				|  |  | +    if(presentQueue == VK_NULL_HANDLE) {
 | 
	
		
			
				|  |  | +        LOG_ERROR("Cannot get device present queue");
 | 
	
		
			
				|  |  | +        return true;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    return (u32)-1;
 | 
	
		
			
				|  |  | +    return false;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static int getDevicePoints(Device* d) {
 | 
	
		
			
				|  |  | +static int getDevicePoints(VkPhysicalDevice pd) {
 | 
	
		
			
				|  |  |      int points = 0;
 | 
	
		
			
				|  |  |      VkPhysicalDeviceProperties p;
 | 
	
		
			
				|  |  | -    vkGetPhysicalDeviceProperties(d->physical, &p);
 | 
	
		
			
				|  |  | +    vkGetPhysicalDeviceProperties(pd, &p);
 | 
	
		
			
				|  |  |      LOG_INFO("Checking '%s'", p.deviceName);
 | 
	
		
			
				|  |  |      switch(p.deviceType) {
 | 
	
		
			
				|  |  |          case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: points += 100; break;
 | 
	
	
		
			
				|  | @@ -223,358 +142,85 @@ static int getDevicePoints(Device* d) {
 | 
	
		
			
				|  |  |          case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: points += 20; break;
 | 
	
		
			
				|  |  |          default: break;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    d->graphicsFamily = findQueueFamilies(d->physical, VK_QUEUE_GRAPHICS_BIT);
 | 
	
		
			
				|  |  | -    if(d->graphicsFamily == (u32)-1) {
 | 
	
		
			
				|  |  | +    u32 gf = findVulkanQueueFamily(pd, VK_QUEUE_GRAPHICS_BIT);
 | 
	
		
			
				|  |  | +    if(gf == INVALID_VULKAN_QUEUE_FAMILY) {
 | 
	
		
			
				|  |  |          LOG_INFO("> ... has no graphics family");
 | 
	
		
			
				|  |  |          points = -1;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +    u32 pf = findVulkanSurfaceQueueFamily(pd, surface);
 | 
	
		
			
				|  |  | +    if(pf == INVALID_VULKAN_QUEUE_FAMILY) {
 | 
	
		
			
				|  |  | +        LOG_INFO("> ... has no present family");
 | 
	
		
			
				|  |  | +        points = -1;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if(!hasVulkanExtension(pd, VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
 | 
	
		
			
				|  |  | +        LOG_INFO("> ... has no swapchain support");
 | 
	
		
			
				|  |  | +        points = -1;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    VkSurfaceFormatKHR sf = {0};
 | 
	
		
			
				|  |  | +    if(findVulkanSurfaceFormat(&sf, pd, surface, getSurfaceFormatPoints)) {
 | 
	
		
			
				|  |  | +        LOG_INFO("> ... has no matching surface format");
 | 
	
		
			
				|  |  | +        points = -1;
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +        points += getSurfaceFormatPoints(&sf);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    VkPresentModeKHR m = 0;
 | 
	
		
			
				|  |  | +    if(findVulkanSurfacePresentMode(
 | 
	
		
			
				|  |  | +           &m, pd, surface, getSurfacePresentModePoints)) {
 | 
	
		
			
				|  |  | +        LOG_INFO("> ... has no matching present mode");
 | 
	
		
			
				|  |  | +        points = -1;
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +        points += getSurfacePresentModePoints(m);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |      LOG_INFO("> Final points: %d", points);
 | 
	
		
			
				|  |  |      return points;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static bool initPhysicalDevice() {
 | 
	
		
			
				|  |  | -    VkPhysicalDevice devices[32];
 | 
	
		
			
				|  |  | -    u32 c = ARRAY_LENGTH(devices);
 | 
	
		
			
				|  |  | -    VK_ASSERT(vkEnumeratePhysicalDevices(vk.instance, &c, devices));
 | 
	
		
			
				|  |  | -    LOG_INFO("Found %u physical devices", c);
 | 
	
		
			
				|  |  | -    int bestPoints = 0;
 | 
	
		
			
				|  |  | -    for(u32 i = 0; i < c; i++) {
 | 
	
		
			
				|  |  | -        Device d = {.physical = devices[i]};
 | 
	
		
			
				|  |  | -        int points = getDevicePoints(&d);
 | 
	
		
			
				|  |  | -        if(points > bestPoints) {
 | 
	
		
			
				|  |  | -            bestPoints = points;
 | 
	
		
			
				|  |  | -            vk.device = d;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    if(bestPoints == 0) {
 | 
	
		
			
				|  |  | +    LOG_INFO("Searching for physical devices ...");
 | 
	
		
			
				|  |  | +    if(findVulkanPhysicalDevice(&physicalDevice, getDevicePoints)) {
 | 
	
		
			
				|  |  |          LOG_ERROR("No matching physical device was found");
 | 
	
		
			
				|  |  |          return true;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      VkPhysicalDeviceProperties p;
 | 
	
		
			
				|  |  | -    vkGetPhysicalDeviceProperties(vk.device.physical, &p);
 | 
	
		
			
				|  |  | +    vkGetPhysicalDeviceProperties(physicalDevice, &p);
 | 
	
		
			
				|  |  |      LOG_INFO("Best Device: %s", p.deviceName);
 | 
	
		
			
				|  |  |      return false;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static bool getDeviceQueue(Device* d, VkQueue* q) {
 | 
	
		
			
				|  |  | -    vkGetDeviceQueue(d->logical, d->graphicsFamily, 0, q);
 | 
	
		
			
				|  |  | -    return *q == VK_NULL_HANDLE;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static bool initDevice(Device* d) {
 | 
	
		
			
				|  |  | -    VkPhysicalDeviceFeatures deviceFeatures = {0};
 | 
	
		
			
				|  |  | -    vkGetPhysicalDeviceFeatures(d->physical, &deviceFeatures);
 | 
	
		
			
				|  |  | -    VkDeviceQueueCreateInfo deviceQueueInfo = {
 | 
	
		
			
				|  |  | -        .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
 | 
	
		
			
				|  |  | -        .queueFamilyIndex = d->graphicsFamily,
 | 
	
		
			
				|  |  | -        .queueCount = 1,
 | 
	
		
			
				|  |  | -        .pQueuePriorities = (float[]){1.0f}};
 | 
	
		
			
				|  |  | -    VkDeviceCreateInfo info = {
 | 
	
		
			
				|  |  | -        .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
 | 
	
		
			
				|  |  | -        .queueCreateInfoCount = 1,
 | 
	
		
			
				|  |  | -        .pQueueCreateInfos = &deviceQueueInfo,
 | 
	
		
			
				|  |  | -        .enabledExtensionCount = 1,
 | 
	
		
			
				|  |  | -        .ppEnabledExtensionNames =
 | 
	
		
			
				|  |  | -            (const char*[]){VK_KHR_SWAPCHAIN_EXTENSION_NAME},
 | 
	
		
			
				|  |  | -        .pEnabledFeatures = &deviceFeatures};
 | 
	
		
			
				|  |  | -    VK_ASSERT(vkCreateDevice(d->physical, &info, nullptr, &d->logical));
 | 
	
		
			
				|  |  | -    if(getDeviceQueue(d, &d->graphicsQueue)) {
 | 
	
		
			
				|  |  | -        LOG_ERROR("Cannot get device graphics queue");
 | 
	
		
			
				|  |  | -        return true;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static bool initSurface() {
 | 
	
		
			
				|  |  | -    VK_ASSERT(glfwCreateWindowSurface(
 | 
	
		
			
				|  |  | -        vk.instance, getWindow(), nullptr, &vk.surface));
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static u32 getSwapImageCount(const VkSurfaceCapabilitiesKHR* caps) {
 | 
	
		
			
				|  |  | -    u32 c = caps->minImageCount + 1;
 | 
	
		
			
				|  |  | -    // according to VkSurfaceCapabilitiesKHR doc:
 | 
	
		
			
				|  |  | -    // maxImageCount is 0 when there is no strict limit
 | 
	
		
			
				|  |  | -    if(caps->maxImageCount != 0 && c > caps->maxImageCount) {
 | 
	
		
			
				|  |  | -        return caps->maxImageCount;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    return c;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static bool getSurfaceFormat(VkSurfaceFormatKHR* sf) {
 | 
	
		
			
				|  |  | -    u32 c = 0;
 | 
	
		
			
				|  |  | -    VK_ASSERT(vkGetPhysicalDeviceSurfaceFormatsKHR(
 | 
	
		
			
				|  |  | -        vk.device.physical, vk.surface, &c, nullptr));
 | 
	
		
			
				|  |  | -    VkSurfaceFormatKHR* formats = coreAllocate(sizeof(VkSurfaceFormatKHR) * c);
 | 
	
		
			
				|  |  | -    VK_ASSERT(vkGetPhysicalDeviceSurfaceFormatsKHR(
 | 
	
		
			
				|  |  | -        vk.device.physical, vk.surface, &c, formats));
 | 
	
		
			
				|  |  | -    for(u32 i = 0; i < c; i++) {
 | 
	
		
			
				|  |  | -        if(formats[i].format == VK_FORMAT_B8G8R8A8_UNORM &&
 | 
	
		
			
				|  |  | -           formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
 | 
	
		
			
				|  |  | -            *sf = formats[i];
 | 
	
		
			
				|  |  | -            coreFree(formats);
 | 
	
		
			
				|  |  | -            return false;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    coreFree(formats);
 | 
	
		
			
				|  |  | -    LOG_ERROR("Could not find any matching surface format");
 | 
	
		
			
				|  |  | -    return true;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static bool getPresentMode(VkPresentModeKHR* pm) {
 | 
	
		
			
				|  |  | -    u32 c = 0;
 | 
	
		
			
				|  |  | -    VK_ASSERT(vkGetPhysicalDeviceSurfacePresentModesKHR(
 | 
	
		
			
				|  |  | -        vk.device.physical, vk.surface, &c, nullptr));
 | 
	
		
			
				|  |  | -    VkPresentModeKHR* modes = coreAllocate(sizeof(VkPresentModeKHR) * c);
 | 
	
		
			
				|  |  | -    VK_ASSERT(vkGetPhysicalDeviceSurfacePresentModesKHR(
 | 
	
		
			
				|  |  | -        vk.device.physical, vk.surface, &c, modes));
 | 
	
		
			
				|  |  | -    for(u32 i = 0; i < c; i++) {
 | 
	
		
			
				|  |  | -        if(modes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
 | 
	
		
			
				|  |  | -            *pm = modes[i];
 | 
	
		
			
				|  |  | -            coreFree(modes);
 | 
	
		
			
				|  |  | -            return false;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    coreFree(modes);
 | 
	
		
			
				|  |  | -    LOG_ERROR("Could not find any matching present modes");
 | 
	
		
			
				|  |  | -    return true;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static bool initSwapchain() {
 | 
	
		
			
				|  |  | -    VkSurfaceCapabilitiesKHR caps = {0};
 | 
	
		
			
				|  |  | -    VK_ASSERT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
 | 
	
		
			
				|  |  | -        vk.device.physical, vk.surface, &caps));
 | 
	
		
			
				|  |  | -    VkSurfaceFormatKHR sf = {0};
 | 
	
		
			
				|  |  | -    if(getSurfaceFormat(&sf)) {
 | 
	
		
			
				|  |  | -        return true;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    vk.swapchain.format = sf.format;
 | 
	
		
			
				|  |  | -    VkPresentModeKHR pm = {0};
 | 
	
		
			
				|  |  | -    if(getPresentMode(&pm)) {
 | 
	
		
			
				|  |  | -        return true;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    VkSwapchainCreateInfoKHR ci = {
 | 
	
		
			
				|  |  | -        .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
 | 
	
		
			
				|  |  | -        .surface = vk.surface,
 | 
	
		
			
				|  |  | -        .minImageCount = getSwapImageCount(&caps),
 | 
	
		
			
				|  |  | -        .imageFormat = sf.format,
 | 
	
		
			
				|  |  | -        .imageColorSpace = sf.colorSpace,
 | 
	
		
			
				|  |  | -        .imageExtent = {.width = vk.width, .height = vk.height},
 | 
	
		
			
				|  |  | -        .imageArrayLayers = 1,
 | 
	
		
			
				|  |  | -        .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
 | 
	
		
			
				|  |  | -                      VK_IMAGE_USAGE_TRANSFER_DST_BIT,
 | 
	
		
			
				|  |  | -        .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
 | 
	
		
			
				|  |  | -        .queueFamilyIndexCount = 1,
 | 
	
		
			
				|  |  | -        .pQueueFamilyIndices = &vk.device.graphicsFamily,
 | 
	
		
			
				|  |  | -        .preTransform = caps.currentTransform,
 | 
	
		
			
				|  |  | -        .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
 | 
	
		
			
				|  |  | -        .presentMode = pm,
 | 
	
		
			
				|  |  | -        .clipped = VK_TRUE,
 | 
	
		
			
				|  |  | -        .oldSwapchain = VK_NULL_HANDLE};
 | 
	
		
			
				|  |  | -    VK_ASSERT(vkCreateSwapchainKHR(
 | 
	
		
			
				|  |  | -        vk.device.logical, &ci, nullptr, &vk.swapchain.handle));
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static bool createImageView(VkImage image, VkImageView* view) {
 | 
	
		
			
				|  |  | -    VkImageViewCreateInfo info = {
 | 
	
		
			
				|  |  | -        .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
 | 
	
		
			
				|  |  | -        .image = image,
 | 
	
		
			
				|  |  | -        .viewType = VK_IMAGE_VIEW_TYPE_2D,
 | 
	
		
			
				|  |  | -        .format = VK_FORMAT_B8G8R8A8_UNORM,
 | 
	
		
			
				|  |  | -        .subresourceRange = {
 | 
	
		
			
				|  |  | -            .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
 | 
	
		
			
				|  |  | -            .baseMipLevel = 0,
 | 
	
		
			
				|  |  | -            .levelCount = 1,
 | 
	
		
			
				|  |  | -            .baseArrayLayer = 0,
 | 
	
		
			
				|  |  | -            .layerCount = 1}};
 | 
	
		
			
				|  |  | -    VK_ASSERT(vkCreateImageView(vk.device.logical, &info, nullptr, view));
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static void destroySwapchainImages() {
 | 
	
		
			
				|  |  | -    for(size_t x = 0; x < vk.swapchain.amount; x++) {
 | 
	
		
			
				|  |  | -        vkDestroyImageView(
 | 
	
		
			
				|  |  | -            vk.device.logical, vk.swapchain.imageViews[x], nullptr);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    coreFree(vk.swapchain.images);
 | 
	
		
			
				|  |  | -    coreFree(vk.swapchain.imageViews);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  static bool initSwapchainImages() {
 | 
	
		
			
				|  |  | -    u32 c = 0;
 | 
	
		
			
				|  |  | -    VK_ASSERT(vkGetSwapchainImagesKHR(
 | 
	
		
			
				|  |  | -        vk.device.logical, vk.swapchain.handle, &c, nullptr));
 | 
	
		
			
				|  |  | -    LOG_INFO("Found %u images", c);
 | 
	
		
			
				|  |  | -    vk.swapchain.amount = c;
 | 
	
		
			
				|  |  | -    vk.swapchain.images = coreAllocate(sizeof(VkImage) * c);
 | 
	
		
			
				|  |  | -    vk.swapchain.imageViews = coreZeroAllocate(sizeof(VkImageView) * c);
 | 
	
		
			
				|  |  | -    VK_ASSERT(vkGetSwapchainImagesKHR(
 | 
	
		
			
				|  |  | -        vk.device.logical, vk.swapchain.handle, &c, vk.swapchain.images));
 | 
	
		
			
				|  |  | -    for(u32 x = 0; x < c; x++) {
 | 
	
		
			
				|  |  | -        if(createImageView(
 | 
	
		
			
				|  |  | -               vk.swapchain.images[x], vk.swapchain.imageViews + x)) {
 | 
	
		
			
				|  |  | -            return true;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static bool initSemaphore(VkSemaphore* s) {
 | 
	
		
			
				|  |  | -    VkSemaphoreCreateInfo info = {
 | 
	
		
			
				|  |  | -        .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
 | 
	
		
			
				|  |  | -    VK_ASSERT(vkCreateSemaphore(vk.device.logical, &info, nullptr, s));
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static void destroySemaphore(VkSemaphore s) {
 | 
	
		
			
				|  |  | -    vkDestroySemaphore(vk.device.logical, s, nullptr);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static bool checkPresentationSupport() {
 | 
	
		
			
				|  |  | -    VkBool32 b = false;
 | 
	
		
			
				|  |  | -    VK_ASSERT(vkGetPhysicalDeviceSurfaceSupportKHR(
 | 
	
		
			
				|  |  | -        vk.device.physical, vk.device.graphicsFamily, vk.surface, &b));
 | 
	
		
			
				|  |  | -    if(!b) {
 | 
	
		
			
				|  |  | -        LOG_ERROR("Presentation is not supported");
 | 
	
		
			
				|  |  | +    if(initVulkanSwapchainImages(
 | 
	
		
			
				|  |  | +           &images, device, swapchain, surfaceFormat.format)) {
 | 
	
		
			
				|  |  | +        LOG_ERROR("Could not get swapchain images");
 | 
	
		
			
				|  |  |          return true;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +    LOG_INFO("Found %u images", images.amount);
 | 
	
		
			
				|  |  |      return false;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static bool initCommandBuffers() {
 | 
	
		
			
				|  |  | -    VkCommandPoolCreateInfo info = {
 | 
	
		
			
				|  |  | -        .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
 | 
	
		
			
				|  |  | -        .queueFamilyIndex = vk.device.graphicsFamily};
 | 
	
		
			
				|  |  | -    VK_ASSERT(vkCreateCommandPool(
 | 
	
		
			
				|  |  | -        vk.device.logical, &info, nullptr, &vk.swapchain.commandPool));
 | 
	
		
			
				|  |  | -    vk.swapchain.commandsBuffers =
 | 
	
		
			
				|  |  | -        coreAllocate(sizeof(VkCommandBuffer) * vk.swapchain.amount);
 | 
	
		
			
				|  |  | -    VkCommandBufferAllocateInfo a = {
 | 
	
		
			
				|  |  | -        .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
 | 
	
		
			
				|  |  | -        .commandPool = vk.swapchain.commandPool,
 | 
	
		
			
				|  |  | -        .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
 | 
	
		
			
				|  |  | -        .commandBufferCount = vk.swapchain.amount};
 | 
	
		
			
				|  |  | -    VK_ASSERT(vkAllocateCommandBuffers(
 | 
	
		
			
				|  |  | -        vk.device.logical, &a, vk.swapchain.commandsBuffers));
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static void destroyCommandBuffers() {
 | 
	
		
			
				|  |  | -    if(vk.swapchain.commandPool != VK_NULL_HANDLE && vk.swapchain.amount > 0) {
 | 
	
		
			
				|  |  | -        vkFreeCommandBuffers(
 | 
	
		
			
				|  |  | -            vk.device.logical, vk.swapchain.commandPool, vk.swapchain.amount,
 | 
	
		
			
				|  |  | -            vk.swapchain.commandsBuffers);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    coreFree(vk.swapchain.commandsBuffers);
 | 
	
		
			
				|  |  | -    vkDestroyCommandPool(vk.device.logical, vk.swapchain.commandPool, nullptr);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static bool initRenderPass() {
 | 
	
		
			
				|  |  | -    VkAttachmentDescription c = {
 | 
	
		
			
				|  |  | -        .format = vk.swapchain.format,
 | 
	
		
			
				|  |  | -        .samples = VK_SAMPLE_COUNT_1_BIT,
 | 
	
		
			
				|  |  | -        .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
 | 
	
		
			
				|  |  | -        .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
 | 
	
		
			
				|  |  | -        .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
 | 
	
		
			
				|  |  | -        .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
 | 
	
		
			
				|  |  | -        .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
 | 
	
		
			
				|  |  | -        .finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR};
 | 
	
		
			
				|  |  | -    VkAttachmentReference ca = {
 | 
	
		
			
				|  |  | -        .attachment = 0, .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
 | 
	
		
			
				|  |  | -    VkSubpassDescription subpass = {
 | 
	
		
			
				|  |  | -        .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
 | 
	
		
			
				|  |  | -        .colorAttachmentCount = 1,
 | 
	
		
			
				|  |  | -        .pColorAttachments = &ca};
 | 
	
		
			
				|  |  | -    VkRenderPassCreateInfo info = {
 | 
	
		
			
				|  |  | -        .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
 | 
	
		
			
				|  |  | -        .attachmentCount = 1,
 | 
	
		
			
				|  |  | -        .pAttachments = &c,
 | 
	
		
			
				|  |  | -        .subpassCount = 1,
 | 
	
		
			
				|  |  | -        .pSubpasses = &subpass};
 | 
	
		
			
				|  |  | -    VK_ASSERT(
 | 
	
		
			
				|  |  | -        vkCreateRenderPass(vk.device.logical, &info, nullptr, &vk.renderPass));
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static bool initFramebuffers() {
 | 
	
		
			
				|  |  | -    vk.swapchain.framebuffers =
 | 
	
		
			
				|  |  | -        coreAllocate(sizeof(VkFramebuffer) * vk.swapchain.amount);
 | 
	
		
			
				|  |  | -    for(u32 i = 0; i < vk.swapchain.amount; i++) {
 | 
	
		
			
				|  |  | -        VkFramebufferCreateInfo info = {
 | 
	
		
			
				|  |  | -            .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
 | 
	
		
			
				|  |  | -            .renderPass = vk.renderPass,
 | 
	
		
			
				|  |  | -            .attachmentCount = 1,
 | 
	
		
			
				|  |  | -            .pAttachments = vk.swapchain.imageViews + i,
 | 
	
		
			
				|  |  | -            .width = vk.width,
 | 
	
		
			
				|  |  | -            .height = vk.height,
 | 
	
		
			
				|  |  | -            .layers = 1};
 | 
	
		
			
				|  |  | -        VK_ASSERT(vkCreateFramebuffer(
 | 
	
		
			
				|  |  | -            vk.device.logical, &info, nullptr, vk.swapchain.framebuffers + i));
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    printf("%u\n", vk.swapchain.amount);
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static void destroyFramebuffers() {
 | 
	
		
			
				|  |  | -    for(u32 i = 0; i < vk.swapchain.amount; i++) {
 | 
	
		
			
				|  |  | -        vkDestroyFramebuffer(
 | 
	
		
			
				|  |  | -            vk.device.logical, vk.swapchain.framebuffers[i], nullptr);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    coreFree(vk.swapchain.framebuffers);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  bool initVulkan() {
 | 
	
		
			
				|  |  | -    vk.width = 400;
 | 
	
		
			
				|  |  | -    vk.height = 300;
 | 
	
		
			
				|  |  | -    return initInstance() || initDebugging() || initSurface() ||
 | 
	
		
			
				|  |  | -           initPhysicalDevice() || initDevice(&vk.device) ||
 | 
	
		
			
				|  |  | -           checkPresentationSupport() || initSwapchain() ||
 | 
	
		
			
				|  |  | -           initSwapchainImages() || initSemaphore(&vk.semaphore) ||
 | 
	
		
			
				|  |  | -           initSemaphore(&vk.renderSemaphore) || initCommandBuffers() ||
 | 
	
		
			
				|  |  | -           initRenderPass() || initFramebuffers();
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static bool fillCommandBuffer(u32 index) {
 | 
	
		
			
				|  |  | -    (void)index;
 | 
	
		
			
				|  |  | -    // VkCommandBufferBeginInfo info = {
 | 
	
		
			
				|  |  | -    //     .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
 | 
	
		
			
				|  |  | -    //     .flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT};
 | 
	
		
			
				|  |  | -    // VK_ASSERT(vkBeginCommandBuffer(vk.swapchain.commandsBuffers[index],
 | 
	
		
			
				|  |  | -    // &info)); VkClearValue v = {.color = {.int32 = {255, 0, 0, 0}}};
 | 
	
		
			
				|  |  | -    // VkRenderPassBeginInfo rInfo = {
 | 
	
		
			
				|  |  | -    //     .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
 | 
	
		
			
				|  |  | -    //     .renderPass = vk.renderPass,
 | 
	
		
			
				|  |  | -    //     .framebuffer = vk.swapchain.framebuffers[index],
 | 
	
		
			
				|  |  | -    //     .renderArea = {.offset = {0, 0}, .extent = {vk.width, vk.height}},
 | 
	
		
			
				|  |  | -    //     .clearValueCount = 1,
 | 
	
		
			
				|  |  | -    //     .pClearValues = &v};
 | 
	
		
			
				|  |  | -    // vkCmdBeginRenderPass(vk.swapchain.commandsBuffers[index], &rInfo,
 | 
	
		
			
				|  |  | -    //                      VK_SUBPASS_CONTENTS_INLINE);
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | +    return initVulkanInstance() || initVulkanDebugging() ||
 | 
	
		
			
				|  |  | +           initVulkanSurface(&surface, getWindow()) || initPhysicalDevice() ||
 | 
	
		
			
				|  |  | +           initDevice() || initSwapchain() || initSwapchainImages();
 | 
	
		
			
				|  |  | +    /*  || initSemaphore(&vk.semaphore) ||
 | 
	
		
			
				|  |  | +       initSemaphore(&vk.renderSemaphore) || initCommandBuffers() ||
 | 
	
		
			
				|  |  | +       initRenderPass() || initFramebuffers()*/
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void renderVulkan() {
 | 
	
		
			
				|  |  | -    for(u32 i = 0; i < vk.swapchain.amount; i++) {
 | 
	
		
			
				|  |  | -        fillCommandBuffer(i);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void destroyVulkan(void) {
 | 
	
		
			
				|  |  | -    if(vk.device.logical != VK_NULL_HANDLE) {
 | 
	
		
			
				|  |  | -        destroyFramebuffers();
 | 
	
		
			
				|  |  | -        vkDestroyRenderPass(vk.device.logical, vk.renderPass, nullptr);
 | 
	
		
			
				|  |  | -        destroyCommandBuffers();
 | 
	
		
			
				|  |  | -        destroySemaphore(vk.semaphore);
 | 
	
		
			
				|  |  | -        destroySemaphore(vk.renderSemaphore);
 | 
	
		
			
				|  |  | -        destroySwapchainImages();
 | 
	
		
			
				|  |  | -        vkDestroySwapchainKHR(vk.device.logical, vk.swapchain.handle, nullptr);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    vkDestroyDevice(vk.device.logical, nullptr);
 | 
	
		
			
				|  |  | -    if(vk.instance != VK_NULL_HANDLE) {
 | 
	
		
			
				|  |  | -        vkDestroySurfaceKHR(vk.instance, vk.surface, nullptr);
 | 
	
		
			
				|  |  | -        destroyDebugMessenger();
 | 
	
		
			
				|  |  | -        destroyDebugReportCallback();
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    vkDestroyInstance(vk.instance, nullptr);
 | 
	
		
			
				|  |  | +    // if(vk.device.logical != VK_NULL_HANDLE) {
 | 
	
		
			
				|  |  | +    //     destroyFramebuffers();
 | 
	
		
			
				|  |  | +    //     vkDestroyRenderPass(vk.device.logical, vk.renderPass, nullptr);
 | 
	
		
			
				|  |  | +    //     destroyCommandBuffers();
 | 
	
		
			
				|  |  | +    //     destroySemaphore(vk.semaphore);
 | 
	
		
			
				|  |  | +    //     destroySemaphore(vk.renderSemaphore);
 | 
	
		
			
				|  |  | +    // }
 | 
	
		
			
				|  |  | +    destroyVulkanSwapchainImages(&images, device);
 | 
	
		
			
				|  |  | +    destroyVulkanSwapchain(swapchain, device);
 | 
	
		
			
				|  |  | +    destroyVulkanDevice(device);
 | 
	
		
			
				|  |  | +    destroyVulkanSurface(surface);
 | 
	
		
			
				|  |  | +    destroyVulkanDebugging();
 | 
	
		
			
				|  |  | +    destroyVulkanInstance();
 | 
	
		
			
				|  |  |  }
 |