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 --- deimos/core/allocator.h | 27 ++++ deimos/vulkan/BUILD | 5 +- deimos/vulkan/vulkan.h | 48 ------ deimos/vulkan/vulkan_backend.cpp | 318 +++++++++++++++++++++++++++++++++++++++ deimos/vulkan/vulkan_backend.h | 33 ++++ deimos/vulkan/vulkan_loader.cpp | 12 +- deimos/vulkan/vulkan_loader.h | 49 ++++++ main/main.cpp | 273 +++------------------------------ 8 files changed, 454 insertions(+), 311 deletions(-) delete mode 100644 deimos/vulkan/vulkan.h create mode 100644 deimos/vulkan/vulkan_backend.cpp create mode 100644 deimos/vulkan/vulkan_backend.h create mode 100644 deimos/vulkan/vulkan_loader.h diff --git a/deimos/core/allocator.h b/deimos/core/allocator.h index 07a214e..9e8dd87 100644 --- a/deimos/core/allocator.h +++ b/deimos/core/allocator.h @@ -116,6 +116,33 @@ public: std::forward(arg3)); } + template + constexpr gsl::owner New( + A0&& arg0, A1&& arg1, A2&& arg2, A3&& arg3, A4&& arg4, + const SourceLocation& source_location = {}) + { + return NewInner(source_location, + std::forward(arg0), + std::forward(arg1), + std::forward(arg2), + std::forward(arg3), + std::forward(arg4)); + } + + template + constexpr gsl::owner New( + A0&& arg0, A1&& arg1, A2&& arg2, A3&& arg3, A4&& arg4, A5&& arg5, + const SourceLocation& source_location = {}) + { + return NewInner(source_location, + std::forward(arg0), + std::forward(arg1), + std::forward(arg2), + std::forward(arg3), + std::forward(arg4), + std::forward(arg5)); + } + template void Delete(gsl::owner t, const SourceLocation& source_location = {}) { diff --git a/deimos/vulkan/BUILD b/deimos/vulkan/BUILD index 5eae9ef..238261f 100644 --- a/deimos/vulkan/BUILD +++ b/deimos/vulkan/BUILD @@ -1,10 +1,13 @@ cc_library( name = "vulkan", hdrs = [ - "vulkan.h", + "vulkan_backend.h", + "vulkan_loader.h", ], srcs = [ + "vulkan_backend.cpp", "vulkan_loader.cpp", + "vulkan_bootstrap_functions.inc", "vulkan_entry_functions.inc", "vulkan_instance_functions.inc", diff --git a/deimos/vulkan/vulkan.h b/deimos/vulkan/vulkan.h deleted file mode 100644 index f116fc0..0000000 --- a/deimos/vulkan/vulkan.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include - -#define VK_NO_STDINT_H -#define VK_NO_STDDEF_H -#include - -#include - -using HINSTANCE = void*; -using HWND = void*; -#include - -namespace deimos -{ - -class ApiRegistry; - -struct VulkanApi -{ -#define FN(NAME) PFN_vk##NAME NAME{}; -#include "deimos/vulkan/vulkan_bootstrap_functions.inc" -#include "deimos/vulkan/vulkan_entry_functions.inc" -#include "deimos/vulkan/vulkan_instance_functions.inc" -#include "deimos/vulkan/vulkan_device_functions.inc" -#undef FN -}; - -class VulkanLoaderApi -{ -public: - VulkanLoaderApi() = default; - deimos_NO_COPY_MOVE(VulkanLoaderApi); - virtual ~VulkanLoaderApi() = default; - - static constexpr IdName kApiName{"deimos::VulkanLoaderApi"}; - - virtual VulkanApi* LoadEntry() = 0; - - virtual void LoadInstance(VulkanApi*, VkInstance) = 0; - virtual void LoadDevice(VulkanApi*, VkDevice) = 0; -}; - -void RegisterVulkanLoaderApi(ApiRegistry*); - -} // namespace deimos - diff --git a/deimos/vulkan/vulkan_backend.cpp b/deimos/vulkan/vulkan_backend.cpp new file mode 100644 index 0000000..173e671 --- /dev/null +++ b/deimos/vulkan/vulkan_backend.cpp @@ -0,0 +1,318 @@ +#include "deimos/vulkan/vulkan_backend.h" + +#include "deimos/vulkan/vulkan_loader.h" + +#include +#include +#include +#include +#include + +namespace +{ + +using namespace deimos; + +LogApi* log_api; +OsApi* os_api; +ApiRegistry* api_registry; +TempAllocatorApi* temp_api; +VulkanLoaderApi* vulkan_loader_api; + +const VkAllocationCallbacks* kVkAlloc = nullptr; + +class VulkanBackendImpl : public IVulkanBackend +{ + VulkanApi* m_vk; + VkInstance m_instance; + VkPhysicalDevice m_physical_device; + uint32_t m_queue_family; + VkSurfaceKHR m_surface; + VkDevice m_device; + VkQueue m_queue = VK_NULL_HANDLE; + +public: + VulkanBackendImpl( + VulkanApi* vk, + VkInstance instance, + VkPhysicalDevice physical_device, + uint32_t queue_family, + VkSurfaceKHR surface, + VkDevice device) : + m_vk{vk}, m_instance{instance}, m_physical_device{physical_device}, + m_queue_family{queue_family}, m_surface{surface}, m_device{device} + { + m_vk->GetDeviceQueue(m_device, m_queue_family, 0, &m_queue); + Ensures(m_queue != VK_NULL_HANDLE); + } +}; + +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; +} + +StatusOr> InitializeVulkan(Allocator* allocator, OsWindow* window) +{ + auto* vk = vulkan_loader_api->LoadEntry(allocator); + + VkInstance instance{}; + { + StatusOr s = CreateInstance(vk); + if (!s.ok()) { return s.status(); } + instance = s.value(); + log_api->LogInfo("Vulkan instance created"); + } + + vulkan_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"); + } + + vulkan_loader_api->LoadDevice(vk, device); + + return allocator->New( + vk, instance, physical_device, + queue_family, surface, device); +} + +} // anonymous namespace + +namespace deimos +{ + +class VulkanBackendApiImpl : public VulkanBackendApi +{ +public: + StatusOr> CreateBackend(Allocator* allocator, OsWindow* window) override + { + return InitializeVulkan(allocator, window); + } +}; + +void RegisterVulkanBackendApi(ApiRegistry* registry) +{ + api_registry = registry; + log_api = registry->Get(); + os_api = registry->Get(); + temp_api = registry->Get(); + vulkan_loader_api = registry->Get(); + + auto* allocator_api = registry->Get(); + + auto* impl = allocator_api->system->New(); + registry->Set(impl); + + log_api->LogInfo("Vulkan backend API registered"); +} + +} // namespace deimos + diff --git a/deimos/vulkan/vulkan_backend.h b/deimos/vulkan/vulkan_backend.h new file mode 100644 index 0000000..90aaf2a --- /dev/null +++ b/deimos/vulkan/vulkan_backend.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include + +namespace deimos +{ + +class ApiRegistry; +class Allocator; +struct OsWindow; + +class IVulkanBackend +{ +public: +}; + +class VulkanBackendApi +{ +public: + VulkanBackendApi() = default; + deimos_NO_COPY_MOVE(VulkanBackendApi); + virtual ~VulkanBackendApi() = default; + + static constexpr IdName kApiName{"deimos::VulkanBackendApi"}; + + virtual StatusOr> CreateBackend(Allocator*, OsWindow*) = 0; +}; + +void RegisterVulkanBackendApi(ApiRegistry*); + +} // namespace deimos + diff --git a/deimos/vulkan/vulkan_loader.cpp b/deimos/vulkan/vulkan_loader.cpp index b9980af..c4d7d87 100644 --- a/deimos/vulkan/vulkan_loader.cpp +++ b/deimos/vulkan/vulkan_loader.cpp @@ -1,4 +1,4 @@ -#include "deimos/vulkan/vulkan.h" +#include "deimos/vulkan/vulkan_loader.h" #include #include @@ -13,13 +13,10 @@ namespace deimos class VulkanLoaderImpl : public VulkanLoaderApi { - Allocator* m_allocator; gsl::owner m_vulkan_dll{}; public: - explicit VulkanLoaderImpl(Allocator* allocator) : m_allocator{allocator} {} - - VulkanApi* LoadEntry() override + VulkanApi* LoadEntry(Allocator* allocator) override { if (m_vulkan_dll == nullptr) { @@ -34,7 +31,7 @@ public: } } - VulkanApi* api = m_allocator->New(); + VulkanApi* api = allocator->New(); #define FN(NAME) api->NAME = (PFN_vk##NAME)os_api->dll->GetSymbol(m_vulkan_dll, "vk" #NAME); #include "deimos/vulkan/vulkan_bootstrap_functions.inc" @@ -76,9 +73,8 @@ void RegisterVulkanLoaderApi(ApiRegistry* registry) log_api = registry->Get(); auto* allocator_api = registry->Get(); - auto* allocator = allocator_api->CreateChild(allocator_api->system, "Vulkan"); - auto* impl = allocator->New(allocator); + auto* impl = allocator_api->system->New(); registry->Set(impl); log_api->LogInfo("Vulkan loader API registered"); diff --git a/deimos/vulkan/vulkan_loader.h b/deimos/vulkan/vulkan_loader.h new file mode 100644 index 0000000..1339ba4 --- /dev/null +++ b/deimos/vulkan/vulkan_loader.h @@ -0,0 +1,49 @@ +#pragma once + +#include + +#define VK_NO_STDINT_H +#define VK_NO_STDDEF_H +#include + +#include + +using HINSTANCE = void*; +using HWND = void*; +#include + +namespace deimos +{ + +class ApiRegistry; +class Allocator; + +struct VulkanApi +{ +#define FN(NAME) PFN_vk##NAME NAME{}; +#include "deimos/vulkan/vulkan_bootstrap_functions.inc" +#include "deimos/vulkan/vulkan_entry_functions.inc" +#include "deimos/vulkan/vulkan_instance_functions.inc" +#include "deimos/vulkan/vulkan_device_functions.inc" +#undef FN +}; + +class VulkanLoaderApi +{ +public: + VulkanLoaderApi() = default; + deimos_NO_COPY_MOVE(VulkanLoaderApi); + virtual ~VulkanLoaderApi() = default; + + static constexpr IdName kApiName{"deimos::VulkanLoaderApi"}; + + virtual VulkanApi* LoadEntry(Allocator* allocator) = 0; + + virtual void LoadInstance(VulkanApi*, VkInstance) = 0; + virtual void LoadDevice(VulkanApi*, VkDevice) = 0; +}; + +void RegisterVulkanLoaderApi(ApiRegistry*); + +} // namespace deimos + 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