From 5f235694cdc339726f305c4715ea2dc4c3209139 Mon Sep 17 00:00:00 2001 From: Matthew Date: Sun, 23 Feb 2025 16:17:23 +1100 Subject: [PATCH] vulkan init done, more added to the platform layer for interfacing with window --- .ignore | 2 + src/main.c | 17 +++ src/platform.c | 10 ++ src/platform.h | 28 ++++ src/platform_linux.c | 60 +++++++++ src/platform_linux.h | 3 +- src/render_vulkan.c | 301 ++++++++++++++++++++++++++++++++++++++++++- src/render_vulkan.h | 24 ++++ src/util.c | 30 +++++ src/util.h | 8 ++ src/vulkan_config.c | 79 ++++++++++++ 11 files changed, 556 insertions(+), 6 deletions(-) create mode 100644 .ignore diff --git a/.ignore b/.ignore new file mode 100644 index 0000000..a634de8 --- /dev/null +++ b/.ignore @@ -0,0 +1,2 @@ +.git +build/ diff --git a/src/main.c b/src/main.c index 51b69eb..7185475 100644 --- a/src/main.c +++ b/src/main.c @@ -20,6 +20,23 @@ int main(int argc, char **argv) Assert(CreateWindow(), "Failed to initialize the window"); Assert(InitRenderer(renderer_arena), "Failed to initialize the renderer"); + b32 quit = false; + WindowEvent e; + while (!quit) + { + while (GetWindowEvent(&e)) + { + switch (e.type) + { + case EVENT_QUIT: + quit = true; + break; + default: + break; + } + } + } + DestroyRenderer(); return 0; diff --git a/src/platform.c b/src/platform.c index a104f5b..08f7ca8 100644 --- a/src/platform.c +++ b/src/platform.c @@ -91,3 +91,13 @@ Window *GetWindow() { return _GetWindow(); } + +b32 GetWindowEvent(WindowEvent *event) +{ + return _GetWindowEvent(event); +} + +WindowSize GetWindowSize() +{ + return _GetWindowSize(); +} diff --git a/src/platform.h b/src/platform.h index 012360d..4c0a153 100644 --- a/src/platform.h +++ b/src/platform.h @@ -1,5 +1,9 @@ #pragma once +typedef enum Event_e Event_e; +typedef struct WindowEvent WindowEvent; +typedef struct WindowSize WindowSize; + #if __linux__ #include "platform_linux.h" #endif @@ -16,6 +20,28 @@ #error Not yet implemented #endif +enum Event_e +{ + EVENT_NONE = 0, + EVENT_QUIT, + EVENT_RESIZE, +}; + +struct WindowSize +{ + u16 w; + u16 h; +}; + +struct WindowEvent +{ + union + { + WindowSize resize; + }; + Event_e type; +}; + // Init b32 LoadLib(const char *name, Library *out_lib); b32 LoadFn(const char *name, Library *lib, Function *out_fn); @@ -35,3 +61,5 @@ i32 EPrintf(const char *fmt, ...); // Window Functions b32 CreateWindow(); Window *GetWindow(); +b32 GetWindowEvent(WindowEvent *event); +WindowSize GetWindowSize(); diff --git a/src/platform_linux.c b/src/platform_linux.c index c204fc3..c8b52d9 100644 --- a/src/platform_linux.c +++ b/src/platform_linux.c @@ -227,4 +227,64 @@ Window *_GetWindow() { return &linux_window; } +WindowSize _GetWindowSize() +{ + return (WindowSize) { + .w = linux_window.w, + .h = linux_window.h, + }; +} + +b32 _GetWindowEvent(WindowEvent *event) +{ + Assert(event != NULL, "GetWindowEvent received a null pointer"); + + b32 valid_event = false; + b32 no_event = false; + do + { + xcb_generic_event_t *e = xcb_poll_for_event(linux_window.connection); + + if (e != NULL) + { + switch (e->response_type & ~0x80) + { + case XCB_CLIENT_MESSAGE: + xcb_client_message_event_t *msg = (xcb_client_message_event_t *)e; + if (msg->data.data32[0] == linux_window.close_event) + { + event->type = EVENT_QUIT; + valid_event = true; + } + break; + case XCB_RESIZE_REQUEST: + event->type = EVENT_RESIZE; + valid_event = true; + + xcb_resize_request_event_t *resize = (xcb_resize_request_event_t *)e; + + if (resize->width > 0) + { + linux_window.w = resize->width; + event->resize.w = resize->width; + } + if (resize->height > 0) + { + linux_window.h = resize->height; + event->resize.h = resize->height; + } + + break; + default: + break; + } + } + else + { + break; + } + } while(!valid_event); + + return valid_event; +} diff --git a/src/platform_linux.h b/src/platform_linux.h index c59bb69..0eebe82 100644 --- a/src/platform_linux.h +++ b/src/platform_linux.h @@ -102,7 +102,8 @@ i32 _EPrintf(const char *fmt, va_list arg); // Window Functions b32 _CreateWindow(); Window *_GetWindow(); - +b32 _GetWindowEvent(WindowEvent *event); +WindowSize _GetWindowSize(); // Platform API END diff --git a/src/render_vulkan.c b/src/render_vulkan.c index 1ccc509..6327037 100644 --- a/src/render_vulkan.c +++ b/src/render_vulkan.c @@ -6,7 +6,6 @@ b32 _InitRenderer(Arena *arena) { Assert(InitVulkan(arena), "InitVkLib failure"); - ArenaFree(arena); return true; } @@ -27,7 +26,9 @@ void _DestroyRenderer() static b32 InitVulkan(Arena *arena) { Assert(arena != NULL, "Vulkan memory is null"); - renderer.arena = arena; + renderer.perm_arena = arena; + void *mem = ArenaAlloc(arena, MB(4)); + renderer.arena = CreateArena(mem, MB(4)); Assert(InitVkGlobalFunctions(), "Unable to load vulkan functions"); Assert(vkCreateInstance(&inst_info, NULL, &renderer.vk.inst) == VK_SUCCESS, "Error initializing instance"); @@ -43,9 +44,17 @@ static b32 InitVulkan(Arena *arena) Assert(CreateSurface(), "Unable to create surface"); Assert(CreateDevice(), "Unable to create device"); + + + Assert(CreateVmaAllocator(), "Unable to create VMA allocator"); Assert(CreateFrameStructures(), "Unable to create frame structures"); Assert(CreateImmediateStructures(), "Unable to create immediate structures"); + Assert(CreateSwapchain(), "Unable to initialize swapchain and draw images"); + + ArenaFree(renderer.arena); + + Printfln("yeah"); return true; } @@ -84,7 +93,7 @@ static DeviceQueues CheckDeviceQueueSupport(VkPhysicalDevice device, VkSurfaceKH u32 queue_count; vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_count, NULL); VkQueueFamilyProperties *families = ArenaAlloc(renderer.arena, sizeof(VkQueueFamilyProperties) * queue_count); - vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_count, &families[0]); + vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_count, families); for (i32 i = 0; i < queue_count; i++) { @@ -115,7 +124,7 @@ static b32 CheckDevicePropertiesSupport(VkPhysicalDevice device, VkSurfaceKHR su u32 ext_count; vkEnumerateDeviceExtensionProperties(device, NULL, &ext_count, NULL); VkExtensionProperties *ext_properties = ArenaAlloc(renderer.arena, sizeof(VkExtensionProperties) * ext_count); - vkEnumerateDeviceExtensionProperties(device, NULL, &ext_count, &ext_properties[0]); + vkEnumerateDeviceExtensionProperties(device, NULL, &ext_count, ext_properties); i32 matched = 0; for (u32 i = 0; i < ext_count; i++) { @@ -179,7 +188,7 @@ static b32 CreateDevice() u32 device_count; vkEnumeratePhysicalDevices(inst, &device_count, NULL); VkPhysicalDevice *devices = ArenaAlloc(renderer.arena, sizeof(VkPhysicalDevice) * device_count); - vkEnumeratePhysicalDevices(inst, &device_count, &devices[0]); + vkEnumeratePhysicalDevices(inst, &device_count, devices); b32 discrete_device = false; DeviceQueues *queues = &renderer.vk.queues; @@ -288,6 +297,8 @@ static b32 InitVkInstanceFunctions() INIT_INST_FN(vkGetDeviceProcAddr); INIT_INST_FN(vkDestroyInstance); INIT_INST_FN(vkDestroySurfaceKHR); + INIT_INST_FN(vkGetPhysicalDeviceSurfaceCapabilitiesKHR); + INIT_INST_FN(vkGetPhysicalDeviceImageFormatProperties); return true; } @@ -364,6 +375,7 @@ static b32 CreateSurface() if (result != VK_SUCCESS) { Printf("Unable to create surface: %d", result); } + Printfln("surface: %d", renderer.vk.surface); return result == VK_SUCCESS; } @@ -471,19 +483,185 @@ static b32 CreateImmediateStructures() static b32 CreateSwapchain() { + Printfln("%d", __LINE__); b32 success = true; + VkPhysicalDevice phys_device = renderer.vk.phys_device; + VkDevice device = renderer.vk.device; + VkSurfaceKHR surface = renderer.vk.surface; + VkSurfaceCapabilitiesKHR capabilities; + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(phys_device, surface, &capabilities); + Printfln("%d", __LINE__); + VkExtent2D extent; + WindowSize win_size = GetWindowSize(); + extent.width = u32Clamp((u32)win_size.w, capabilities.minImageExtent.width, capabilities.maxImageExtent.width); + extent.height = u32Clamp((u32)win_size.h, capabilities.minImageExtent.height, capabilities.maxImageExtent.height); + + u32 format_count; + vkGetPhysicalDeviceSurfaceFormatsKHR(phys_device, surface, &format_count, NULL); + VkSurfaceFormatKHR *formats = ArenaAlloc(renderer.arena, sizeof(VkSurfaceFormatKHR) * format_count); + vkGetPhysicalDeviceSurfaceFormatsKHR(phys_device, surface, &format_count, formats); + + renderer.vk.sc_info.format = formats[0].format; + renderer.vk.sc_info.color_space = formats[0].colorSpace; + + u32 present_count; + vkGetPhysicalDeviceSurfacePresentModesKHR(phys_device, surface, &present_count, NULL); + VkPresentModeKHR *present_modes = ArenaAlloc(renderer.arena, sizeof(VkSurfaceFormatKHR) * present_count); + vkGetPhysicalDeviceSurfacePresentModesKHR(phys_device, surface, &present_count, present_modes); + + Printfln("%d", __LINE__); + + VkPresentModeKHR present_mode; + for (u32 i = 0; i < present_count; i++) + { + if (present_modes[i] == VK_PRESENT_MODE_MAILBOX_KHR) + { + present_mode = VK_PRESENT_MODE_MAILBOX_KHR; + break; + } + } + + if (present_mode != VK_PRESENT_MODE_MAILBOX_KHR) + present_mode = VK_PRESENT_MODE_FIFO_KHR; + + swapchain_create_info.minImageCount = capabilities.minImageCount + 1; + swapchain_create_info.surface = surface; + swapchain_create_info.imageFormat = renderer.vk.sc_info.format; + swapchain_create_info.imageColorSpace = renderer.vk.sc_info.color_space; + swapchain_create_info.imageExtent = extent; + swapchain_create_info.preTransform = capabilities.currentTransform; + swapchain_create_info.presentMode = present_mode; + + VkResult result; + result = vkCreateSwapchainKHR(device, &swapchain_create_info, NULL, &renderer.vk.swapchain); + if (result != VK_SUCCESS) + success = false; + + u32 image_count; + vkGetSwapchainImagesKHR(device, renderer.vk.swapchain, &image_count, NULL); + VkImage *sc_images = ArenaAlloc(renderer.perm_arena, sizeof(VkImage) * image_count); + VkImageView *sc_views = ArenaAlloc(renderer.perm_arena, sizeof(VkImage) * image_count); + vkGetSwapchainImagesKHR(device, renderer.vk.swapchain, &image_count, sc_images); + + for (u32 i = 0; i < image_count; i++) + { + sc_image_view_create_info.image = sc_images[i]; + sc_image_view_create_info.format = renderer.vk.sc_info.format; + + result = vkCreateImageView(device, &sc_image_view_create_info, NULL, &sc_views[i]); + if (result != VK_SUCCESS) + success = false; + } + + renderer.vk.sc_info.imgs = sc_images; + renderer.vk.sc_info.views = sc_views; + renderer.vk.sc_info.img_count = image_count; + + VkFormat image_format = GetImageFormat(); + VkExtent3D extent_3d = { + .width = extent.width, + .height = extent.height, + .depth = 1, + }; + + renderer.vk.sc_info.extent = extent_3d; + + VmaAllocationCreateInfo alloc_create_info = { + .usage = VMA_MEMORY_USAGE_GPU_ONLY, + .requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + }; + + // Draw Image + draw_image_create_info.format = image_format; + draw_image_create_info.extent = extent_3d; + + result = vmaCreateImage(renderer.vk.alloc, &draw_image_create_info, + &alloc_create_info, &renderer.vk.sc_info.draw_img.img, &renderer.vk.sc_info.draw_img.alloc, NULL); + if (result != VK_SUCCESS) + success = false; + + // Draw Image View + draw_image_view_create_info.image = renderer.vk.sc_info.draw_img.img; + draw_image_view_create_info.format = image_format; + + result = vkCreateImageView(device, &draw_image_view_create_info, NULL, &renderer.vk.sc_info.draw_img.view); + if (result != VK_SUCCESS) + success = false; + + // Depth Image + depth_image_create_info.extent = extent_3d; + + result = vmaCreateImage(renderer.vk.alloc, &depth_image_create_info, + &alloc_create_info, &renderer.vk.sc_info.depth_img.img, &renderer.vk.sc_info.depth_img.alloc, NULL); + if (result != VK_SUCCESS) + success = false; + + // Depth Image View + depth_image_view_create_info.image = renderer.vk.sc_info.depth_img.img; + result = vkCreateImageView(device, &depth_image_view_create_info, NULL, &renderer.vk.sc_info.depth_img.view); + if (result != VK_SUCCESS) + success = false; + return success; } +static VkFormat GetImageFormat() +{ + VkPhysicalDevice phys_device = renderer.vk.phys_device; + VkImageType image_type = VK_IMAGE_TYPE_2D; + VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL; + VkImageUsageFlags usage_flags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | + VK_IMAGE_USAGE_TRANSFER_DST_BIT | + VK_IMAGE_USAGE_STORAGE_BIT | + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + + VkFormat format = 0; + for (i32 i = 0; i < Len(VK_IMAGE_FORMATS); i++) + { + VkImageFormatProperties properties; + VkResult result; + result = vkGetPhysicalDeviceImageFormatProperties(phys_device, VK_IMAGE_FORMATS[i], image_type, + tiling, usage_flags, 0, &properties); + if (result == VK_ERROR_FORMAT_NOT_SUPPORTED) + continue; + + if (result == VK_SUCCESS) + { + format = VK_IMAGE_FORMATS[i]; + break; + } + } + + Assert(format != 0, "[Error] unable to find appropriate image format"); + + return format; +} + static void DestroyVulkan() { VkDevice device = renderer.vk.device; VkInstance instance = renderer.vk.inst; FrameStructures data = renderer.vk.frame; ImmediateStructures imm = renderer.vk.imm; + SwapchainInfo sc_info = renderer.vk.sc_info; + VmaAllocator vma_alloc = renderer.vk.alloc; + VkSwapchainKHR swapchain = renderer.vk.swapchain; + + vkDestroyImageView(device, sc_info.draw_img.view, NULL); + vmaDestroyImage(vma_alloc, sc_info.draw_img.img, sc_info.draw_img.alloc); + + vkDestroyImageView(device, sc_info.depth_img.view, NULL); + vmaDestroyImage(vma_alloc, sc_info.depth_img.img, sc_info.depth_img.alloc); + + for (u32 i = 0; i < sc_info.img_count; i++) + { + vkDestroyImageView(device, sc_info.views[i], NULL); + } + + vkDestroySwapchainKHR(device, swapchain, NULL); vkDestroyFence(device, imm.fence, NULL); vkFreeCommandBuffers(device, imm.pool, 1, &imm.buffer); @@ -511,6 +689,119 @@ static void DestroyVulkan() vkDestroyInstance(renderer.vk.inst, NULL); } +const char *VkResultStr(VkResult result) +{ + switch (result) + { + case VK_SUCCESS: + return "VK_SUCCESS"; + case VK_NOT_READY: + return "VK_NOT_READY"; + case VK_TIMEOUT: + return "VK_TIMEOUT"; + case VK_EVENT_SET: + return "VK_EVENT_SET"; + case VK_EVENT_RESET: + return "VK_EVENT_RESET"; + case VK_INCOMPLETE: + return "VK_INCOMPLETE"; + case VK_ERROR_OUT_OF_HOST_MEMORY: + return "VK_ERROR_OUT_OF_HOST_MEMORY"; + case VK_ERROR_OUT_OF_DEVICE_MEMORY: + return "VK_ERROR_OUT_OF_DEVICE_MEMORY"; + case VK_ERROR_INITIALIZATION_FAILED: + return "VK_ERROR_INITIALIZATION_FAILED"; + case VK_ERROR_DEVICE_LOST: + return "VK_ERROR_DEVICE_LOST"; + case VK_ERROR_MEMORY_MAP_FAILED: + return "VK_ERROR_MEMORY_MAP_FAILED"; + case VK_ERROR_LAYER_NOT_PRESENT: + return "VK_ERROR_LAYER_NOT_PRESENT"; + case VK_ERROR_EXTENSION_NOT_PRESENT: + return "VK_ERROR_EXTENSION_NOT_PRESENT"; + case VK_ERROR_FEATURE_NOT_PRESENT: + return "VK_ERROR_FEATURE_NOT_PRESENT"; + case VK_ERROR_INCOMPATIBLE_DRIVER: + return "VK_ERROR_INCOMPATIBLE_DRIVER"; + case VK_ERROR_TOO_MANY_OBJECTS: + return "VK_ERROR_TOO_MANY_OBJECTS"; + case VK_ERROR_FORMAT_NOT_SUPPORTED: + return "VK_ERROR_FORMAT_NOT_SUPPORTED"; + case VK_ERROR_FRAGMENTED_POOL: + return "VK_ERROR_FRAGMENTED_POOL"; + case VK_ERROR_UNKNOWN: + return "VK_ERROR_UNKNOWN"; + case VK_ERROR_OUT_OF_POOL_MEMORY: + return "VK_ERROR_OUT_OF_POOL_MEMORY"; + case VK_ERROR_INVALID_EXTERNAL_HANDLE: + return "VK_ERROR_INVALID_EXTERNAL_HANDLE"; + case VK_ERROR_FRAGMENTATION: + return "VK_ERROR_FRAGMENTATION"; + case VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS: + return "VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS"; + case VK_PIPELINE_COMPILE_REQUIRED: + return "VK_PIPELINE_COMPILE_REQUIRED"; + case VK_ERROR_SURFACE_LOST_KHR: + return "VK_ERROR_SURFACE_LOST_KHR"; + case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: + return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR"; + case VK_SUBOPTIMAL_KHR: + return "VK_SUBOPTIMAL_KHR"; + case VK_ERROR_OUT_OF_DATE_KHR: + return "VK_ERROR_OUT_OF_DATE_KHR"; + case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: + return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR"; + case VK_ERROR_VALIDATION_FAILED_EXT: + return "VK_ERROR_VALIDATION_FAILED_EXT"; + case VK_ERROR_INVALID_SHADER_NV: + return "VK_ERROR_INVALID_SHADER_NV"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR: + return "VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR"; +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR: + return "VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR"; +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR: + return "VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR"; +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR: + return "VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR"; +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR: + return "VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR"; +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR: + return "VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR"; +#endif + case VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT: + return "VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT"; + case VK_ERROR_NOT_PERMITTED_KHR: + return "VK_ERROR_NOT_PERMITTED_KHR"; + case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT: + return "VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT"; + case VK_THREAD_IDLE_KHR: + return "VK_THREAD_IDLE_KHR"; + case VK_THREAD_DONE_KHR: + return "VK_THREAD_DONE_KHR"; + case VK_OPERATION_DEFERRED_KHR: + return "VK_OPERATION_DEFERRED_KHR"; + case VK_OPERATION_NOT_DEFERRED_KHR: + return "VK_OPERATION_NOT_DEFERRED_KHR"; + case VK_ERROR_COMPRESSION_EXHAUSTED_EXT: + return "VK_ERROR_COMPRESSION_EXHAUSTED_EXT"; + case VK_RESULT_MAX_ENUM: + return "VK_RESULT_MAX_ENUM"; + default: + return "??????"; + } +} + static VkBool32 DebugCallback( VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, VkDebugUtilsMessageTypeFlagsEXT message_type, diff --git a/src/render_vulkan.h b/src/render_vulkan.h index 0b597a9..5490544 100644 --- a/src/render_vulkan.h +++ b/src/render_vulkan.h @@ -47,6 +47,7 @@ VK_DECLARE(vkEnumerateDeviceExtensionProperties); VK_DECLARE(vkGetPhysicalDeviceSurfacePresentModesKHR); VK_DECLARE(vkGetPhysicalDeviceSurfaceFormatsKHR); VK_DECLARE(vkGetPhysicalDeviceSurfaceCapabilitiesKHR); +VK_DECLARE(vkGetPhysicalDeviceImageFormatProperties); #ifdef __linux__ VK_DECLARE(vkCreateXcbSurfaceKHR); @@ -137,16 +138,36 @@ typedef struct { VkQueue graphics_queue, transfer_queue; } DeviceQueues; +typedef struct { + VkImage img; + VkImageView view; + VmaAllocation alloc; + VkFormat fmt; +} Image; + +typedef struct { + VkFormat format; + VkColorSpaceKHR color_space; + VkExtent3D extent; + VkImage *imgs; + VkImageView *views; + u32 img_count; + Image draw_img; + Image depth_img; +} SwapchainInfo; + typedef struct { Library lib; VkInstance inst; VkSurfaceKHR surface; VkDevice device; + VkSwapchainKHR swapchain; VkPhysicalDevice phys_device; DeviceQueues queues; VmaAllocator alloc; FrameStructures frame; ImmediateStructures imm; + SwapchainInfo sc_info; #ifdef BUILD_DEBUG VkDebugUtilsMessengerEXT debug; #endif @@ -155,6 +176,7 @@ typedef struct { typedef struct { Vulkan_t vk; Arena *arena; + Arena *perm_arena; } Renderer_t; // Renderer Function Declarations @@ -167,6 +189,7 @@ static VkBool32 DebugCallback( const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, void *pUserData ); +const char *VkResultStr(VkResult result); // Init static b32 LoadVulkanLib(); @@ -184,6 +207,7 @@ static b32 CreateVmaAllocator(); static b32 CreateFrameStructures(); static b32 CreateImmediateStructures(); static b32 CreateSwapchain(); +static VkFormat GetImageFormat(); // Destroy static void DestroyVulkan(); diff --git a/src/util.c b/src/util.c index c7fb39b..8989a00 100644 --- a/src/util.c +++ b/src/util.c @@ -78,3 +78,33 @@ void MemZero(void *ptr, isize size) assert(test_ptr[i] == 0); } } + +u32 u32Min(u32 l, u32 r) +{ + return l >= r ? r : l; +} + +i32 i32Min(i32 l, i32 r) +{ + return l >= r ? r : l; +} + +u32 u32Max(u32 l, u32 r) +{ + return l >= r ? l : r; +} + +i32 i32Max(i32 l, i32 r) +{ + return l >= r ? l : r; +} + +i32 i32Clamp(i32 v, i32 min, i32 max) +{ + return i32Min(max, i32Max(v, min)); +} + +u32 u32Clamp(u32 v, u32 min, u32 max) +{ + return i32Min(max, i32Max(v, min)); +} diff --git a/src/util.h b/src/util.h index 18cff16..deb00ba 100644 --- a/src/util.h +++ b/src/util.h @@ -17,3 +17,11 @@ i32 SPrintf(char *buf, rawptr fmt, ...); // Memory Functions void MemZero(void *ptr, isize size); + +// Math Functions +u32 u32Min(u32 l, u32 r); +i32 i32Min(i32 l, i32 r); +u32 u32Max(u32 l, u32 r); +i32 i32Max(i32 l, i32 r); +i32 i32Clamp(i32 v, i32 min, i32 max); +u32 u32Clamp(u32 v, u32 min, u32 max); diff --git a/src/vulkan_config.c b/src/vulkan_config.c index 7e1de83..761bf2c 100644 --- a/src/vulkan_config.c +++ b/src/vulkan_config.c @@ -1,5 +1,11 @@ // VULKAN CONFIG + +static const VkFormat VK_IMAGE_FORMATS[] = { + VK_FORMAT_R16G16B16A16_UNORM, + VK_FORMAT_R8G8B8A8_UNORM, +}; + static VkApplicationInfo app_info = { .sType = STYPE(APPLICATION_INFO), .pApplicationName = "Video Game", @@ -110,3 +116,76 @@ static VkCommandBufferAllocateInfo cmd_buf_info = { .commandBufferCount = 1, .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, }; + +static VkSwapchainCreateInfoKHR swapchain_create_info = { + .sType = STYPE(SWAPCHAIN_CREATE_INFO_KHR), + .imageArrayLayers = 1, + .imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, + .clipped = VK_TRUE, + .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE, +}; + +static VkImageViewCreateInfo sc_image_view_create_info = { + .sType = STYPE(IMAGE_VIEW_CREATE_INFO), + .viewType = VK_IMAGE_VIEW_TYPE_2D, + .components = { + .r = VK_COMPONENT_SWIZZLE_IDENTITY, + .g = VK_COMPONENT_SWIZZLE_IDENTITY, + .b = VK_COMPONENT_SWIZZLE_IDENTITY, + .a = VK_COMPONENT_SWIZZLE_IDENTITY, + }, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }, +}; + +static VkImageCreateInfo draw_image_create_info = { + .sType = STYPE(IMAGE_CREATE_INFO), + .imageType = VK_IMAGE_TYPE_2D, + .mipLevels = 1, + .arrayLayers = 1, + .samples = VK_SAMPLE_COUNT_1_BIT, + .tiling = VK_IMAGE_TILING_OPTIMAL, + .usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, +}; + +static VkImageViewCreateInfo draw_image_view_create_info = { + .sType = STYPE(IMAGE_VIEW_CREATE_INFO), + .viewType = VK_IMAGE_VIEW_TYPE_2D, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }, +}; + +static VkImageCreateInfo depth_image_create_info = { + .sType = STYPE(IMAGE_CREATE_INFO), + .imageType = VK_IMAGE_TYPE_2D, + .mipLevels = 1, + .arrayLayers = 1, + .samples = VK_SAMPLE_COUNT_1_BIT, + .tiling = VK_IMAGE_TILING_OPTIMAL, + .format = VK_FORMAT_D32_SFLOAT, + .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, +}; + +static VkImageViewCreateInfo depth_image_view_create_info = { + .sType = STYPE(IMAGE_VIEW_CREATE_INFO), + .viewType = VK_IMAGE_VIEW_TYPE_2D, + .format = VK_FORMAT_D32_SFLOAT, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }, +};