summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--deimos/core/allocator.h27
-rw-r--r--deimos/vulkan/BUILD5
-rw-r--r--deimos/vulkan/vulkan_backend.cpp318
-rw-r--r--deimos/vulkan/vulkan_backend.h33
-rw-r--r--deimos/vulkan/vulkan_loader.cpp12
-rw-r--r--deimos/vulkan/vulkan_loader.h (renamed from deimos/vulkan/vulkan.h)3
-rw-r--r--main/main.cpp273
7 files changed, 407 insertions, 264 deletions
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<A3>(arg3));
}
+ template<typename T, typename A0, typename A1, typename A2, typename A3, typename A4>
+ constexpr gsl::owner<T*> New(
+ A0&& arg0, A1&& arg1, A2&& arg2, A3&& arg3, A4&& arg4,
+ const SourceLocation& source_location = {})
+ {
+ return NewInner<T>(source_location,
+ std::forward<A0>(arg0),
+ std::forward<A1>(arg1),
+ std::forward<A2>(arg2),
+ std::forward<A3>(arg3),
+ std::forward<A4>(arg4));
+ }
+
+ template<typename T, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5>
+ constexpr gsl::owner<T*> New(
+ A0&& arg0, A1&& arg1, A2&& arg2, A3&& arg3, A4&& arg4, A5&& arg5,
+ const SourceLocation& source_location = {})
+ {
+ return NewInner<T>(source_location,
+ std::forward<A0>(arg0),
+ std::forward<A1>(arg1),
+ std::forward<A2>(arg2),
+ std::forward<A3>(arg3),
+ std::forward<A4>(arg4),
+ std::forward<A5>(arg5));
+ }
+
template<typename T>
void Delete(gsl::owner<T*> 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_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 <deimos/core/api_registry.h>
+#include <deimos/core/allocator.h>
+#include <deimos/core/temp_allocator.h>
+#include <deimos/core/log.h>
+#include <deimos/core/os.h>
+
+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<VkInstance> 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<VkSurfaceKHR> 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<uint32_t> 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<VkQueueFamilyProperties>(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<VkPhysicalDevice>(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<VkDevice> 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<gsl::owner<IVulkanBackend*>> InitializeVulkan(Allocator* allocator, OsWindow* window)
+{
+ auto* vk = vulkan_loader_api->LoadEntry(allocator);
+
+ VkInstance instance{};
+ {
+ StatusOr<VkInstance> 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<VkSurfaceKHR> 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<VkDevice> 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<VulkanBackendImpl>(
+ vk, instance, physical_device,
+ queue_family, surface, device);
+}
+
+} // anonymous namespace
+
+namespace deimos
+{
+
+class VulkanBackendApiImpl : public VulkanBackendApi
+{
+public:
+ StatusOr<gsl::owner<IVulkanBackend*>> CreateBackend(Allocator* allocator, OsWindow* window) override
+ {
+ return InitializeVulkan(allocator, window);
+ }
+};
+
+void RegisterVulkanBackendApi(ApiRegistry* registry)
+{
+ api_registry = registry;
+ log_api = registry->Get<LogApi>();
+ os_api = registry->Get<OsApi>();
+ temp_api = registry->Get<TempAllocatorApi>();
+ vulkan_loader_api = registry->Get<VulkanLoaderApi>();
+
+ auto* allocator_api = registry->Get<AllocatorApi>();
+
+ auto* impl = allocator_api->system->New<VulkanBackendApiImpl>();
+ 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 <deimos/core/id_name.h>
+#include <deimos/core/status.h>
+
+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<gsl::owner<IVulkanBackend*>> 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 <deimos/core/api_registry.h>
#include <deimos/core/allocator.h>
@@ -13,13 +13,10 @@ namespace deimos
class VulkanLoaderImpl : public VulkanLoaderApi
{
- Allocator* m_allocator;
gsl::owner<OsDll*> 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>();
+ VulkanApi* api = allocator->New<VulkanApi>();
#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<LogApi>();
auto* allocator_api = registry->Get<AllocatorApi>();
- auto* allocator = allocator_api->CreateChild(allocator_api->system, "Vulkan");
- auto* impl = allocator->New<VulkanLoaderImpl>(allocator);
+ auto* impl = allocator_api->system->New<VulkanLoaderImpl>();
registry->Set(impl);
log_api->LogInfo("Vulkan loader API registered");
diff --git a/deimos/vulkan/vulkan.h b/deimos/vulkan/vulkan_loader.h
index f116fc0..1339ba4 100644
--- a/deimos/vulkan/vulkan.h
+++ b/deimos/vulkan/vulkan_loader.h
@@ -16,6 +16,7 @@ namespace deimos
{
class ApiRegistry;
+class Allocator;
struct VulkanApi
{
@@ -36,7 +37,7 @@ public:
static constexpr IdName kApiName{"deimos::VulkanLoaderApi"};
- virtual VulkanApi* LoadEntry() = 0;
+ virtual VulkanApi* LoadEntry(Allocator* allocator) = 0;
virtual void LoadInstance(VulkanApi*, VkInstance) = 0;
virtual void LoadDevice(VulkanApi*, VkDevice) = 0;
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 <deimos/core/temp_allocator.h>
#include <deimos/core/os.h>
#include <deimos/core/status.h>
-#include <deimos/vulkan/vulkan.h>
+#include <deimos/vulkan/vulkan_loader.h>
+#include <deimos/vulkan/vulkan_backend.h>
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<VkInstance> 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<VkSurfaceKHR> 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<uint32_t> 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<VkQueueFamilyProperties>(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<VkPhysicalDevice>(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<VkDevice> 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<VulkanLoaderApi>();
- auto* vk = loader_api->LoadEntry();
-
- VkInstance instance{};
- {
- StatusOr<VkInstance> 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<VkSurfaceKHR> 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<VkDevice> 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<LogApi>();
- temp_api = api_registry->Get<TempAllocatorApi>();
+ allocator_api = api_registry->Get<AllocatorApi>();
os_api = api_registry->Get<OsApi>();
-
log_api->LogInfo("Base APIs registered");
+
+ RegisterVulkanLoaderApi(api_registry);
+ RegisterVulkanBackendApi(api_registry);
+ vulkan_backend_api = api_registry->Get<VulkanBackendApi>();
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<IVulkanBackend*> 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))