diff options
Diffstat (limited to 'src/game.c')
-rw-r--r-- | src/game.c | 1950 |
1 files changed, 0 insertions, 1950 deletions
diff --git a/src/game.c b/src/game.c deleted file mode 100644 index 50f686e..0000000 --- a/src/game.c +++ /dev/null @@ -1,1950 +0,0 @@ -#include <stddef.h> -#include <stdlib.h> -#include <time.h> - -#include <shaderc/shaderc.h> - -#define SDL_MAIN_HANDLED -#define VK_USE_PLATFORM_XCB_KHR -#include <SDL2/SDL.h> -#include <SDL2/SDL_vulkan.h> - -#include <vulkan/vulkan.h> - -#define VMA_STATIC_VULKAN_FUNCTIONS 0 -#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1 -#include "vk_mem_alloc.h" - -#define STB_IMAGE_IMPLEMENTATION -#include "../lib/stb_image.h" - -//#include "cplusplus.h" -#include "vkutil.h" -#include "state.h" - -// embedded clgm library -uint32_t currentFrame = 0; -state_t s; - -const char *const validation_layers[] = { - "VK_LAYER_KHRONOS_validation" -}; -const uint32_t validation_layer_count = VK_ARRAY_LEN(validation_layers); - -const char *const device_extensions[] = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME, -}; -const uint32_t deviceExtensionCount = VK_ARRAY_LEN(device_extensions); - - -#ifdef VKDEBUG - const bool enableValidationLayers = true; -#else - const bool enableValidationLayers = false; -#endif - -typedef struct { - float x; - float y; -} V2; - -typedef struct { - float x; - float y; - float z; -} V3; - -typedef struct { - V3 pos; - V3 color; - V2 texCoord; -} Vertex; - -/* Vertex vertices[] = { */ -/* (Vertex) { (V2) {-0.2f, -0.5f}, (V3) {0.0f, 1.0f, 0.0f}}, */ -/* (Vertex) { (V2) {0.5f, 0.3f}, (V3) {0.0f, 0.0f, 1.0f}}, */ -/* (Vertex) { (V2) {-0.5f, 0.7f}, (V3) {1.0f, 0.0f, 0.0f}}, */ - -/* (Vertex) { (V2) {0.2f, -0.5f}, (V3) {0.0f, 0.0f, 1.0f}}, */ -/* (Vertex) { (V2) {0.5f, 0.7f}, (V3) {1.0f, 0.0f, 0.0f}}, */ -/* (Vertex) { (V2) {-0.5f, 0.3f}, (V3) {0.0f, 1.0f, 0.0f}}, */ - -/* (Vertex) { (V2) {0.0f, -0.5f}, (V3) {1.0f, 0.0f, 0.0f}}, */ -/* (Vertex) { (V2) {0.5f, 0.5f}, (V3) {0.0f, 1.0f, 0.0f}}, */ -/* (Vertex) { (V2) {-0.5f, 0.5f}, (V3) {0.0f, 0.0f, 1.0f}}, */ -/* }; */ -/* const int VERTICES_SIZE = VK_ARRAY_LEN(vertices); */ - -/* const uint16_t indices[] = { */ -/* 0, 1, 2, 3, 4, 5, 6, 7, 8, */ -/* }; */ -/* const int INDICES_SIZE = VK_ARRAY_LEN(indices); */ - -Vertex vertices[] = { - (Vertex) { (V3) {-0.5f, -0.5f, 0.0f}, (V3) {1.0f, 0.0f, 0.0f}, (V2) {0.0f, 0.0f}}, - (Vertex) { (V3) {0.5f, -0.5f, 0.0f}, (V3) {0.0f, 1.0f, 0.0f}, (V2) {1.0f, 0.0f}}, - (Vertex) { (V3) {0.5f, 0.5f, 0.0f}, (V3) {0.0f, 0.0f, 1.0f}, (V2) {1.0f, 1.0f}}, - (Vertex) { (V3) {-0.5f, 0.5f, 0.0f}, (V3) {1.0f, 1.0f, 1.0f}, (V2) {0.0f, 1.0f}}, - (Vertex) { (V3) {-0.5f, -0.5f, -0.5f}, (V3) {1.0f, 0.0f, 0.0f}, (V2) {0.0f, 0.0f}}, - (Vertex) { (V3) {0.5f, -0.5f, -0.5f}, (V3) {0.0f, 1.0f, 0.0f}, (V2) {1.0f, 0.0f}}, - (Vertex) { (V3) {0.5f, 0.5f, -0.5f}, (V3) {0.0f, 0.0f, 1.0f}, (V2) {1.0f, 1.0f}}, - (Vertex) { (V3) {-0.5f, 0.5f, -0.5f}, (V3) {1.0f, 1.0f, 1.0f}, (V2) {0.0f, 1.0f}}, -}; -const int VERTICES_SIZE = VK_ARRAY_LEN(vertices); - -const uint16_t indices[] = { - 0, 1, 2, 2, 3, 0, 4, 5, 6, 6, 7, 4 -}; -const int INDICES_SIZE = VK_ARRAY_LEN(indices); - -static int resizing_event_watcher(void* data, SDL_Event* event) { - if (event->type == SDL_WINDOWEVENT && - event->window.event == SDL_WINDOWEVENT_RESIZED) { - s.sdl_window_resized = 1; - } - return 0; -} - -bool -init() -{ - if (SDL_Init(SDL_INIT_VIDEO) < 0) { - vk_log(VK_INFO, "SDL could not initialize! SDL_Error: %s\n", SDL_GetError()); - return false; - } - - s.sdl_window = SDL_CreateWindow("Vulkanizater", - SDL_WINDOWPOS_UNDEFINED, - SDL_WINDOWPOS_UNDEFINED, - s.window_w, - s.window_h, - SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_VULKAN); - if (s.sdl_window == NULL) { - vk_log(VK_INFO, "Window could not be created! SDL_Error: %s\n", SDL_GetError()); - return false; - } - - SDL_AddEventWatch(resizing_event_watcher,NULL); - - return true; -} - -void -closeSDL() -{ - SDL_DestroyWindow(s.sdl_window); - s.sdl_window = NULL; - SDL_Quit(); -} - -bool -checkValidationLayerSupport() -{ - uint32_t layerCount; - vkEnumerateInstanceLayerProperties(&layerCount, NULL); - - VkLayerProperties availableLayers[layerCount]; - vkEnumerateInstanceLayerProperties(&layerCount, availableLayers); - - for (uint32_t i = 0; i < validation_layer_count; i++) { - bool layerFound = false; - - for (uint32_t j = 0; j < layerCount; j++) { - if (strcmp(validation_layers[i], availableLayers[j].layerName) == 0) { - layerFound = true; - break; - } - } - - if (!layerFound) { - return false; - } - } - - return true; -} - -static VKAPI_ATTR VkBool32 VKAPI_CALL -debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, - VkDebugUtilsMessageTypeFlagsEXT messageType, - const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, - void* pUserData) -{ - vk_log(VK_ERROR, "validation layer: %s\n", pCallbackData->pMessage); - return VK_FALSE; -} - -void -vulkan_setup_debug_messenger() -{ - if (!enableValidationLayers) return; - VkDebugUtilsMessengerCreateInfoEXT createInfo = {0}; - createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; - createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; - createInfo.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; - createInfo.pfnUserCallback = debugCallback; - createInfo.pUserData = NULL; // Optional - - - // TODO: func pointers returned are NULL - s.pfnCreateDebugUtilsMessengerEXT = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(s.vk_instance, "vkCreateDebugUtilsMessengerEXT"); - s.pfnDestroyDebugUtilsMessengerEXT = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(s.vk_instance, "vkDestroyDebugUtilsMessengerEXT"); - - VkResult result = s.pfnCreateDebugUtilsMessengerEXT(s.vk_instance, &createInfo, NULL, &s.vk_debug_messenger); - if (result != VK_SUCCESS) { - vk_log(VK_WARN, "failed to set up debug messenger!\n"); - } else { - vk_log(VK_INFO, "Debug messanger created!\n"); - } -} - -void -vulkan_create_instance() -{ - if (enableValidationLayers && !checkValidationLayerSupport()) { - vk_log(VK_ERROR, "validation layers requested, but not available!\n"); - } - - uint32_t instanceVersion; - VkResult result = vkEnumerateInstanceVersion(&instanceVersion); - if (result == VK_SUCCESS) { - if (instanceVersion < VK_MAKE_API_VERSION(0, 1, 3, 0)) { - vk_log(VK_ERROR, "Vulkan version 1.3 or greater required!\n"); - exit(1); - } - vk_log(VK_INFO, "Vulkan version found (%d) %d.%d.%d\n", - VK_API_VERSION_VARIANT(instanceVersion), - VK_API_VERSION_MAJOR(instanceVersion), - VK_API_VERSION_MINOR(instanceVersion), - VK_API_VERSION_PATCH(instanceVersion)); - } else { - vk_log(VK_ERROR, "Failed to retrieve vulkan version, is vulkan supported in this system?\n"); - exit(1); - } - - // Load Vulkan and create instance - VkApplicationInfo appInfo = { - .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, - .pApplicationName = "Vulkan Application", - .applicationVersion = VK_MAKE_API_VERSION(0, 1, 3, 0), - .pEngineName = NULL, - .engineVersion = VK_MAKE_API_VERSION(0, 1, 3, 0), - .apiVersion = VK_MAKE_API_VERSION(0, 1, 3, 0), - }; - - uint32_t sdlExtensionCount = 0; - - if (SDL_Vulkan_GetInstanceExtensions(s.sdl_window, &sdlExtensionCount, NULL) == SDL_FALSE) { - vk_log(VK_ERROR, "SDL_Vulkan_GetInstanceExtensions failed: %s\n", SDL_GetError()); - } - - // make space for debug extenetion - if (enableValidationLayers) { - sdlExtensionCount++; - } - - const char* sdlExtensions[sdlExtensionCount]; - - if (SDL_Vulkan_GetInstanceExtensions(s.sdl_window, &sdlExtensionCount, sdlExtensions) == SDL_FALSE) { - vk_log(VK_ERROR, "SDL_Vulkan_GetInstanceExtensions failed: %s\n", SDL_GetError()); - } - - // add debug extenetion - if (enableValidationLayers) { - sdlExtensions[sdlExtensionCount] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME; - } - - vk_log(VK_INFO, "The sdl extensions:\n"); - for (uint32_t i = 0; i < sdlExtensionCount; i++) { - vk_log(VK_INFO, "\t%s\n", sdlExtensions[i]); - } - - VkInstanceCreateInfo createInfo = { - .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, - .pApplicationInfo = &appInfo, - .enabledExtensionCount = sdlExtensionCount, - .ppEnabledExtensionNames = sdlExtensions, - .enabledLayerCount = 0, - }; - - if (enableValidationLayers) { - createInfo.enabledLayerCount = validation_layer_count; - createInfo.ppEnabledLayerNames = validation_layers; - } - - if (vkCreateInstance(&createInfo, NULL, &s.vk_instance) != VK_SUCCESS) { - vk_log(VK_ERROR, "Can't start vulkan instance\n"); - } - vk_log(VK_INFO, "Vulkan instance created\n"); -} - -VkExtent2D -chooseSwapExtent(const VkSurfaceCapabilitiesKHR * capabilities) -{ - if (capabilities->currentExtent.width != UINT32_MAX) { - return capabilities->currentExtent; - } else { - int width, height; - SDL_GetWindowSize(s.sdl_window, &width, &height); - - VkExtent2D actualExtent; - actualExtent.width = (uint32_t) width; - actualExtent.height = (uint32_t) height; - - // Manual implementation of std::clamp since it is not available in C - actualExtent.width = (actualExtent.width < capabilities->minImageExtent.width) ? capabilities->minImageExtent.width : - (actualExtent.width > capabilities->maxImageExtent.width) ? capabilities->maxImageExtent.width : - actualExtent.width; - - actualExtent.height = (actualExtent.height < capabilities->minImageExtent.height) ? capabilities->minImageExtent.height : - (actualExtent.height > capabilities->maxImageExtent.height) ? capabilities->maxImageExtent.height : - actualExtent.height; - - return actualExtent; - } -} - -VkSurfaceFormatKHR -chooseSwapSurfaceFormat(const VkSurfaceFormatKHR * availableFormats, uint32_t formatCount) -{ - for (uint32_t i = 0 ; i < formatCount; i ++) { - if (availableFormats[i].format == VK_FORMAT_B8G8R8A8_SRGB && - availableFormats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { - return availableFormats[i]; - } - } - - // if it fails pick the first one - return availableFormats[0]; -} - -VkPresentModeKHR -chooseSwapPresentMode(const VkPresentModeKHR * presentModes, uint32_t presentModeCount) -{ - for (uint32_t i = 0 ; i < presentModeCount; i ++) { - if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) { - return presentModes[i]; - } - } - - // if it fails pick the the FIFO one - return VK_PRESENT_MODE_FIFO_KHR; -} - -typedef struct SwapChainSupportDetails { - VkSurfaceCapabilitiesKHR capabilities; - VkSurfaceFormatKHR formats[100]; - uint32_t formatCount; - VkPresentModeKHR presentModes[100]; - uint32_t presentModeCount; -} SwapChainSupportDetails; - -SwapChainSupportDetails -querySwapChainSupport(VkPhysicalDevice device) -{ - // TODO Make SwapChainSupportDetails malloc it;s arrays and free it after it is used. - SwapChainSupportDetails details; - - vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, s.vk_surface, &details.capabilities); - - vkGetPhysicalDeviceSurfaceFormatsKHR(device, s.vk_surface, &details.formatCount, NULL); - - if (details.formatCount != 0) { - // todo alloc format arrray - vkGetPhysicalDeviceSurfaceFormatsKHR(device, s.vk_surface, &details.formatCount, details.formats); - } - - vkGetPhysicalDeviceSurfacePresentModesKHR(device, s.vk_surface, &details.presentModeCount, NULL); - - if (details.presentModeCount != 0) { - // todo alloc presentModes array - vkGetPhysicalDeviceSurfacePresentModesKHR(device, s.vk_surface, &details.presentModeCount, details.presentModes); - } - - return details; -} - -typedef struct QueueFamilyIndices { - uint32_t graphicsFamily; - bool graphicsFlag; - uint32_t presentFamily; - bool presentFlag; -} QueueFamilyIndices; - -bool -vulkan_queue_family_check_flags(QueueFamilyIndices x) -{ - return x.graphicsFlag && x.presentFlag; -} - -QueueFamilyIndices vulkan_find_queue_families(VkPhysicalDevice device) { - QueueFamilyIndices indices; - indices.graphicsFlag = false; - indices.presentFlag = false; - - uint32_t queueFamilyCount = 0; - vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, NULL); - - VkQueueFamilyProperties queueFamilies[queueFamilyCount]; - vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies); - - for (uint32_t i = 0; i < queueFamilyCount; i++) { - if (queueFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { - indices.graphicsFamily = i; - indices.graphicsFlag = true; - } - - VkBool32 presentSupport = false; - vkGetPhysicalDeviceSurfaceSupportKHR(device, i, s.vk_surface, &presentSupport); - if (presentSupport) { - indices.presentFamily = i; - indices.presentFlag = true; - } - - if (vulkan_queue_family_check_flags(indices)) break; - } - - return indices; -} - -bool -vulkan_check_device_extension_support(VkPhysicalDevice device) -{ - uint32_t extensionCount; - vkEnumerateDeviceExtensionProperties(device, NULL, &extensionCount, NULL); - - VkExtensionProperties availableExtensions[extensionCount]; - vkEnumerateDeviceExtensionProperties(device, NULL, &extensionCount, availableExtensions); - - uint32_t flag = 0; - - for (uint32_t i = 0; i < deviceExtensionCount; i++) { - for (uint32_t j = 0; j < extensionCount; j++) { - if (strcmp(device_extensions[i], availableExtensions[j].extensionName) == 0) { - flag++; - break; - } - } - } - - return flag == deviceExtensionCount; -} - -bool -vulkan_is_device_suitable(VkPhysicalDevice device) -{ - QueueFamilyIndices indices = vulkan_find_queue_families(device); - bool extensionsSupported = vulkan_check_device_extension_support(device); - - bool swapChainAdequate = false; - if (extensionsSupported) { - SwapChainSupportDetails swapChainSupport = querySwapChainSupport(device); - swapChainAdequate = !(swapChainSupport.formatCount == 0) && !(swapChainSupport.presentModeCount == 0); - } - - - VkPhysicalDeviceFeatures supportedFeatures; - vkGetPhysicalDeviceFeatures(device, &supportedFeatures); - - return vulkan_queue_family_check_flags(indices) && extensionsSupported - && swapChainAdequate && supportedFeatures.samplerAnisotropy; -} - -void -vulkan_pick_physical_device() -{ - uint32_t deviceCount = 0; - vkEnumeratePhysicalDevices(s.vk_instance, &deviceCount, NULL); - if (deviceCount == 0) { - vk_log(VK_INFO, "failed to find GPUs with Vulkan support!\n"); - } - - VkPhysicalDevice devices[deviceCount]; - vkEnumeratePhysicalDevices(s.vk_instance, &deviceCount, devices); - - for (uint32_t i = 0; i < deviceCount; i++) { - if (vulkan_is_device_suitable(devices[i])) { - s.vk_physical_device = devices[i]; - break; - } - } - - if (s.vk_physical_device == VK_NULL_HANDLE) { - vk_log(VK_ERROR, "failed to find a suitable GPU!\n"); - } - - VkPhysicalDeviceProperties deviceProperties; - vkGetPhysicalDeviceProperties(s.vk_physical_device, &deviceProperties); - vk_log(VK_INFO, "Picked [%s] physical device.\n", deviceProperties.deviceName); - - uint32_t extensionCount = 0; - vkEnumerateInstanceExtensionProperties(NULL, &extensionCount, NULL); - VkExtensionProperties extensions[extensionCount]; - VkResult result = vkEnumerateInstanceExtensionProperties(NULL, &extensionCount, extensions); - - vk_log(VK_INFO, "Vulkan enabled extensions: %s\n", string_VkResult(result)); - for (uint32_t i = 0; i < extensionCount; i++) { - vk_log(VK_INFO, "\t%s\n", extensions[i].extensionName); - } - -} - -void -vulkan_create_logical_device() -{ - QueueFamilyIndices indices = vulkan_find_queue_families(s.vk_physical_device); - - // TODO CREATE MULPILE QUEUES - // https://vulkan-tutorial.com/en/Drawing_a_triangle/Presentation/Window_surface#page_Creating-the-presentation-queue - - VkDeviceQueueCreateInfo queueCreateInfo = { - .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, - .queueFamilyIndex = indices.graphicsFamily, - .queueCount = 1, - }; - - float queuePriority = 1.0f; - queueCreateInfo.pQueuePriorities = &queuePriority; - - VkPhysicalDeviceFeatures deviceFeatures = {0}; - vkGetPhysicalDeviceFeatures(s.vk_physical_device, &deviceFeatures); - deviceFeatures.samplerAnisotropy = VK_TRUE; -#ifndef NDEBUG - /* Disable robust buffer access when building without debug */ - deviceFeatures.robustBufferAccess = VK_FALSE; -#endif - - VkPhysicalDeviceDynamicRenderingFeaturesKHR dynamic_rendering_feature = { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR, - .dynamicRendering = VK_TRUE, - }; - - VkDeviceCreateInfo createInfo = { - .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, - .pQueueCreateInfos = &queueCreateInfo, - .queueCreateInfoCount = 1, - .pNext = &dynamic_rendering_feature, - .pEnabledFeatures = &deviceFeatures, - .enabledExtensionCount = deviceExtensionCount, - .ppEnabledExtensionNames = device_extensions, - .enabledLayerCount = 0, - }; - - if (vkCreateDevice(s.vk_physical_device, &createInfo, NULL, &s.vk_device) != VK_SUCCESS) { - vk_log(VK_ERROR, "failed to create logical device!\n"); - } - vk_log(VK_INFO, "Vulkan logical device created\n"); - - vkGetDeviceQueue(s.vk_device, indices.graphicsFamily, 0, &s.vk_graphics_queue); - vkGetDeviceQueue(s.vk_device, indices.presentFamily, 0, &s.vk_present_queue); -} - -void -update_camera(float xoffset, float yoffset) -{ - s.camera.yaw += xoffset; - s.camera.pitch += yoffset; - - // Make sure that when pitch is out of bounds, the screen doesn't get flipped - if (s.camera.pitch > 89.0f) - s.camera.pitch = 89.0f; - if (s.camera.pitch < -89.0f) - s.camera.pitch = -89.0f; - - /* vec3 front; */ - /* front[0] = -sin(glm_rad(s.camera.yaw)) * cos(glm_rad(s.camera.pitch)); */ - /* front[1] = sin(glm_rad(s.camera.pitch)); */ - /* front[2] = -cos(glm_rad(s.camera.yaw)) * cos(glm_rad(s.camera.pitch)); */ - /* glm_normalize_to(front, s.camera.front); */ -} - -void -mouseCallback(SDL_Event *event) -{ - if (event->type != SDL_MOUSEMOTION) return; - if (!s.mouse_pressed) return; - float xoffset = event->motion.xrel; - float yoffset = -event->motion.yrel; // Reversed since y-coordinates range from bottom to top - - float sensitivity = 0.1f; // Change this value to your liking - xoffset *= sensitivity; - yoffset *= sensitivity; - - update_camera(xoffset, yoffset); -} - -void -vulkan_create_surface() -{ - if (SDL_Vulkan_CreateSurface(s.sdl_window, s.vk_instance, &s.vk_surface) == SDL_FALSE) { - vk_log(VK_ERROR, "Failed to create surface\n"); - } else { - vk_log(VK_INFO, "Vulkan surface created\n"); - } -} - -void -vulkan_create_swap_chain() -{ - SwapChainSupportDetails swapChainSupport = querySwapChainSupport(s.vk_physical_device); - - VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats, swapChainSupport.formatCount); - VkPresentModeKHR presentMode = chooseSwapPresentMode(swapChainSupport.presentModes, swapChainSupport.presentModeCount); - VkExtent2D extent = chooseSwapExtent(&swapChainSupport.capabilities); - - uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1; - - if (swapChainSupport.capabilities.maxImageCount > 0 && imageCount > swapChainSupport.capabilities.maxImageCount) { - imageCount = swapChainSupport.capabilities.maxImageCount; - } - - VkSwapchainCreateInfoKHR createInfo = { - .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, - .surface = s.vk_surface, - .minImageCount = imageCount, - .imageFormat = surfaceFormat.format, - .imageColorSpace = surfaceFormat.colorSpace, - .imageExtent = extent, - .imageArrayLayers = 1, - .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - }; - - QueueFamilyIndices indices = vulkan_find_queue_families(s.vk_physical_device); - - uint32_t queueFamilyIndices[] = {indices.graphicsFamily, indices.presentFamily}; - - if (indices.graphicsFamily != indices.presentFamily) { - createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT; - createInfo.queueFamilyIndexCount = 2; - createInfo.pQueueFamilyIndices = queueFamilyIndices; - } else { - createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - createInfo.queueFamilyIndexCount = 0; // Optional - createInfo.pQueueFamilyIndices = NULL; // Optional - } - - createInfo.preTransform = swapChainSupport.capabilities.currentTransform; - createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - createInfo.presentMode = presentMode; - createInfo.clipped = VK_TRUE; - createInfo.oldSwapchain = VK_NULL_HANDLE; - - VK_CHECK(vkCreateSwapchainKHR(s.vk_device, &createInfo, NULL, &s.vk_swap_chain)); - /* if (result != VK_SUCCESS) { */ - /* vk_log(VK_ERROR, "ERROR: failed to create swap chain! %s\n", string_VkResult(result)); */ - /* } */ - - VK_CHECK(vkGetSwapchainImagesKHR(s.vk_device, s.vk_swap_chain, &s.vk_swap_chain_image_count, NULL)); - //vk_log(VK_INFO, "vk_swap_chain_images count: %d\n", s.vk_swap_chain_image_count); - // todo alloc space for images - VK_CHECK(vkGetSwapchainImagesKHR(s.vk_device, s.vk_swap_chain, &s.vk_swap_chain_image_count, s.vk_swap_chain_images)); - - s.vk_swap_chain_image_format = surfaceFormat.format; - s.vk_swap_chain_extent = extent; - - vk_log(VK_INFO, "Vulkan swapchain created!\n"); -} - - -VkImageView -create_image_view(VkImage image, VkFormat format, VkImageAspectFlags aspectFlags) -{ - VkImageViewCreateInfo viewInfo = {0}; - viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - viewInfo.image = image; - viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - viewInfo.format = format; - viewInfo.subresourceRange.aspectMask = aspectFlags; - viewInfo.subresourceRange.baseMipLevel = 0; - viewInfo.subresourceRange.levelCount = 1; - viewInfo.subresourceRange.baseArrayLayer = 0; - viewInfo.subresourceRange.layerCount = 1; - - VkImageView imageView; - VK_CHECK(vkCreateImageView(s.vk_device, &viewInfo, NULL, &imageView)); - - return imageView; -} - -void -vulkan_create_image_views() -{ - for (size_t i = 0; i < s.vk_swap_chain_image_count; i++) { - s.vk_swap_chain_image_views[i] = create_image_view(s.vk_swap_chain_images[i], s.vk_swap_chain_image_format, VK_IMAGE_ASPECT_COLOR_BIT); - } - vk_log(VK_INFO, "Vulkan image views created!\n"); -} - -VkShaderModule -createShaderModule(const char * code, long size) -{ - VkShaderModuleCreateInfo createInfo = {0}; - createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - createInfo.codeSize = size; - createInfo.pCode = (const uint32_t *)code; - - VkShaderModule shaderModule; - if (vkCreateShaderModule(s.vk_device, &createInfo, NULL, &shaderModule) != VK_SUCCESS) { - vk_log(VK_ERROR, "failed to create shader module!\n"); - } - - return shaderModule; -} - -shaderc_compilation_result_t -load_compile_shader_data(const char * path, shaderc_shader_kind shader_kind) -{ - FILE* file = fopen(path, "r"); - if (!file) { - vk_log(VK_ERROR, "SHADER COMPILATION: Failed to open file: %s\n", path); - return NULL; - } - - fseek(file, 0, SEEK_END); - long glsl_length = ftell(file); - fseek(file, 0, SEEK_SET); - - char* glsl_src = (char*)malloc(glsl_length + 1); - if (!glsl_src) { - vk_log(VK_ERROR, "SHADER COMPILATION: Failed to allocate memory\n"); - fclose(file); - return NULL; - } - - fread(glsl_src, 1, glsl_length, file); - glsl_src[glsl_length] = '\0'; - fclose(file); - - shaderc_compiler_t compiler = shaderc_compiler_initialize(); - if (!compiler) { - vk_log(VK_ERROR, "SHADER COMPILATION: Failed to initialize shader compiler\n"); - free(glsl_src); - return NULL; - } - - shaderc_compile_options_t options = shaderc_compile_options_initialize(); - shaderc_compilation_result_t result = shaderc_compile_into_spv(compiler, - glsl_src, - glsl_length, - shader_kind, - path, "main", options); - - if (shaderc_result_get_compilation_status(result) != shaderc_compilation_status_success) { - vk_log(VK_ERROR, "SHADER COMPILATION: error: %s\n", shaderc_result_get_error_message(result)); - shaderc_result_release(result); - shaderc_compiler_release(compiler); - free(glsl_src); - return NULL; - } - - shaderc_compiler_release(compiler); - free(glsl_src); - - return result; -} - -uint32_t -findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) -{ - VkPhysicalDeviceMemoryProperties memProperties; - vkGetPhysicalDeviceMemoryProperties(s.vk_physical_device, &memProperties); - - for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) { - if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) { - return i; - } - } - - vk_log(VK_ERROR, "failed to find suitable memory type!\n"); - return 9999; -} - -void -createImage(uint32_t width, uint32_t height, VkFormat format, - VkImageTiling tiling, VkImageUsageFlags usage, - VkMemoryPropertyFlags properties, VkImage *image, - VkDeviceMemory *imageMemory) -{ - VkImageCreateInfo imageInfo = {0}; - imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - imageInfo.imageType = VK_IMAGE_TYPE_2D; - imageInfo.extent.width = width; - imageInfo.extent.height = height; - imageInfo.extent.depth = 1; - imageInfo.mipLevels = 1; - imageInfo.arrayLayers = 1; - imageInfo.format = format; - imageInfo.tiling = tiling; - imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imageInfo.usage = usage; - imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - - VK_CHECK(vkCreateImage(s.vk_device, &imageInfo, NULL, image)); - - VkMemoryRequirements memRequirements; - vkGetImageMemoryRequirements(s.vk_device, *image, &memRequirements); - - VkMemoryAllocateInfo allocInfo = {0}; - allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - allocInfo.allocationSize = memRequirements.size; - allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties); - - VK_CHECK(vkAllocateMemory(s.vk_device, &allocInfo, NULL, imageMemory)); - - vkBindImageMemory(s.vk_device, *image, *imageMemory , 0); -} - -VkCommandBuffer -beginSingleTimeCommands() -{ - VkCommandBufferAllocateInfo allocInfo = {0}; - allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - allocInfo.commandPool = s.vk_command_pool; - allocInfo.commandBufferCount = 1; - - VkCommandBuffer commandBuffer; - VK_CHECK(vkAllocateCommandBuffers(s.vk_device, &allocInfo, &commandBuffer)); - - VkCommandBufferBeginInfo beginInfo = {0}; - beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - - VK_CHECK(vkBeginCommandBuffer(commandBuffer, &beginInfo)); - - return commandBuffer; -} - -void -endSingleTimeCommands(VkCommandBuffer commandBuffer) -{ - VK_CHECK(vkEndCommandBuffer(commandBuffer)); - - VkSubmitInfo submitInfo = {0}; - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &commandBuffer; - - VK_CHECK(vkQueueSubmit(s.vk_graphics_queue, 1, &submitInfo, VK_NULL_HANDLE)); - VK_CHECK(vkQueueWaitIdle(s.vk_graphics_queue)); - - vkFreeCommandBuffers(s.vk_device, s.vk_command_pool, 1, &commandBuffer); -} - -int -hasStencilComponent(VkFormat format) -{ - return format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT; -} - -void -transitionImageLayout(VkImage image, VkFormat format, - VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, - VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, - VkImageLayout oldLayout, VkImageLayout newLayout) -{ - VkCommandBuffer commandBuffer = beginSingleTimeCommands(); - - VkImageMemoryBarrier barrier = {0}; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.srcAccessMask = srcAccessMask; - barrier.dstAccessMask = dstAccessMask; - barrier.oldLayout = oldLayout; - barrier.newLayout = newLayout; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.image = image; - - // barrier.subresourceRange.aspectMask = - if (newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { - barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - - if (hasStencilComponent(format)) { - barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; - } - } else { - barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - } - - barrier.subresourceRange.baseMipLevel = 0; - barrier.subresourceRange.levelCount = 1; - barrier.subresourceRange.baseArrayLayer = 0; - barrier.subresourceRange.layerCount = 1; - - vkCmdPipelineBarrier(commandBuffer, - srcStageMask, dstStageMask, - 0, - 0, NULL, - 0, NULL, - 1, &barrier); - endSingleTimeCommands(commandBuffer); -} - -VkFormat -findSupportedFormat(VkFormat *candidates, size_t n, - VkImageTiling tiling, - VkFormatFeatureFlags features) -{ - for (size_t i = 0; i < n; i++) { - VkFormat format = candidates[i]; - VkFormatProperties props; - vkGetPhysicalDeviceFormatProperties(s.vk_physical_device, format, &props); - - if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features) { - return format; - } else if (tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures & features) == features) { - return format; - } - } - - vk_log(VK_ERROR, "failed to find supported format!\n"); - abort(); -} - -VkFormat -findDepthFormat() -{ - VkFormat formats[] = { VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT}; - return findSupportedFormat(formats, VK_ARRAY_LEN(formats), - VK_IMAGE_TILING_OPTIMAL, - VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT); -} - -void -vulkan_create_depth_resources() -{ - VkFormat depthFormat = findDepthFormat(); - createImage(s.vk_swap_chain_extent.width, s.vk_swap_chain_extent.height, - depthFormat, VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - &s.vk_depth_image, &s.vk_depth_image_memory); - s.vk_depth_image_view = create_image_view(s.vk_depth_image, depthFormat, - VK_IMAGE_ASPECT_DEPTH_BIT); - - transitionImageLayout(s.vk_depth_image, depthFormat, - VK_ACCESS_NONE, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); -} - -void -vulkan_create_graphics_pipeline() -{ - shaderc_compilation_result_t vert_result = load_compile_shader_data("src/shader.vert", shaderc_vertex_shader); - if (!vert_result) { - vk_log(VK_ERROR, "Can't load vertex shader\n"); - if (s.prev_vert_result) { - vert_result = s.prev_vert_result; - } - } - if (s.prev_vert_result && vert_result != s.prev_vert_result) shaderc_result_release(s.prev_vert_result); - s.prev_vert_result = vert_result; - shaderc_compilation_result_t frag_result = load_compile_shader_data("src/shader.frag", shaderc_fragment_shader); - if (!frag_result) { - vk_log(VK_ERROR, "Can't load fragment shader\n"); - if (s.prev_frag_result) { - frag_result = s.prev_frag_result; - } - } - if (s.prev_frag_result && frag_result != s.prev_frag_result) shaderc_result_release(s.prev_frag_result); - s.prev_frag_result = frag_result; - - const char * vert_data = shaderc_result_get_bytes(vert_result); - long vert_size = shaderc_result_get_length(vert_result); - const char * frag_data = shaderc_result_get_bytes(frag_result); - long frag_size = shaderc_result_get_length(frag_result); - - vk_log(VK_INFO, "Shaders loaded\n"); - - VkShaderModule vertShaderModule = createShaderModule(vert_data, vert_size); - VkShaderModule fragShaderModule = createShaderModule(frag_data, frag_size); - - VkPipelineShaderStageCreateInfo vertShaderStageInfo = {0}; - vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; - vertShaderStageInfo.module = vertShaderModule; - vertShaderStageInfo.pName = "main"; - - VkPipelineShaderStageCreateInfo fragShaderStageInfo = {0}; - fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; - fragShaderStageInfo.module = fragShaderModule; - fragShaderStageInfo.pName = "main"; - - VkPipelineShaderStageCreateInfo shaderStages[] = {vertShaderStageInfo, fragShaderStageInfo}; - - VkDynamicState dynamicStates[] = { - VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_SCISSOR, - VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE, - VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE - }; - - VkPipelineDynamicStateCreateInfo dynamicState = {0}; - dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - dynamicState.dynamicStateCount = VK_ARRAY_LEN(dynamicStates); - dynamicState.pDynamicStates = dynamicStates; - - VkVertexInputBindingDescription bindingDescription = {0}; - bindingDescription.binding = 0; - bindingDescription.stride = sizeof(Vertex); - bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - - VkVertexInputAttributeDescription attributeDescriptions[3] = {0}; - attributeDescriptions[0].binding = 0; - attributeDescriptions[0].location = 0; - attributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT; - attributeDescriptions[0].offset = offsetof(Vertex, pos); - - attributeDescriptions[1].binding = 0; - attributeDescriptions[1].location = 1; - attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT; - attributeDescriptions[1].offset = offsetof(Vertex, color); - - attributeDescriptions[2].binding = 0; - attributeDescriptions[2].location = 2; - attributeDescriptions[2].format = VK_FORMAT_R32G32_SFLOAT; - attributeDescriptions[2].offset = offsetof(Vertex, texCoord); - - VkPipelineVertexInputStateCreateInfo vertexInputInfo = {0}; - vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vertexInputInfo.vertexBindingDescriptionCount = 1; - vertexInputInfo.pVertexBindingDescriptions = &bindingDescription; - vertexInputInfo.vertexAttributeDescriptionCount = VK_ARRAY_LEN(attributeDescriptions); - vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions; - - VkPipelineInputAssemblyStateCreateInfo inputAssembly = {}; - inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - inputAssembly.primitiveRestartEnable = VK_FALSE; - - VkViewport viewport = {0}; - viewport.x = 0.0f; - viewport.y = 0.0f; - viewport.width = (float) s.vk_swap_chain_extent.width; - viewport.height = (float) s.vk_swap_chain_extent.height; - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - - VkRect2D scissor = {0}; - scissor.offset = (VkOffset2D){0, 0}; - scissor.extent = s.vk_swap_chain_extent; - - VkPipelineViewportStateCreateInfo viewportState = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, - .viewportCount = 1, - .pViewports = &viewport, - .scissorCount = 1, - .pScissors = &scissor, - }; - - VkPipelineRasterizationStateCreateInfo rasterizer = {0}; - rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rasterizer.depthClampEnable = VK_FALSE; - rasterizer.rasterizerDiscardEnable = VK_FALSE; - rasterizer.polygonMode = VK_POLYGON_MODE_FILL; - rasterizer.lineWidth = 1.0f; - rasterizer.cullMode = VK_CULL_MODE_NONE; - //rasterizer.cullMode = VK_CULL_MODE_BACK_BIT; - //rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; - rasterizer.depthBiasEnable = VK_FALSE; - rasterizer.depthBiasConstantFactor = 0.0f; // Optional - rasterizer.depthBiasClamp = 0.0f; // Optional - rasterizer.depthBiasSlopeFactor = 0.0f; // Optional - - VkPipelineMultisampleStateCreateInfo multisampling = {0}; - multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - multisampling.sampleShadingEnable = VK_FALSE; - multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - multisampling.minSampleShading = 1.0f; // Optional - multisampling.pSampleMask = NULL; // Optional - multisampling.alphaToCoverageEnable = VK_FALSE; // Optional - multisampling.alphaToOneEnable = VK_FALSE; // Optional - - VkPipelineColorBlendAttachmentState colorBlendAttachment = {0}; - colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; - colorBlendAttachment.blendEnable = VK_TRUE; - colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; - colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; - colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; - colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; - /* colorBlendAttachment.blendEnable = VK_FALSE; */ - /* colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; // Optional */ - /* colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; // Optional */ - /* colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; // Optional */ - /* colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; // Optional */ - /* colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; // Optional */ - /* colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; // Optional */ - - VkPipelineColorBlendStateCreateInfo colorBlending = {0}; - colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - colorBlending.logicOpEnable = VK_TRUE; - colorBlending.logicOp = VK_LOGIC_OP_COPY; // Optional - colorBlending.attachmentCount = 1; - colorBlending.pAttachments = &colorBlendAttachment; - colorBlending.blendConstants[0] = 0.0f; // Optional - colorBlending.blendConstants[1] = 0.0f; // Optional - colorBlending.blendConstants[2] = 0.0f; // Optional - colorBlending.blendConstants[3] = 0.0f; // Optional - - VkPipelineLayoutCreateInfo pipelineLayoutInfo = {0}; - pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipelineLayoutInfo.setLayoutCount = 1; - pipelineLayoutInfo.pSetLayouts = &s.vk_descriptor_set_layout; - pipelineLayoutInfo.pushConstantRangeCount = 0; // Optional - pipelineLayoutInfo.pPushConstantRanges = NULL; // Optional - - if (vkCreatePipelineLayout(s.vk_device, &pipelineLayoutInfo, NULL, &s.vk_pipeline_layout) != VK_SUCCESS) { - vk_log(VK_ERROR, "failed to create pipeline layout!\n"); - } - - VkPipelineDepthStencilStateCreateInfo depthStencil = {0}; - depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - depthStencil.depthTestEnable = VK_TRUE; - depthStencil.depthWriteEnable = VK_TRUE; - depthStencil.depthBoundsTestEnable = VK_FALSE; - depthStencil.stencilTestEnable = VK_FALSE; - depthStencil.depthCompareOp = VK_COMPARE_OP_LESS; - depthStencil.minDepthBounds = 0.0f; // Optional - depthStencil.maxDepthBounds = 1.0f; // Optional - depthStencil.front = (VkStencilOpState){0}; // Optional - depthStencil.back = (VkStencilOpState){0}; // Optional - - // TODO depthAttachment - VkPipelineRenderingCreateInfo pipeline_rendering_create_info = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR, - .colorAttachmentCount = 1, - .pColorAttachmentFormats = &s.vk_swap_chain_image_format, - .depthAttachmentFormat = findDepthFormat(), - }; - VkGraphicsPipelineCreateInfo pipelineInfo = {0}; - pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipelineInfo.stageCount = 2; - pipelineInfo.pStages = shaderStages; - - pipelineInfo.pNext = &pipeline_rendering_create_info, - pipelineInfo.pVertexInputState = &vertexInputInfo; - pipelineInfo.pInputAssemblyState = &inputAssembly; - pipelineInfo.pViewportState = &viewportState; - pipelineInfo.pRasterizationState = &rasterizer; - pipelineInfo.pMultisampleState = &multisampling; - pipelineInfo.pDepthStencilState = &depthStencil; - pipelineInfo.pColorBlendState = &colorBlending; - pipelineInfo.pDynamicState = &dynamicState; - pipelineInfo.layout = s.vk_pipeline_layout; - pipelineInfo.renderPass = VK_NULL_HANDLE; - pipelineInfo.subpass = 0; - pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; // Optional - pipelineInfo.basePipelineIndex = -1; // Optional - - if (vkCreateGraphicsPipelines(s.vk_device, VK_NULL_HANDLE, 1, &pipelineInfo, NULL, &s.vk_graphics_pipeline) != VK_SUCCESS) { - vk_log(VK_ERROR, "failed to create graphics pipeline!\n"); - } - - if (s.prev_vert_result != vert_result) { - shaderc_result_release(vert_result); - } - if (s.prev_frag_result != frag_result) { - shaderc_result_release(frag_result); - } - - vkDestroyShaderModule(s.vk_device, fragShaderModule, NULL); - vkDestroyShaderModule(s.vk_device, vertShaderModule, NULL); -} - -void -vulkan_create_command_pool() -{ - QueueFamilyIndices queueFamilyIndices = vulkan_find_queue_families(s.vk_physical_device); - - VkCommandPoolCreateInfo poolInfo = {0}; - poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily; - - VK_CHECK(vkCreateCommandPool(s.vk_device, &poolInfo, NULL, &s.vk_command_pool)); -} - -void -vulkan_create_command_buffer() -{ - // TODO Find a way to group allocation - for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - VkCommandBufferAllocateInfo allocInfo = {0}; - allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - allocInfo.commandPool = s.vk_command_pool; - allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - allocInfo.commandBufferCount = 1; - - VK_CHECK(vkAllocateCommandBuffers(s.vk_device, &allocInfo, &s.frames[i].vk_command_buffer)); - } -} - -void -recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) -{ - VkCommandBufferBeginInfo beginInfo = {0}; - beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - beginInfo.flags = 0; // Optional - beginInfo.pInheritanceInfo = NULL; // Optional - - VK_CHECK(vkBeginCommandBuffer(commandBuffer, &beginInfo)); - vkCmdSetDepthTestEnable(commandBuffer, 1); - vkCmdSetDepthWriteEnable(commandBuffer, 1); - - transitionImageLayout( - s.vk_swap_chain_images[imageIndex], VK_FORMAT_R8G8B8A8_SRGB, 0, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - - VkRenderingAttachmentInfo colorAttachment = {0}; - colorAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; - colorAttachment.imageView = s.vk_swap_chain_image_views[imageIndex]; - colorAttachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - colorAttachment.clearValue.color = - (VkClearColorValue){0.0f, 0.0f, 0.0f, 1.0f}; - - VkRenderingAttachmentInfo depthAttachment = {0}; - depthAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; - depthAttachment.imageView = s.vk_depth_image_view; - depthAttachment.imageLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL; - depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - depthAttachment.clearValue.depthStencil = (VkClearDepthStencilValue){1.0f, 0u}; - - VkRenderingInfo renderingInfo = {}; - renderingInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO; - renderingInfo.renderArea = - (VkRect2D){{0, 0}, s.vk_swap_chain_extent}; - renderingInfo.layerCount = 1; - renderingInfo.colorAttachmentCount = 1; - renderingInfo.pColorAttachments = &colorAttachment; - renderingInfo.pDepthAttachment = &depthAttachment; - - vkCmdBeginRendering(commandBuffer, &renderingInfo); - - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - s.vk_graphics_pipeline); - - VkViewport viewport = {0}; - viewport.x = 0.0f; - viewport.y = 0.0f; - viewport.width = (float)(s.vk_swap_chain_extent.width); - viewport.height = (float)(s.vk_swap_chain_extent.height); - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - vkCmdSetViewport(commandBuffer, 0, 1, &viewport); - - VkRect2D scissor = {0}; - scissor.offset = (VkOffset2D){0, 0}; - scissor.extent = s.vk_swap_chain_extent; - vkCmdSetScissor(commandBuffer, 0, 1, &scissor); - - VkBuffer vertexBuffers[] = {s.vk_vertex_buffer}; - VkDeviceSize offsets[] = {0}; - vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets); - vkCmdBindIndexBuffer(commandBuffer, s.vk_index_buffer, 0, - VK_INDEX_TYPE_UINT16); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - s.vk_pipeline_layout, 0, 1, - &s.frames[currentFrame].vk_descriptor_set, 0, NULL); - - - vkCmdDrawIndexed(commandBuffer, INDICES_SIZE, 1, 0, 0, 0); - vkCmdEndRendering(commandBuffer); - - transitionImageLayout(s.vk_swap_chain_images[imageIndex], - VK_FORMAT_R8G8B8A8_SRGB, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 0, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); - - VK_CHECK(vkEndCommandBuffer(commandBuffer)); -} - -void -vulkan_create_sync_objects() -{ - VkSemaphoreCreateInfo semaphoreInfo = {0}; - semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - - VkFenceCreateInfo fenceInfo = {0}; - fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; - - for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - VK_CHECK(vkCreateSemaphore(s.vk_device, &semaphoreInfo, NULL, &s.frames[i].image_available_semaphore)); - VK_CHECK(vkCreateSemaphore(s.vk_device, &semaphoreInfo, NULL, &s.frames[i].render_finished_semaphore)); - VK_CHECK(vkCreateFence(s.vk_device, &fenceInfo, NULL, &s.frames[i].in_flight_fence)); - } -} - -void -createBuffer(VkDeviceSize size, - VkBufferUsageFlags usage, - VkMemoryPropertyFlags properties, - VkBuffer *buffer, VkDeviceMemory *bufferMemory) -{ - VkBufferCreateInfo bufferInfo = {0}; - bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bufferInfo.size = size; - bufferInfo.usage = usage; - bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - - VK_CHECK(vkCreateBuffer(s.vk_device, &bufferInfo, NULL, buffer)); - - VkMemoryRequirements memRequirements; - vkGetBufferMemoryRequirements(s.vk_device, *buffer, &memRequirements); - - VkMemoryAllocateInfo allocInfo = {0}; - allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - allocInfo.allocationSize = memRequirements.size; - allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties); - - // TODO: group allocations etc... (allocations limited by hardware) - VK_CHECK(vkAllocateMemory(s.vk_device, &allocInfo, NULL, bufferMemory)); - - VK_CHECK(vkBindBufferMemory(s.vk_device, *buffer, *bufferMemory, 0)); -} - -void copy_buffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) { - VkCommandBuffer commandBuffer = beginSingleTimeCommands(); - VkBufferCopy copyRegion = {0}; - copyRegion.srcOffset = 0; // Optional - copyRegion.dstOffset = 0; // Optional - copyRegion.size = size; - vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, ©Region); - endSingleTimeCommands(commandBuffer); -} - -void -vulkan_create_vertex_buffer() -{ - VkDeviceSize bufferSize = sizeof(vertices[0]) * VERTICES_SIZE; - - VkBuffer stagingBuffer; - VkDeviceMemory stagingBufferMemory; - - createBuffer(bufferSize, - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &stagingBuffer, &stagingBufferMemory); - - void* data; - VK_CHECK(vkMapMemory(s.vk_device, stagingBufferMemory, 0, bufferSize, 0, &data)); - memcpy(data, vertices, (size_t) bufferSize); - vkUnmapMemory(s.vk_device, stagingBufferMemory); - - createBuffer(bufferSize, - VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - &s.vk_vertex_buffer, &s.vk_vertex_buffer_memory); - - copy_buffer(stagingBuffer, s.vk_vertex_buffer, bufferSize); - - vkDestroyBuffer(s.vk_device, stagingBuffer, NULL); - vkFreeMemory(s.vk_device, stagingBufferMemory, NULL); -} - -void -vulkan_create_index_buffer() -{ - VkDeviceSize bufferSize = sizeof(indices[0]) * INDICES_SIZE; - - VkBuffer stagingBuffer; - VkDeviceMemory stagingBufferMemory; - - createBuffer(bufferSize, - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &stagingBuffer, &stagingBufferMemory); - - void* data; - VK_CHECK(vkMapMemory(s.vk_device, stagingBufferMemory, 0, bufferSize, 0, &data)); - memcpy(data, indices, (size_t) bufferSize); - vkUnmapMemory(s.vk_device, stagingBufferMemory); - - createBuffer(bufferSize, - VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - &s.vk_index_buffer, &s.vk_index_buffer_memory); - - copy_buffer(stagingBuffer, s.vk_index_buffer, bufferSize); - - vkDestroyBuffer(s.vk_device, stagingBuffer, NULL); - vkFreeMemory(s.vk_device, stagingBufferMemory, NULL); -} - -void -vulkan_create_descriptor_set_layout() -{ - VkDescriptorSetLayoutBinding uboLayoutBinding = {0}; - uboLayoutBinding.binding = 0; - uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - uboLayoutBinding.descriptorCount = 1; - uboLayoutBinding.stageFlags = VK_SHADER_STAGE_ALL; - //uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; - uboLayoutBinding.pImmutableSamplers = NULL; // optional - - VkDescriptorSetLayoutBinding samplerLayoutBinding = {0}; - samplerLayoutBinding.binding = 1; - samplerLayoutBinding.descriptorCount = 1; - samplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - samplerLayoutBinding.pImmutableSamplers = NULL; - samplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - - VkDescriptorSetLayoutBinding bindings[2] = {uboLayoutBinding, samplerLayoutBinding}; - - VkDescriptorSetLayoutCreateInfo layoutInfo = {0}; - layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - layoutInfo.bindingCount = VK_ARRAY_LEN(bindings); - layoutInfo.pBindings = bindings; - - VK_CHECK(vkCreateDescriptorSetLayout(s.vk_device, &layoutInfo, NULL, &s.vk_descriptor_set_layout)); -} - -void -vulkan_create_uniform_buffers() -{ - VkDeviceSize bufferSize = sizeof(UniformBufferObject); - - for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - createBuffer(bufferSize, - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &s.frames[i].vk_uniform_buffer, &s.frames[i].vk_uniform_buffer_memory); - - VK_CHECK(vkMapMemory(s.vk_device, s.frames[i].vk_uniform_buffer_memory, 0, bufferSize, 0, &s.frames[i].vk_uniform_buffer_mapped)); - } -} - -void -vulkan_create_descriptor_pool() -{ - VkDescriptorPoolSize poolSizes[2] = {0}; - poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - poolSizes[0].descriptorCount = MAX_FRAMES_IN_FLIGHT; - poolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - poolSizes[1].descriptorCount = MAX_FRAMES_IN_FLIGHT; - - VkDescriptorPoolCreateInfo poolInfo = {0}; - poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - poolInfo.poolSizeCount = VK_ARRAY_LEN(poolSizes); - poolInfo.pPoolSizes = poolSizes; - poolInfo.maxSets = MAX_FRAMES_IN_FLIGHT; - - VK_CHECK(vkCreateDescriptorPool(s.vk_device, &poolInfo, NULL, &s.vk_descriptor_pool)); -} - -void -vulkan_create_descriptor_sets() -{ - VkDescriptorSetLayout layouts[MAX_FRAMES_IN_FLIGHT] = {0}; - - for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - layouts[i] = s.vk_descriptor_set_layout; - } - - // TODO Find a way to group allocation - for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - VkDescriptorSetAllocateInfo allocInfo = {0}; - allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - allocInfo.descriptorPool = s.vk_descriptor_pool; - allocInfo.descriptorSetCount = 1; - allocInfo.pSetLayouts = layouts; - - VK_CHECK(vkAllocateDescriptorSets(s.vk_device, &allocInfo, &s.frames[i].vk_descriptor_set)); - } - - for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - VkDescriptorBufferInfo bufferInfo = {0}; - bufferInfo.buffer = s.frames[i].vk_uniform_buffer; - bufferInfo.offset = 0; - bufferInfo.range = sizeof(UniformBufferObject); - - VkDescriptorImageInfo imageInfo = {0}; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - imageInfo.imageView = s.vk_texture_image_view; - imageInfo.sampler = s.vk_texture_sampler; - - VkWriteDescriptorSet descriptorWrites[2] = {0}; - descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrites[0].dstSet = s.frames[i].vk_descriptor_set; - descriptorWrites[0].dstBinding = 0; - descriptorWrites[0].dstArrayElement = 0; - descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptorWrites[0].descriptorCount = 1; - descriptorWrites[0].pBufferInfo = &bufferInfo; - - descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrites[1].dstSet = s.frames[i].vk_descriptor_set; - descriptorWrites[1].dstBinding = 1; - descriptorWrites[1].dstArrayElement = 0; - descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptorWrites[1].descriptorCount = 1; - descriptorWrites[1].pImageInfo = &imageInfo; - - vkUpdateDescriptorSets(s.vk_device, VK_ARRAY_LEN(descriptorWrites), descriptorWrites, 0, NULL); - } -} - -void -cleanupSwapChain() -{ - vkDestroyImageView(s.vk_device, s.vk_depth_image_view, NULL); - vkDestroyImage(s.vk_device, s.vk_depth_image, NULL); - vkFreeMemory(s.vk_device, s.vk_depth_image_memory, NULL); - - for (uint32_t i = 0; i < s.vk_swap_chain_image_count; i++) { - vkDestroyImageView(s.vk_device, s.vk_swap_chain_image_views[i], NULL); - } - vkDestroySwapchainKHR(s.vk_device, s.vk_swap_chain, NULL); -} - -void -recreateSwapChain() -{ - vkDeviceWaitIdle(s.vk_device); - - cleanupSwapChain(); - - vulkan_create_swap_chain(); - vulkan_create_image_views(); - vulkan_create_depth_resources(); -} - -void -handle_input(bool * quit) -{ - SDL_Event e; - - while (SDL_PollEvent(&e) != 0) { - // User requests quit - if (e.type == SDL_QUIT) { - *quit = true; - } - // User presses a key - else if (e.type == SDL_KEYDOWN) { - switch (e.key.keysym.sym) { - case SDLK_w: - s.camera.pos[0] += 0.1f; - break; - case SDLK_s: - s.camera.pos[0] -= 0.1f; - break; - case SDLK_LEFT: - break; - case SDLK_g: // reload shaders - recreateSwapChain(); - vkDestroyPipeline(s.vk_device, s.vk_graphics_pipeline, NULL); - vkDestroyPipelineLayout(s.vk_device, s.vk_pipeline_layout, NULL); - vulkan_create_graphics_pipeline(); - break; - case SDLK_l: - s.rotate = s.rotate ? 0 : 1; - break; - case SDLK_r: - s.camera.pos[0] = 1.0f; - s.camera.pos[1] = 1.0f; - s.camera.pos[2] = 1.0f; - - s.camera.front[0] = 0.0f; - s.camera.front[1] = 0.0f; - s.camera.front[2] = 0.0f; - - s.camera.up[0] = 0.0f; - s.camera.up[1] = 0.0f; - s.camera.up[2] = 1.0f; - - s.camera.yaw = 0.0f; - s.camera.pitch = 90.0f; - s.camera.lastX = 400.0f; - s.camera.lastY = 300.0f; - s.camera.fov = 45.0f; - update_camera(0,0); - break; - } - } - else if (e.type == SDL_MOUSEWHEEL) { - if(e.wheel.y > 0) // scroll up - { - s.zoom += 1; - } - else if(e.wheel.y < 0) // scroll down - { - s.zoom -= 1; - if (s.zoom == -100) s.zoom = 1; - } - } - else if (e.type == SDL_MOUSEBUTTONDOWN) { - s.mouse_pressed = 1; - } - else if (e.type == SDL_MOUSEBUTTONUP) { - s.mouse_pressed = 0; - } - mouseCallback(&e); - } -} - -void -copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, - uint32_t height) -{ - VkCommandBuffer commandBuffer = beginSingleTimeCommands(); - - VkBufferImageCopy region = {0}; - region.bufferOffset = 0; - region.bufferRowLength = 0; - region.bufferImageHeight = 0; - - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.imageSubresource.mipLevel = 0; - region.imageSubresource.baseArrayLayer = 0; - region.imageSubresource.layerCount = 1; - - region.imageOffset = (VkOffset3D){0, 0, 0}; - region.imageExtent = (VkExtent3D){width, height, 1}; - - vkCmdCopyBufferToImage(commandBuffer, - buffer, - image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, - ®ion - ); - - endSingleTimeCommands(commandBuffer); -} - -void -vulkan_create_texture_image() -{ - int texWidth, texHeight, texChannels; - stbi_uc* pixels = stbi_load("assets/texture.jpg", &texWidth, &texHeight, &texChannels, STBI_rgb_alpha); - VkDeviceSize imageSize = texWidth * texHeight * 4; - - if (!pixels) { - vk_log(VK_ERROR, "failed to load texture image!\n"); - } - - VkBuffer stagingBuffer; - VkDeviceMemory stagingBufferMemory; - - createBuffer(imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingBuffer, &stagingBufferMemory); - void* data; - vkMapMemory(s.vk_device, stagingBufferMemory, 0, imageSize, 0, &data); - memcpy(data, pixels, (size_t)imageSize); - vkUnmapMemory(s.vk_device, stagingBufferMemory); - - stbi_image_free(pixels); - - createImage(texWidth, texHeight, VK_FORMAT_R8G8B8A8_SRGB, - VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &s.vk_texture_image, - &s.vk_texture_image_memory); - - transitionImageLayout( - s.vk_texture_image, VK_FORMAT_R8G8B8A8_SRGB, 0, - VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - copyBufferToImage(stagingBuffer, s.vk_texture_image, (uint32_t)texWidth, - (uint32_t)texHeight); - transitionImageLayout( - s.vk_texture_image, VK_FORMAT_R8G8B8A8_SRGB, - VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - vkDestroyBuffer(s.vk_device, stagingBuffer, NULL); - vkFreeMemory(s.vk_device, stagingBufferMemory, NULL); -} - -void -vulkan_create_texture_image_view() -{ - s.vk_texture_image_view = create_image_view(s.vk_texture_image, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT); -} - -void vulkan_create_texture_sampler() { - VkSamplerCreateInfo samplerInfo = {0}; - samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; - samplerInfo.magFilter = VK_FILTER_LINEAR; - samplerInfo.minFilter = VK_FILTER_LINEAR; - samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; - samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; - samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; - samplerInfo.anisotropyEnable = VK_TRUE; - - VkPhysicalDeviceProperties properties = {0}; - vkGetPhysicalDeviceProperties(s.vk_physical_device, &properties); - - samplerInfo.maxAnisotropy = properties.limits.maxSamplerAnisotropy; - samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; - samplerInfo.unnormalizedCoordinates = VK_FALSE; - samplerInfo.compareEnable = VK_FALSE; - samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; - samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - samplerInfo.mipLodBias = 0.0f; - samplerInfo.minLod = 0.0f; - samplerInfo.maxLod = 0.0f; - - VK_CHECK(vkCreateSampler(s.vk_device, &samplerInfo, NULL, &s.vk_texture_sampler)); -} - -void -init_vulkan() -{ - vk_log(VK_WARN, "====================================\n"); - vk_log(VK_WARN, " DEBUG ON \n"); - vk_log(VK_WARN, "====================================\n"); - - vulkan_create_instance(); - // vulkan_setup_debug_messenger(); - vulkan_create_surface(); - vulkan_pick_physical_device(); - vulkan_create_logical_device(); - vulkan_create_swap_chain(); - vulkan_create_image_views(); - vulkan_create_descriptor_set_layout(); - vulkan_create_graphics_pipeline(); - vulkan_create_command_pool(); - vulkan_create_depth_resources(); - vulkan_create_texture_image(); - vulkan_create_texture_image_view(); - vulkan_create_texture_sampler(); - vulkan_create_vertex_buffer(); - vulkan_create_index_buffer(); - vulkan_create_uniform_buffers(); - vulkan_create_descriptor_pool(); - vulkan_create_descriptor_sets(); - vulkan_create_command_buffer(); - vulkan_create_sync_objects(); -} - -void -close_vulkan() -{ - vkDeviceWaitIdle(s.vk_device); - // Cleanup - for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - vkDestroySemaphore(s.vk_device, s.frames[i].image_available_semaphore, NULL); - vkDestroySemaphore(s.vk_device, s.frames[i].render_finished_semaphore, NULL); - vkDestroyFence(s.vk_device, s.frames[i].in_flight_fence, NULL); - } - - vkDestroyCommandPool(s.vk_device, s.vk_command_pool, NULL); - - cleanupSwapChain(); - - vkDestroySampler(s.vk_device, s.vk_texture_sampler, NULL); - vkDestroyImageView(s.vk_device, s.vk_texture_image_view, NULL); - - vkDestroyImage(s.vk_device, s.vk_texture_image, NULL); - vkFreeMemory(s.vk_device, s.vk_texture_image_memory, NULL); - - for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - vkDestroyBuffer(s.vk_device, s.frames[i].vk_uniform_buffer, NULL); - vkFreeMemory(s.vk_device, s.frames[i].vk_uniform_buffer_memory, NULL); - } - vkDestroyDescriptorPool(s.vk_device, s.vk_descriptor_pool, NULL); - vkDestroyDescriptorSetLayout(s.vk_device, s.vk_descriptor_set_layout, NULL); - - vkDestroyBuffer(s.vk_device, s.vk_vertex_buffer, NULL); - vkFreeMemory(s.vk_device, s.vk_vertex_buffer_memory, NULL); - - vkDestroyBuffer(s.vk_device, s.vk_index_buffer, NULL); - vkFreeMemory(s.vk_device, s.vk_index_buffer_memory, NULL); - - vkDestroyPipeline(s.vk_device, s.vk_graphics_pipeline, NULL); - vkDestroyPipelineLayout(s.vk_device, s.vk_pipeline_layout, NULL); - vkDestroyDevice(s.vk_device, NULL); - vkDestroySurfaceKHR(s.vk_instance, s.vk_surface, NULL); - /* if (enableValidationLayers) { */ - /* DestroyDebugUtilsMessengerEXT(s.vk_instance, s.vk_debug_messenger, NULL); */ - /* } */ - vkDestroyInstance(s.vk_instance, NULL); - - if (s.prev_vert_result) { - shaderc_result_release(s.prev_vert_result); - } - if (s.prev_frag_result) { - shaderc_result_release(s.prev_frag_result); - } -} - -float -current_time() -{ - static struct timespec startTime; - static int isStartTimeInitialized = 0; - - if (!isStartTimeInitialized) { - clock_gettime(CLOCK_MONOTONIC, &startTime); - isStartTimeInitialized = 1; - } - - struct timespec currentTime; - clock_gettime(CLOCK_MONOTONIC, ¤tTime); - - return (currentTime.tv_sec - startTime.tv_sec) + - (currentTime.tv_nsec - startTime.tv_nsec) / 1e9f; -} - -void -updateUniformBuffer(uint32_t currentImage) -{ - float time = current_time(); - - UniformBufferObject ubo = {0}; - - ubo.resolution[0] = s.vk_swap_chain_extent.width; - ubo.resolution[1] = s.vk_swap_chain_extent.height; - - glm_mat4_identity(ubo.model); - - if (s.rotate) - glm_rotate(ubo.model, glm_rad(50 * time * glm_rad(90.0f)), GLM_ZUP); - - vec3 eye = GLM_VEC3_ONE_INIT; - vec3 center = GLM_VEC3_ZERO_INIT; - -// vk_log(VK_INFO, "{%.2f, %.2f, %.2f}\n", s.camera.front[0], s.camera.front[1], s.camera.front[2]); - /* glm_vec3_add(s.camera.pos, s.camera.front, center); */ - glm_lookat(s.camera.pos, s.camera.front, s.camera.up, ubo.view); - - /* glm_lookat(eye, center, GLM_ZUP, ubo.view); */ - - float aspect = s.vk_swap_chain_extent.width / (float)s.vk_swap_chain_extent.height; - glm_perspective(glm_rad(45.0f ), aspect, 1.0f, 10.0f, ubo.proj); - - // Inverting the Y axis for Vulkan - ubo.proj[1][1] *= -1; - - memcpy(s.frames[currentImage].vk_uniform_buffer_mapped, &ubo, sizeof(ubo)); -} - -void -draw_frame() { - vkWaitForFences(s.vk_device, 1, &s.frames[currentFrame].in_flight_fence, VK_TRUE, UINT64_MAX); - - uint32_t imageIndex; - VkResult result = vkAcquireNextImageKHR(s.vk_device, s.vk_swap_chain, UINT64_MAX, s.frames[currentFrame].image_available_semaphore, VK_NULL_HANDLE, &imageIndex); - - if (result == VK_ERROR_OUT_OF_DATE_KHR) { - recreateSwapChain(); - return; - } else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) { - vk_log(VK_ERROR, "failed to acquire swap chain image!\n"); - } - - updateUniformBuffer(currentFrame); - - vkResetFences(s.vk_device, 1, &s.frames[currentFrame].in_flight_fence); - - vkResetCommandBuffer(s.frames[currentFrame].vk_command_buffer, 0); - recordCommandBuffer(s.frames[currentFrame].vk_command_buffer, imageIndex); - - VkSubmitInfo submitInfo = {0}; - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - - VkSemaphore waitSemaphores[] = {s.frames[currentFrame].image_available_semaphore}; - VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; - submitInfo.waitSemaphoreCount = 1; - submitInfo.pWaitSemaphores = waitSemaphores; - submitInfo.pWaitDstStageMask = waitStages; - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &s.frames[currentFrame].vk_command_buffer; - - VkSemaphore signalSemaphores[] = {s.frames[currentFrame].render_finished_semaphore}; - submitInfo.signalSemaphoreCount = 1; - submitInfo.pSignalSemaphores = signalSemaphores; - - if (vkQueueSubmit(s.vk_graphics_queue, 1, &submitInfo, s.frames[currentFrame].in_flight_fence) != VK_SUCCESS) { - vk_log(VK_ERROR, "failed to submit draw command buffer!\n"); - } - - VkSwapchainKHR swapChains[] = {s.vk_swap_chain}; - VkPresentInfoKHR presentInfo = {0}; - presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; - presentInfo.waitSemaphoreCount = 1; - presentInfo.pWaitSemaphores = signalSemaphores; - presentInfo.swapchainCount = 1; - presentInfo.pSwapchains = swapChains; - presentInfo.pImageIndices = &imageIndex; - presentInfo.pResults = NULL; - - result = vkQueuePresentKHR(s.vk_present_queue, &presentInfo); - - if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || s.sdl_window_resized) { - s.sdl_window_resized = 0; - recreateSwapChain(); - } else if (result != VK_SUCCESS) { - vk_log(VK_ERROR, "failed to present swap chain image!\n"); - } - - currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; -} - -int -main(int argc, char* args[]) -{ - init_state(&s); - if (!init()) { - vk_log(VK_INFO, "Failed to initialize!\n"); - } - else { - init_vulkan(); - - bool quit = false; - - - /* VMA POC */ - VmaVulkanFunctions vulkanFunctions = {0}; - vulkanFunctions.vkGetInstanceProcAddr = &vkGetInstanceProcAddr; - vulkanFunctions.vkGetDeviceProcAddr = &vkGetDeviceProcAddr; - - VmaAllocatorCreateInfo allocatorCreateInfo = {0}; - allocatorCreateInfo.flags = VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT; - allocatorCreateInfo.vulkanApiVersion = VK_API_VERSION_1_2; - allocatorCreateInfo.physicalDevice = s.vk_physical_device; - allocatorCreateInfo.device = s.vk_device; - allocatorCreateInfo.instance = s.vk_instance; - allocatorCreateInfo.pVulkanFunctions = &vulkanFunctions; - - VmaAllocator allocator; - vmaCreateAllocator(&allocatorCreateInfo, &allocator); - - // Entire program... - - // At the end, don't forget to: - vmaDestroyAllocator(allocator); - - // Game loop - update_camera(0, 0); - while (!quit) { - handle_input(&quit); - draw_frame(); - //SDL_Delay(16); - } - - close_vulkan(); - } - - // Free resources and close SDL - closeSDL(); - - return 0; - -} |