From e02f9fd89b059919baf3a8d8bf8b783470976a27 Mon Sep 17 00:00:00 2001
From: Steven Le Rouzic <steven.lerouzic@gmail.com>
Date: Sat, 27 Apr 2024 01:16:21 +0200
Subject: Some work on Vulkan initialization

---
 deimos/core/allocator.h                      | 21 +++++++++++++++++++++
 deimos/core/base.h                           | 19 ++++++++++++++++++-
 deimos/core/log.cpp                          |  8 +++++---
 deimos/core/status.h                         | 14 ++++++++++++--
 deimos/core/std.h                            |  1 +
 deimos/core/temp_allocator.cpp               | 12 ++----------
 deimos/vulkan/BUILD                          |  2 ++
 deimos/vulkan/vulkan.h                       |  4 ++++
 deimos/vulkan/vulkan_bootstrap_functions.inc |  3 +++
 deimos/vulkan/vulkan_entry_functions.inc     |  1 -
 deimos/vulkan/vulkan_instance_functions.inc  |  6 ++++++
 deimos/vulkan/vulkan_loader.cpp              | 18 +++++++++++++++++-
 12 files changed, 91 insertions(+), 18 deletions(-)
 create mode 100644 deimos/vulkan/vulkan_bootstrap_functions.inc
 create mode 100644 deimos/vulkan/vulkan_instance_functions.inc

(limited to 'deimos')

diff --git a/deimos/core/allocator.h b/deimos/core/allocator.h
index 26374bd..5afb824 100644
--- a/deimos/core/allocator.h
+++ b/deimos/core/allocator.h
@@ -125,6 +125,27 @@ public:
         }
         Free(t, sizeof(T), source_location);
     }
+
+    template<typename T>
+    gsl::owner<Span<T>> NewArray(int64_t count, const SourceLocation& source_location = {})
+        requires std::is_default_constructible_v<T>
+    {
+        Expects(count > 0);
+        
+        auto* raw = Allocate((int64_t)sizeof(T) * count, source_location);
+        if constexpr (std::is_trivially_default_constructible_v<T>)
+        {
+            MemoryZero(raw, (int64_t)sizeof(T) * count);
+        }
+        else
+        {
+            for (int64_t i = 0; i < count; ++i)
+            {
+                new((T*)raw + i) T{};
+            }
+        }
+        return Span<T>{ (T*)raw, count };
+    }
 };
 
 class AllocatorApi
diff --git a/deimos/core/base.h b/deimos/core/base.h
index 5cd3a40..70958a5 100644
--- a/deimos/core/base.h
+++ b/deimos/core/base.h
@@ -5,7 +5,13 @@
 
 #define deimos_StaticAssert(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
 
-#define deimos_Panic(MSG) do { __builtin_trap(); } while (0)
+[[noreturn]]
+inline void deimos_Trap()
+{
+    __builtin_trap();
+}
+
+#define deimos_Panic(MSG) do { deimos_Trap(); } while (0)
 
 #define deimos_NO_COPY(TYPE)                            \
     TYPE(const TYPE&) = delete;                         \
@@ -78,6 +84,11 @@ constexpr void MemoryCopy(void* dst, const void* src, int64_t size)
     __builtin_memcpy(dst, src, (size_t)size);
 }
 
+inline void MemoryZero(void* dst, int64_t size)
+{
+    __builtin_memset(dst, 0, (size_t)size);
+}
+
 template<typename T, int64_t N>
 constexpr int64_t ArraySize(const T (&)[N]) { return N; }
 
@@ -117,6 +128,12 @@ public:
     constexpr T* end() const { return m_begin + m_size; } // NOLINT
     constexpr int64_t size() const { return m_size; }
     constexpr bool empty() const { return m_size == 0; }
+
+    constexpr T& operator[](int64_t i) const
+    {
+        Expects(i >= 0 && i < m_size);
+        return m_begin[i]; // NOLINT
+    }
 };
 
 template<typename T>
diff --git a/deimos/core/log.cpp b/deimos/core/log.cpp
index e05c360..b8e7805 100644
--- a/deimos/core/log.cpp
+++ b/deimos/core/log.cpp
@@ -35,10 +35,12 @@ public:
         m_writer(os_console_api, OsConsoleType::kStdOut)
     {}
 
