Gears-C/src/renderer_vulkan.h

476 lines
12 KiB
C

#pragma once
#if __linux__
#define VK_USE_PLATFORM_XCB_KHR
#elif _WIN32
#define VK_USE_PLATFORM_WIN32_KHR
#endif
#define VK_NO_PROTOTYPES
#include <vulkan/vulkan.h>
#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"