From 55bc67bf7989acfeadf0233a4bdd5660e8f0bb69 Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Sun, 9 Jun 2024 23:34:38 +0200 Subject: Start work on render backend --- deimos/core/os_win32.cpp | 2 +- deimos/core/status.cpp | 7 ++-- deimos/core/status.h | 10 ++++-- deimos/render/BUILD | 11 ++++++ deimos/render/backend.h | 19 ++++++++++ deimos/vulkan/BUILD | 1 + deimos/vulkan/vulkan_backend.cpp | 59 ++++++++++++++++++++++++------- deimos/vulkan/vulkan_backend.h | 6 ++++ deimos/vulkan/vulkan_device_functions.inc | 4 +++ 9 files changed, 101 insertions(+), 18 deletions(-) create mode 100644 deimos/render/BUILD create mode 100644 deimos/render/backend.h (limited to 'deimos') diff --git a/deimos/core/os_win32.cpp b/deimos/core/os_win32.cpp index 84fc3a3..9a8233d 100644 --- a/deimos/core/os_win32.cpp +++ b/deimos/core/os_win32.cpp @@ -169,7 +169,7 @@ public: if (hwnd == nullptr) { - return InternalError("Error while creating Win32 window"); + return RuntimeError("Error while creating Win32 window"); } ::ShowWindow(hwnd, SW_SHOW); diff --git a/deimos/core/status.cpp b/deimos/core/status.cpp index 10965bc..2d9e7c2 100644 --- a/deimos/core/status.cpp +++ b/deimos/core/status.cpp @@ -18,14 +18,15 @@ StringView StatusCodeToString(StatusCode code) case StatusCode::kInvalidArgument: return StringView("Invalid argument"); case StatusCode::kUnimplemented: return StringView("Unimplemented"); case StatusCode::kInternal: return StringView("Internal error"); + case StatusCode::kRuntime: return StringView("Runtime error"); } } struct StatusRep { - Atomic ref_count; - StatusCode code{}; - StringView message; + Atomic ref_count; + StatusCode code{}; + StringView message; }; Status::Status(StatusCode code, StringView message) diff --git a/deimos/core/status.h b/deimos/core/status.h index 8141dad..3738ae9 100644 --- a/deimos/core/status.h +++ b/deimos/core/status.h @@ -14,6 +14,7 @@ enum class StatusCode : uint32_t kInvalidArgument, kUnimplemented, kInternal, + kRuntime, }; StringView StatusCodeToString(StatusCode code); @@ -106,6 +107,11 @@ inline Status InternalError(StringView message = {}) return Status(StatusCode::kInternal, message); } +inline Status RuntimeError(StringView message = {}) +{ + return Status(StatusCode::kRuntime, message); +} + namespace statusor_internals { }; @@ -150,7 +156,7 @@ public: Expects(!m_status.ok()); if (m_status.ok()) { - m_status = InternalError("StatusOr constructed from OK"); + m_status = InvalidArgumentError("StatusOr constructed from OK"); } } @@ -159,7 +165,7 @@ public: Expects(!m_status.ok()); if (m_status.ok()) { - m_status = InternalError("StatusOr constructed from OK"); + m_status = InvalidArgumentError("StatusOr constructed from OK"); } } diff --git a/deimos/render/BUILD b/deimos/render/BUILD new file mode 100644 index 0000000..a94c085 --- /dev/null +++ b/deimos/render/BUILD @@ -0,0 +1,11 @@ +cc_library( + name = "render", + hdrs = [ + "backend.h", + ], + deps = [ + "//deimos/core", + ], + visibility = ["//:__subpackages__"], +) + diff --git a/deimos/render/backend.h b/deimos/render/backend.h new file mode 100644 index 0000000..cba8d90 --- /dev/null +++ b/deimos/render/backend.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +namespace deimos +{ + +class IRenderBackend +{ +public: + IRenderBackend() = default; + deimos_NO_COPY_MOVE(IRenderBackend); + virtual ~IRenderBackend() = default; + + virtual void BeginFrame() = 0; + virtual void EndFrame() = 0; +}; + +} // namespace deimos diff --git a/deimos/vulkan/BUILD b/deimos/vulkan/BUILD index 238261f..8d4ef3a 100644 --- a/deimos/vulkan/BUILD +++ b/deimos/vulkan/BUILD @@ -16,6 +16,7 @@ cc_library( deps = [ "//deimos/core", "//3rd_party/vulkan", + "//deimos/render", ], visibility = ["//:__subpackages__"], ) diff --git a/deimos/vulkan/vulkan_backend.cpp b/deimos/vulkan/vulkan_backend.cpp index 173e671..87e4451 100644 --- a/deimos/vulkan/vulkan_backend.cpp +++ b/deimos/vulkan/vulkan_backend.cpp @@ -7,21 +7,22 @@ #include #include #include +#include namespace { using namespace deimos; -LogApi* log_api; -OsApi* os_api; -ApiRegistry* api_registry; +LogApi* log_api; +OsApi* os_api; +ApiRegistry* api_registry; TempAllocatorApi* temp_api; -VulkanLoaderApi* vulkan_loader_api; +VulkanLoaderApi* vulkan_loader_api; const VkAllocationCallbacks* kVkAlloc = nullptr; -class VulkanBackendImpl : public IVulkanBackend +class VulkanBackendImpl : public IVulkanBackend, public IRenderBackend { VulkanApi* m_vk; VkInstance m_instance; @@ -31,6 +32,13 @@ class VulkanBackendImpl : public IVulkanBackend VkDevice m_device; VkQueue m_queue = VK_NULL_HANDLE; + struct FrameResources + { + VkCommandPool cmd_pool = VK_NULL_HANDLE; + }; + + FrameResources m_frame_resources; + public: VulkanBackendImpl( VulkanApi* vk, @@ -45,6 +53,33 @@ public: m_vk->GetDeviceQueue(m_device, m_queue_family, 0, &m_queue); Ensures(m_queue != VK_NULL_HANDLE); } + + IRenderBackend* AsRenderBackend() override + { + return this; + } + + void BeginFrame() override + { + VkCommandPoolCreateInfo create_info; + create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + create_info.pNext = nullptr; + create_info.flags = 0; + create_info.queueFamilyIndex = m_queue_family; + + VkResult res = m_vk->CreateCommandPool(m_device, &create_info, kVkAlloc, &m_frame_resources.cmd_pool); + if (res != VK_SUCCESS) + { + log_api->LogError("Couldn't allocate Vulkan command pool: $", (int)res); + return; + } + } + + void EndFrame() override + { + m_vk->DeviceWaitIdle(m_device); + m_vk->DestroyCommandPool(m_device, m_frame_resources.cmd_pool, kVkAlloc); + } }; StatusOr CreateInstance(VulkanApi* vk) @@ -85,7 +120,7 @@ StatusOr CreateInstance(VulkanApi* vk) const VkResult res = vk->CreateInstance(&create_info, kVkAlloc, &instance); if (res != VK_SUCCESS) { - return InternalError("vkCreateInstance failed"); + return RuntimeError("vkCreateInstance failed"); } return instance; @@ -105,7 +140,7 @@ StatusOr CreateSurface(VulkanApi* vk, VkInstance instance, OsWindo const VkResult res = vk->CreateWin32SurfaceKHR(instance, &create_info, kVkAlloc, &surface); if (res != VK_SUCCESS) { - return InternalError("vkCreateWin32SurfaceKHR failed"); + return RuntimeError("vkCreateWin32SurfaceKHR failed"); } return surface; @@ -119,7 +154,7 @@ StatusOr FindQueueFamily(VulkanApi* vk, VkPhysicalDevice physical_devi vk->GetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_family_count, nullptr); if (queue_family_count == 0) { - return InternalError("No queue on this physical device"); + return RuntimeError("No queue on this physical device"); } log_api->LogInfo("Physical device has $ queue families", queue_family_count); @@ -143,7 +178,7 @@ StatusOr FindQueueFamily(VulkanApi* vk, VkPhysicalDevice physical_devi } } - return InternalError("Couldn't find a suitable queue"); + return RuntimeError("Couldn't find a suitable queue"); } Status FindPhysicalDevice( @@ -159,7 +194,7 @@ Status FindPhysicalDevice( vk->EnumeratePhysicalDevices(instance, &physical_device_count, nullptr); if (physical_device_count == 0) { - return InternalError("No Vulkan device found"); + return RuntimeError("No Vulkan device found"); } log_api->LogInfo("Found $ physical devices", physical_device_count); @@ -196,7 +231,7 @@ Status FindPhysicalDevice( log_api->LogInfo("Incompatible because: $", maybe_queue_family); } - return InternalError("No suitable device found"); + return RuntimeError("No suitable device found"); } StatusOr CreateDevice(VulkanApi* vk, VkPhysicalDevice physical_device, uint32_t queue_family) @@ -233,7 +268,7 @@ StatusOr CreateDevice(VulkanApi* vk, VkPhysicalDevice physical_device, const VkResult res = vk->CreateDevice(physical_device, &create_info, kVkAlloc, &device); if (res != VK_SUCCESS) { - return InternalError("vkCreateDeviceFailed"); + return RuntimeError("vkCreateDeviceFailed"); } return device; diff --git a/deimos/vulkan/vulkan_backend.h b/deimos/vulkan/vulkan_backend.h index 90aaf2a..031c81b 100644 --- a/deimos/vulkan/vulkan_backend.h +++ b/deimos/vulkan/vulkan_backend.h @@ -8,11 +8,17 @@ namespace deimos class ApiRegistry; class Allocator; +class IRenderBackend; struct OsWindow; class IVulkanBackend { public: + IVulkanBackend() = default; + deimos_NO_COPY_MOVE(IVulkanBackend); + virtual ~IVulkanBackend() = default; + + virtual IRenderBackend* AsRenderBackend() = 0; }; class VulkanBackendApi diff --git a/deimos/vulkan/vulkan_device_functions.inc b/deimos/vulkan/vulkan_device_functions.inc index 8267fb9..f83ebb7 100644 --- a/deimos/vulkan/vulkan_device_functions.inc +++ b/deimos/vulkan/vulkan_device_functions.inc @@ -1,4 +1,8 @@ // NOLINTBEGIN FN(DestroyDevice) FN(GetDeviceQueue) +FN(CreateCommandPool) +FN(ResetCommandPool) +FN(DestroyCommandPool) +FN(DeviceWaitIdle) // NOLINTEND -- cgit