-    void Log(LogSeverity severity, const SourceLocation& location, StringView msg) override
+    void Log(LogSeverity severity, const SourceLocation& /* location */, StringView msg) override
     {
-        Format(&m_writer, "$[ $ ] $:$: $\033[0m\n", SeverityToColor(severity),
-            SeverityToStr(severity), location.file, location.line, msg);
+        // Format(&m_writer, "$[ $ ] $:$: $\033[0m\n", SeverityToColor(severity),
+        //     SeverityToStr(severity), location.file, location.line, msg);
+        Format(&m_writer, "$[ $ ] $\033[0m\n", SeverityToColor(severity),
+            SeverityToStr(severity), msg);
     }
 };
 
diff --git a/deimos/core/status.h b/deimos/core/status.h
index 912d4c8..8141dad 100644
--- a/deimos/core/status.h
+++ b/deimos/core/status.h
@@ -147,18 +147,18 @@ public:
 
     StatusOr(const Status& status) : m_status{status} // NOLINT
     {
+        Expects(!m_status.ok());
         if (m_status.ok())
         {
-            deimos_Panic("Cannot construct a StatusOr from OK");
             m_status = InternalError("StatusOr constructed from OK");
         }
     }
 
     StatusOr(Status&& status) : m_status{std::move(status)} // NOLINT
     {
+        Expects(!m_status.ok());
         if (m_status.ok())
         {
-            deimos_Panic("Cannot construct a StatusOr from OK");
             m_status = InternalError("StatusOr constructed from OK");
         }
     }
@@ -229,6 +229,16 @@ public:
     }
 
     constexpr bool ok() const { return m_status.ok(); }
+
+    constexpr StatusCode code() const { return m_status.code(); }
+
+    constexpr const Status& status() const { return m_status; }
+
+    constexpr const T& value() const & { Expects(m_status.ok()); return m_value; }
+    
+    constexpr T& value() & { Expects(m_status.ok()); return m_value; }
+    
+    constexpr T&& value() && { Expects(m_status.ok()); return std::move(m_value); }
     
     friend void DeimosFormat(IWriter* writer, const StatusOr<T>& status)
     {
diff --git a/deimos/core/std.h b/deimos/core/std.h
index 47f161a..27b5bc4 100644
--- a/deimos/core/std.h
+++ b/deimos/core/std.h
@@ -26,6 +26,7 @@ template<typename T> concept unsigned_integral = integral<T> && __is_unsigned(T)
 template<typename T> constexpr bool is_trivially_destructible_v = __is_trivially_destructible(T);
 template<typename T, typename... Args> constexpr bool is_constructible_v = __is_constructible(T, Args...);
 template<typename T> constexpr bool is_default_constructible_v = __is_constructible(T);
+template<typename T> constexpr bool is_trivially_default_constructible_v = __is_trivially_constructible(T);
 template<typename T> constexpr bool is_copy_constructible_v = __is_constructible(T, const T&);
 template<typename T> constexpr bool is_move_constructible_v = __is_constructible(T, T&&);
 template<typename T> constexpr bool is_copy_assignable_v = __is_assignable(T, const T&);
diff --git a/deimos/core/temp_allocator.cpp b/deimos/core/temp_allocator.cpp
index d2b7900..99ee630 100644
--- a/deimos/core/temp_allocator.cpp
+++ b/deimos/core/temp_allocator.cpp
@@ -35,7 +35,6 @@ public:
         if (new_current > m_reserve_end)
         {
             deimos_Panic("Ran out of temporary memory");
-            return nullptr;
         }
 
         if (new_current > m_commit_end)
@@ -73,15 +72,8 @@ public:
     {
         void* rewind_base = std::bit_cast<void*>(tag.tag);
         Expects(rewind_base >= m_base && rewind_base <= m_commit_end);
-        
-        if (rewind_base < m_current)
-        {
-            m_current = rewind_base;
-        }
-        else
-        {
-            deimos_Panic("Invalid temporary allocator rewind");
-        }
+        Expects(rewind_base <= m_current);
+        m_current = rewind_base;
     }
 };
 
