diff --git a/CHANGELOG b/CHANGELOG index e07d5cac..73ed2910 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -45,6 +45,7 @@ Current Version: RGFW 1.6-dev - change RGFW_window_fullscreen to RGFW_window_setFullscreen - make RGFW_window_setFullscreen use exclusive fullscreen - add RGFW_window_isFullscreen +- add refreshRate to RGFW_monitor_scale Release: RGFW 1.5 (Jan 14, 2024) ----------------------------------------------- @@ -277,6 +278,7 @@ new examples: - Add custom backend example - Add gamepad example - Add no standard library example +- add RGFW_VK_SURFACE and RGFW_window_createVKSurface directly to RGFW Current Release: RGFW 1.06 (Aug 14, 2024) ----------------------------------------------- diff --git a/Makefile b/Makefile index def41018..b924011d 100644 --- a/Makefile +++ b/Makefile @@ -146,7 +146,7 @@ else endif -examples/vk10/vk10: examples/vk10/vk10.c RGFW.h +examples/vk10/vk10: examples/vk10/vk10.c examples/vk10/vkinit.h RGFW.h ifneq ($(NO_VULKAN), 1) glslangValidator -V examples/vk10/shaders/vert.vert -o examples/vk10/shaders/vert.h --vn vert_code glslangValidator -V examples/vk10/shaders/frag.frag -o examples/vk10/shaders/frag.h --vn frag_code diff --git a/RGFW.h b/RGFW.h index 94d05edb..dbdc46bc 100644 --- a/RGFW.h +++ b/RGFW.h @@ -563,7 +563,7 @@ typedef RGFW_ENUM(u8, RGFW_gamepadCodes) { RGFWDEF RGFW_monitor* RGFW_getMonitors(void); /*! get the primary monitor */ RGFWDEF RGFW_monitor RGFW_getPrimaryMonitor(void); - /*! scale monitor to area */ + /*! scale monitor to area and refreshRate, if refreshRate == 0, it's ignored */ RGFWDEF RGFW_bool RGFW_monitor_scale(RGFW_monitor mon, RGFW_area area, u32 refreshRate); #endif @@ -1175,6 +1175,27 @@ typedef struct { you can use this function to get a pointer the instance */ RGFWDEF RGFW_directXinfo* RGFW_getDirectXInfo(void); +#elif defined(RGFW_VULKAN) + #if defined(RGFW_X11) + #define VK_USE_PLATFORM_XLIB_KHR + #define RGFW_VK_SURFACE "VK_KHR_xlib_surface" + #elif defined(RGFW_WINDOWS) + #define VK_USE_PLATFORM_WIN32_KHR + #define OEMRESOURCE + #define RGFW_VK_SURFACE "VK_KHR_win32_surface" + #elif defined(RGFW_MACOS) && !defined(RGFW_MACOS_X11) + #define VK_USE_PLATFORM_MACOS_MVK + #define RGFW_VK_SURFACE "VK_MVK_macos_surface" + #elif defined(RGFW_WAYLAND) + #define VK_USE_PLATFORM_WAYLAND_KHR + #define RGFW_VK_SURFACE "VK_KHR_wayland_surface" + #else + #define RGFW_VK_SURFACE NULL + #endif + +#include + +RGFWDEF VkResult RGFW_window_createVKSurface(RGFW_window* win, VkInstance instance, VkSurfaceKHR* surface); #endif /** @} */ @@ -2454,7 +2475,33 @@ void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { /* end of RGFW_EGL defines */ -#endif /* RGFW_GL (OpenGL, EGL, OSMesa )*/ +/* end of RGFW_GL (OpenGL, EGL, OSMesa )*/ + +/* + RGFW_VULKAN defines +*/ +#elif defined(RGFW_VULKAN) + +VkResult RGFW_window_createVKSurface(RGFW_window* win, VkInstance instance, VkSurfaceKHR* surface) { + assert(win != NULL); assert(instance); + assert(surface != NULL); + + *surface = VK_NULL_HANDLE; + +#ifdef RGFW_X11 + VkXlibSurfaceCreateInfoKHR x11 = { VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, 0, 0, (Display*) win->src.display, (Window) win->src.window }; + return vkCreateXlibSurfaceKHR(instance, &x11, NULL, surface); +#elif defined(RGFW_WINDOWS) + VkWin32SurfaceCreateInfoKHR win32 = { VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, 0, 0, GetModuleHandle(NULL), (HWND)win->src.window }; + + return vkCreateWin32SurfaceKHR(instance, &win32, NULL, surface); +#elif defined(RGFW_MACOS) && !defined(RGFW_MACOS_X11) + VkMacOSSurfaceCreateFlagsMVK macos = { VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK, 0, 0, vulkWin->display, (void *)win->src.window }; + + return vkCreateMacOSSurfaceMVK(instance, &macos, NULL, surface); +#endif +} +#endif /* end of RGFW_vulkan */ /* This is where OS specific stuff starts diff --git a/examples/vk10/RGFW_vulkan.h b/examples/vk10/RGFW_vulkan.h deleted file mode 100644 index c95b6fb0..00000000 --- a/examples/vk10/RGFW_vulkan.h +++ /dev/null @@ -1,614 +0,0 @@ -#ifndef RGFW_HEADER -#error RGFW must be included before this header -#endif - -#ifndef RGFW_VULKAN_H -#define RGFW_VULKAN_H - -#ifndef RGFW_MAX_FRAMES_IN_FLIGHT -#define RGFW_MAX_FRAMES_IN_FLIGHT 2 -#endif - -#ifdef RGFW_X11 -#define VK_USE_PLATFORM_XLIB_KHR -#endif -#ifdef RGFW_WINDOWS -#define VK_USE_PLATFORM_WIN32_KHR -#endif -#ifdef RGFW_MACOS -#define VK_USE_PLATFORM_MACOS_MVK -#endif - -#include - - -typedef struct RGFW_window_vulkanInfo { - VkSurfaceKHR rSurf; /*!< source graphics context */ - - /* vulkan data */ - VkSwapchainKHR swapchain; - u32 image_count; - VkImage* swapchain_images; - VkImageView* swapchain_image_views; -} RGFW_window_vulkanInfo; - -typedef struct RGFW_vulkanInfo { - VkInstance instance; - VkPhysicalDevice physical_device; - VkDevice device; - - VkDebugUtilsMessengerEXT debugMessenger; - - VkQueue graphics_queue; - VkQueue present_queue; - - VkFramebuffer* framebuffers; - - VkRenderPass render_pass; - VkPipelineLayout pipeline_layout; - VkPipeline graphics_pipeline; - - VkCommandPool command_pool; - VkCommandBuffer* command_buffers; - - VkSemaphore* available_semaphores; - VkSemaphore* finished_semaphore; - VkFence* in_flight_fences; - VkFence* image_in_flight; - size_t current_frame; -} RGFW_vulkanInfo; - -RGFWDEF RGFW_vulkanInfo* RGFW_initVulkan(RGFW_window* win, RGFW_window_vulkanInfo* vulkWin); -RGFWDEF void RGFW_freeVulkan(RGFW_window_vulkanInfo* vulkWin); - -RGFWDEF RGFW_vulkanInfo* RGFW_getVulkanInfo(void); - -RGFWDEF int RGFW_initData(RGFW_window_vulkanInfo* vulkWin); -RGFWDEF void RGFW_createSurface(VkInstance instance, RGFW_window* win, RGFW_window_vulkanInfo* vulkWin); -int RGFW_deviceInitialization(RGFW_window* win, RGFW_window_vulkanInfo* vulkWin); -int RGFW_createSwapchain(RGFW_window* win, RGFW_window_vulkanInfo* vulkWin); -RGFWDEF int RGFW_createRenderPass(void); -int RGFW_createCommandPool(void); -int RGFW_createCommandBuffers(RGFW_window_vulkanInfo* vulkWin); -int RGFW_createSyncObjects(RGFW_window_vulkanInfo* vulkWin); -RGFWDEF int RGFW_createFramebuffers(RGFW_window* win, RGFW_window_vulkanInfo* vulkWin); -RGFWDEF VkShaderModule RGFW_createShaderModule(const u32* code, size_t code_size); -void RGFW_createDebugCallback(); -const char* RGFW_getDebugSeverityStr(VkDebugUtilsMessageSeverityFlagBitsEXT Severity); -const char* RGFW_getDebugType(VkDebugUtilsMessageTypeFlagsEXT Type); - -#endif - -#ifdef RGFW_VULKAN_IMPLEMENTATION - -RGFW_vulkanInfo RGFW_vulkan_info; - - -RGFW_vulkanInfo* RGFW_initVulkan(RGFW_window* win, RGFW_window_vulkanInfo* vulkWin) { - assert(win != NULL); - - if ( - RGFW_initData(vulkWin) || - RGFW_deviceInitialization(win, vulkWin) || - RGFW_createSwapchain(win, vulkWin) - ) - return NULL; - - u32 graphics_family_index = 0; - u32 present_family_index = 0; - - vkGetDeviceQueue(RGFW_vulkan_info.device, graphics_family_index, 0, &RGFW_vulkan_info.graphics_queue); - vkGetDeviceQueue(RGFW_vulkan_info.device, present_family_index, 0, &RGFW_vulkan_info.present_queue); - - if ( - RGFW_createRenderPass() || - RGFW_createFramebuffers(win, vulkWin) || - RGFW_createCommandPool() || - RGFW_createCommandBuffers(vulkWin) || - RGFW_createSyncObjects(vulkWin) - ) - return NULL; - - return &RGFW_vulkan_info; -} -static VKAPI_ATTR VkBool32 VKAPI_CALL RGFW_debugCallback( - VkDebugUtilsMessageSeverityFlagBitsEXT Severity, - VkDebugUtilsMessageTypeFlagsEXT Type, - const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, - void* pUserData -){ - printf("\nDebug callback: %s\n",pCallbackData->pMessage); - printf(" Severity: %s\n",RGFW_getDebugSeverityStr(Severity)); - printf(" Type: %s\n",RGFW_getDebugType(Type)); - printf(" Objects "); - - for (u32 i= 0; i < pCallbackData->objectCount; i++) { - #ifdef _WIN32 - printf("%llx ", pCallbackData->pObjects[i].objectHandle); - #else - printf("%lx ", pCallbackData->pObjects[i].objectHandle); - #endif - } -} - -const char* RGFW_getDebugSeverityStr(VkDebugUtilsMessageSeverityFlagBitsEXT Severity) -{ - switch (Severity) { - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: - return "Verbose"; - - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: - return "Info"; - - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: - return "Warning"; - - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: - return "Error"; - - default: - printf("Invalid severity code %d\n", Severity); - exit(1); - } - - return "NO SUCH SEVERITY!"; -} -const char* RGFW_getDebugType(VkDebugUtilsMessageTypeFlagsEXT Type) -{ - switch (Type) { - case VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT: - return "General"; - - case VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT: - return "Validation"; - - case VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT: - return "Performance"; - -#ifdef _WIN64 // doesn't work on my Linux for some reason - case VK_DEBUG_UTILS_MESSAGE_TYPE_DEVICE_ADDRESS_BINDING_BIT_EXT: - return "Device address binding"; -#endif - - default: - printf("Invalid type code %d\n", Type); - exit(1); - } - - return "NO SUCH TYPE!"; -} -void RGFW_createDebugCallback(){ -printf("Creating debug callback\n"); - VkDebugUtilsMessengerCreateInfoEXT MessengerCreateInfo = { - .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, - .pNext = NULL, - .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, - .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 = &RGFW_debugCallback, - .pUserData = NULL - }; - - PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessenger = VK_NULL_HANDLE; - vkCreateDebugUtilsMessenger=(PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(RGFW_vulkan_info.instance,"vkCreateDebugUtilsMessengerEXT"); - if(!vkCreateDebugUtilsMessenger) { - printf("vkCreateDebugUtilsMessenger Failed\n"); - exit(1); - } - VkResult debug_result = vkCreateDebugUtilsMessenger( - RGFW_vulkan_info.instance, - &MessengerCreateInfo, - NULL, - &RGFW_vulkan_info.debugMessenger - ); - if (debug_result != VK_SUCCESS) { - printf("Failed to create debug messenger!"); - } -} -int RGFW_initData(RGFW_window_vulkanInfo* vulkWin) { - assert(vulkWin != NULL); - - vulkWin->swapchain = VK_NULL_HANDLE; - vulkWin->image_count = 0; - RGFW_vulkan_info.current_frame = 0; - - return 0; -} - -void RGFW_createSurface(VkInstance instance, RGFW_window* win, RGFW_window_vulkanInfo* vulkWin) { - assert(win != NULL); - assert(instance); - - vulkWin->rSurf = VK_NULL_HANDLE; - -#ifdef RGFW_X11 - VkXlibSurfaceCreateInfoKHR x11 = { VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, 0, 0, (Display*) win->src.display, (Window) win->src.window }; - - vkCreateXlibSurfaceKHR(RGFW_vulkan_info.instance, &x11, NULL, &vulkWin->rSurf); -#endif -#ifdef RGFW_WINDOWS - VkWin32SurfaceCreateInfoKHR win32 = { VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, 0, 0, GetModuleHandle(NULL), (HWND)win->src.window }; - - vkCreateWin32SurfaceKHR(RGFW_vulkan_info.instance, &win32, NULL, &vulkWin->rSurf); -#endif -#if defined(RGFW_MACOS) && !defined(RGFW_MACOS_X11) - VkMacOSSurfaceCreateFlagsMVK macos = { VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK, 0, 0, vulkWin->display, (void *)win->src.window }; - - vkCreateMacOSSurfaceMVK(RGFW_vulkan_info.instance, &macos, NULL, &vulkWin->rSurf); -#endif -} - -RGFW_vulkanInfo* RGFW_getVulkanInfo(void) { - return &RGFW_vulkan_info; -} - -int RGFW_deviceInitialization(RGFW_window* win, RGFW_window_vulkanInfo* vulkWin) { - assert(win != NULL); - - VkApplicationInfo appInfo = { 0 }; - appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; - appInfo.pApplicationName = "RGFW app"; - appInfo.apiVersion = VK_MAKE_VERSION(1, 0, 0); - -const char* ppEnabledExtensionNames[] = {VK_KHR_SURFACE_EXTENSION_NAME}; -uint32_t enabledExtensionCount = 1; - - char* extension = -#ifdef RGFW_WINDOWS - "VK_KHR_win32_surface"; -#elif defined(RGFW_X11) - VK_KHR_XLIB_SURFACE_EXTENSION_NAME; -#elif defined(RGFW_MACOS) - "VK_MVK_macos_surface"; -#else - NULL; -#endif - -if (extension != NULL) { - ppEnabledExtensionNames[enabledExtensionCount++] = extension; -} - - char* debugExtension = -#ifdef RGFW_DEBUG_VULKAN - VK_EXT_DEBUG_UTILS_EXTENSION_NAME; -#else - NULL; -#endif - -if (debugExtension != NULL) { - ppEnabledExtensionNames[enabledExtensionCount++] = debugExtension; -} - // Print each extension name - for (int i = 0; i < enabledExtensionCount; i++) { - printf("%s\n", ppEnabledExtensionNames[i]); - } - VkInstanceCreateInfo instance_create_info = { 0 }; - instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; - instance_create_info.pApplicationInfo = &appInfo; - instance_create_info.enabledExtensionCount = enabledExtensionCount; - instance_create_info.ppEnabledExtensionNames = ppEnabledExtensionNames; - - if (vkCreateInstance(&instance_create_info, NULL, &RGFW_vulkan_info.instance) != VK_SUCCESS) { - fprintf(stderr, "failed to create instance!\n"); - return -1; - } - -#ifdef RGFW_DEBUG_VULKAN - RGFW_vulkan_info.debugMessenger= VK_NULL_HANDLE; - RGFW_createDebugCallback(); -#endif - RGFW_createSurface(RGFW_vulkan_info.instance, win, vulkWin); - - u32 deviceCount = 0; - vkEnumeratePhysicalDevices(RGFW_vulkan_info.instance, &deviceCount, NULL); - VkPhysicalDevice* devices = (VkPhysicalDevice*) malloc(sizeof(VkPhysicalDevice) * deviceCount); - vkEnumeratePhysicalDevices(RGFW_vulkan_info.instance, &deviceCount, devices); - - RGFW_vulkan_info.physical_device = devices[0]; - - u32 queue_family_count = 0; - - if (RGFW_vulkan_info.physical_device != NULL && deviceCount) { - vkGetPhysicalDeviceQueueFamilyProperties(RGFW_vulkan_info.physical_device, &queue_family_count, NULL); - VkQueueFamilyProperties* queueFamilies = (VkQueueFamilyProperties*) malloc(sizeof(VkQueueFamilyProperties) * queue_family_count); - - vkGetPhysicalDeviceQueueFamilyProperties(RGFW_vulkan_info.physical_device, &queue_family_count, queueFamilies); - } - - float queuePriority = 1.0f; - - VkPhysicalDeviceFeatures device_features = { 0 }; - - VkDeviceCreateInfo device_create_info = { 0 }; - device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - VkDeviceQueueCreateInfo queue_create_infos[2] = { - {0}, - {0}, - }; - queue_create_infos[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queue_create_infos[0].queueCount = 1; - queue_create_infos[0].pQueuePriorities = &queuePriority; - queue_create_infos[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queue_create_infos[1].queueCount = 1; - queue_create_infos[1].pQueuePriorities = &queuePriority; - device_create_info.queueCreateInfoCount = 2; - device_create_info.pQueueCreateInfos = queue_create_infos; - - device_create_info.enabledExtensionCount = 1; - - const char* device_extensions[] = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME - }; - - device_create_info.ppEnabledExtensionNames = device_extensions; - device_create_info.pEnabledFeatures = &device_features; - if ((RGFW_vulkan_info.physical_device == NULL || deviceCount == 0) || - vkCreateDevice(RGFW_vulkan_info.physical_device, &device_create_info, NULL, &RGFW_vulkan_info.device) != VK_SUCCESS) { - fprintf(stderr, "failed to create logical device!\n"); - return -1; - } - - return 0; -} - -int RGFW_createSwapchain(RGFW_window* win, RGFW_window_vulkanInfo* vulkWin) { - assert(win != NULL); - - VkSurfaceFormatKHR surfaceFormat = { VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }; - VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR; - - VkSurfaceCapabilitiesKHR capabilities = { 0 }; - vkGetPhysicalDeviceSurfaceCapabilitiesKHR(RGFW_vulkan_info.physical_device, vulkWin->rSurf, &capabilities); - - vulkWin->image_count = capabilities.minImageCount + 1; - if (capabilities.maxImageCount > 0 && vulkWin->image_count > capabilities.maxImageCount) { - vulkWin->image_count = capabilities.maxImageCount; - } - - VkSwapchainCreateInfoKHR swapchain_create_info = { 0 }; - swapchain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; - swapchain_create_info.surface = vulkWin->rSurf; - swapchain_create_info.minImageCount = vulkWin->image_count; - swapchain_create_info.imageFormat = surfaceFormat.format; - swapchain_create_info.imageColorSpace = surfaceFormat.colorSpace; - swapchain_create_info.imageExtent = (VkExtent2D){ win->r.w, win->r.h }; - swapchain_create_info.imageArrayLayers = 1; - swapchain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - swapchain_create_info.queueFamilyIndexCount = 2; - swapchain_create_info.preTransform = capabilities.currentTransform; - swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - swapchain_create_info.presentMode = presentMode; - swapchain_create_info.clipped = VK_TRUE; - swapchain_create_info.oldSwapchain = VK_NULL_HANDLE; - - if (vkCreateSwapchainKHR(RGFW_vulkan_info.device, &swapchain_create_info, NULL, &vulkWin->swapchain) != VK_SUCCESS) { - fprintf(stderr, "failed to create swap chain!\n"); - return -1; - } - - u32 imageCount; - vkGetSwapchainImagesKHR(RGFW_vulkan_info.device, vulkWin->swapchain, &imageCount, NULL); - vulkWin->swapchain_images = (VkImage*) malloc(sizeof(VkImage) * imageCount); - vkGetSwapchainImagesKHR(RGFW_vulkan_info.device, vulkWin->swapchain, &imageCount, vulkWin->swapchain_images); - - vulkWin->swapchain_image_views = (VkImageView*) malloc(sizeof(VkImageView) * imageCount); - for (u32 i = 0; i < imageCount; i++) { - VkImageViewCreateInfo image_view_cre_infos = { 0 }; - image_view_cre_infos.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - image_view_cre_infos.image = vulkWin->swapchain_images[i]; - image_view_cre_infos.viewType = VK_IMAGE_VIEW_TYPE_2D; - image_view_cre_infos.format = VK_FORMAT_B8G8R8A8_SRGB; - image_view_cre_infos.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; - image_view_cre_infos.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; - image_view_cre_infos.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; - image_view_cre_infos.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; - image_view_cre_infos.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - image_view_cre_infos.subresourceRange.baseMipLevel = 0; - image_view_cre_infos.subresourceRange.levelCount = 1; - image_view_cre_infos.subresourceRange.baseArrayLayer = 0; - image_view_cre_infos.subresourceRange.layerCount = 1; - if (vkCreateImageView(RGFW_vulkan_info.device, &image_view_cre_infos, NULL, &vulkWin->swapchain_image_views[i]) != VK_SUCCESS) { - fprintf(stderr, "failed to create image views!"); - return -1; - } - } - - return 0; -} - -int RGFW_createRenderPass(void) { - VkAttachmentDescription color_attachment = { 0 }; - color_attachment.format = VK_FORMAT_B8G8R8A8_SRGB; - color_attachment.samples = VK_SAMPLE_COUNT_1_BIT; - color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - color_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - color_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - color_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - color_attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - - VkAttachmentReference color_attachment_ref = { 0 }; - color_attachment_ref.attachment = 0; - color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass = { 0 }; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &color_attachment_ref; - - VkSubpassDependency dependency = { 0 }; - dependency.srcSubpass = VK_SUBPASS_EXTERNAL; - dependency.dstSubpass = 0; - dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.srcAccessMask = 0; - dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - - VkRenderPassCreateInfo render_pass_info = { 0 }; - render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - render_pass_info.attachmentCount = 1; - render_pass_info.pAttachments = &color_attachment; - render_pass_info.subpassCount = 1; - render_pass_info.pSubpasses = &subpass; - render_pass_info.dependencyCount = 1; - render_pass_info.pDependencies = &dependency; - - if (vkCreateRenderPass(RGFW_vulkan_info.device, &render_pass_info, NULL, &RGFW_vulkan_info.render_pass) != VK_SUCCESS) { - fprintf(stderr, "failed to create render pass\n"); - return -1; // failed to create render pass! - } - return 0; -} - -int RGFW_createCommandPool(void) { - VkCommandPoolCreateInfo pool_info = { 0 }; - pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - pool_info.queueFamilyIndex = 0; - - if (vkCreateCommandPool(RGFW_vulkan_info.device, &pool_info, NULL, &RGFW_vulkan_info.command_pool) != VK_SUCCESS) { - fprintf(stderr, "failed to create command pool\n"); - return -1; // failed to create command pool - } - return 0; -} - -int RGFW_createCommandBuffers(RGFW_window_vulkanInfo* vulkWin) { - assert(vulkWin != NULL); - - RGFW_vulkan_info.command_buffers = (VkCommandBuffer*) malloc(sizeof(VkCommandBuffer) * vulkWin->image_count); - - VkCommandBufferAllocateInfo allocInfo = { 0 }; - allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - allocInfo.commandPool = RGFW_vulkan_info.command_pool; - allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - allocInfo.commandBufferCount = (u32) vulkWin->image_count; - - if (vkAllocateCommandBuffers(RGFW_vulkan_info.device, &allocInfo, RGFW_vulkan_info.command_buffers) != VK_SUCCESS) { - return -1; // failed to allocate command buffers; - } - - return 0; -} - -int RGFW_createSyncObjects(RGFW_window_vulkanInfo* vulkWin) { - assert(vulkWin != NULL); - - RGFW_vulkan_info.available_semaphores = (VkSemaphore*) malloc(sizeof(VkSemaphore) * RGFW_MAX_FRAMES_IN_FLIGHT); - RGFW_vulkan_info.finished_semaphore = (VkSemaphore*) malloc(sizeof(VkSemaphore) * RGFW_MAX_FRAMES_IN_FLIGHT); - RGFW_vulkan_info.in_flight_fences = (VkFence*) malloc(sizeof(VkFence) * RGFW_MAX_FRAMES_IN_FLIGHT); - RGFW_vulkan_info.image_in_flight = (VkFence*) malloc(sizeof(VkFence) * vulkWin->image_count); - - VkSemaphoreCreateInfo semaphore_info = { 0 }; - semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - - VkFenceCreateInfo fence_info = { 0 }; - fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT; - - for (size_t i = 0; i < RGFW_MAX_FRAMES_IN_FLIGHT; i++) { - if (vkCreateSemaphore(RGFW_vulkan_info.device, &semaphore_info, NULL, &RGFW_vulkan_info.available_semaphores[i]) != VK_SUCCESS || - vkCreateSemaphore(RGFW_vulkan_info.device, &semaphore_info, NULL, &RGFW_vulkan_info.finished_semaphore[i]) != VK_SUCCESS || - vkCreateFence(RGFW_vulkan_info.device, &fence_info, NULL, &RGFW_vulkan_info.in_flight_fences[i]) != VK_SUCCESS) { - fprintf(stderr, "failed to create sync objects\n"); - return -1; // failed to create synchronization objects for a frame - } - } - - for (size_t i = 0; i < vulkWin->image_count; i++) { - RGFW_vulkan_info.image_in_flight[i] = VK_NULL_HANDLE; - } - - return 0; -} - -int RGFW_createFramebuffers(RGFW_window* win, RGFW_window_vulkanInfo* vulkWin) { - assert(vulkWin != NULL); - - RGFW_vulkan_info.framebuffers = (VkFramebuffer*) malloc(sizeof(VkFramebuffer) * vulkWin->image_count); - - for (size_t i = 0; i < vulkWin->image_count; i++) { - VkImageView attachments[] = { vulkWin->swapchain_image_views[i] }; - - VkFramebufferCreateInfo framebuffer_info = { 0 }; - framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - framebuffer_info.renderPass = RGFW_vulkan_info.render_pass; - framebuffer_info.attachmentCount = 1; - framebuffer_info.pAttachments = attachments; - framebuffer_info.width = win->r.w; - framebuffer_info.height = win->r.h; - framebuffer_info.layers = 1; - - if (vkCreateFramebuffer(RGFW_vulkan_info.device, &framebuffer_info, NULL, &RGFW_vulkan_info.framebuffers[i]) != VK_SUCCESS) { - return -1; // failed to create framebuffer - } - } - return 0; -} - -void RGFW_freeVulkan(RGFW_window_vulkanInfo* vulkWin) { - for (u32 i = 0; i < vulkWin->image_count; i++) { - vkDestroyImageView(RGFW_vulkan_info.device, vulkWin->swapchain_image_views[i], NULL); - } - - for (u32 i = 0; i < vulkWin->image_count; i++) { - vkDestroyFramebuffer(RGFW_vulkan_info.device, RGFW_vulkan_info.framebuffers[i], NULL); - } - - vkDestroySwapchainKHR(RGFW_vulkan_info.device, vulkWin->swapchain, NULL); - vkDestroySurfaceKHR(RGFW_vulkan_info.instance, vulkWin->rSurf, NULL); - free(vulkWin->swapchain_image_views); - free(vulkWin->swapchain_images); - - vkDeviceWaitIdle(RGFW_vulkan_info.device); - - for (size_t i = 0; i < RGFW_MAX_FRAMES_IN_FLIGHT; i++) { - vkDestroySemaphore(RGFW_vulkan_info.device, RGFW_vulkan_info.finished_semaphore[i], NULL); - vkDestroySemaphore(RGFW_vulkan_info.device, RGFW_vulkan_info.available_semaphores[i], NULL); - vkDestroyFence(RGFW_vulkan_info.device, RGFW_vulkan_info.in_flight_fences[i], NULL); - } - - vkDestroyCommandPool(RGFW_vulkan_info.device, RGFW_vulkan_info.command_pool, NULL); - - vkDestroyPipeline(RGFW_vulkan_info.device, RGFW_vulkan_info.graphics_pipeline, NULL); - vkDestroyPipelineLayout(RGFW_vulkan_info.device, RGFW_vulkan_info.pipeline_layout, NULL); - vkDestroyRenderPass(RGFW_vulkan_info.device, RGFW_vulkan_info.render_pass, NULL); - -#ifdef RGFW_DEBUG_VULKAN - printf("RGFW_DEBUG_VULKAN is defined"); - PFN_vkDestroyDebugUtilsMessengerEXT func = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(RGFW_vulkan_info.instance, "vkDestroyDebugUtilsMessengerEXT"); - if (func != NULL) { - func(RGFW_vulkan_info.instance, RGFW_vulkan_info.debugMessenger, NULL); - } -#endif - - vkDestroyDevice(RGFW_vulkan_info.device, NULL); - vkDestroyInstance(RGFW_vulkan_info.instance, NULL); - - free(RGFW_vulkan_info.framebuffers); - free(RGFW_vulkan_info.command_buffers); - free(RGFW_vulkan_info.available_semaphores); - free(RGFW_vulkan_info.finished_semaphore); - free(RGFW_vulkan_info.in_flight_fences); - free(RGFW_vulkan_info.image_in_flight); -} - -VkShaderModule RGFW_createShaderModule(const u32* code, size_t code_size) { - VkShaderModuleCreateInfo create_info = {0}; - create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - create_info.codeSize = code_size; - create_info.pCode = code; - - VkShaderModule shaderModule; - if (RGFW_vulkan_info.device == NULL || vkCreateShaderModule(RGFW_vulkan_info.device, &create_info, NULL, &shaderModule) != VK_SUCCESS) { - return VK_NULL_HANDLE; - } - - return shaderModule; -} -#endif diff --git a/examples/vk10/vk10.c b/examples/vk10/vk10.c index 29120bd0..3b00e121 100644 --- a/examples/vk10/vk10.c +++ b/examples/vk10/vk10.c @@ -1,6 +1,7 @@ #include #include +#define RGFW_VULKAN #define RGFW_IMPLEMENTATION #define RGFW_PRINT_ERRORS #define RGFW_NO_API @@ -9,9 +10,11 @@ This isn't included in RGFW.h itself because you'd want to define that stuff yourself in most usecases */ -#define RGFW_VULKAN_IMPLEMENTATION -#define RGFW_DEBUG_VULKAN -#include "RGFW_vulkan.h" + +#define MAX_FRAMES_IN_FLIGHT 2 +#define VKINIT_IMPLEMENTATION +//#define VKINIT_DEBUG_VULKAN +#include "vkinit.h" /** * ```bash @@ -23,15 +26,16 @@ #include "shaders/frag.h" #include "shaders/vert.h" -RGFW_vulkanInfo *vulkan_info; +vulkanInfo* vkinit_vulkan_info; -int createGraphicsPipeline(RGFW_window* win); -int commandBuffers(RGFW_window* win, RGFW_window_vulkanInfo *vulkWin); -int draw_frame(RGFW_window* win, RGFW_window_vulkanInfo *vulkWin); +int createGraphicsPipeline(vulkanContext* ctx); +int commandBuffers(vulkanContext *ctx); +int draw_frame(vulkanContext *ctx); float mouse_data[2] = {0.0f, 0.0f}; -RGFWDEF void mousePosCallback(RGFW_window *win, RGFW_point point); -void mousePosCallback(RGFW_window *win, RGFW_point point) { +RGFWDEF void mousePosCallback(RGFW_window *win, RGFW_point point, RGFW_point vector); +void mousePosCallback(RGFW_window *win, RGFW_point point, RGFW_point vector) { + RGFW_UNUSED(vector); printf("mouse moved %i %i\n", point.x, point.y); float halfWidth = (float)(win->r.w / 2.0f); float halfHeight = (float)(win->r.h / 2.0f); @@ -46,11 +50,16 @@ int main(void) { RGFW_setMousePosCallback(mousePosCallback); - RGFW_window_vulkanInfo vulkWin; + vulkanContext ctx; + + int res = initVulkanDevice(win, &ctx); + if (res == 0) { + vkinit_vulkan_info = initVulkan(&ctx); - vulkan_info = RGFW_initVulkan(win, &vulkWin); - if (vulkan_info != NULL) - createGraphicsPipeline(win); + if (vkinit_vulkan_info != NULL) + createGraphicsPipeline(&ctx); + else return 0; + } u8 running = 1; while (running && !RGFW_isPressed(win, RGFW_escape)) { @@ -61,23 +70,23 @@ int main(void) { } } - if (vulkan_info != NULL) { - draw_frame(win, &vulkWin); + if (vkinit_vulkan_info != NULL) { + draw_frame(&ctx); } } - if (vulkan_info != NULL) - RGFW_freeVulkan(&vulkWin); + if (vkinit_vulkan_info != NULL) + freeVulkan(&ctx); RGFW_window_close(win); return 0; } -int createGraphicsPipeline(RGFW_window* win) { +int createGraphicsPipeline(vulkanContext* ctx) { VkShaderModule vert_module = - RGFW_createShaderModule(vert_code, sizeof(vert_code)); + createShaderModule(vert_code, sizeof(vert_code)); VkShaderModule frag_module = - RGFW_createShaderModule(frag_code, sizeof(frag_code)); + createShaderModule(frag_code, sizeof(frag_code)); if (vert_module == VK_NULL_HANDLE || frag_module == VK_NULL_HANDLE) { printf("failed to create shader module\n"); @@ -112,15 +121,15 @@ int createGraphicsPipeline(RGFW_window* win) { VkViewport viewport; viewport.x = 0.0f; viewport.y = 0.0f; - viewport.width = (float)win->r.w; - viewport.height = (float)win->r.h; + viewport.width = (float)ctx->width; + viewport.height = (float)ctx->height; viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; VkRect2D scissor; scissor.offset.x = 0; scissor.offset.y = 0; - scissor.extent = (VkExtent2D){win->r.w, win->r.h}; + scissor.extent = (VkExtent2D){ctx->width, ctx->height}; VkPipelineViewportStateCreateInfo viewport_state = {0}; viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; @@ -173,8 +182,8 @@ int createGraphicsPipeline(RGFW_window* win) { pipeline_layout_info.pushConstantRangeCount = 1; pipeline_layout_info.pPushConstantRanges = ⦥ - if (vkCreatePipelineLayout(vulkan_info->device, &pipeline_layout_info, NULL, - &vulkan_info->pipeline_layout) != VK_SUCCESS) { + if (vkCreatePipelineLayout(vkinit_vulkan_info->device, &pipeline_layout_info, NULL, + &vkinit_vulkan_info->pipeline_layout) != VK_SUCCESS) { printf("failed to create pipeline layout\n"); return -1; // failed to create pipeline layout } @@ -197,29 +206,29 @@ int createGraphicsPipeline(RGFW_window* win) { pipeline_info.pMultisampleState = &multisampling; pipeline_info.pColorBlendState = &color_blending; pipeline_info.pDynamicState = &dynamic_info; - pipeline_info.layout = vulkan_info->pipeline_layout; - pipeline_info.renderPass = vulkan_info->render_pass; + pipeline_info.layout = vkinit_vulkan_info->pipeline_layout; + pipeline_info.renderPass = vkinit_vulkan_info->render_pass; pipeline_info.subpass = 0; pipeline_info.basePipelineHandle = VK_NULL_HANDLE; if (vkCreateGraphicsPipelines( - vulkan_info->device, VK_NULL_HANDLE, 1, &pipeline_info, NULL, - &vulkan_info->graphics_pipeline) != VK_SUCCESS) { + vkinit_vulkan_info->device, VK_NULL_HANDLE, 1, &pipeline_info, NULL, + &vkinit_vulkan_info->graphics_pipeline) != VK_SUCCESS) { printf("failed to create pipline\n"); return -1; // failed to create graphics pipeline } - vkDestroyShaderModule(vulkan_info->device, frag_module, NULL); - vkDestroyShaderModule(vulkan_info->device, vert_module, NULL); + vkDestroyShaderModule(vkinit_vulkan_info->device, frag_module, NULL); + vkDestroyShaderModule(vkinit_vulkan_info->device, vert_module, NULL); return 0; } -int commandBuffers(RGFW_window* win, RGFW_window_vulkanInfo *vulkWin) { - for (size_t i = 0; i < vulkWin->image_count; i++) { +int commandBuffers(vulkanContext* ctx) { + for (size_t i = 0; i < ctx->image_count; i++) { VkCommandBufferBeginInfo begin_info = {0}; begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - if (vkBeginCommandBuffer(vulkan_info->command_buffers[i], &begin_info) != + if (vkBeginCommandBuffer(vkinit_vulkan_info->command_buffers[i], &begin_info) != VK_SUCCESS) { printf("Failed to begin recording command buffer\n"); return -1; @@ -227,11 +236,11 @@ int commandBuffers(RGFW_window* win, RGFW_window_vulkanInfo *vulkWin) { VkRenderPassBeginInfo render_pass_info = {0}; render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - render_pass_info.renderPass = vulkan_info->render_pass; - render_pass_info.framebuffer = vulkan_info->framebuffers[i]; + render_pass_info.renderPass = vkinit_vulkan_info->render_pass; + render_pass_info.framebuffer = vkinit_vulkan_info->framebuffers[i]; render_pass_info.renderArea.offset.x = 0; render_pass_info.renderArea.offset.y = 0; - render_pass_info.renderArea.extent = (VkExtent2D){win->r.w, win->r.h}; + render_pass_info.renderArea.extent = (VkExtent2D){ctx->width, ctx->height}; VkClearValue clearColor; clearColor.color.float32[0] = 1.0f; @@ -244,35 +253,35 @@ int commandBuffers(RGFW_window* win, RGFW_window_vulkanInfo *vulkWin) { VkViewport viewport; viewport.x = 0.0f; viewport.y = 0.0f; - viewport.width = (float)win->r.w; - viewport.height = (float)win->r.h; + viewport.width = (float)ctx->width; + viewport.height = (float)ctx->height; viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; VkRect2D scissor; scissor.offset.x = 0; scissor.offset.y = 0; - scissor.extent = (VkExtent2D){win->r.w, win->r.h}; - vkCmdSetScissor(vulkan_info->command_buffers[i], 0, 1, &scissor); + scissor.extent = (VkExtent2D){ctx->width, ctx->height}; + vkCmdSetScissor(vkinit_vulkan_info->command_buffers[i], 0, 1, &scissor); - vkCmdSetViewport(vulkan_info->command_buffers[i], 0, 1, &viewport); + vkCmdSetViewport(vkinit_vulkan_info->command_buffers[i], 0, 1, &viewport); - vkCmdBeginRenderPass(vulkan_info->command_buffers[i], &render_pass_info, + vkCmdBeginRenderPass(vkinit_vulkan_info->command_buffers[i], &render_pass_info, VK_SUBPASS_CONTENTS_INLINE); - vkCmdBindPipeline(vulkan_info->command_buffers[i], + vkCmdBindPipeline(vkinit_vulkan_info->command_buffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, - vulkan_info->graphics_pipeline); + vkinit_vulkan_info->graphics_pipeline); // Push mouse position as a push constant - vkCmdPushConstants(vulkan_info->command_buffers[i], - vulkan_info->pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, + vkCmdPushConstants(vkinit_vulkan_info->command_buffers[i], + vkinit_vulkan_info->pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(mouse_data), &mouse_data); - vkCmdDraw(vulkan_info->command_buffers[i], 3, 1, 0, 0); - vkCmdEndRenderPass(vulkan_info->command_buffers[i]); + vkCmdDraw(vkinit_vulkan_info->command_buffers[i], 3, 1, 0, 0); + vkCmdEndRenderPass(vkinit_vulkan_info->command_buffers[i]); - if (vkEndCommandBuffer(vulkan_info->command_buffers[i]) != VK_SUCCESS) { + if (vkEndCommandBuffer(vkinit_vulkan_info->command_buffers[i]) != VK_SUCCESS) { printf("failed to record command buffer\n"); return -1; // failed to record command buffer! @@ -281,51 +290,51 @@ int commandBuffers(RGFW_window* win, RGFW_window_vulkanInfo *vulkWin) { return 0; } -int draw_frame(RGFW_window* win, RGFW_window_vulkanInfo *vulkWin) { - vkWaitForFences(vulkan_info->device, 1, - &vulkan_info->in_flight_fences[vulkan_info->current_frame], +int draw_frame(vulkanContext *ctx) { + vkWaitForFences(vkinit_vulkan_info->device, 1, + &vkinit_vulkan_info->in_flight_fences[vkinit_vulkan_info->current_frame], VK_TRUE, UINT64_MAX); u32 image_index = 0; vkAcquireNextImageKHR( - vulkan_info->device, vulkWin->swapchain, UINT64_MAX, - vulkan_info->available_semaphores[vulkan_info->current_frame], + vkinit_vulkan_info->device, ctx->swapchain, UINT64_MAX, + vkinit_vulkan_info->available_semaphores[vkinit_vulkan_info->current_frame], VK_NULL_HANDLE, &image_index); - if (vulkan_info->image_in_flight[image_index] != VK_NULL_HANDLE) { - vkWaitForFences(vulkan_info->device, 1, - &vulkan_info->image_in_flight[image_index], VK_TRUE, + if (vkinit_vulkan_info->image_in_flight[image_index] != VK_NULL_HANDLE) { + vkWaitForFences(vkinit_vulkan_info->device, 1, + &vkinit_vulkan_info->image_in_flight[image_index], VK_TRUE, UINT64_MAX); } - vulkan_info->image_in_flight[image_index] = - vulkan_info->in_flight_fences[vulkan_info->current_frame]; + vkinit_vulkan_info->image_in_flight[image_index] = + vkinit_vulkan_info->in_flight_fences[vkinit_vulkan_info->current_frame]; VkSubmitInfo submitInfo = {0}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; VkSemaphore wait_semaphores[] = { - vulkan_info->available_semaphores[vulkan_info->current_frame]}; + vkinit_vulkan_info->available_semaphores[vkinit_vulkan_info->current_frame]}; VkPipelineStageFlags wait_stages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; submitInfo.waitSemaphoreCount = 1; submitInfo.pWaitSemaphores = wait_semaphores; submitInfo.pWaitDstStageMask = wait_stages; - commandBuffers(win, vulkWin); + commandBuffers(ctx); submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &vulkan_info->command_buffers[image_index]; + submitInfo.pCommandBuffers = &vkinit_vulkan_info->command_buffers[image_index]; /**/ VkSemaphore signal_semaphores[] = { - vulkan_info->finished_semaphore[vulkan_info->current_frame]}; + vkinit_vulkan_info->finished_semaphore[vkinit_vulkan_info->current_frame]}; submitInfo.signalSemaphoreCount = 1; submitInfo.pSignalSemaphores = signal_semaphores; - vkResetFences(vulkan_info->device, 1, - &vulkan_info->in_flight_fences[vulkan_info->current_frame]); + vkResetFences(vkinit_vulkan_info->device, 1, + &vkinit_vulkan_info->in_flight_fences[vkinit_vulkan_info->current_frame]); if (vkQueueSubmit( - vulkan_info->graphics_queue, 1, &submitInfo, - vulkan_info->in_flight_fences[vulkan_info->current_frame]) != + vkinit_vulkan_info->graphics_queue, 1, &submitInfo, + vkinit_vulkan_info->in_flight_fences[vkinit_vulkan_info->current_frame]) != VK_SUCCESS) { printf("failed to submit draw command buffer\n"); return -1; //"failed to submit draw command buffer @@ -337,15 +346,15 @@ int draw_frame(RGFW_window* win, RGFW_window_vulkanInfo *vulkWin) { present_info.waitSemaphoreCount = 1; present_info.pWaitSemaphores = signal_semaphores; - VkSwapchainKHR swapChains[] = {vulkWin->swapchain}; + VkSwapchainKHR swapChains[] = {ctx->swapchain}; present_info.swapchainCount = 1; present_info.pSwapchains = swapChains; present_info.pImageIndices = &image_index; - vkQueuePresentKHR(vulkan_info->present_queue, &present_info); + vkQueuePresentKHR(vkinit_vulkan_info->present_queue, &present_info); - vulkan_info->current_frame = - (vulkan_info->current_frame + 1) % RGFW_MAX_FRAMES_IN_FLIGHT; + vkinit_vulkan_info->current_frame = + (vkinit_vulkan_info->current_frame + 1) % MAX_FRAMES_IN_FLIGHT; return 0; } diff --git a/examples/vk10/vkinit.h b/examples/vk10/vkinit.h new file mode 100644 index 00000000..2406fb1c --- /dev/null +++ b/examples/vk10/vkinit.h @@ -0,0 +1,551 @@ +#ifndef RGFW_HEADER +#error RGFW must be included before this header +#endif + +#ifndef VKINIT_H +#define VKINIT_H + +#include + + +typedef struct vulkanContext { + VkSurfaceKHR surface; /*!< source graphics context */ + u32 width, height; /* size*/ + + /* vulkan data */ + VkSwapchainKHR swapchain; + u32 image_count; + VkImage* swapchain_images; + VkImageView* swapchain_image_views; +} vulkanContext; + +typedef struct vulkanInfo { + VkInstance instance; + VkPhysicalDevice physical_device; + VkDevice device; + + VkDebugUtilsMessengerEXT debugMessenger; + + VkQueue graphics_queue; + VkQueue present_queue; + + VkFramebuffer* framebuffers; + + VkRenderPass render_pass; + VkPipelineLayout pipeline_layout; + VkPipeline graphics_pipeline; + + VkCommandPool command_pool; + VkCommandBuffer* command_buffers; + + VkSemaphore* available_semaphores; + VkSemaphore* finished_semaphore; + VkFence* in_flight_fences; + VkFence* image_in_flight; + size_t current_frame; +} vulkanInfo; + +RGFWDEF int initVulkanDevice(RGFW_window* win, vulkanContext* ctx); +RGFWDEF vulkanInfo* initVulkan(vulkanContext* ctx); +RGFWDEF void freeVulkan(vulkanContext* ctx); + +RGFWDEF vulkanInfo* getVulkanInfo(void); + +int createSwapchain(vulkanContext* ctx); +RGFWDEF int createRenderPass(void); +int createCommandPool(void); +int createCommandBuffers(vulkanContext* ctx); +int createSyncObjects(vulkanContext* ctx); +RGFWDEF int createFramebuffers(vulkanContext* ctx); +RGFWDEF VkShaderModule createShaderModule(const u32* code, size_t code_size); +void createDebugCallback(); +const char* getDebugSeverityStr(VkDebugUtilsMessageSeverityFlagBitsEXT Severity); +const char* getDebugType(VkDebugUtilsMessageTypeFlagsEXT Type); + +#endif + +#ifdef VKINIT_IMPLEMENTATION + +vulkanInfo vkInit_vulkan_info; + + +vulkanInfo* initVulkan(vulkanContext* ctx) { + if (createSwapchain(ctx)) + return NULL; + + u32 graphics_family_index = 0; + u32 present_family_index = 0; + + vkGetDeviceQueue(vkInit_vulkan_info.device, graphics_family_index, 0, &vkInit_vulkan_info.graphics_queue); + vkGetDeviceQueue(vkInit_vulkan_info.device, present_family_index, 0, &vkInit_vulkan_info.present_queue); + + if ( + createRenderPass() || + createFramebuffers(ctx) || + createCommandPool() || + createCommandBuffers(ctx) || + createSyncObjects(ctx) + ) + return NULL; + + return &vkInit_vulkan_info; +} +static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback( + VkDebugUtilsMessageSeverityFlagBitsEXT Severity, + VkDebugUtilsMessageTypeFlagsEXT Type, + const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, + void* pUserData +){ + printf("\nDebug callback: %s\n",pCallbackData->pMessage); + printf(" Severity: %s\n",getDebugSeverityStr(Severity)); + printf(" Type: %s\n",getDebugType(Type)); + printf(" Objects "); + + for (u32 i= 0; i < pCallbackData->objectCount; i++) { + #ifdef _WIN32 + printf("%llx ", pCallbackData->pObjects[i].objectHandle); + #else + printf("%lx ", pCallbackData->pObjects[i].objectHandle); + #endif + } +} + +const char* getDebugSeverityStr(VkDebugUtilsMessageSeverityFlagBitsEXT Severity) +{ + switch (Severity) { + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: + return "Verbose"; + + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: + return "Info"; + + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: + return "Warning"; + + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: + return "Error"; + + default: + printf("Invalid severity code %d\n", Severity); + exit(1); + } + + return "NO SUCH SEVERITY!"; +} +const char* getDebugType(VkDebugUtilsMessageTypeFlagsEXT Type) +{ + switch (Type) { + case VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT: + return "General"; + + case VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT: + return "Validation"; + + case VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT: + return "Performance"; + +#ifdef _WIN64 // doesn't work on my Linux for some reason + case VK_DEBUG_UTILS_MESSAGE_TYPE_DEVICE_ADDRESS_BINDING_BIT_EXT: + return "Device address binding"; +#endif + + default: + printf("Invalid type code %d\n", Type); + exit(1); + } + + return "NO SUCH TYPE!"; +} +void createDebugCallback(){ +printf("Creating debug callback\n"); + VkDebugUtilsMessengerCreateInfoEXT MessengerCreateInfo = { + .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, + .pNext = NULL, + .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, + .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 = &debugCallback, + .pUserData = NULL + }; + + PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessenger = VK_NULL_HANDLE; + vkCreateDebugUtilsMessenger=(PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(vkInit_vulkan_info.instance,"vkCreateDebugUtilsMessengerEXT"); + if(!vkCreateDebugUtilsMessenger) { + printf("vkCreateDebugUtilsMessenger Failed\n"); + exit(1); + } + VkResult debug_result = vkCreateDebugUtilsMessenger( + vkInit_vulkan_info.instance, + &MessengerCreateInfo, + NULL, + &vkInit_vulkan_info.debugMessenger + ); + if (debug_result != VK_SUCCESS) { + printf("Failed to create debug messenger!"); + } +} + +vulkanInfo* getVulkanInfo(void) { + return &vkInit_vulkan_info; +} + +int initVulkanDevice(RGFW_window* win, vulkanContext* ctx) { + assert(win != NULL); + + ctx->swapchain = VK_NULL_HANDLE; + ctx->image_count = 0; + vkInit_vulkan_info.current_frame = 0; + + ctx->width = win->r.w; + ctx->height = win->r.h; + + VkApplicationInfo appInfo = { 0 }; + appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + appInfo.pApplicationName = "RGFW app"; + appInfo.apiVersion = VK_MAKE_VERSION(1, 0, 0); + + const char* ppEnabledExtensionNames[] = {VK_KHR_SURFACE_EXTENSION_NAME, RGFW_VK_SURFACE}; + uint32_t enabledExtensionCount = 2; + + char* debugExtension = + #ifdef VKINIT_DEBUG_VULKAN + VK_EXT_DEBUG_UTILS_EXTENSION_NAME; + #else + NULL; + #endif + + if (debugExtension != NULL) { + ppEnabledExtensionNames[enabledExtensionCount++] = debugExtension; + } + // Print each extension name + for (int i = 0; i < enabledExtensionCount; i++) { + printf("%s\n", ppEnabledExtensionNames[i]); + } + VkInstanceCreateInfo instance_create_info = { 0 }; + instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + instance_create_info.pApplicationInfo = &appInfo; + instance_create_info.enabledExtensionCount = enabledExtensionCount; + instance_create_info.ppEnabledExtensionNames = ppEnabledExtensionNames; + + if (vkCreateInstance(&instance_create_info, NULL, &vkInit_vulkan_info.instance) != VK_SUCCESS) { + fprintf(stderr, "failed to create instance!\n"); + return -1; + } + +#ifdef VKINIT_DEBUG_VULKAN + vkInit_vulkan_info.debugMessenger= VK_NULL_HANDLE; + createDebugCallback(); +#endif + RGFW_window_createVKSurface(win, vkInit_vulkan_info.instance, &ctx->surface); + + u32 deviceCount = 0; + vkEnumeratePhysicalDevices(vkInit_vulkan_info.instance, &deviceCount, NULL); + VkPhysicalDevice* devices = (VkPhysicalDevice*) malloc(sizeof(VkPhysicalDevice) * deviceCount); + vkEnumeratePhysicalDevices(vkInit_vulkan_info.instance, &deviceCount, devices); + + vkInit_vulkan_info.physical_device = devices[0]; + + u32 queue_family_count = 0; + + if (vkInit_vulkan_info.physical_device != NULL && deviceCount) { + vkGetPhysicalDeviceQueueFamilyProperties(vkInit_vulkan_info.physical_device, &queue_family_count, NULL); + VkQueueFamilyProperties* queueFamilies = (VkQueueFamilyProperties*) malloc(sizeof(VkQueueFamilyProperties) * queue_family_count); + + vkGetPhysicalDeviceQueueFamilyProperties(vkInit_vulkan_info.physical_device, &queue_family_count, queueFamilies); + } + + float queuePriority = 1.0f; + + VkPhysicalDeviceFeatures device_features = { 0 }; + + VkDeviceCreateInfo device_create_info = { 0 }; + device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + VkDeviceQueueCreateInfo queue_create_infos[2] = { + {0}, + {0}, + }; + queue_create_infos[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queue_create_infos[0].queueCount = 1; + queue_create_infos[0].pQueuePriorities = &queuePriority; + queue_create_infos[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queue_create_infos[1].queueCount = 1; + queue_create_infos[1].pQueuePriorities = &queuePriority; + device_create_info.queueCreateInfoCount = 2; + device_create_info.pQueueCreateInfos = queue_create_infos; + + device_create_info.enabledExtensionCount = 1; + + const char* device_extensions[] = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME + }; + + device_create_info.ppEnabledExtensionNames = device_extensions; + device_create_info.pEnabledFeatures = &device_features; + if ((vkInit_vulkan_info.physical_device == NULL || deviceCount == 0) || + vkCreateDevice(vkInit_vulkan_info.physical_device, &device_create_info, NULL, &vkInit_vulkan_info.device) != VK_SUCCESS) { + fprintf(stderr, "failed to create logical device!\n"); + return -1; + } + + return 0; +} + +int createSwapchain(vulkanContext* ctx) { + VkSurfaceFormatKHR surfaceFormat = { VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }; + VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR; + + VkSurfaceCapabilitiesKHR capabilities = { 0 }; + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vkInit_vulkan_info.physical_device, ctx->surface, &capabilities); + + ctx->image_count = capabilities.minImageCount + 1; + if (capabilities.maxImageCount > 0 && ctx->image_count > capabilities.maxImageCount) { + ctx->image_count = capabilities.maxImageCount; + } + + VkSwapchainCreateInfoKHR swapchain_create_info = { 0 }; + swapchain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + swapchain_create_info.surface = ctx->surface; + swapchain_create_info.minImageCount = ctx->image_count; + swapchain_create_info.imageFormat = surfaceFormat.format; + swapchain_create_info.imageColorSpace = surfaceFormat.colorSpace; + swapchain_create_info.imageExtent = (VkExtent2D){ ctx->width, ctx->height }; + swapchain_create_info.imageArrayLayers = 1; + swapchain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + swapchain_create_info.queueFamilyIndexCount = 2; + swapchain_create_info.preTransform = capabilities.currentTransform; + swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + swapchain_create_info.presentMode = presentMode; + swapchain_create_info.clipped = VK_TRUE; + swapchain_create_info.oldSwapchain = VK_NULL_HANDLE; + + if (vkCreateSwapchainKHR(vkInit_vulkan_info.device, &swapchain_create_info, NULL, &ctx->swapchain) != VK_SUCCESS) { + fprintf(stderr, "failed to create swap chain!\n"); + return -1; + } + + u32 imageCount; + vkGetSwapchainImagesKHR(vkInit_vulkan_info.device, ctx->swapchain, &imageCount, NULL); + ctx->swapchain_images = (VkImage*) malloc(sizeof(VkImage) * imageCount); + vkGetSwapchainImagesKHR(vkInit_vulkan_info.device, ctx->swapchain, &imageCount, ctx->swapchain_images); + + ctx->swapchain_image_views = (VkImageView*) malloc(sizeof(VkImageView) * imageCount); + for (u32 i = 0; i < imageCount; i++) { + VkImageViewCreateInfo image_view_cre_infos = { 0 }; + image_view_cre_infos.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + image_view_cre_infos.image = ctx->swapchain_images[i]; + image_view_cre_infos.viewType = VK_IMAGE_VIEW_TYPE_2D; + image_view_cre_infos.format = VK_FORMAT_B8G8R8A8_SRGB; + image_view_cre_infos.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_cre_infos.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_cre_infos.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_cre_infos.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_cre_infos.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + image_view_cre_infos.subresourceRange.baseMipLevel = 0; + image_view_cre_infos.subresourceRange.levelCount = 1; + image_view_cre_infos.subresourceRange.baseArrayLayer = 0; + image_view_cre_infos.subresourceRange.layerCount = 1; + if (vkCreateImageView(vkInit_vulkan_info.device, &image_view_cre_infos, NULL, &ctx->swapchain_image_views[i]) != VK_SUCCESS) { + fprintf(stderr, "failed to create image views!"); + return -1; + } + } + + return 0; +} + +int createRenderPass(void) { + VkAttachmentDescription color_attachment = { 0 }; + color_attachment.format = VK_FORMAT_B8G8R8A8_SRGB; + color_attachment.samples = VK_SAMPLE_COUNT_1_BIT; + color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + color_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + color_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + color_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + color_attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + + VkAttachmentReference color_attachment_ref = { 0 }; + color_attachment_ref.attachment = 0; + color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkSubpassDescription subpass = { 0 }; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &color_attachment_ref; + + VkSubpassDependency dependency = { 0 }; + dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstSubpass = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.srcAccessMask = 0; + dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + + VkRenderPassCreateInfo render_pass_info = { 0 }; + render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + render_pass_info.attachmentCount = 1; + render_pass_info.pAttachments = &color_attachment; + render_pass_info.subpassCount = 1; + render_pass_info.pSubpasses = &subpass; + render_pass_info.dependencyCount = 1; + render_pass_info.pDependencies = &dependency; + + if (vkCreateRenderPass(vkInit_vulkan_info.device, &render_pass_info, NULL, &vkInit_vulkan_info.render_pass) != VK_SUCCESS) { + fprintf(stderr, "failed to create render pass\n"); + return -1; // failed to create render pass! + } + return 0; +} + +int createCommandPool(void) { + VkCommandPoolCreateInfo pool_info = { 0 }; + pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + pool_info.queueFamilyIndex = 0; + + if (vkCreateCommandPool(vkInit_vulkan_info.device, &pool_info, NULL, &vkInit_vulkan_info.command_pool) != VK_SUCCESS) { + fprintf(stderr, "failed to create command pool\n"); + return -1; // failed to create command pool + } + return 0; +} + +int createCommandBuffers(vulkanContext* ctx) { + assert(ctx != NULL); + + vkInit_vulkan_info.command_buffers = (VkCommandBuffer*) malloc(sizeof(VkCommandBuffer) * ctx->image_count); + + VkCommandBufferAllocateInfo allocInfo = { 0 }; + allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + allocInfo.commandPool = vkInit_vulkan_info.command_pool; + allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + allocInfo.commandBufferCount = (u32) ctx->image_count; + + if (vkAllocateCommandBuffers(vkInit_vulkan_info.device, &allocInfo, vkInit_vulkan_info.command_buffers) != VK_SUCCESS) { + return -1; // failed to allocate command buffers; + } + + return 0; +} + +int createSyncObjects(vulkanContext* ctx) { + assert(ctx != NULL); + + vkInit_vulkan_info.available_semaphores = (VkSemaphore*) malloc(sizeof(VkSemaphore) * MAX_FRAMES_IN_FLIGHT); + vkInit_vulkan_info.finished_semaphore = (VkSemaphore*) malloc(sizeof(VkSemaphore) * MAX_FRAMES_IN_FLIGHT); + vkInit_vulkan_info.in_flight_fences = (VkFence*) malloc(sizeof(VkFence) * MAX_FRAMES_IN_FLIGHT); + vkInit_vulkan_info.image_in_flight = (VkFence*) malloc(sizeof(VkFence) * ctx->image_count); + + VkSemaphoreCreateInfo semaphore_info = { 0 }; + semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + + VkFenceCreateInfo fence_info = { 0 }; + fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT; + + for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { + if (vkCreateSemaphore(vkInit_vulkan_info.device, &semaphore_info, NULL, &vkInit_vulkan_info.available_semaphores[i]) != VK_SUCCESS || + vkCreateSemaphore(vkInit_vulkan_info.device, &semaphore_info, NULL, &vkInit_vulkan_info.finished_semaphore[i]) != VK_SUCCESS || + vkCreateFence(vkInit_vulkan_info.device, &fence_info, NULL, &vkInit_vulkan_info.in_flight_fences[i]) != VK_SUCCESS) { + fprintf(stderr, "failed to create sync objects\n"); + return -1; // failed to create synchronization objects for a frame + } + } + + for (size_t i = 0; i < ctx->image_count; i++) { + vkInit_vulkan_info.image_in_flight[i] = VK_NULL_HANDLE; + } + + return 0; +} + +int createFramebuffers(vulkanContext* ctx) { + assert(ctx != NULL); + + vkInit_vulkan_info.framebuffers = (VkFramebuffer*) malloc(sizeof(VkFramebuffer) * ctx->image_count); + + for (size_t i = 0; i < ctx->image_count; i++) { + VkImageView attachments[] = { ctx->swapchain_image_views[i] }; + + VkFramebufferCreateInfo framebuffer_info = { 0 }; + framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + framebuffer_info.renderPass = vkInit_vulkan_info.render_pass; + framebuffer_info.attachmentCount = 1; + framebuffer_info.pAttachments = attachments; + framebuffer_info.width = ctx->width; + framebuffer_info.height = ctx->height; + framebuffer_info.layers = 1; + + if (vkCreateFramebuffer(vkInit_vulkan_info.device, &framebuffer_info, NULL, &vkInit_vulkan_info.framebuffers[i]) != VK_SUCCESS) { + return -1; // failed to create framebuffer + } + } + return 0; +} + +void freeVulkan(vulkanContext* ctx) { + for (u32 i = 0; i < ctx->image_count; i++) { + vkDestroyImageView(vkInit_vulkan_info.device, ctx->swapchain_image_views[i], NULL); + } + + for (u32 i = 0; i < ctx->image_count; i++) { + vkDestroyFramebuffer(vkInit_vulkan_info.device, vkInit_vulkan_info.framebuffers[i], NULL); + } + + vkDestroySwapchainKHR(vkInit_vulkan_info.device, ctx->swapchain, NULL); + vkDestroySurfaceKHR(vkInit_vulkan_info.instance, ctx->surface, NULL); + free(ctx->swapchain_image_views); + free(ctx->swapchain_images); + + vkDeviceWaitIdle(vkInit_vulkan_info.device); + + for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { + vkDestroySemaphore(vkInit_vulkan_info.device, vkInit_vulkan_info.finished_semaphore[i], NULL); + vkDestroySemaphore(vkInit_vulkan_info.device, vkInit_vulkan_info.available_semaphores[i], NULL); + vkDestroyFence(vkInit_vulkan_info.device, vkInit_vulkan_info.in_flight_fences[i], NULL); + } + + vkDestroyCommandPool(vkInit_vulkan_info.device, vkInit_vulkan_info.command_pool, NULL); + + vkDestroyPipeline(vkInit_vulkan_info.device, vkInit_vulkan_info.graphics_pipeline, NULL); + vkDestroyPipelineLayout(vkInit_vulkan_info.device, vkInit_vulkan_info.pipeline_layout, NULL); + vkDestroyRenderPass(vkInit_vulkan_info.device, vkInit_vulkan_info.render_pass, NULL); + +#ifdef VKINIT_DEBUG_VULKAN + printf("VKINIT_DEBUG_VULKAN is defined"); + PFN_vkDestroyDebugUtilsMessengerEXT func = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(vkInit_vulkan_info.instance, "vkDestroyDebugUtilsMessengerEXT"); + if (func != NULL) { + func(vkInit_vulkan_info.instance, vkInit_vulkan_info.debugMessenger, NULL); + } +#endif + + vkDestroyDevice(vkInit_vulkan_info.device, NULL); + vkDestroyInstance(vkInit_vulkan_info.instance, NULL); + + free(vkInit_vulkan_info.framebuffers); + free(vkInit_vulkan_info.command_buffers); + free(vkInit_vulkan_info.available_semaphores); + free(vkInit_vulkan_info.finished_semaphore); + free(vkInit_vulkan_info.in_flight_fences); + free(vkInit_vulkan_info.image_in_flight); +} + +VkShaderModule createShaderModule(const u32* code, size_t code_size) { + VkShaderModuleCreateInfo create_info = {0}; + create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + create_info.codeSize = code_size; + create_info.pCode = code; + + VkShaderModule shaderModule; + if (vkInit_vulkan_info.device == NULL || vkCreateShaderModule(vkInit_vulkan_info.device, &create_info, NULL, &shaderModule) != VK_SUCCESS) { + return VK_NULL_HANDLE; + } + + return shaderModule; +} +#endif \ No newline at end of file