From a3fdb87df94f8d377b7ea90ca50a06418fda3867 Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Wed, 1 May 2024 22:11:54 +0200 Subject: Open window & basic lifetime --- deimos/core/allocator.h | 6 ++-- deimos/core/os.h | 8 +++-- deimos/core/os_win32.cpp | 84 ++++++++++++++++++++++++++++++++++++++++++------ main/main.cpp | 17 ++++++---- 4 files changed, 95 insertions(+), 20 deletions(-) diff --git a/deimos/core/allocator.h b/deimos/core/allocator.h index 5afb824..07a214e 100644 --- a/deimos/core/allocator.h +++ b/deimos/core/allocator.h @@ -25,15 +25,15 @@ struct IAllocator class Allocator { - gsl::owner m_allocator; - const MemoryScope m_scope; + IAllocator* m_allocator; + MemoryScope m_scope; public: constexpr Allocator(IAllocator* allocator, MemoryScope scope) : m_allocator{allocator}, m_scope{scope} {} - deimos_NO_COPY_MOVE(Allocator); + deimos_DEFAULT_COPY_MOVE(Allocator); ~Allocator() = default; diff --git a/deimos/core/os.h b/deimos/core/os.h index ecbe3cd..c440555 100644 --- a/deimos/core/os.h +++ b/deimos/core/os.h @@ -50,7 +50,7 @@ public: virtual void Commit(void* ptr, int64_t size) = 0; }; -struct OsWindowHandle; +struct OsWindow; class OsWindowApi { @@ -59,7 +59,11 @@ public: deimos_NO_COPY_MOVE(OsWindowApi); virtual ~OsWindowApi() = default; - virtual StatusOr> Create(gsl::czstring title, int32_t width, int32_t height) = 0; + virtual StatusOr> Create(gsl::czstring title, int32_t width, int32_t height) = 0; + + virtual void Update(OsWindow*) = 0; + + virtual bool QuitRequested(const OsWindow*) = 0; }; class OsApi diff --git a/deimos/core/os_win32.cpp b/deimos/core/os_win32.cpp index fe904cd..e80a1d5 100644 --- a/deimos/core/os_win32.cpp +++ b/deimos/core/os_win32.cpp @@ -10,9 +10,9 @@ namespace deimos gsl::cwzstring Utf8ToUtf16Z(StringView src, Span buffer) { - Expects(buffer.size() > 0 && buffer.size() > src.size()); + Expects(!buffer.empty() && buffer.size() > src.size()); - int res = ::MultiByteToWideChar(CP_UTF8, 0, src.data(), (int)src.size_bytes(), buffer.data(), (int)buffer.size() - 1); + const int res = ::MultiByteToWideChar(CP_UTF8, 0, src.data(), (int)src.size_bytes(), buffer.data(), (int)buffer.size() - 1); if (res < 0) { return L"< MBTWC ERROR >"; } buffer[res] = L'\0'; @@ -84,18 +84,56 @@ public: } }; +struct OsWindow +{ + HWND hwnd{}; + bool destroyed{}; + bool quit_requested{}; +}; + class Win32WindowApiImpl : public OsWindowApi { static constexpr wchar_t kClassName[] = L"Deimos window class"; - bool m_class_registered = false; + Allocator* m_allocator; + bool m_class_registered = false; + + static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + if (uMsg == WM_CREATE) + { + const auto* create = (const CREATESTRUCT*)lParam; // NOLINT + ::SetWindowLongPtrW(hwnd, GWLP_USERDATA, std::bit_cast(create->lpCreateParams)); + return 0; + } + + auto* window = std::bit_cast(::GetWindowLongPtrW(hwnd, GWLP_USERDATA)); + + switch (uMsg) + { + case WM_CLOSE: + { + window->quit_requested = true; + ::DestroyWindow(hwnd); + return 0; + } + case WM_DESTROY: + { + window->destroyed = true; + ::PostQuitMessage(0); + return 0; + } + default: + return ::DefWindowProcW(hwnd, uMsg, wParam, lParam); + } + } void RegisterClass() { Expects(!m_class_registered); WNDCLASSW wnd_class{}; - wnd_class.lpfnWndProc = ::DefWindowProcW; + wnd_class.lpfnWndProc = WindowProc; wnd_class.hInstance = ::GetModuleHandleW(nullptr); wnd_class.lpszClassName = kClassName; @@ -105,7 +143,11 @@ class Win32WindowApiImpl : public OsWindowApi } public: - StatusOr> Create(gsl::czstring title, int32_t width, int32_t height) override + explicit Win32WindowApiImpl(Allocator* allocator) : + m_allocator{allocator} + {} + + StatusOr> Create(gsl::czstring title, int32_t width, int32_t height) override { if (!m_class_registered) { @@ -115,11 +157,13 @@ public: wchar_t title_w_buffer[128]{}; gsl::cwzstring title_w = Utf8ToUtf16Z(title, title_w_buffer); + + auto* window = m_allocator->New(); HWND hwnd = ::CreateWindowExW( 0, kClassName, title_w, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, width, height, - nullptr, nullptr, ::GetModuleHandle(nullptr), nullptr); + nullptr, nullptr, ::GetModuleHandle(nullptr), window); if (hwnd == nullptr) { @@ -128,7 +172,25 @@ public: ::ShowWindow(hwnd, SW_SHOW); - return nullptr; + window->hwnd = hwnd; + return window; + } + + void Update(OsWindow* window) override + { + if (window->destroyed) { return; } + + MSG msg; + while (::PeekMessageW(&msg, window->hwnd, 0, 0, PM_REMOVE) != 0) + { + TranslateMessage(&msg); + DispatchMessageW(&msg); + } + } + + bool QuitRequested(const OsWindow* window) override + { + return window->quit_requested; } }; @@ -140,7 +202,8 @@ class Win32OsApiImpl : public OsApi Win32WindowApiImpl m_window_api; public: - Win32OsApiImpl() + explicit Win32OsApiImpl(Allocator* allocator) : + m_window_api(allocator) { console = &m_console_api; dll = &m_dll_api; @@ -152,7 +215,10 @@ public: void RegisterOsApi(ApiRegistry* api_registry) { auto* allocator_api = api_registry->Get(); - auto* os_api = allocator_api->system->New(); + + Allocator* allocator = allocator_api->CreateChild(allocator_api->system, "OS"); + auto* os_api = allocator_api->system->New(allocator); + api_registry->Set(os_api); } diff --git a/main/main.cpp b/main/main.cpp index 938d225..4a999ce 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -99,8 +99,8 @@ StatusOr FindQueueFamily(VulkanApi* vk, VkPhysicalDevice physical_devi { const auto& prps = queue_families[index]; - bool supports_graphics_compute = (prps.queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0 && (prps.queueFlags & VK_QUEUE_COMPUTE_BIT) != 0; - bool supports_presentation = vk->GetPhysicalDeviceWin32PresentationSupportKHR(physical_device, index) == VK_TRUE; + const bool supports_graphics_compute = (prps.queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0 && (prps.queueFlags & VK_QUEUE_COMPUTE_BIT) != 0; + const bool supports_presentation = vk->GetPhysicalDeviceWin32PresentationSupportKHR(physical_device, index) == VK_TRUE; if (supports_graphics_compute && supports_presentation) { return index; @@ -114,7 +114,7 @@ StatusOr CreateDevice(VulkanApi* vk, VkPhysicalDevice physical_device, { const float queue_priority = 1.0F; - VkDeviceQueueCreateInfo queue_create_info{ + const VkDeviceQueueCreateInfo queue_create_info{ .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, .pNext = nullptr, .flags = 0, @@ -127,7 +127,7 @@ StatusOr CreateDevice(VulkanApi* vk, VkPhysicalDevice physical_device, VK_KHR_SWAPCHAIN_EXTENSION_NAME, }; - VkDeviceCreateInfo create_info{ + const VkDeviceCreateInfo create_info{ .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, .pNext = nullptr, .flags = 0, @@ -141,7 +141,7 @@ StatusOr CreateDevice(VulkanApi* vk, VkPhysicalDevice physical_device, }; VkDevice device = VK_NULL_HANDLE; - VkResult res = vk->CreateDevice(physical_device, &create_info, kVkAlloc, &device); + const VkResult res = vk->CreateDevice(physical_device, &create_info, kVkAlloc, &device); if (res != VK_SUCCESS) { return InternalError("vkCreateDeviceFailed"); @@ -224,7 +224,7 @@ int main(int /* argc */, char* /* argv */[]) log_api->LogInfo("Base APIs registered"); - OsWindowHandle* window{}; + OsWindow* window{}; { auto s = os_api->window->Create("Deimos", 1280, 720); if (!s.ok()) @@ -235,6 +235,11 @@ int main(int /* argc */, char* /* argv */[]) window = s.value(); } + while (!os_api->window->QuitRequested(window)) + { + os_api->window->Update(window); + } + const Status s = InitializeVulkan(api_registry); if (!s.ok()) { -- cgit