#pragma once #if __linux__ #define VK_USE_PLATFORM_XCB_KHR #elif _WIN32 #define VK_USE_PLATFORM_WIN32_KHR #endif #define VK_NO_PROTOTYPES #include #include "file_data/spv.c" // Macros #define VK_DECLARE(fn) static PFN_##fn fn = NULL #define STYPE(type) VK_STRUCTURE_TYPE_ ## type #define INIT_FN(name) do { \ name = (PFN_##name)vkGetInstanceProcAddr(NULL, MakeString(name)); \ if (!name) return false; \ } while (0) #define INIT_INST_FN(name) do { \ name = (PFN_##name)vkGetInstanceProcAddr(instance, MakeString(name)); \ if (!name) return false; \ } while (0) #define INIT_DEV_FN(name) do { \ name = (PFN_##name)vkGetDeviceProcAddr(device, MakeString(name)); \ if (!name) return false; \ } while (0) #define FRAME_OVERLAP 2 #define DESC_MAX_BINDINGS 256 // Macros END // Vulkan Functions // Global VK_DECLARE(vkGetInstanceProcAddr); VK_DECLARE(vkCreateInstance); VK_DECLARE(vkEnumerateInstanceLayerProperties); // Instance VK_DECLARE(vkEnumeratePhysicalDevices); VK_DECLARE(vkCreateDevice); VK_DECLARE(vkGetPhysicalDeviceQueueFamilyProperties); VK_DECLARE(vkGetPhysicalDeviceSurfaceSupportKHR); VK_DECLARE(vkGetPhysicalDeviceProperties); VK_DECLARE(vkGetPhysicalDeviceFeatures2); VK_DECLARE(vkEnumerateDeviceExtensionProperties); VK_DECLARE(vkGetPhysicalDeviceSurfacePresentModesKHR); VK_DECLARE(vkGetPhysicalDeviceSurfaceFormatsKHR); VK_DECLARE(vkGetPhysicalDeviceSurfaceCapabilitiesKHR); VK_DECLARE(vkGetPhysicalDeviceImageFormatProperties); #ifdef __linux__ VK_DECLARE(vkCreateXcbSurfaceKHR); #elif _WIN32 VK_DECLARE(vkCreateWin32SurfaceKHR); #elif __APPLE__ || __MACH__ #error Not yet implemented #elif __unix__ && !__linux__ #error Not yet implemented #endif #ifdef BUILD_DEBUG VK_DECLARE(vkCreateDebugUtilsMessengerEXT); VK_DECLARE(vkDestroyDebugUtilsMessengerEXT); #endif // Device VK_DECLARE(vkGetDeviceProcAddr); VK_DECLARE(vkCreateSwapchainKHR); VK_DECLARE(vkCreateImage); VK_DECLARE(vkCreateImageView); VK_DECLARE(vkGetSwapchainImagesKHR); VK_DECLARE(vkGetDeviceQueue); VK_DECLARE(vkCreateSemaphore); VK_DECLARE(vkAllocateCommandBuffers); VK_DECLARE(vkCreateCommandPool); VK_DECLARE(vkCreateFence); VK_DECLARE(vkCreateDescriptorPool); VK_DECLARE(vkCreateDescriptorSetLayout); VK_DECLARE(vkAllocateDescriptorSets); VK_DECLARE(vkCreatePipelineLayout); VK_DECLARE(vkResetDescriptorPool); VK_DECLARE(vkCreateShaderModule); VK_DECLARE(vkCreateGraphicsPipelines); VK_DECLARE(vkCreateComputePipelines); VK_DECLARE(vkUpdateDescriptorSets); VK_DECLARE(vkDestroyDevice); VK_DECLARE(vkDestroyInstance); VK_DECLARE(vkDestroySurfaceKHR); VK_DECLARE(vkDestroyDescriptorPool); VK_DECLARE(vkDestroySwapchainKHR); VK_DECLARE(vkDestroyImage); VK_DECLARE(vkDestroyImageView); VK_DECLARE(vkDestroyCommandPool); VK_DECLARE(vkDestroySemaphore); VK_DECLARE(vkDestroyFence); VK_DECLARE(vkDestroyPipelineLayout); VK_DECLARE(vkDestroyPipeline); VK_DECLARE(vkWaitForFences); VK_DECLARE(vkBeginCommandBuffer); VK_DECLARE(vkEndCommandBuffer); VK_DECLARE(vkAcquireNextImageKHR); VK_DECLARE(vkCmdBindPipeline); VK_DECLARE(vkCmdBindDescriptorSets); VK_DECLARE(vkCmdDispatch); VK_DECLARE(vkCmdBeginRendering); VK_DECLARE(vkCmdEndRendering); VK_DECLARE(vkCmdSetViewport); VK_DECLARE(vkCmdSetScissor); VK_DECLARE(vkCmdPushConstants); VK_DECLARE(vkCmdBindIndexBuffer); VK_DECLARE(vkCmdDrawIndexed); VK_DECLARE(vkCmdBlitImage2); VK_DECLARE(vkCmdPipelineBarrier2); VK_DECLARE(vkCmdCopyBufferToImage); VK_DECLARE(vkCmdCopyBuffer); VK_DECLARE(vkQueueSubmit2); VK_DECLARE(vkResetFences); VK_DECLARE(vkResetCommandBuffer); VK_DECLARE(vkFreeCommandBuffers); VK_DECLARE(vkDestroyDescriptorSetLayout); VK_DECLARE(vkDestroyShaderModule); VK_DECLARE(vkQueuePresentKHR); VK_DECLARE(vkCmdDraw); VK_DECLARE(vkDeviceWaitIdle); VK_DECLARE(vkCmdClearColorImage); // Vulkan Functions END #include "vma/vk_mem_alloc.h" // Types typedef enum Pipeline_e { PIPELINE_CUBE, PIPELINE_MAX, } PipelineHandle; typedef enum DescType_e { DESC_TYPE_SHARED, DESC_TYPE_COMBINED_SAMPLER, DESC_TYPE_STORAGE_IMAGE, DESC_TYPE_UNIFORM, DESC_TYPE_MAX, } DescType; typedef struct { u16 *free; u16 *used; } DescBindings; typedef struct { VkPipelineLayout pipeline_layout; VkDescriptorPool pool; VkDescriptorSetLayout layouts[DESC_TYPE_MAX]; VkDescriptorSet sets[DESC_TYPE_MAX]; DescBindings *bindings; u16 bindings_count; VkPipeline pipelines[PIPELINE_MAX]; } PipelineStructures; typedef struct { Mat4 view_matrix; VkDeviceAddress vertex_buf; u32 img_ix; u32 samp_ix; u32 storage_ix; } PushConst; typedef struct { VkCommandPool *pools; VkCommandBuffer *buffers; VkSemaphore *swapchain_sems; VkSemaphore *render_sems; VkFence *render_fences; } FrameStructures; typedef struct { VkCommandPool pool; VkCommandBuffer buffer; VkFence fence; } ImmediateStructures; typedef struct { i32 graphics, transfer; VkQueue graphics_queue, transfer_queue; } DeviceQueues; typedef struct { VkImage img; VkImageView view; VmaAllocation alloc; VkFormat fmt; VkImageLayout curr_layout; } Image; typedef struct { VkFormat format; VkColorSpaceKHR color_space; VkExtent3D extent; VkImage *imgs; VkImageView *views; u32 img_count; Image draw_img; Image depth_img; } SwapchainStructures; typedef struct { u32 img_ix; u64 frame_cnt; b8 comp_started; b8 gfx_started; } FrameState; typedef struct { Library lib; VkInstance inst; VkSurfaceKHR surface; VkDevice device; VkSwapchainKHR swapchain; VkPhysicalDevice phys_device; DeviceQueues queues; VmaAllocator alloc; FrameStructures frame; ImmediateStructures imm; SwapchainStructures sc; PipelineStructures pipe; #ifdef BUILD_DEBUG VkDebugUtilsMessengerEXT debug; #endif } Vulkan_t; typedef struct { u16 render_width; u16 render_height; b8 resized; } PendingUpdates; typedef struct { Vulkan_t vk; FrameState frame_state; PendingUpdates pending; Arena *arena; Arena *perm_arena; } Renderer_t; // Renderer Function Declarations // Debug static b32 VLayersSupported(); static VKAPI_ATTR VkBool32 DebugCallback( VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, VkDebugUtilsMessageTypeFlagsEXT message_types, const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, void *pUserData ); const char *VkResultStr(VkResult result); // Init static b32 LoadVulkanLib(); static b32 InitVulkan(Arena *arena); static b32 InitVkInstanceFunctions(); static b32 InitVkGlobalFunctions(); static b32 CreateSurface(); static b32 CreateDevice(); static b32 CheckQueueSurfaceSupport(i32 index, VkPhysicalDevice device, VkSurfaceKHR surface); static DeviceQueues CheckDeviceQueueSupport(VkPhysicalDevice device, VkSurfaceKHR surface); static b32 CheckDevicePropertiesSupport(VkPhysicalDevice device, VkSurfaceKHR surface, b32 *discrete); static b32 CheckDeviceFeatureSupport(VkPhysicalDevice device); static b32 InitVkDeviceFunctions(); static b32 CreateVmaAllocator(); static b32 CreateFrameStructures(); static b32 CreateImmediateStructures(); static b32 CreateSwapchain(); static b32 CreateDrawImages(); static VkFormat GetImageFormat(); static b32 CreateDescriptors(); static b32 CreatePipelines(); static b32 CreateShaderModule(u8 *bytes, u32 len, VkShaderModule *module); // Util static VkCommandBuffer GetFrameCmdBuf(); static VkFence *GetFrameRenderFence(); static VkSemaphore GetFrameRenderSem(); static VkSemaphore GetFrameSwapSem(); static u32 GetFrameIndex(); static VkImage GetFrameSwapImage(); // Destroy static void DestroyVulkan(); static void DestroySwapchain(); static void DestroyDrawImages(); // Util static void TransitionImage(VkCommandBuffer cmd, Image *img, VkImageLayout new); static void TransitionImageLayout(VkCommandBuffer cmd, VkImage img, VkImageLayout curr, VkImageLayout new); static void CopyImageToImage(VkCommandBuffer cmd, VkImage src, VkImage dst, VkExtent2D src_ext, VkExtent2D dst_ext); // Swapchain static VkExtent2D SelectSwapchainExtent(VkSurfaceCapabilitiesKHR *capabilities); static VkSurfaceFormatKHR SelectSwapchainFormat(VkSurfaceFormatKHR *formats); static void ResizeSwapchain(); // Renderer Functions Declarations END #include "vulkan_config.c" static Renderer_t renderer = { .vk = { .queues = { .graphics = -1, .transfer = -1, } } }; static const char *_VK_VALIDATION = "VK_LAYER_KHRONOS_validation"; #if __linux__ static char *vulkan_libs[] = { "libvulkan.so.1", "libvulkan.so" }; #endif #if _WIN32 static char *vulkan_libs[] = { "vulkan-1.dll", }; #endif #if __APPLE__ || __MACH__ #error Not yet implemented #endif #if __unix__ && !__linux__ #error Not yet implemented #endif // BACKEND API // Init b32 _InitRenderer(Arena *arena); void _DestroyRenderer(); // Rendering static b32 _BeginFrame(); static void _DrawTriangle(); static b32 _FinishFrame(); static void _SetRenderResolution(u32 x, u32 y);