summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clang-tidy2
-rw-r--r--deimos/core/base.h6
-rw-r--r--deimos/core/format.cpp3
-rw-r--r--deimos/core/format.h39
-rw-r--r--deimos/core/log.h6
-rw-r--r--deimos/core/status.cpp30
-rw-r--r--deimos/core/status.h10
-rw-r--r--deimos/core/std.h1
-rw-r--r--deimos/core/temp_allocator.cpp2
-rw-r--r--deimos/vulkan/vulkan.h11
-rw-r--r--main/main.cpp59
11 files changed, 149 insertions, 20 deletions
diff --git a/.clang-tidy b/.clang-tidy
index c8c8c55..be78fe7 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -24,3 +24,5 @@ Checks:
- "-*-noexcept-move"
- "-*-noexcept-move-constructor"
- "-*-noexcept-move-operations"
+ - "-*-bounds-array-to-pointer-decay"
+ - "-*-no-array-decay"
diff --git a/deimos/core/base.h b/deimos/core/base.h
index f24991d..5cd3a40 100644
--- a/deimos/core/base.h
+++ b/deimos/core/base.h
@@ -78,6 +78,9 @@ constexpr void MemoryCopy(void* dst, const void* src, int64_t size)
__builtin_memcpy(dst, src, (size_t)size);
}
+template<typename T, int64_t N>
+constexpr int64_t ArraySize(const T (&)[N]) { return N; }
+
template<typename T>
class Span
{
@@ -113,6 +116,7 @@ public:
constexpr T* begin() const { return m_begin; }
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; }
};
template<typename T>
@@ -141,8 +145,8 @@ public:
{}
constexpr const char* data() const { return m_begin; }
-
constexpr int64_t size() const { return m_size; }
+ constexpr bool empty() const { return m_size == 0; }
};
inline Span<const std::byte> AsBytes(StringView span)
diff --git a/deimos/core/format.cpp b/deimos/core/format.cpp
index af0a851..5f420e9 100644
--- a/deimos/core/format.cpp
+++ b/deimos/core/format.cpp
@@ -51,6 +51,9 @@ public:
case FormatArg::kUnsignedInteger:
PushUnsignedInteger(arg.integer);
break;
+ case FormatArg::kCustom:
+ arg.custom.callback(m_writer, arg.custom.payload);
+ break;
}
}
};
diff --git a/deimos/core/format.h b/deimos/core/format.h
index 3424dc2..ba1a3e2 100644
--- a/deimos/core/format.h
+++ b/deimos/core/format.h
@@ -7,6 +7,14 @@ namespace deimos
class IWriter;
+struct CustomFormatter
+{
+ using Callback = void (*)(IWriter*, const void* payload);
+
+ const void* payload;
+ Callback callback;
+};
+
struct FormatArg
{
enum Type : uint8_t
@@ -14,42 +22,57 @@ struct FormatArg
kInteger,
kUnsignedInteger,
kString,
+ kCustom,
};
Type type;
union
{
- int64_t integer;
- uint64_t unsigned_integer;
- StringView string;
+ int64_t integer;
+ uint64_t unsigned_integer;
+ StringView string;
+ CustomFormatter custom;
};
- explicit FormatArg(std::signed_integral auto value) :
+ constexpr explicit FormatArg(std::signed_integral auto value) :
type{kInteger},
integer{value}
{}
- explicit FormatArg(std::unsigned_integral auto value) :
+ constexpr explicit FormatArg(std::unsigned_integral auto value) :
type{kUnsignedInteger},
unsigned_integer{value}
{}
- explicit FormatArg(StringView value) :
+ constexpr explicit FormatArg(StringView value) :
type{kString},
string{value}
{}
+
+ template<typename T>
+ constexpr explicit FormatArg(const T& payload, CustomFormatter::Callback callback) :
+ type{kCustom},
+ custom{CustomFormatter{&payload, callback}}
+ {}
};
template<typename T>
-concept Formattable = requires (T value) { FormatArg(value); };
+deimos::FormatArg DeimosMakeFormatArg(T&& value)
+ requires std::is_constructible_v<deimos::FormatArg, T>
+{
+ return deimos::FormatArg(value);
+}
+
+template<typename T>
+concept Formattable = std::same_as<deimos::FormatArg, decltype(DeimosMakeFormatArg(std::declval<T>()))>;
void FormatVa(IWriter*, gsl::czstring fmt, Span<const FormatArg>);
template<Formattable... Args>
void Format(IWriter* writer, gsl::czstring fmt, Args&&... args)
{
- FormatVa(writer, fmt, { FormatArg(std::forward<Args>(args))... });
+ FormatVa(writer, fmt, { DeimosMakeFormatArg(std::forward<Args>(args))... });
}
} // namespace deimos
diff --git a/deimos/core/log.h b/deimos/core/log.h
index 9bb4dbb..260d9a4 100644
--- a/deimos/core/log.h
+++ b/deimos/core/log.h
@@ -50,19 +50,19 @@ public:
template<Formattable... Args>
void LogInfo(const LogSourceLocation& fmt_source_location, Args&&... args)
{
- LogVa(LogSeverity::kInfo, fmt_source_location.source_location, fmt_source_location.fmt, { FormatArg(std::forward<Args>(args))... });
+ LogVa(LogSeverity::kInfo, fmt_source_location.source_location, fmt_source_location.fmt, { DeimosMakeFormatArg(std::forward<Args>(args))... });
}
template<Formattable... Args>
void LogDebug(const LogSourceLocation& fmt_source_location, Args&&... args)
{
- LogVa(LogSeverity::kDebug, fmt_source_location.source_location, fmt_source_location.fmt, { FormatArg(std::forward<Args>(args))... });
+ LogVa(LogSeverity::kDebug, fmt_source_location.source_location, fmt_source_location.fmt, { DeimosMakeFormatArg(std::forward<Args>(args))... });
}
template<Formattable... Args>
void LogError(const LogSourceLocation& fmt_source_location, Args&&... args)
{
- LogVa(LogSeverity::kError, fmt_source_location.source_location, fmt_source_location.fmt, { FormatArg(std::forward<Args>(args))... });
+ LogVa(LogSeverity::kError, fmt_source_location.source_location, fmt_source_location.fmt, { DeimosMakeFormatArg(std::forward<Args>(args))... });
}
};
diff --git a/deimos/core/status.cpp b/deimos/core/status.cpp
index f472aac..efdd6df 100644
--- a/deimos/core/status.cpp
+++ b/deimos/core/status.cpp
@@ -9,6 +9,18 @@ static deimos::AllocatorApi* allocator_api;
namespace deimos
{
+StringView StatusCodeToString(StatusCode code)
+{
+ switch (code)
+ {
+ case StatusCode::kOk: return StringView("OK");
+ case StatusCode::kUnknown: return StringView("Unknown error");
+ case StatusCode::kInvalidArgument: return StringView("Invalid argument");
+ case StatusCode::kUnimplemented: return StringView("Unimplemented");
+ case StatusCode::kInternal: return StringView("Internal error");
+ }
+}
+
struct StatusRep
{
Atomic<int32_t> ref_count;
@@ -18,9 +30,9 @@ struct StatusRep
Status::Status(StatusCode code, StringView message)
{
- if (code == StatusCode::kOk)
+ if (code == StatusCode::kOk || message.empty())
{
- m_rep = CodeToRep(StatusCode::kOk);
+ m_rep = CodeToRep(code);
}
else
{
@@ -74,6 +86,20 @@ void Status::Unref() const
}
}
+void Status::FormatStatus(IWriter* writer, const void* payload)
+{
+ const auto& status = *(const Status*)payload; // NOLINT
+ if (status.IsInline())
+ {
+ Format(writer, "[$]", StatusCodeToString(status.code()));
+ }
+ else
+ {
+ auto* rep = std::bit_cast<StatusRep*>(status.m_rep);
+ Format(writer, "[$: $]", StatusCodeToString(rep->code), rep->message);
+ }
+}
+
void InitializeStatus(ApiRegistry* api_registry)
{
allocator_api = api_registry->Get<AllocatorApi>();
diff --git a/deimos/core/status.h b/deimos/core/status.h
index bf34833..7350cc5 100644
--- a/deimos/core/status.h
+++ b/deimos/core/status.h
@@ -1,6 +1,7 @@
#pragma once
#include "deimos/core/base.h"
+#include "deimos/core/format.h"
namespace deimos
{
@@ -15,6 +16,8 @@ enum class StatusCode : uint32_t
kInternal,
};
+StringView StatusCodeToString(StatusCode code);
+
class Status
{
uintptr_t m_rep;
@@ -79,6 +82,13 @@ public:
if (IsInline()) { return (StatusCode)(m_rep >> 1U); }
return RepCode();
}
+
+ static void FormatStatus(IWriter* writer, const void* payload);
+
+ friend constexpr deimos::FormatArg DeimosMakeFormatArg(const Status& status)
+ {
+ return deimos::FormatArg(status, FormatStatus);
+ }
};
inline Status UnknownError(StringView message = {})
diff --git a/deimos/core/std.h b/deimos/core/std.h
index 4bb2983..0e0336e 100644
--- a/deimos/core/std.h
+++ b/deimos/core/std.h
@@ -24,6 +24,7 @@ template<typename T> concept signed_integral = integral<T> && __is_signed(T);
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_trivially_copyable_v = __is_trivially_copyable(T);
template<typename U, typename V> constexpr bool _is_same_helper = false;
diff --git a/deimos/core/temp_allocator.cpp b/deimos/core/temp_allocator.cpp
index 2f07bcc..d2b7900 100644
--- a/deimos/core/temp_allocator.cpp
+++ b/deimos/core/temp_allocator.cpp
@@ -41,7 +41,7 @@ public:
if (new_current > m_commit_end)
{
const int64_t new_commit_size = AlignUp(
- (uint64_t)(std::bit_cast<uintptr_t>(new_current) - std::bit_cast<uintptr_t>(m_base)), // NOLINT
+ (int64_t)(std::bit_cast<uintptr_t>(new_current) - std::bit_cast<uintptr_t>(m_base)), // NOLINT
kPageSize);
os_api->virtual_memory->Commit(m_base, new_commit_size);
m_commit_end = OffsetBytes(m_base, new_commit_size);
diff --git a/deimos/vulkan/vulkan.h b/deimos/vulkan/vulkan.h
index 549deac..48d53b3 100644
--- a/deimos/vulkan/vulkan.h
+++ b/deimos/vulkan/vulkan.h
@@ -1,7 +1,16 @@
#pragma once
#include <deimos/core/id_name.h>
-#include <vulkan.h>
+
+#define VK_NO_STDINT_H
+#define VK_NO_STDDEF_H
+#include <vk_platform.h>
+
+#include <vulkan_core.h>
+
+using HINSTANCE = void*;
+using HWND = void*;
+#include <vulkan_win32.h>
namespace deimos
{
diff --git a/main/main.cpp b/main/main.cpp
index 9fb4755..00e7d71 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -1,22 +1,73 @@
#include <deimos/core/api_registry.h>
#include <deimos/core/log.h>
#include <deimos/core/temp_allocator.h>
+#include <deimos/core/status.h>
#include <deimos/vulkan/vulkan.h>
using namespace deimos;
+static LogApi* log_api;
+
+[[nodiscard]]
+Status CreateInstance(VulkanApi* vk, VkInstance* instance)
+{
+ 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",
+ "VK_KHR_win32_surfaceu",
+ };
+
+ const char* layers[]{
+ "VK_LAYER_KHRONOS_validation",
+ "VK_LAYER_LUNARG_monitor",
+ };
+
+ 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,
+ };
+
+ VkResult res = vk->CreateInstance(&create_info, nullptr, instance);
+ if (res != VK_SUCCESS)
+ {
+ return UnknownError();
+ }
+
+ return {};
+}
+
int main(int /* argc */, char* /* argv */[])
{
auto* api_registry = InitializeGlobalApiRegistry();
- auto* log_api = api_registry->Get<LogApi>();
+ log_api = api_registry->Get<LogApi>();
log_api->LogInfo("Base APIs registered");
RegisterVulkanLoaderApi(api_registry);
auto* vulkan_loader_api = api_registry->Get<VulkanLoaderApi>();
- auto* vk = vulkan_loader_api->LoadEntry();
+ auto* vk = vulkan_loader_api->LoadEntry();
+
+ VkInstance instance{};
+ Status s = CreateInstance(vk, &instance);
+ if (!s.ok())
+ {
+ log_api->LogError("Couldn't create Vulkan instance: $", s);
+ }
- Ensures(vk->GetInstanceProcAddr != nullptr);
- Ensures(vk->CreateInstance != nullptr);
log_api->LogInfo("OK");
return 0;