From 909304e44763c58c0ebbe40068a58784ebaced7b Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Fri, 3 May 2024 00:40:22 +0200 Subject: Add Vulkan backend API --- main/main.cpp | 273 ++++------------------------------------------------------ 1 file changed, 19 insertions(+), 254 deletions(-) (limited to 'main/main.cpp') diff --git a/main/main.cpp b/main/main.cpp index 602b6ab..0f0de71 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -3,269 +3,29 @@ #include #include #include -#include +#include +#include using namespace deimos; static LogApi* log_api; -static TempAllocatorApi* temp_api; +static AllocatorApi* allocator_api; static OsApi* os_api; +static VulkanBackendApi* vulkan_backend_api; -static const VkAllocationCallbacks* kVkAlloc = nullptr; - -StatusOr CreateInstance(VulkanApi* vk) -{ - const VkApplicationInfo application_info{ - .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, - .pNext = nullptr, - .pApplicationName = "Deimos game", - .applicationVersion = 0, - .pEngineName = "Deimos engine", - .engineVersion = 0, - .apiVersion = VK_API_VERSION_1_3, - }; - - const char* extensions[]{ - VK_KHR_SURFACE_EXTENSION_NAME, - VK_KHR_WIN32_SURFACE_EXTENSION_NAME, - }; - - // @Todo Select layers & extensions based on config - const char* layers[]{ - "VK_LAYER_KHRONOS_validation", - "VK_LAYER_LUNARG_monitor", - }; - - const VkInstanceCreateInfo create_info{ - .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .pApplicationInfo = &application_info, - .enabledLayerCount = (uint32_t)ArraySize(layers), - .ppEnabledLayerNames = layers, - .enabledExtensionCount = (uint32_t)ArraySize(extensions), - .ppEnabledExtensionNames = extensions, - }; - - VkInstance instance{}; - const VkResult res = vk->CreateInstance(&create_info, kVkAlloc, &instance); - if (res != VK_SUCCESS) - { - return InternalError("vkCreateInstance failed"); - } - - return instance; -} - -StatusOr CreateSurface(VulkanApi* vk, VkInstance instance, OsWindow* window) -{ - const VkWin32SurfaceCreateInfoKHR create_info{ - .sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, - .pNext = nullptr, - .flags = 0, - .hinstance = os_api->window->Win32Hinstance(window), - .hwnd = os_api->window->Win32Hwnd(window), - }; - - VkSurfaceKHR surface{}; - const VkResult res = vk->CreateWin32SurfaceKHR(instance, &create_info, kVkAlloc, &surface); - if (res != VK_SUCCESS) - { - return InternalError("vkCreateWin32SurfaceKHR failed"); - } - - return surface; -} - -StatusOr FindQueueFamily(VulkanApi* vk, VkPhysicalDevice physical_device, VkSurfaceKHR surface) -{ - auto temp_alloc = temp_api->Acquire(); - - uint32_t queue_family_count = 0; - vk->GetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_family_count, nullptr); - if (queue_family_count == 0) - { - return InternalError("No queue on this physical device"); - } - - log_api->LogInfo("Physical device has $ queue families", queue_family_count); - - auto queue_families = temp_alloc.allocator().NewArray(queue_family_count); - vk->GetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_family_count, queue_families.data()); - - for (uint32_t index = 0; index < queue_family_count; ++index) - { - const auto& prps = queue_families[index]; - - const bool supports_graphics_compute = (prps.queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0 && (prps.queueFlags & VK_QUEUE_COMPUTE_BIT) != 0; - - VkBool32 vk_supports_presentation{}; - const VkResult presentation_res = vk->GetPhysicalDeviceSurfaceSupportKHR(physical_device, index, surface, &vk_supports_presentation); - const bool supports_presentation = presentation_res == VK_SUCCESS && vk_supports_presentation == VK_TRUE; - - if (supports_graphics_compute && supports_presentation) - { - return index; - } - } - - return InternalError("Couldn't find a suitable queue"); -} - -Status FindPhysicalDevice( - VulkanApi* vk, - VkInstance instance, - VkSurfaceKHR surface, - VkPhysicalDevice* out_physical_device, - uint32_t* out_queue_family) -{ - auto temp_alloc = temp_api->Acquire(); - - uint32_t physical_device_count = 0; - vk->EnumeratePhysicalDevices(instance, &physical_device_count, nullptr); - if (physical_device_count == 0) - { - return InternalError("No Vulkan device found"); - } - - log_api->LogInfo("Found $ physical devices", physical_device_count); - - auto physical_devices = temp_alloc.allocator().NewArray(physical_device_count); - vk->EnumeratePhysicalDevices(instance, &physical_device_count, physical_devices.data()); - - for (VkPhysicalDevice physical_device: physical_devices) - { - { - VkPhysicalDeviceVulkan12Properties prps12{}; - prps12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES; - prps12.pNext = nullptr; - - VkPhysicalDeviceProperties2 prps{}; - prps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; - prps.pNext = &prps12; - - vk->GetPhysicalDeviceProperties2(physical_device, &prps); - - log_api->LogInfo("Trying Vulkan device $ ($, $)", - prps.properties.deviceName, prps12.driverName, prps12.driverInfo); - } - - auto maybe_queue_family = FindQueueFamily(vk, physical_device, surface); - if (maybe_queue_family.ok()) - { - log_api->LogInfo("This device is compatible, choosing it"); - *out_physical_device = physical_device; - *out_queue_family = maybe_queue_family.value(); - return {}; - } - - log_api->LogInfo("Incompatible because: $", maybe_queue_family); - } - - return InternalError("No suitable device found"); -} - -StatusOr CreateDevice(VulkanApi* vk, VkPhysicalDevice physical_device, uint32_t queue_family) -{ - const float queue_priority = 1.0F; - - const VkDeviceQueueCreateInfo queue_create_info{ - .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .queueFamilyIndex = queue_family, - .queueCount = 1, - .pQueuePriorities = &queue_priority, - }; - - const char* extensions[]{ - VK_KHR_SWAPCHAIN_EXTENSION_NAME, - }; - - const VkDeviceCreateInfo create_info{ - .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .queueCreateInfoCount = 1, - .pQueueCreateInfos = &queue_create_info, - .enabledLayerCount = 0, - .ppEnabledLayerNames = nullptr, - .enabledExtensionCount = ArraySize(extensions), - .ppEnabledExtensionNames = extensions, - .pEnabledFeatures = nullptr, - }; - - VkDevice device = VK_NULL_HANDLE; - const VkResult res = vk->CreateDevice(physical_device, &create_info, kVkAlloc, &device); - if (res != VK_SUCCESS) - { - return InternalError("vkCreateDeviceFailed"); - } - - return device; -} - -Status InitializeVulkan(ApiRegistry* api_registry, OsWindow* window) -{ - RegisterVulkanLoaderApi(api_registry); - auto* loader_api = api_registry->Get(); - auto* vk = loader_api->LoadEntry(); - - VkInstance instance{}; - { - StatusOr s = CreateInstance(vk); - if (!s.ok()) { return s.status(); } - instance = s.value(); - log_api->LogInfo("Vulkan instance created"); - } - - loader_api->LoadInstance(vk, instance); - - VkSurfaceKHR surface{}; - { - StatusOr s = CreateSurface(vk, instance, window); - if (!s.ok()) { return s.status(); } - surface = s.value(); - log_api->LogInfo("Vulkan surface created"); - } - - VkPhysicalDevice physical_device{}; - uint32_t queue_family{}; - { - Status s = FindPhysicalDevice(vk, instance, surface, &physical_device, &queue_family); - if (!s.ok()) { return s; } - log_api->LogInfo("Vulkan queue family: $", queue_family); - } - - VkDevice device = VK_NULL_HANDLE; - { - StatusOr s = CreateDevice(vk, physical_device, queue_family); - if (!s.ok()) { return s.status(); } - device = s.value(); - log_api->LogInfo("Vulkan device created"); - } - - loader_api->LoadDevice(vk, device); - - VkQueue queue = VK_NULL_HANDLE; - vk->GetDeviceQueue(device, queue_family, 0, &queue); - Ensures(queue != VK_NULL_HANDLE); - - vk->DestroyDevice(device, kVkAlloc); - vk->DestroySurfaceKHR(instance, surface, kVkAlloc); - vk->DestroyInstance(instance, kVkAlloc); - - return {}; -} int main(int /* argc */, char* /* argv */[]) { auto* api_registry = InitializeGlobalApiRegistry(); + log_api = api_registry->Get(); - temp_api = api_registry->Get(); + allocator_api = api_registry->Get(); os_api = api_registry->Get(); - log_api->LogInfo("Base APIs registered"); + + RegisterVulkanLoaderApi(api_registry); + RegisterVulkanBackendApi(api_registry); + vulkan_backend_api = api_registry->Get(); OsWindow* window{}; { @@ -278,11 +38,16 @@ int main(int /* argc */, char* /* argv */[]) window = s.value(); } - const Status s = InitializeVulkan(api_registry, window); - if (!s.ok()) + IVulkanBackend* vulkan = nullptr; { - log_api->LogError("Vulkan initializaiton error: $", s); - return 1; + StatusOr s = vulkan_backend_api->CreateBackend(allocator_api->system, window); + if (!s.ok()) + { + log_api->LogError("Vulkan initialization error: $", s); + return 1; + } + vulkan = s.value(); + log_api->LogInfo("Vulkan backend created"); } while (!os_api->window->QuitRequested(window)) -- cgit