#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" // ::Vulkan::Constants::Header:: 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 __unix__ && !__linux__ #error Not yet implemented #endif // ::Vulkan::Macros::Header:: #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) // ::Vulkan::GlobalFunctions::Header:: VK_DECLARE(vkGetInstanceProcAddr); VK_DECLARE(vkCreateInstance); VK_DECLARE(vkEnumerateInstanceLayerProperties); // ::Vulkan::InstanceFunctions::Header:: 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); // ::Vulkan::PlatformFunctions::Header:: #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 // ::Vulkan::DeviceFunctions::Header:: 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(vkCmdBindVertexBuffers); 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); VK_DECLARE(vkCreateSampler); #include "vma/vk_mem_alloc.h" // ::Vulkan::Defines::Header:: #define FRAME_OVERLAP 2 #define DESC_MAX_BINDINGS 256 #define BUFFER_QUEUE_LEN 32 #define HOST_VISIBLE_BUFFERS (RENDER_BUFFER_TYPE_UNIFORM | RENDER_BUFFER_TYPE_STAGING) // ::Vulkan::Types::Header:: typedef enum DescType_e { DESC_TYPE_SHARED, DESC_TYPE_SAMPLER, // DO NOT MOVE FROM POSITION 1 !! DESC_TYPE_STORAGE_IMAGE, DESC_TYPE_UNIFORM, DESC_TYPE_BUFFER, DESC_TYPE_MAX, } DescType; typedef struct ShaderGlobals { Vec2 res; } ShaderGlobals; typedef struct Image { VkImage img; VkImageView view; VkSampler sampler; VmaAllocation alloc; VkFormat fmt; VkImageLayout curr_layout; } Image; typedef struct TextureBuffer { TextureBufferType type; Image image; u32 width; u32 height; u32 channels; u32 index; } TextureBuffer; typedef struct RenderBuffer { RenderBufferType type; VkBuffer buffer; VmaAllocation alloc; VmaAllocationInfo info; u32 size; u32 index; // TODO(MA): use this } RenderBuffer; typedef struct MeshBuffer { RenderBuffer index_buf, vertex_buf; u32 index_count; } MeshBuffer; typedef struct GlobalUniforms { f32 res[2]; } GlobalUniforms; typedef struct DescAssetInfo { DescHandle handle; DescType type; union { u64 asset_id; TextureAsset texture_id; }; } DescAssetInfo; typedef struct DescBindings { u16 *free; u16 free_count; u16 *used; u16 used_count; HashTable lookup_table; } DescBindings; typedef struct PipelineStructures { 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 PushConst { Vec2 res; Vec2 img_res; } PushConst; typedef struct FrameStructures { VkCommandPool *pools; VkCommandBuffer *buffers; VkSemaphore *swapchain_sems; VkSemaphore *render_sems; VkFence *render_fences; RenderBuffer **buffer_destroy_queues; u32 *buffer_counts; } FrameStructures; typedef struct UploadQueue { union { RenderBuffer **queued_buffers; TextureBuffer **queued_textures; rawptr *queued_ptrs; }; rawptr *data; TicketMut ticket_mut; Mut mut; JobQueue job_queue; } UploadQueue; typedef struct ImmediateStructures { VkCommandPool *pools; VkCommandBuffer *cmds; VkFence *fences; JobQueue buffer_queue; JobQueue texture_queue; } ImmediateStructures; typedef struct DeviceQueues { i32 graphics, transfer; VkQueue graphics_queue, transfer_queue; b8 single_queue; } DeviceQueues; typedef struct SwapchainStructures { VkFormat format; VkColorSpaceKHR color_space; VkPresentModeKHR present_mode; VkExtent3D extent; VkImage *imgs; VkImageView *views; u32 img_count; Image draw_img; Image depth_img; } SwapchainStructures; typedef struct FrameState { u32 img_ix; u64 frame_cnt; u64 prev_frame; b8 begin_rendering; PipelineHandle last_pipeline; RenderBuffer *prev_buffers; u32 prev_buffer_count; } FrameState; typedef struct Vulkan { 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; typedef struct PendingUpdates { u16 render_width; u16 render_height; b8 resized; } PendingUpdates; typedef struct VulkanConfig { u8 avail_threads; #ifdef __linux__ pthread_t *threads; #elif _WIN32 #error not yet implemented #endif } VulkanConfig; typedef struct Renderer { Vulkan vk; VulkanConfig vk_conf; FrameState frame_state; PendingUpdates pending; Arena *arena; Arena *perm_arena; UploadQueue upload_queues[DESC_TYPE_MAX]; } Renderer; // ::Vulkan::Debug::Functions::Header:: static b32 VLayersSupported(); static VKAPI_ATTR VkBool32 DebugCallback( VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, VkDebugUtilsMessageTypeFlagsEXT message_types, const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, void *pUserData ); const char *VkResultStr(VkResult result); // ::Vulkan::Init::Functions::Header:: static b32 LoadVulkanLib(); 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); static void CreateUploadQueues(); static void StartVkLoaderThreads(); // ::Vulkan::Util::Functions::Header:: static inline VkCommandBuffer GetFrameCmdBuf(); static inline VkFence *GetFrameRenderFence(); static inline VkSemaphore GetFrameRenderSem(); static inline VkSemaphore GetFrameSwapSem(); static inline u32 GetFrameIndex(); static inline VkImage GetFrameSwapImage(); static inline u32 *GetFrameBufferCount(); static inline RenderBuffer *GetFrameRenderBuffers(); static inline void TransitionImage(VkCommandBuffer cmd, Image *img, VkImageLayout new); static inline void TransitionImageLayout(VkCommandBuffer cmd, VkImage img, VkImageLayout curr, VkImageLayout new); static inline void CopyImageToImage(VkCommandBuffer cmd, VkImage src, VkImage dst, VkExtent2D src_ext, VkExtent2D dst_ext); // ::Vulkan::Async::Functions::Header:: #ifdef __linux__ void *VkLoaderStart(void *thread_data); #elif _WIN32 # error not yet implemented #endif void VkLoaderWake(); static u32 VkLoaderProcessBuffers(u32 thread_index); static u32 VkLoaderProcessSamplers(u32 thread_index); // ::Vulkan::ImmediateSubmit::Functions::Header:: static b32 BeginImmSubmit(VkDevice device, VkFence fence, VkCommandBuffer cmd); static b32 FinishImmSubmit(VkDevice device, VkFence fence, VkCommandBuffer cmd, VkQueue queue); // ::Vulkan::Rendering::Functions::Header:: static void BeginRendering(); // ::Vulkan::Swapchain::Functions::Header:: static void ResizeSwapchain(); // ::Vulkan::Images::Functions::Header:: static b32 CreateVkSampler(TextureBuffer *buffer); static void UploadToImage(TextureBuffer *buffer, u8 *data, u32 thread_idx); // ::Vulkan::Descriptors::Functions::Header:: static DescAssetInfo *DescriptorTableSearch(DescType type, u64 asset_id); // ::Vulkan::CleanUp::Functions::Header:: static void DestroySwapchain(); static void DestroyDrawImages(); // ::Vulkan::Logging::Functions::Header:: static void VkInfo(const char *str); static void VkWarn(const char *str); static void VkError(const char *str); #include "vulkan_config.c"