diff options
-rw-r--r-- | .clang-tidy | 2 | ||||
-rw-r--r-- | deimos/core/base.h | 6 | ||||
-rw-r--r-- | deimos/core/format.cpp | 3 | ||||
-rw-r--r-- | deimos/core/format.h | 39 | ||||
-rw-r--r-- | deimos/core/log.h | 6 | ||||
-rw-r--r-- | deimos/core/status.cpp | 30 | ||||
-rw-r--r-- | deimos/core/status.h | 10 | ||||
-rw-r--r-- | deimos/core/std.h | 1 | ||||
-rw-r--r-- | deimos/core/temp_allocator.cpp | 2 | ||||
-rw-r--r-- | deimos/vulkan/vulkan.h | 11 | ||||
-rw-r--r-- | main/main.cpp | 59 |
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;
|