diff --git a/deimos/vulkan/BUILD b/deimos/vulkan/BUILD
index a773fa1..8f0a79e 100644
--- a/deimos/vulkan/BUILD
+++ b/deimos/vulkan/BUILD
@@ -5,7 +5,9 @@ cc_library(
     ],
     srcs = [
         "vulkan_loader.cpp",
+        "vulkan_bootstrap_functions.inc",
         "vulkan_entry_functions.inc",
+        "vulkan_instance_functions.inc",
     ],
     deps = [
         "//deimos/core",
diff --git a/deimos/vulkan/vulkan.h b/deimos/vulkan/vulkan.h
index 48d53b3..4315230 100644
--- a/deimos/vulkan/vulkan.h
+++ b/deimos/vulkan/vulkan.h
@@ -20,7 +20,9 @@ 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"
 #undef FN
 };
 
@@ -34,6 +36,8 @@ public:
     static constexpr IdName kApiName{"deimos::VulkanLoaderApi"};
 
     virtual VulkanApi* LoadEntry() = 0;
+
+    virtual void LoadInstance(VulkanApi*, VkInstance) = 0;
 };
 
 void RegisterVulkanLoaderApi(ApiRegistry*);
diff --git a/deimos/vulkan/vulkan_bootstrap_functions.inc b/deimos/vulkan/vulkan_bootstrap_functions.inc
new file mode 100644
index 0000000..a69c5a6
--- /dev/null
+++ b/deimos/vulkan/vulkan_bootstrap_functions.inc
@@ -0,0 +1,3 @@
+// NOLINTBEGIN
+FN(GetInstanceProcAddr)
+// NOLINTEND
diff --git a/deimos/vulkan/vulkan_entry_functions.inc b/deimos/vulkan/vulkan_entry_functions.inc
index fe5f9ea..761cb0f 100644
--- a/deimos/vulkan/vulkan_entry_functions.inc
+++ b/deimos/vulkan/vulkan_entry_functions.inc
@@ -1,4 +1,3 @@
 // NOLINTBEGIN
-FN(GetInstanceProcAddr)
 FN(CreateInstance)
 // NOLINTEND
diff --git a/deimos/vulkan/vulkan_instance_functions.inc b/deimos/vulkan/vulkan_instance_functions.inc
new file mode 100644
index 0000000..34535ad
--- /dev/null
+++ b/deimos/vulkan/vulkan_instance_functions.inc
@@ -0,0 +1,6 @@
+// NOLINTBEGIN
+FN(EnumeratePhysicalDevices)
+FN(GetPhysicalDeviceProperties2)
+FN(GetPhysicalDeviceQueueFamilyProperties)
+FN(DestroyInstance)
+// NOLINTEND
diff --git a/deimos/vulkan/vulkan_loader.cpp b/deimos/vulkan/vulkan_loader.cpp
index ddd5cf0..0760c67 100644
--- a/deimos/vulkan/vulkan_loader.cpp
+++ b/deimos/vulkan/vulkan_loader.cpp
@@ -31,16 +31,32 @@ public:
             else
             {
                 deimos_Panic("Couldn't load Vulkan DLL");
-                return nullptr;
             }
         }
 
         VulkanApi* api = m_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"
+#undef FN
+
+#define FN(NAME) api->NAME = (PFN_vk##NAME)api->GetInstanceProcAddr(VK_NULL_HANDLE, "vk" #NAME);
 #include "deimos/vulkan/vulkan_entry_functions.inc"
 #undef FN
+
         return api;
     }
+    
+    void LoadInstance(VulkanApi* api, VkInstance instance) override
+    {
+        Expects(api != nullptr);
+        Expects(instance != VK_NULL_HANDLE);
+        Expects(api->GetInstanceProcAddr != nullptr);
+        
+#define FN(NAME) api->NAME = (PFN_vk##NAME)api->GetInstanceProcAddr(instance, "vk" #NAME);
+#include "deimos/vulkan/vulkan_instance_functions.inc"
+#undef FN
+    }
 };
 
 void RegisterVulkanLoaderApi(ApiRegistry* registry)
-- 
cgit