From 7507648ad80868615007d83990cfb33e5a67724e Mon Sep 17 00:00:00 2001 From: YasInvolved Date: Tue, 2 Jun 2026 01:03:03 +0200 Subject: [PATCH 01/13] add window api --- Engine/src/delta/platform/os_internal.h | 5 ++ Engine/src/delta/platform/os_win32.cpp | 80 +++++++++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/Engine/src/delta/platform/os_internal.h b/Engine/src/delta/platform/os_internal.h index ac6c713..390cc6e 100644 --- a/Engine/src/delta/platform/os_internal.h +++ b/Engine/src/delta/platform/os_internal.h @@ -71,4 +71,9 @@ namespace delta::platform void Sync_SignalSemaphore(SemaphoreHandle sem); void Sync_WaitSemaphore(SemaphoreHandle sem); void Sync_Sleep(uint32_t milliseconds); + + // Window API + struct Window; + + Window* Window_Create(); } diff --git a/Engine/src/delta/platform/os_win32.cpp b/Engine/src/delta/platform/os_win32.cpp index df4806b..cb835f3 100644 --- a/Engine/src/delta/platform/os_win32.cpp +++ b/Engine/src/delta/platform/os_win32.cpp @@ -419,6 +419,86 @@ namespace delta::platform { Sleep(milliseconds); } + + struct Window + { + HWND hwnd; + }; + + static LRESULT CALLBACK DltWindowProc(HWND hwnd, UINT umesg, WPARAM wparam, LPARAM lparam) + { + switch (umesg) + { + case WM_CLOSE: + // DestroyWindow(hwnd); + return 0; + default: + return DefWindowProcA(hwnd, umesg, wparam, lparam); + } + } + + Window* Window_Create() + { + Window* window = new(delta::Engine::AllocationType::PERSISTENT) Window(); + + static constexpr const char MAIN_WND_CLASS_NAME[] = "DltWindow"; + HINSTANCE hInstance = GetModuleHandleA(nullptr); + + STARTUPINFOA startupInfo = { sizeof(STARTUPINFOA) }; + GetStartupInfoA(&startupInfo); + int nCmdShow = (startupInfo.dwFlags & STARTF_USESHOWWINDOW) ? startupInfo.wShowWindow : SW_SHOWDEFAULT; + + const WNDCLASSEXA wc = + { + .cbSize = sizeof(WNDCLASSEXA), + .style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC, + .lpfnWndProc = DltWindowProc, + .cbClsExtra = 0, + .cbWndExtra = 0, + .hInstance = hInstance, + .hCursor = LoadCursorA(nullptr, IDC_ARROW), + .hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH), + .lpszClassName = MAIN_WND_CLASS_NAME + }; + + if (!RegisterClassExA(&wc)) + { + [[maybe_unused]] DWORD e = GetLastError(); + return nullptr; + } + + uint32_t clientWidth = 1280; + uint32_t clientHeight = 720; + + RECT wr = { 0, 0, static_cast(clientWidth), static_cast(clientHeight) }; + DWORD windowStyle = WS_OVERLAPPEDWINDOW | WS_VISIBLE; + + AdjustWindowRect(&wr, windowStyle, FALSE); + + window->hwnd = CreateWindowExA( + 0, + MAIN_WND_CLASS_NAME, + "Delta Engine", + windowStyle, + CW_USEDEFAULT, CW_USEDEFAULT, + wr.right - wr.left, + wr.bottom - wr.top, + nullptr, + nullptr, + hInstance, + nullptr + ); + + if (!window->hwnd) + { + return nullptr; + } + + ShowWindow(window->hwnd, nCmdShow); + UpdateWindow(window->hwnd); + + return window; + } } #endif From 92466b51ad9e8a4c9ba43d251c0d5e44d1976f70 Mon Sep 17 00:00:00 2001 From: YasInvolved Date: Tue, 2 Jun 2026 01:18:30 +0200 Subject: [PATCH 02/13] make hInstance and startupInfo global --- Engine/src/delta/platform/os_win32.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/Engine/src/delta/platform/os_win32.cpp b/Engine/src/delta/platform/os_win32.cpp index cb835f3..169e4c0 100644 --- a/Engine/src/delta/platform/os_win32.cpp +++ b/Engine/src/delta/platform/os_win32.cpp @@ -152,11 +152,18 @@ namespace delta::platform return true; } + // TODO: Move this variables to the reasonable place + static HINSTANCE s_hInstance = nullptr; + static STARTUPINFOA s_StartupInfo = { sizeof(STARTUPINFOA) }; + void Initialize() { memset(&g_osInfo, 0u, sizeof(OSInfo)); fetchCpuidValues(); + s_hInstance = GetModuleHandleA(nullptr); + GetStartupInfoA(&s_StartupInfo); + SYSTEM_INFO info; GetSystemInfo(&info); @@ -420,11 +427,15 @@ namespace delta::platform Sleep(milliseconds); } + // ------------------------------------------ WINDOW API ------------------------------------------ + struct Window { HWND hwnd; }; + static constexpr const char MAIN_WND_CLASS_NAME[] = "DltWindow"; + static LRESULT CALLBACK DltWindowProc(HWND hwnd, UINT umesg, WPARAM wparam, LPARAM lparam) { switch (umesg) @@ -439,10 +450,10 @@ namespace delta::platform Window* Window_Create() { + assert(s_hInstance); Window* window = new(delta::Engine::AllocationType::PERSISTENT) Window(); - static constexpr const char MAIN_WND_CLASS_NAME[] = "DltWindow"; - HINSTANCE hInstance = GetModuleHandleA(nullptr); + int nCmdShow = (s_StartupInfo.dwFlags & STARTF_USESHOWWINDOW) ? s_StartupInfo.wShowWindow : SW_SHOWDEFAULT; STARTUPINFOA startupInfo = { sizeof(STARTUPINFOA) }; GetStartupInfoA(&startupInfo); @@ -455,7 +466,7 @@ namespace delta::platform .lpfnWndProc = DltWindowProc, .cbClsExtra = 0, .cbWndExtra = 0, - .hInstance = hInstance, + .hInstance = s_hInstance, .hCursor = LoadCursorA(nullptr, IDC_ARROW), .hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH), .lpszClassName = MAIN_WND_CLASS_NAME @@ -485,7 +496,7 @@ namespace delta::platform wr.bottom - wr.top, nullptr, nullptr, - hInstance, + s_hInstance, nullptr ); From a5e71e5ba7a02216e7fb92411894556bfcd6ab16 Mon Sep 17 00:00:00 2001 From: YasInvolved Date: Tue, 2 Jun 2026 01:18:52 +0200 Subject: [PATCH 03/13] window lifetime functions --- Engine/src/delta/platform/os_internal.h | 2 ++ Engine/src/delta/platform/os_win32.cpp | 25 +++++++++++++++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/Engine/src/delta/platform/os_internal.h b/Engine/src/delta/platform/os_internal.h index 390cc6e..6549aed 100644 --- a/Engine/src/delta/platform/os_internal.h +++ b/Engine/src/delta/platform/os_internal.h @@ -76,4 +76,6 @@ namespace delta::platform struct Window; Window* Window_Create(); + void Window_ProcessEvents(); + void Window_Destroy(Window* window); } diff --git a/Engine/src/delta/platform/os_win32.cpp b/Engine/src/delta/platform/os_win32.cpp index 169e4c0..2093ca9 100644 --- a/Engine/src/delta/platform/os_win32.cpp +++ b/Engine/src/delta/platform/os_win32.cpp @@ -455,10 +455,6 @@ namespace delta::platform int nCmdShow = (s_StartupInfo.dwFlags & STARTF_USESHOWWINDOW) ? s_StartupInfo.wShowWindow : SW_SHOWDEFAULT; - STARTUPINFOA startupInfo = { sizeof(STARTUPINFOA) }; - GetStartupInfoA(&startupInfo); - int nCmdShow = (startupInfo.dwFlags & STARTF_USESHOWWINDOW) ? startupInfo.wShowWindow : SW_SHOWDEFAULT; - const WNDCLASSEXA wc = { .cbSize = sizeof(WNDCLASSEXA), @@ -510,6 +506,27 @@ namespace delta::platform return window; } + + void Window_ProcessEvents() + { + MSG msg = {}; + while (PeekMessageA(&msg, nullptr, 0, 0, PM_REMOVE)) + { + if (msg.message == WM_QUIT) + { + // TODO: Handle this + } + + TranslateMessage(&msg); + DispatchMessageA(&msg); + } + } + + void Window_Destroy(Window* window) + { + DestroyWindow(window->hwnd); + UnregisterClassA(MAIN_WND_CLASS_NAME, s_hInstance); + } } #endif From ed56396dfce9177532f41a5052d4abc99d0c5f28 Mon Sep 17 00:00:00 2001 From: YasInvolved Date: Tue, 2 Jun 2026 19:17:55 +0200 Subject: [PATCH 04/13] platform header mess fix --- Engine/CMakeLists.txt | 3 +- Engine/include/delta/core/engine.h | 2 ++ Engine/include/delta/platform/os.h | 26 +------------- Engine/include/delta/platform/os_types.h | 36 +++++++++++++++++++ Engine/src/delta/core/ThreadContext.cpp | 2 +- Engine/src/delta/platform/os_internal.h | 22 +----------- Engine/src/delta/platform/os_internal_types.h | 27 ++++++++++++++ 7 files changed, 70 insertions(+), 48 deletions(-) create mode 100644 Engine/include/delta/platform/os_types.h create mode 100644 Engine/src/delta/platform/os_internal_types.h diff --git a/Engine/CMakeLists.txt b/Engine/CMakeLists.txt index d056fcf..b0afb61 100644 --- a/Engine/CMakeLists.txt +++ b/Engine/CMakeLists.txt @@ -20,6 +20,7 @@ add_library(ProjectDelta SHARED "include/delta/definitions.h" "src/delta/platform/os_internal.h" "src/delta/platform/os_win32.cpp" + "include/delta/platform/os_types.h" "include/delta/platform/os.h" "include/delta/pch.h" "src/delta/pch.h" @@ -31,7 +32,7 @@ add_library(ProjectDelta SHARED "src/delta/core/MemoryConfig.cpp" "src/delta/core/Worker.h" "src/delta/core/Worker.cpp" -) + "src/delta/platform/os_internal_types.h") target_compile_definitions(ProjectDelta PRIVATE DLT_EXPORT_SYMBOLS diff --git a/Engine/include/delta/core/engine.h b/Engine/include/delta/core/engine.h index 40fc429..b021679 100644 --- a/Engine/include/delta/core/engine.h +++ b/Engine/include/delta/core/engine.h @@ -15,11 +15,13 @@ */ #include +#include namespace delta::Engine { struct Context { + delta::platform::WindowHandle window; bool isRunning; }; diff --git a/Engine/include/delta/platform/os.h b/Engine/include/delta/platform/os.h index 75e1525..a92fcb6 100644 --- a/Engine/include/delta/platform/os.h +++ b/Engine/include/delta/platform/os.h @@ -15,34 +15,10 @@ */ #pragma once +#include namespace delta::platform { - struct OSInfo - { - const char* cpuArchitecture; - - uint32_t cpuPhysicalCoreCount; - uint32_t cpuLogicalProcessorCount; - uint32_t osPageSize; - - char cpuBrandString[sizeof(int) * 12 + 1]; - char cpuManufacturerId[13]; - - bool cpuHasSMT; - bool cpuHasAVX2; - bool cpuHasAVX512f; - bool cpuHasAVX512cd; - bool cpuHasAVX512er; - bool cpuHasAVX512pf; - }; - - struct MemoryStatus - { - uint64_t physicalInstalled; - uint64_t physicalFree; - }; - DLT_API const OSInfo* getOSInfo() noexcept; DLT_API MemoryStatus getMemoryStatus(); } diff --git a/Engine/include/delta/platform/os_types.h b/Engine/include/delta/platform/os_types.h new file mode 100644 index 0000000..151f302 --- /dev/null +++ b/Engine/include/delta/platform/os_types.h @@ -0,0 +1,36 @@ +#pragma once + +#define DLT_DEFINE_HANDLE(name)\ + struct name;\ + using name##Handle = name*;\ + inline constexpr name##Handle INVALID_##name##_HANDLE = nullptr + +namespace delta::platform +{ + DLT_DEFINE_HANDLE(Window); + + struct OSInfo + { + const char* cpuArchitecture; + + uint32_t cpuPhysicalCoreCount; + uint32_t cpuLogicalProcessorCount; + uint32_t osPageSize; + + char cpuBrandString[sizeof(int) * 12 + 1]; + char cpuManufacturerId[13]; + + bool cpuHasSMT; + bool cpuHasAVX2; + bool cpuHasAVX512f; + bool cpuHasAVX512cd; + bool cpuHasAVX512er; + bool cpuHasAVX512pf; + }; + + struct MemoryStatus + { + uint64_t physicalInstalled; + uint64_t physicalFree; + }; +} diff --git a/Engine/src/delta/core/ThreadContext.cpp b/Engine/src/delta/core/ThreadContext.cpp index 8e3019c..e1baf12 100644 --- a/Engine/src/delta/core/ThreadContext.cpp +++ b/Engine/src/delta/core/ThreadContext.cpp @@ -156,7 +156,7 @@ namespace delta::core WorkerExecutionContext& ctx = GetExecutionContext(i); ctx.generic.type = ThreadType::WORKER; ctx.generic.threadIx = i; - ctx.generic.threadHandle = delta::platform::INVALID_THREAD_HANDLE; // Initialized when thread starts + ctx.generic.threadHandle = delta::platform::INVALID_Thread_HANDLE; // Initialized when thread starts ctx.isAsleep.store(false, std::memory_order_relaxed); ctx.shouldClose.store(false, std::memory_order_relaxed); ctx.sleepSemaphore = delta::platform::Sync_CreateSemaphore(); diff --git a/Engine/src/delta/platform/os_internal.h b/Engine/src/delta/platform/os_internal.h index 6549aed..69d8942 100644 --- a/Engine/src/delta/platform/os_internal.h +++ b/Engine/src/delta/platform/os_internal.h @@ -15,6 +15,7 @@ */ #pragma once +#include namespace delta::platform { @@ -31,28 +32,12 @@ namespace delta::platform bool Memory_ElevateLockLimit(size_t maxBytesToLock); // Timer API - struct Timer_Internal; - struct Timer - { - alignas(8) uint8_t opaqueData[32]; - }; - void Timer_Initialize(Timer* timer); int64_t Timer_GetTimestamp(); double Timer_TicksToMilliseconds(const Timer* timer, int64_t startTicks, int64_t endTicks); double Timer_TicksToMicroseconds(const Timer* timer, int64_t startTicks, int64_t endTicks); // Thread API - struct Thread; - using ThreadHandle = Thread*; - inline constexpr ThreadHandle INVALID_THREAD_HANDLE = nullptr; // random number 696767 - - struct ThreadCreateInfo - { - void (*fn)(void*); - void* args; - }; - uint32_t Thread_GetCurrentId(); uint32_t Thread_GetId(ThreadHandle thread); ThreadHandle Thread_GetCurrentHandle(); @@ -63,9 +48,6 @@ namespace delta::platform void Thread_JoinMultiple(ThreadHandle* threads, uint32_t count); // Sync API - struct Semaphore; - using SemaphoreHandle = Semaphore*; - SemaphoreHandle Sync_CreateSemaphore(); void Sync_DestroySemaphore(SemaphoreHandle sem); void Sync_SignalSemaphore(SemaphoreHandle sem); @@ -73,8 +55,6 @@ namespace delta::platform void Sync_Sleep(uint32_t milliseconds); // Window API - struct Window; - Window* Window_Create(); void Window_ProcessEvents(); void Window_Destroy(Window* window); diff --git a/Engine/src/delta/platform/os_internal_types.h b/Engine/src/delta/platform/os_internal_types.h new file mode 100644 index 0000000..864a8ef --- /dev/null +++ b/Engine/src/delta/platform/os_internal_types.h @@ -0,0 +1,27 @@ +#pragma once +#include + +namespace delta::platform +{ + // Timer API + struct Timer_Internal; + struct Timer + { + alignas(8) uint8_t opaqueData[32]; + }; + + // Thread API + DLT_DEFINE_HANDLE(Thread); + + struct ThreadCreateInfo + { + void (*fn)(void*); + void* args; + }; + + // Sync API + DLT_DEFINE_HANDLE(Semaphore); + + // Window API + // Window defined in the public header +} From f410d7e802ad4f8551847f6b5bfc6e5f5ec773f2 Mon Sep 17 00:00:00 2001 From: YasInvolved Date: Tue, 2 Jun 2026 19:28:43 +0200 Subject: [PATCH 05/13] expose Window_SetTitle function --- Engine/include/delta/platform/os.h | 5 +++++ Engine/src/delta/core/engine.cpp | 7 ++++++- Engine/src/delta/platform/os_win32.cpp | 5 +++++ Examples/HelloWorldGame/game.cpp | 17 +---------------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Engine/include/delta/platform/os.h b/Engine/include/delta/platform/os.h index a92fcb6..fb17395 100644 --- a/Engine/include/delta/platform/os.h +++ b/Engine/include/delta/platform/os.h @@ -19,6 +19,11 @@ namespace delta::platform { + // General + // TODO: Change names to the adequate ones DLT_API const OSInfo* getOSInfo() noexcept; DLT_API MemoryStatus getMemoryStatus(); + + // Window API + DLT_API void Window_SetTitle(WindowHandle window, const char* newTitle); } diff --git a/Engine/src/delta/core/engine.cpp b/Engine/src/delta/core/engine.cpp index bfdcdc7..c135e11 100644 --- a/Engine/src/delta/core/engine.cpp +++ b/Engine/src/delta/core/engine.cpp @@ -43,18 +43,23 @@ namespace delta::Engine delta::platform::ThreadHandle th = delta::platform::Thread_GetCurrentHandle(); delta::platform::Thread_AssignPhysicalCore(th, 0); delta::core::Worker_Init(totalThreads-1); + + context.window = delta::platform::Window_Create(); } void Update(Context& context) { // blah blah blah // do something - delta::platform::Sync_Sleep(100); + + delta::platform::Window_ProcessEvents(); + delta::platform::Sync_Sleep(10); delta::core::ThreadArena_Reset(delta::core::GetTransientArena()); } void Shutdown(Context& context) { + Engine::Free(context.window); delta::core::Worker_Shutdown(); delta::core::ThreadContext_Shutdown(); delta::core::MemoryConfig_Shutdown(); diff --git a/Engine/src/delta/platform/os_win32.cpp b/Engine/src/delta/platform/os_win32.cpp index 2093ca9..a2ac708 100644 --- a/Engine/src/delta/platform/os_win32.cpp +++ b/Engine/src/delta/platform/os_win32.cpp @@ -527,6 +527,11 @@ namespace delta::platform DestroyWindow(window->hwnd); UnregisterClassA(MAIN_WND_CLASS_NAME, s_hInstance); } + + void Window_SetTitle(WindowHandle window, const char* newTitle) + { + SetWindowTextA(window->hwnd, newTitle); + } } #endif diff --git a/Examples/HelloWorldGame/game.cpp b/Examples/HelloWorldGame/game.cpp index 44bb162..7a1cdc9 100644 --- a/Examples/HelloWorldGame/game.cpp +++ b/Examples/HelloWorldGame/game.cpp @@ -38,22 +38,7 @@ extern "C" void GAME_API Game_OnInit(delta::Engine::Context* context) { const OSInfo* info = delta::platform::getOSInfo(); - - std::cout << "Initializing game\n"; - std::cout << "System Info:\n"; - std::cout << - "\tOS Page Size: " << info->osPageSize << " bytes\n" << - "\tCPU Architecture: " << info->cpuArchitecture << "\n" << - "\tCPU Manufacturer: " << info->cpuManufacturerId << "\n" << - "\tCPU Model: " << info->cpuBrandString << "\n" << - "\tCPU Physical Cores: " << info->cpuPhysicalCoreCount << "\n" << - "\tCPU Logical Cores: " << info->cpuLogicalProcessorCount << "\n" << - "\tCPU Has SMT: " << STDOUT_BOOL_FORMAT(info->cpuHasSMT) << "\n" << - "\tAVX2 Available: " << STDOUT_BOOL_FORMAT(info->cpuHasAVX2) << "\n" << - "\tAVX512 Foundation Available: " << STDOUT_BOOL_FORMAT(info->cpuHasAVX512f) << "\n" << - "\tAVX512 Conflict Detection Available: " << STDOUT_BOOL_FORMAT(info->cpuHasAVX512cd) << "\n" << - "\tAVX512 Exponential and Reciprocal Available: " << STDOUT_BOOL_FORMAT(info->cpuHasAVX512er) << "\n" << - "\tAVX512 Prefetch Available: " << STDOUT_BOOL_FORMAT(info->cpuHasAVX512pf) << "\n"; + delta::platform::Window_SetTitle(context->window, "Hello World Game"); } void GAME_API Game_OnUpdate(delta::Engine::Context* context) From 7cd511e63b09fb89f0ccc035af493e70228dda94 Mon Sep 17 00:00:00 2001 From: YasInvolved Date: Tue, 2 Jun 2026 22:17:17 +0200 Subject: [PATCH 06/13] expand the win32 api a little with new window functions --- Engine/include/delta/platform/os.h | 6 +++ Engine/src/delta/core/engine.cpp | 2 + Engine/src/delta/platform/os_internal.h | 5 ++- Engine/src/delta/platform/os_win32.cpp | 51 +++++++++++++++++++++---- 4 files changed, 55 insertions(+), 9 deletions(-) diff --git a/Engine/include/delta/platform/os.h b/Engine/include/delta/platform/os.h index fb17395..7a29f01 100644 --- a/Engine/include/delta/platform/os.h +++ b/Engine/include/delta/platform/os.h @@ -26,4 +26,10 @@ namespace delta::platform // Window API DLT_API void Window_SetTitle(WindowHandle window, const char* newTitle); + DLT_API void Window_Show(WindowHandle window); + DLT_API void Window_Hide(WindowHandle window); + DLT_API void Window_SetSize(WindowHandle window, uint32_t w, uint32_t h); + DLT_API void Window_SetPos(WindowHandle window, uint32_t x, uint32_t y); + DLT_API void Window_ShowCursor(WindowHandle window); + DLT_API void Window_HideCursor(WindowHandle window); } diff --git a/Engine/src/delta/core/engine.cpp b/Engine/src/delta/core/engine.cpp index c135e11..8790ef9 100644 --- a/Engine/src/delta/core/engine.cpp +++ b/Engine/src/delta/core/engine.cpp @@ -45,6 +45,8 @@ namespace delta::Engine delta::core::Worker_Init(totalThreads-1); context.window = delta::platform::Window_Create(); + delta::platform::Window_Show(context.window); + delta::platform::Window_Win32_Update(context.window); } void Update(Context& context) diff --git a/Engine/src/delta/platform/os_internal.h b/Engine/src/delta/platform/os_internal.h index 69d8942..c9332be 100644 --- a/Engine/src/delta/platform/os_internal.h +++ b/Engine/src/delta/platform/os_internal.h @@ -55,7 +55,8 @@ namespace delta::platform void Sync_Sleep(uint32_t milliseconds); // Window API - Window* Window_Create(); + WindowHandle Window_Create(); + void Window_Win32_Update(WindowHandle window); void Window_ProcessEvents(); - void Window_Destroy(Window* window); + void Window_Destroy(WindowHandle window); } diff --git a/Engine/src/delta/platform/os_win32.cpp b/Engine/src/delta/platform/os_win32.cpp index a2ac708..9c1d05c 100644 --- a/Engine/src/delta/platform/os_win32.cpp +++ b/Engine/src/delta/platform/os_win32.cpp @@ -25,6 +25,9 @@ #define CHECK_CPUID_FLAG(register, flag) ((register & (1 << flag)) != 0) +_declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; +_declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; + namespace delta::platform { static OSInfo g_osInfo; @@ -448,10 +451,10 @@ namespace delta::platform } } - Window* Window_Create() + WindowHandle Window_Create() { assert(s_hInstance); - Window* window = new(delta::Engine::AllocationType::PERSISTENT) Window(); + WindowHandle window = new(delta::Engine::AllocationType::PERSISTENT) Window(); int nCmdShow = (s_StartupInfo.dwFlags & STARTF_USESHOWWINDOW) ? s_StartupInfo.wShowWindow : SW_SHOWDEFAULT; @@ -478,7 +481,7 @@ namespace delta::platform uint32_t clientHeight = 720; RECT wr = { 0, 0, static_cast(clientWidth), static_cast(clientHeight) }; - DWORD windowStyle = WS_OVERLAPPEDWINDOW | WS_VISIBLE; + static constexpr DWORD windowStyle = WS_OVERLAPPEDWINDOW; AdjustWindowRect(&wr, windowStyle, FALSE); @@ -501,12 +504,14 @@ namespace delta::platform return nullptr; } - ShowWindow(window->hwnd, nCmdShow); - UpdateWindow(window->hwnd); - return window; } + void Window_Win32_Update(WindowHandle window) + { + UpdateWindow(window->hwnd); + } + void Window_ProcessEvents() { MSG msg = {}; @@ -522,7 +527,7 @@ namespace delta::platform } } - void Window_Destroy(Window* window) + void Window_Destroy(WindowHandle window) { DestroyWindow(window->hwnd); UnregisterClassA(MAIN_WND_CLASS_NAME, s_hInstance); @@ -532,6 +537,38 @@ namespace delta::platform { SetWindowTextA(window->hwnd, newTitle); } + + void Window_Show(WindowHandle window) + { + ShowWindow(window->hwnd, SW_SHOW); + } + + void Window_Hide(WindowHandle window) + { + ShowWindow(window->hwnd, SW_HIDE); + } + + void Window_SetSize(WindowHandle window, uint32_t w, uint32_t h) + { + static constexpr UINT FLAGS = SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW; + SetWindowPos(window->hwnd, nullptr, 0, 0, w, h, FLAGS); + } + + void Window_SetPos(WindowHandle window, uint32_t x, uint32_t y) + { + static constexpr UINT FLAGS = SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW; + SetWindowPos(window->hwnd, nullptr, x, y, 0, 0, FLAGS); + } + + void Window_ShowCursor(WindowHandle window) + { + ShowCursor(TRUE); + } + + void Window_HideCursor(WindowHandle window) + { + ShowCursor(FALSE); + } } #endif From eb936626833e639c2f8bc8f05664617f5ac39aef Mon Sep 17 00:00:00 2001 From: YasInvolved Date: Fri, 10 Jul 2026 01:07:52 +0200 Subject: [PATCH 07/13] fix namespace inconsistency (cosmetics, but I needed to do it) --- Engine/CMakeLists.txt | 1 + Engine/include/delta/core/core_types.h | 18 ++++++++++++++++++ Engine/include/delta/core/engine.h | 13 ++----------- Engine/include/delta/core/memory.h | 21 ++++++++++----------- Engine/src/delta/core/Worker.cpp | 4 ++-- Engine/src/delta/core/engine.cpp | 4 ++-- Engine/src/delta/platform/os_win32.cpp | 8 ++++---- Examples/HelloWorldGame/game.cpp | 6 +++--- Launcher/main.cpp | 14 +++++++------- 9 files changed, 49 insertions(+), 40 deletions(-) create mode 100644 Engine/include/delta/core/core_types.h diff --git a/Engine/CMakeLists.txt b/Engine/CMakeLists.txt index a49c22b..e649808 100644 --- a/Engine/CMakeLists.txt +++ b/Engine/CMakeLists.txt @@ -34,6 +34,7 @@ add_library(ProjectDelta SHARED "src/delta/core/Worker.cpp" "include/delta/utils/StaticArray.h" "src/delta/platform/os_internal_types.h" + "include/delta/core/core_types.h" ) target_compile_definitions(ProjectDelta diff --git a/Engine/include/delta/core/core_types.h b/Engine/include/delta/core/core_types.h new file mode 100644 index 0000000..3d331a8 --- /dev/null +++ b/Engine/include/delta/core/core_types.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +namespace delta::core +{ + struct Context + { + delta::platform::WindowHandle window; + bool isRunning; + }; + + enum class AllocationType : uint8_t { TRANSIENT, PERSISTENT }; + + typedef void (*GameInitFunc)(Context*); + typedef void (*GameUpdateFunc)(Context*); + typedef void (*GameShutdownFunc)(Context*); +} diff --git a/Engine/include/delta/core/engine.h b/Engine/include/delta/core/engine.h index b021679..3fe4bef 100644 --- a/Engine/include/delta/core/engine.h +++ b/Engine/include/delta/core/engine.h @@ -15,20 +15,11 @@ */ #include +#include #include -namespace delta::Engine +namespace delta::core { - struct Context - { - delta::platform::WindowHandle window; - bool isRunning; - }; - - typedef void (*GameInitFunc)(Context*); - typedef void (*GameUpdateFunc)(Context*); - typedef void (*GameShutdownFunc)(Context*); - DLT_API void Initialize(Context& context); DLT_API void Update(Context& context); DLT_API void Shutdown(Context& context); diff --git a/Engine/include/delta/core/memory.h b/Engine/include/delta/core/memory.h index 0c1ba98..45ef8ac 100644 --- a/Engine/include/delta/core/memory.h +++ b/Engine/include/delta/core/memory.h @@ -17,21 +17,20 @@ #pragma once #include +#include -namespace delta::Engine +namespace delta::core { - enum class AllocationType : uint8_t { TRANSIENT, PERSISTENT }; - [[nodiscard]] DLT_API void* Allocate(size_t size, AllocationType type, size_t alignment = 8) noexcept; DLT_API void Free(void* ptr) noexcept; } -[[nodiscard]] inline void* operator new(size_t size) { return delta::Engine::Allocate(size, delta::Engine::AllocationType::PERSISTENT); } -[[nodiscard]] inline void* operator new(size_t size, delta::Engine::AllocationType type) { return delta::Engine::Allocate(size, type); } -[[nodiscard]] inline void* operator new[](size_t size) { return delta::Engine::Allocate(size, delta::Engine::AllocationType::PERSISTENT); } -[[nodiscard]] inline void* operator new[](size_t size, delta::Engine::AllocationType type) { return delta::Engine::Allocate(size, type); } +[[nodiscard]] inline void* operator new(size_t size) { return delta::core::Allocate(size, delta::core::AllocationType::PERSISTENT); } +[[nodiscard]] inline void* operator new(size_t size, delta::core::AllocationType type) { return delta::core::Allocate(size, type); } +[[nodiscard]] inline void* operator new[](size_t size) { return delta::core::Allocate(size, delta::core::AllocationType::PERSISTENT); } +[[nodiscard]] inline void* operator new[](size_t size, delta::core::AllocationType type) { return delta::core::Allocate(size, type); } -inline void operator delete(void* ptr) { return delta::Engine::Free(ptr); } -inline void operator delete(void* ptr, delta::Engine::AllocationType) { return delta::Engine::Free(ptr); } -inline void operator delete[](void* ptr) { return delta::Engine::Free(ptr); } -inline void operator delete[](void* ptr, delta::Engine::AllocationType) { return delta::Engine::Free(ptr); } +inline void operator delete(void* ptr) { return delta::core::Free(ptr); } +inline void operator delete(void* ptr, delta::core::AllocationType) { return delta::core::Free(ptr); } +inline void operator delete[](void* ptr) { return delta::core::Free(ptr); } +inline void operator delete[](void* ptr, delta::core::AllocationType) { return delta::core::Free(ptr); } diff --git a/Engine/src/delta/core/Worker.cpp b/Engine/src/delta/core/Worker.cpp index 7cded61..4331851 100644 --- a/Engine/src/delta/core/Worker.cpp +++ b/Engine/src/delta/core/Worker.cpp @@ -65,8 +65,8 @@ namespace delta::core // TODO: Take a look at native thread api and figure out how this could be done better // TODO: Set thread affinity mask - s_Threads = new(delta::Engine::AllocationType::PERSISTENT) ThreadHandle[count]; - ThreadCreateInfo* cs = new(delta::Engine::AllocationType::TRANSIENT) ThreadCreateInfo[count]; + s_Threads = new(delta::core::AllocationType::PERSISTENT) ThreadHandle[count]; + ThreadCreateInfo* cs = new(delta::core::AllocationType::TRANSIENT) ThreadCreateInfo[count]; for (uint32_t i = 0; i < count; i++) { diff --git a/Engine/src/delta/core/engine.cpp b/Engine/src/delta/core/engine.cpp index 8790ef9..35477ea 100644 --- a/Engine/src/delta/core/engine.cpp +++ b/Engine/src/delta/core/engine.cpp @@ -24,7 +24,7 @@ #include "ThreadContext.h" #include "Worker.h" -namespace delta::Engine +namespace delta::core { using GenericExecutionContext = delta::core::GenericExecutionContext; @@ -61,7 +61,7 @@ namespace delta::Engine void Shutdown(Context& context) { - Engine::Free(context.window); + delta::core::Free(context.window); delta::core::Worker_Shutdown(); delta::core::ThreadContext_Shutdown(); delta::core::MemoryConfig_Shutdown(); diff --git a/Engine/src/delta/platform/os_win32.cpp b/Engine/src/delta/platform/os_win32.cpp index d0f62ee..99cd3a7 100644 --- a/Engine/src/delta/platform/os_win32.cpp +++ b/Engine/src/delta/platform/os_win32.cpp @@ -336,7 +336,7 @@ namespace delta::platform ThreadHandle Thread_GetCurrentHandle() { - Thread* t = new(delta::Engine::AllocationType::PERSISTENT) Thread(); + Thread* t = new(delta::core::AllocationType::PERSISTENT) Thread(); t->hThread = GetCurrentThread(); if (!t->hThread) return nullptr; @@ -373,7 +373,7 @@ namespace delta::platform ThreadHandle Thread_Create(ThreadCreateInfo* createInfo) { - Thread* thread = new(delta::Engine::AllocationType::PERSISTENT) Thread{}; + Thread* thread = new(delta::core::AllocationType::PERSISTENT) Thread{}; thread->hThread = CreateThread(nullptr, 0, DeltaThreadProc, (void*)createInfo, 0, 0); if (thread->hThread == 0) return nullptr; @@ -400,7 +400,7 @@ namespace delta::platform SemaphoreHandle Sync_CreateSemaphore() { - Semaphore* s = new(delta::Engine::AllocationType::PERSISTENT) Semaphore{}; + Semaphore* s = new(delta::core::AllocationType::PERSISTENT) Semaphore{}; s->hSemaphore = CreateSemaphoreA(nullptr, 0, 1000000, nullptr); if (s->hSemaphore == nullptr) return nullptr; @@ -455,7 +455,7 @@ namespace delta::platform WindowHandle Window_Create() { assert(s_hInstance); - WindowHandle window = new(delta::Engine::AllocationType::PERSISTENT) Window(); + WindowHandle window = new(delta::core::AllocationType::PERSISTENT) Window(); int nCmdShow = (s_StartupInfo.dwFlags & STARTF_USESHOWWINDOW) ? s_StartupInfo.wShowWindow : SW_SHOWDEFAULT; diff --git a/Examples/HelloWorldGame/game.cpp b/Examples/HelloWorldGame/game.cpp index 7a1cdc9..39db5d1 100644 --- a/Examples/HelloWorldGame/game.cpp +++ b/Examples/HelloWorldGame/game.cpp @@ -35,18 +35,18 @@ using OSInfo = delta::platform::OSInfo; extern "C" { - void GAME_API Game_OnInit(delta::Engine::Context* context) + void GAME_API Game_OnInit(delta::core::Context* context) { const OSInfo* info = delta::platform::getOSInfo(); delta::platform::Window_SetTitle(context->window, "Hello World Game"); } - void GAME_API Game_OnUpdate(delta::Engine::Context* context) + void GAME_API Game_OnUpdate(delta::core::Context* context) { } - void GAME_API Game_OnShutdown(delta::Engine::Context* context) + void GAME_API Game_OnShutdown(delta::core::Context* context) { } diff --git a/Launcher/main.cpp b/Launcher/main.cpp index d1525ae..1e38e37 100644 --- a/Launcher/main.cpp +++ b/Launcher/main.cpp @@ -40,9 +40,9 @@ namespace fs = std::filesystem; -using InitFunc = delta::Engine::GameInitFunc; -using UpdateFunc = delta::Engine::GameUpdateFunc; -using ShutdownFunc = delta::Engine::GameShutdownFunc; +using InitFunc = delta::core::GameInitFunc; +using UpdateFunc = delta::core::GameUpdateFunc; +using ShutdownFunc = delta::core::GameShutdownFunc; template inline T loadSymbol(const char* symName, DynamicLibrary lib) @@ -129,7 +129,7 @@ struct Game } }; -static delta::Engine::Context g_context; +static delta::core::Context g_context; static trigger::SignalSocket g_reloadSocket; int main(int argc, char** argv) @@ -148,7 +148,7 @@ int main(int argc, char** argv) } - delta::Engine::Initialize(g_context); + delta::core::Initialize(g_context); const char* libPath = argv[1]; Game game(libPath); @@ -172,12 +172,12 @@ int main(int argc, char** argv) continue; } - delta::Engine::Update(g_context); + delta::core::Update(g_context); game.updateFn(&g_context); } game.shutdownFn(&g_context); - delta::Engine::Shutdown(g_context); + delta::core::Shutdown(g_context); return 0; } From 395577c3d91a1f7596334d3d0908adf9f2933c77 Mon Sep 17 00:00:00 2001 From: YasInvolved Date: Fri, 10 Jul 2026 03:51:32 +0200 Subject: [PATCH 08/13] CTMath header --- Engine/CMakeLists.txt | 1 + Engine/include/delta/utils/CTMath.h | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 Engine/include/delta/utils/CTMath.h diff --git a/Engine/CMakeLists.txt b/Engine/CMakeLists.txt index e649808..83ef314 100644 --- a/Engine/CMakeLists.txt +++ b/Engine/CMakeLists.txt @@ -35,6 +35,7 @@ add_library(ProjectDelta SHARED "include/delta/utils/StaticArray.h" "src/delta/platform/os_internal_types.h" "include/delta/core/core_types.h" + "include/delta/utils/CTMath.h" ) target_compile_definitions(ProjectDelta diff --git a/Engine/include/delta/utils/CTMath.h b/Engine/include/delta/utils/CTMath.h new file mode 100644 index 0000000..f57d4ca --- /dev/null +++ b/Engine/include/delta/utils/CTMath.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +namespace delta::utils +{ + template + inline constexpr bool is_power_of_two(T value) noexcept + { + return value > 0 && (value & (value - 1)) == 0; + } + + template + [[nodiscard]] inline constexpr T align_up(T value, T alignment) noexcept + { + T a = alignment - 1; + return ((alignment & a) == 0) + ? ((value + a) & ~(a)) + : (((value + a) / alignment) * alignment); + } +} From 35ea839b929bfaf97099c34f698d8eac10c8fa1a Mon Sep 17 00:00:00 2001 From: YasInvolved Date: Fri, 10 Jul 2026 19:11:06 +0200 Subject: [PATCH 09/13] introduce aos_helper header --- Engine/CMakeLists.txt | 1 + Engine/src/delta/core/aos_helper.h | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 Engine/src/delta/core/aos_helper.h diff --git a/Engine/CMakeLists.txt b/Engine/CMakeLists.txt index 83ef314..2726809 100644 --- a/Engine/CMakeLists.txt +++ b/Engine/CMakeLists.txt @@ -36,6 +36,7 @@ add_library(ProjectDelta SHARED "src/delta/platform/os_internal_types.h" "include/delta/core/core_types.h" "include/delta/utils/CTMath.h" + "src/delta/core/aos_helper.h" ) target_compile_definitions(ProjectDelta diff --git a/Engine/src/delta/core/aos_helper.h b/Engine/src/delta/core/aos_helper.h new file mode 100644 index 0000000..f5f980d --- /dev/null +++ b/Engine/src/delta/core/aos_helper.h @@ -0,0 +1,30 @@ +#pragma once + +#define DLT_INT_AOS_SCALAR(type) type +#define DLT_INT_SOA_POINTER(type) type* + +#define DLT_DEFAULT_FIELD_DEF(Layout, type, name) Layout(type, name, DLT_INT_AOS_SCALAR, DLT_INT_SOA_POINTER) + +#define DLT_PARSE_AOS(type, name, aos_meta, soa_meta) aos_meta(type) name; +#define DLT_PARSE_SOA(type, name, aos_meta, soa_meta) soa_meta(type) name; + +#define DLT_RESOURCE_GROUP_OPEN(Layout, name) struct { +#define DLT_RESOURCE_GROUP_CLOSE(Layout, name) } name; + +#define DLT_GEN_STRUCT_REPRESENTATIONS(StructName, FieldList) \ + struct StructName##AoS { \ + FieldList(DLT_PARSE_AOS) \ + }; \ + \ + struct StructName##SoA { \ + FieldList(DLT_PARSE_SOA) \ + }; + +#define DLT_GEN_ALIGNED_STRUCT_REPRESENTATIONS(StructName, Alignment, FieldList) \ + struct alignas(Alignment) StructName##AoS { \ + FieldList(DLT_PARSE_AOS) \ + }; \ + \ + struct StructName##SoA { \ + FieldList(DLT_PARSE_SOA) \ + }; From 5b7f1d78715b5325c863d853ffff65d4b771c612 Mon Sep 17 00:00:00 2001 From: YasInvolved Date: Fri, 10 Jul 2026 19:12:04 +0200 Subject: [PATCH 10/13] start reworking ThreadContext to use AoS layout (will be used later in the jobs rework and events impl) --- Engine/CMakeLists.txt | 6 +- Engine/src/delta/core/EngineTypes.h | 132 +++---- Engine/src/delta/core/MemoryConfig.h | 16 +- Engine/src/delta/core/ThreadContext.cpp | 359 ------------------ Engine/src/delta/core/ThreadContext.h | 109 ------ .../src/delta/core/ThreadContextManager.cpp | 74 ++++ Engine/src/delta/core/ThreadContextManager.h | 33 ++ Engine/src/delta/core/Worker.cpp | 90 ----- Engine/src/delta/core/Worker.h | 25 -- Engine/src/delta/core/engine.cpp | 12 +- 10 files changed, 161 insertions(+), 695 deletions(-) delete mode 100644 Engine/src/delta/core/ThreadContext.cpp delete mode 100644 Engine/src/delta/core/ThreadContext.h create mode 100644 Engine/src/delta/core/ThreadContextManager.cpp create mode 100644 Engine/src/delta/core/ThreadContextManager.h delete mode 100644 Engine/src/delta/core/Worker.cpp delete mode 100644 Engine/src/delta/core/Worker.h diff --git a/Engine/CMakeLists.txt b/Engine/CMakeLists.txt index 2726809..455344c 100644 --- a/Engine/CMakeLists.txt +++ b/Engine/CMakeLists.txt @@ -26,17 +26,15 @@ add_library(ProjectDelta SHARED "src/delta/pch.h" "src/delta/pch.cpp" "src/delta/core/EngineTypes.h" - "src/delta/core/ThreadContext.h" - "src/delta/core/ThreadContext.cpp" "src/delta/core/MemoryConfig.h" "src/delta/core/MemoryConfig.cpp" - "src/delta/core/Worker.h" - "src/delta/core/Worker.cpp" "include/delta/utils/StaticArray.h" "src/delta/platform/os_internal_types.h" "include/delta/core/core_types.h" "include/delta/utils/CTMath.h" "src/delta/core/aos_helper.h" + "src/delta/core/ThreadContextManager.h" + "src/delta/core/ThreadContextManager.cpp" ) target_compile_definitions(ProjectDelta diff --git a/Engine/src/delta/core/EngineTypes.h b/Engine/src/delta/core/EngineTypes.h index 98db880..67d7b7a 100644 --- a/Engine/src/delta/core/EngineTypes.h +++ b/Engine/src/delta/core/EngineTypes.h @@ -17,95 +17,51 @@ #pragma once #include +#include +#include namespace delta::core { - // TODO: revise this structure and its purpose - struct ThreadPageCoordinator - { - uint8_t* virtualAddressBase; - size_t commitedOffset; - size_t reservedCapacity; - size_t pageSize; - }; - - struct ThreadArena - { - uint8_t* backingMemory; - size_t capacity; - size_t offset; - size_t maxCapacity; - }; - - struct DependencyCounter - { - std::atomic count; - }; - - using task_t = void (*)(void*); - using payload_t = void*; - using queue_index_t = int64_t; - struct TaskQueue // SoA structure, Chase-Lev queue - { - alignas(64) std::atomic top; - alignas(64) std::atomic bottom; - - alignas(64) queue_index_t size; - queue_index_t mask; - - task_t* tasks; - payload_t* payloads; - DependencyCounter* depCounterPtr; - - static inline constexpr size_t FIELD_SIZE = sizeof(task_t) + sizeof(payload_t); - }; - - enum class ThreadType : uint8_t { MAIN, WORKER }; - - struct alignas(64) GenericExecutionContext - { - // SHARED TRAITS - ThreadType type; - uint32_t threadIx; - delta::platform::ThreadHandle threadHandle; - - ThreadPageCoordinator pageCoordinator; - ThreadArena transientArena; - delta::platform::Timer perThreadTimer; - }; - - struct alignas(64) MainExecutionContext - { - // SHARED TRAITS - GenericExecutionContext generic; - - // ROLE TRAITS - ThreadArena persistentStorage; - DependencyCounter depCounter; - }; - - struct alignas(64) WorkerExecutionContext - { - GenericExecutionContext generic; - - // ROLE TRAITS - TaskQueue taskQueue; - delta::platform::SemaphoreHandle sleepSemaphore; - std::atomic isAsleep; - std::atomic shouldClose; - }; - - template - concept ExecutionContext = - std::is_same_v, GenericExecutionContext> || - std::is_same_v, MainExecutionContext> || - std::is_same_v, WorkerExecutionContext>; - - // COMPILE TIME CONSTANTS - inline constexpr size_t THREAD_EXECUTION_CONTEXT_STRIDE = std::max(sizeof(MainExecutionContext), sizeof(WorkerExecutionContext)); - inline constexpr size_t THREAD_EXECUTION_CONTEXT_SIZE = (THREAD_EXECUTION_CONTEXT_STRIDE + 63) & ~(63); - - // EXTERN VARIABLES & FUNCTIONS - extern uintptr_t g_MasterSlabStart; - extern uintptr_t g_MasterSlabEnd; + inline constexpr size_t THREADCTX_ALIGNMENT = 64ull; + + #define DLT_CORE_PAGECRD_FIELDS(Layout) \ + DLT_DEFAULT_FIELD_DEF(Layout, uint8_t*, base) \ + DLT_DEFAULT_FIELD_DEF(Layout, size_t, size) + + #define DLT_CORE_THREADARENA_FIELDS(Layout) \ + DLT_DEFAULT_FIELD_DEF(Layout, uint8_t*, base) \ + DLT_DEFAULT_FIELD_DEF(Layout, size_t, offset) \ + DLT_DEFAULT_FIELD_DEF(Layout, size_t, reserved) \ + DLT_DEFAULT_FIELD_DEF(Layout, size_t, size) + + #define DLT_CORE_MASTERTHREADCTX_FIELDS(Layout) \ + DLT_DEFAULT_FIELD_DEF(Layout, uint32_t, threadId) \ + \ + DLT_RESOURCE_GROUP_OPEN(Layout, pagecrd) \ + DLT_CORE_PAGECRD_FIELDS(Layout) \ + DLT_RESOURCE_GROUP_CLOSE(Layout, pagecrd) \ + \ + DLT_RESOURCE_GROUP_OPEN(Layout, persistentStorage) \ + DLT_CORE_THREADARENA_FIELDS(Layout) \ + DLT_RESOURCE_GROUP_CLOSE(Layout, persistentStorage) \ + \ + DLT_RESOURCE_GROUP_OPEN(Layout, transientStorage) \ + DLT_CORE_THREADARENA_FIELDS(Layout) \ + DLT_RESOURCE_GROUP_CLOSE(Layout, transientStorage) + + #define DLT_CORE_WORKERTHREADCTX_FIELDS(Layout) \ + DLT_DEFAULT_FIELD_DEF(Layout, uint32_t, threadId) \ + \ + DLT_RESOURCE_GROUP_OPEN(Layout, pagecrd) \ + DLT_CORE_PAGECRD_FIELDS(Layout) \ + DLT_RESOURCE_GROUP_CLOSE(Layout, pagecrd) \ + \ + DLT_RESOURCE_GROUP_OPEN(Layout, transientStorage) \ + DLT_CORE_THREADARENA_FIELDS(Layout) \ + DLT_RESOURCE_GROUP_CLOSE(Layout, transientStorage) + + DLT_GEN_STRUCT_REPRESENTATIONS(PageCoordinator, DLT_CORE_PAGECRD_FIELDS) + DLT_GEN_STRUCT_REPRESENTATIONS(ThreadArena, DLT_CORE_THREADARENA_FIELDS) + DLT_GEN_ALIGNED_STRUCT_REPRESENTATIONS(MasterThreadContext, THREADCTX_ALIGNMENT, DLT_CORE_MASTERTHREADCTX_FIELDS) + DLT_GEN_ALIGNED_STRUCT_REPRESENTATIONS(WorkerThreadContext, THREADCTX_ALIGNMENT, DLT_CORE_WORKERTHREADCTX_FIELDS) } diff --git a/Engine/src/delta/core/MemoryConfig.h b/Engine/src/delta/core/MemoryConfig.h index 87ad05b..391e968 100644 --- a/Engine/src/delta/core/MemoryConfig.h +++ b/Engine/src/delta/core/MemoryConfig.h @@ -45,38 +45,34 @@ namespace delta::core inline constexpr size_t VIRT_ZONE_SPACE_LENGTH = (1ull << 35); inline constexpr PoolDescriptor generic_transientArena(0ull, (1ull << 30), (1ull << 26)); - inline constexpr PoolDescriptor generic_eventBuffer(generic_transientArena, (1ull << 27), (1ull << 17)); // Index Registry inline constexpr uint32_t VIRT_ZONE_GENERIC_TA_INDEX = 0u; - inline constexpr uint32_t VIRT_ZONE_GENERIC_EB_INDEX = 1u; // -- MAIN -- - inline constexpr uint32_t VIRT_ZONE_MAIN_PS_INDEX = 2u; + inline constexpr uint32_t VIRT_ZONE_MAIN_PS_INDEX = 1u; // -- WORKER -- - inline constexpr uint32_t VIRT_ZONE_WORKER_TQ_INDEX = 2u; - inline constexpr uint32_t VIRT_ZONE_WORKER_CP_INDEX = 3u; - inline constexpr uint32_t VIRT_ZONE_WORKER_IO_INDEX = 4u; + inline constexpr uint32_t VIRT_ZONE_WORKER_TQ_INDEX = 1u; + inline constexpr uint32_t VIRT_ZONE_WORKER_CP_INDEX = 2u; + inline constexpr uint32_t VIRT_ZONE_WORKER_IO_INDEX = 3u; inline constexpr auto VIRT_MAP_MAIN = []() consteval { - auto permaStorage = PoolDescriptor(generic_eventBuffer, (1ull << 31), (1ull << 26)); + auto permaStorage = PoolDescriptor(generic_transientArena, (1ull << 31), (1ull << 26)); return delta::utils::StaticArray{ generic_transientArena, - generic_eventBuffer, permaStorage }; }(); inline constexpr auto VIRT_MAP_WORKER = []() consteval { - auto taskQueue = PoolDescriptor(generic_eventBuffer, (1ull << 16)); + auto taskQueue = PoolDescriptor(generic_transientArena, (1ull << 16)); auto componentPool = PoolDescriptor(taskQueue, (1ull << 33), (1ull << 27)); auto io = PoolDescriptor(componentPool, (1ull << 30)); return delta::utils::StaticArray{ generic_transientArena, - generic_eventBuffer, taskQueue, componentPool, io diff --git a/Engine/src/delta/core/ThreadContext.cpp b/Engine/src/delta/core/ThreadContext.cpp deleted file mode 100644 index aca800d..0000000 --- a/Engine/src/delta/core/ThreadContext.cpp +++ /dev/null @@ -1,359 +0,0 @@ -/* - * Copyright 2026 Jakub Bączyk - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include "ThreadContext.h" -#include "MemoryConfig.h" - -#define ALIGN(size, alignment) ((size + (alignment - 1)) & ~(alignment - 1)) - -namespace delta::core -{ - using PoolDescriptor = MemoryMap::PoolDescriptor; - - uintptr_t g_MasterSlabStart = 0; - uintptr_t g_MasterSlabEnd = 0; - - static uint32_t g_ThreadCount = 0; - static uint32_t g_WorkerCount = 0; - static GenericExecutionContext* g_ThreadContexts = nullptr; - static thread_local GenericExecutionContext* tl_CurrentThreadContext = nullptr; - - DLT_FORCE_INLINE static void InitializePageCoordinator(ThreadPageCoordinator& pageCoord, size_t pageSize, uint8_t* baseAddress) - { - pageCoord.pageSize = pageSize; - pageCoord.virtualAddressBase = baseAddress; - pageCoord.commitedOffset = 0; - pageCoord.reservedCapacity = MemoryMap::VIRT_ZONE_SPACE_LENGTH; - } - - DLT_FORCE_INLINE static void InitializeQueue( - const ThreadPageCoordinator& pageCoord, - TaskQueue& queue, - DependencyCounter* depCounter, - const PoolDescriptor& pd) - { - queue.size = pd.size / TaskQueue::FIELD_SIZE; - queue.mask = queue.size - 1; - queue.top.store(0, std::memory_order_relaxed); - queue.bottom.store(0, std::memory_order_relaxed); - - // a queue is commited in whole - uint8_t* pTarget = pageCoord.virtualAddressBase + pd.offset; - void* p = delta::platform::Memory_Commit(pTarget, pd.size); - if (!delta::platform::Memory_Lock(pTarget, pd.size)) - std::cout << "[DeltaEngine-Warning] Failed to lock task queue memory. You may experience stuttering.\n"; - assert(p != nullptr); - - uint8_t* tasksArrayPtr = pTarget; - uint8_t* payloadsArrayPtr = pTarget + queue.size; - queue.tasks = reinterpret_cast(tasksArrayPtr); - queue.payloads = reinterpret_cast(payloadsArrayPtr); - } - - DLT_FORCE_INLINE static void InitializeArena( - const ThreadPageCoordinator& pageCoord, - ThreadArena& arena, - const PoolDescriptor& pd) - { - uint8_t* pTarget = pageCoord.virtualAddressBase + pd.offset; - void* res = delta::platform::Memory_Commit(pTarget, pd.baseline); - assert(res != nullptr); - - if (!delta::platform::Memory_Lock(pTarget, pd.baseline)) - std::cout << "[DeltaEngine-Warning] Failed to lock arena memory. You may experience stuttering.\n"; - - arena.backingMemory = pTarget; - arena.capacity = pd.baseline; - arena.offset = 0; - arena.maxCapacity = pd.size; - } - - template - DLT_FORCE_INLINE ContextType& GetExecutionContext(size_t i) - { - return reinterpret_cast(*(reinterpret_cast(g_ThreadContexts) + i * THREAD_EXECUTION_CONTEXT_SIZE)); - } - - void ThreadContext_Initialize(uint32_t threadCount, size_t pageSize) - { - g_ThreadCount = threadCount; - g_WorkerCount = threadCount - 1; - - // assign 32Gb of address space per thread - // master pool size is rounded up to page size - constexpr size_t ADDR_SLICE_PER_THREAD = (1ull << 35); - size_t contextArraySize = THREAD_EXECUTION_CONTEXT_SIZE * threadCount; - size_t alignedContextArraySize = ALIGN(contextArraySize, pageSize); - size_t masterPoolSize = (ADDR_SLICE_PER_THREAD * threadCount) + alignedContextArraySize; - - uint8_t* masterPoolBase = reinterpret_cast( - delta::platform::Memory_Reserve(masterPoolSize) - ); - assert(masterPoolBase != nullptr && "Failed to reserve master pool"); - - g_MasterSlabStart = reinterpret_cast(masterPoolBase); - g_MasterSlabEnd = g_MasterSlabStart + masterPoolSize; - - g_ThreadContexts = reinterpret_cast( - delta::platform::Memory_Commit(masterPoolBase, alignedContextArraySize) - ); - assert(g_ThreadContexts != nullptr && "Failed to commit thread context array"); - - if (!delta::platform::Memory_Lock(masterPoolBase, alignedContextArraySize)) - std::cout << "[DeltaEngine-Warning] Failed to lock memory resource: Master Thread Context Pool\n"; - - // pre-initialize generics - uint8_t* runwayCursor = masterPoolBase + alignedContextArraySize; - for (uint32_t i = 0; i < threadCount; i++) - { - GenericExecutionContext& ctx = GetExecutionContext(i); - delta::platform::Timer_Initialize(&ctx.perThreadTimer); - InitializePageCoordinator(ctx.pageCoordinator, pageSize, runwayCursor); - InitializeArena( - ctx.pageCoordinator, - ctx.transientArena, - MemoryMap::VIRT_MAP_MAIN[MemoryMap::VIRT_ZONE_GENERIC_TA_INDEX] - ); - - runwayCursor += MemoryMap::VIRT_ZONE_SPACE_LENGTH; - } - - // Finish initializing main thread context - DependencyCounter* depCounterPtr = nullptr; - { - MainExecutionContext& ctx = GetExecutionContext(0); - ctx.generic.type = ThreadType::MAIN; - ctx.generic.threadIx = 0; - ctx.generic.threadHandle = delta::platform::Thread_GetCurrentHandle(); - ctx.depCounter.count.store(0, std::memory_order_relaxed); - depCounterPtr = &ctx.depCounter; - - InitializeArena( - ctx.generic.pageCoordinator, - ctx.persistentStorage, - MemoryMap::VIRT_MAP_MAIN[MemoryMap::VIRT_ZONE_MAIN_PS_INDEX] - ); - } - - for (uint32_t i = 1; i < threadCount; i++) - { - WorkerExecutionContext& ctx = GetExecutionContext(i); - ctx.generic.type = ThreadType::WORKER; - ctx.generic.threadIx = i; - ctx.generic.threadHandle = delta::platform::INVALID_Thread_HANDLE; // Initialized when thread starts - ctx.isAsleep.store(false, std::memory_order_relaxed); - ctx.shouldClose.store(false, std::memory_order_relaxed); - ctx.sleepSemaphore = delta::platform::Sync_CreateSemaphore(); - - InitializeQueue( - ctx.generic.pageCoordinator, - ctx.taskQueue, - depCounterPtr, - MemoryMap::VIRT_MAP_WORKER[MemoryMap::VIRT_ZONE_WORKER_TQ_INDEX] - ); - } - - tl_CurrentThreadContext = &g_ThreadContexts[0]; - } - - void ThreadContext_Shutdown() - { - delta::platform::Memory_Release(g_ThreadContexts); - } - - GenericExecutionContext* ThreadContext_GetCurrent() noexcept - { - return tl_CurrentThreadContext; - } - - GenericExecutionContext* ThreadContext_GetForIndex(uint32_t i) noexcept - { - return &GetExecutionContext(i); - } - - void ThreadContext_SetCurrent(GenericExecutionContext* ctx) noexcept - { - tl_CurrentThreadContext = ctx; - } - - void TaskQueue_Push(TaskQueue* queue, task_t task, payload_t payload) - { - queue_index_t b = queue->bottom.load(std::memory_order_relaxed); - queue_index_t t = queue->top.load(std::memory_order_acquire); - - if (b - t > queue->size) - { - // execute immadietely if the queue is full - task(payload); - return; - } - - queue_index_t ix = b & queue->mask; - queue->tasks[ix] = task; - queue->payloads[ix] = payload; - - std::atomic_thread_fence(std::memory_order_release); - queue->bottom.store(b + 1, std::memory_order_relaxed); - } - - bool TaskQueue_Pop(TaskQueue* queue, task_t* outTask, payload_t* outPayload) - { - queue_index_t b = queue->bottom.load(std::memory_order_relaxed) - 1; - queue->bottom.store(b, std::memory_order_relaxed); - - std::atomic_thread_fence(std::memory_order_seq_cst); - queue_index_t t = queue->top.load(std::memory_order_relaxed); - - if (t > b) - { - queue->bottom.store(b + 1, std::memory_order_relaxed); - return false; - } - - queue_index_t ix = b & queue->mask; - *outTask = queue->tasks[ix]; - *outPayload = queue->payloads[ix]; - - if (t == b) - { - queue_index_t expectedTop = t; - if (!queue->top.compare_exchange_strong(expectedTop, expectedTop + 1, std::memory_order_seq_cst, std::memory_order_relaxed)) - { - queue->bottom.store(b + 1, std::memory_order_relaxed); - return false; - } - - queue->bottom.store(b + 1, std::memory_order_relaxed); - } - - return true; - } - - bool TaskQueue_Steal(TaskQueue* queue, task_t* outTask, payload_t* outPayload) - { - queue_index_t t = queue->top.load(std::memory_order_acquire); - - std::atomic_thread_fence(std::memory_order_seq_cst); - queue_index_t b = queue->bottom.load(std::memory_order_acquire); - - if (t >= b) - return false; - - queue_index_t ix = t & queue->mask; - *outTask = queue->tasks[ix]; - *outPayload = queue->payloads[ix]; - - if (!queue->top.compare_exchange_strong(t, t + 1, std::memory_order_seq_cst, std::memory_order_relaxed)) - return false; - - return true; - } - - void Scheduler_ProcessTaskBatch(task_t* tasks, payload_t* payloads, size_t length) - { - assert(IsMainThread()); // CAN BE EXECUTED ONLY ON MAIN THREAD! - GetMainContext().depCounter.count.store(length, std::memory_order_relaxed); - - for (size_t i = 0; i < length; i++) - { - size_t targetIx = 1 + (i % g_WorkerCount); - WorkerExecutionContext& ctx = GetExecutionContext(targetIx); - TaskQueue_Push(&ctx.taskQueue, tasks[i], payloads[i]); - - if (ctx.isAsleep.load(std::memory_order_acquire)) - delta::platform::Sync_SignalSemaphore(ctx.sleepSemaphore); - } - } - - void Scheduler_Sync() - { - assert(tl_CurrentThreadContext->threadIx == 0); // CAN BE EXECUTED ONLY ON MAIN THREAD! - - uint32_t workerIx = 1; - uint32_t consecutiveEmptyQueues = 0; - - while (consecutiveEmptyQueues < g_ThreadCount) - { - WorkerExecutionContext& ctx = GetExecutionContext(workerIx); - task_t task = nullptr; - payload_t payload = nullptr; - - if (TaskQueue_Steal(&ctx.taskQueue, &task, &payload)) - { - consecutiveEmptyQueues = 0; - assert(task && payload); - - size_t snapshot = tl_CurrentThreadContext->transientArena.offset; - task(payload); - tl_CurrentThreadContext->transientArena.offset = snapshot; - } - else - { - consecutiveEmptyQueues++; - } - - workerIx = 1 + (workerIx % g_WorkerCount); - } - } - - ThreadArena* GetTransientArena() noexcept - { - auto* ctx = tl_CurrentThreadContext; - assert(ctx); - return &ctx->transientArena; - } - - void* ThreadArena_Allocate(ThreadArena* arena, size_t size, size_t alignment) - { - uintptr_t currentAddress = reinterpret_cast(arena->backingMemory) + arena->offset; - uintptr_t alignedAddress = ALIGN(currentAddress, alignment); - size_t padding = alignedAddress - currentAddress; - size_t totalSpace = padding + size; - - if (arena->offset + totalSpace > arena->maxCapacity) - { - // TODO: Handle it better. I don't know how yet, but I will know soon. - assert(false); // arena overflown - } - - if (totalSpace > arena->capacity) - { - // the slow path: assign more pages - // assigning twice 2 up front to avoid further slower-path-taking - size_t bytesNeeded = totalSpace - arena->capacity; - size_t spaceInPages = ALIGN(bytesNeeded, tl_CurrentThreadContext->pageCoordinator.pageSize) * 2; - uint8_t* targetAddress = arena->backingMemory + arena->capacity; - void* p = delta::platform::Memory_Commit(targetAddress, spaceInPages); - if (p && delta::platform::Memory_Lock(p, spaceInPages)) - { - return nullptr; - } - - arena->capacity += spaceInPages; - } - - uint8_t* ptr = reinterpret_cast(alignedAddress); - arena->offset += totalSpace; - - return ptr; - } - - void ThreadArena_Reset(ThreadArena* arena) - { - arena->offset = 0; - } -} diff --git a/Engine/src/delta/core/ThreadContext.h b/Engine/src/delta/core/ThreadContext.h deleted file mode 100644 index a4aa6a9..0000000 --- a/Engine/src/delta/core/ThreadContext.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2026 Jakub Bączyk - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include "EngineTypes.h" - -namespace delta::core -{ - // Lifecycle - void ThreadContext_Initialize(uint32_t workerCount, size_t pageSize); - void ThreadContext_Shutdown(); - - // Getters - GenericExecutionContext* ThreadContext_GetCurrent() noexcept; - GenericExecutionContext* ThreadContext_GetForIndex(uint32_t ix) noexcept; - void ThreadContext_SetCurrent(GenericExecutionContext* ctx) noexcept; - - // Thread Task Queue API - void TaskQueue_Push(TaskQueue* queue, task_t task, payload_t payload); - bool TaskQueue_Pop(TaskQueue* queue, task_t* outTask, payload_t* outPayload); - bool TaskQueue_Steal(TaskQueue* queue, task_t* outTask, payload_t* outPayload); - - // Scheduler API - void Scheduler_ProcessTaskBatch(task_t* tasks, payload_t* payloads, size_t length); - void Scheduler_Sync(); - - // Engine Arena API - ThreadArena* GetTransientArena() noexcept; - void* ThreadArena_Allocate(ThreadArena* arena, size_t size, size_t alignment = 8); - void ThreadArena_Reset(ThreadArena* arena); - void ThreadArena_Reset(ThreadArena* arena); - - // Inline Helpers - template - [[deprecated]] [[nodiscard]] inline TargetType* ThreadContextCast(GenericExecutionContext* ctx) - { - if (!ctx) return nullptr; - - if constexpr (std::is_same_v) - { - if (ctx->type == ThreadType::MAIN) - return reinterpret_cast(ctx); - } - else if constexpr (std::is_same_v) - { - if (ctx->type == ThreadType::WORKER) - return reinterpret_cast(ctx); - } - - assert(false); // CRITICAL: Casting to invalid type - return nullptr; - } - - inline bool IsCustomAllocated(void* ptr) - { - // range scan - return g_MasterSlabStart <= reinterpret_cast(ptr) && reinterpret_cast(ptr) <= g_MasterSlabEnd; - } - - inline bool IsMainThread() - { - auto* ctx = ThreadContext_GetCurrent(); - return ctx && ctx->type == ThreadType::MAIN; - } - - inline bool IsWorkerThread() - { - auto* ctx = ThreadContext_GetCurrent(); - return ctx && ctx->type == ThreadType::WORKER; - } - - DLT_DISABLE_WARNING_PUSH - DLT_DISABLE_MISSING_RETURN - inline MainExecutionContext& GetMainContext() - { - auto* ctx = ThreadContext_GetCurrent(); - if (ctx->type == ThreadType::MAIN) - return reinterpret_cast(*ctx); - - assert(false); // this shouldn't ever happen - DLT_UNREACHABLE; - } - - inline WorkerExecutionContext& GetWorkerContext() - { - auto* ctx = ThreadContext_GetCurrent(); - if (ctx->type == ThreadType::WORKER) - return reinterpret_cast(*ctx); - - assert(false); - DLT_UNREACHABLE; - } - DLT_DISABLE_WARNING_POP -} diff --git a/Engine/src/delta/core/ThreadContextManager.cpp b/Engine/src/delta/core/ThreadContextManager.cpp new file mode 100644 index 0000000..816dffb --- /dev/null +++ b/Engine/src/delta/core/ThreadContextManager.cpp @@ -0,0 +1,74 @@ +#include "ThreadContextManager.h" +#include "MemoryConfig.h" + +#include +#include + +namespace delta::core +{ + static MasterThreadContextAoS g_MasterThreadCtx; + static WorkerThreadContextSoA g_WorkerThreadCtx; + + static DLT_FORCE_INLINE bool InitializeContextArray(tca_cursor_t& cursor, size_t ctxArraySize, uint32_t workers) + { + void* p = delta::platform::Memory_Commit(cursor, ctxArraySize); + if (!p) + return false; + + if (!delta::platform::Memory_Lock(cursor, ctxArraySize)) + return false; + + // set array pointers + g_WorkerThreadCtx.threadId = cursor; + cursor += workers * sizeof(WorkerThreadContextAoS::threadId); + + g_WorkerThreadCtx.pagecrd.base = cursor; + cursor += workers * sizeof(WorkerThreadContextAoS::pagecrd.base); + + g_WorkerThreadCtx.pagecrd.size = cursor; + cursor += workers * sizeof(WorkerThreadContextAoS::pagecrd.size); + + g_WorkerThreadCtx.transientStorage.base = cursor; + cursor += workers * sizeof(WorkerThreadContextAoS::transientStorage.base); + + g_WorkerThreadCtx.transientStorage.offset = cursor; + cursor += workers * sizeof(WorkerThreadContextAoS::transientStorage.offset); + + g_WorkerThreadCtx.transientStorage.reserved = cursor; + cursor += workers * sizeof(WorkerThreadContextAoS::transientStorage.reserved); + + g_WorkerThreadCtx.transientStorage.size = cursor; + cursor += workers * sizeof(WorkerThreadContextAoS::transientStorage.size); + + return true; + } + + void ThreadContextManager_Initialize(uint32_t totalThreads, uint32_t pageSize) + { + const uint32_t workers = totalThreads - 1; + const size_t addrSpaceSize = delta::utils::align_up(totalThreads * MemoryMap::VIRT_ZONE_SPACE_LENGTH, pageSize); + const size_t ctxArraySize = delta::utils::align_up(workers * sizeof(WorkerThreadContextAoS), pageSize); + const size_t reservationSize = ctxArraySize + addrSpaceSize; + + void* addrSpace = delta::platform::Memory_Reserve(reservationSize); + if (!addrSpace) + { + std::cout << "[DeltaEngine-Critical] Failed to reserve virtual address space\n"; + std::abort(); + } + + { + tca_cursor_t cursor(addrSpace); + if (!InitializeContextArray(cursor, ctxArraySize, workers)) + { + std::cout << "[DeltaEngine-Critical] Failed to initialize Thread Context Array\n"; + std::abort(); + } + } + } + + void ThreadContextManager_Shutdown() + { + + } +} diff --git a/Engine/src/delta/core/ThreadContextManager.h b/Engine/src/delta/core/ThreadContextManager.h new file mode 100644 index 0000000..b2c07f9 --- /dev/null +++ b/Engine/src/delta/core/ThreadContextManager.h @@ -0,0 +1,33 @@ +#pragma once + +#include "EngineTypes.h" + +namespace delta::core +{ + template + struct Cursor + { + Cursor(void* _ptr) + : ptr(reinterpret_cast(_ptr)) + { } + + uintptr_t ptr; + + template + inline operator T* () const noexcept + { + return reinterpret_cast(ptr); + } + + template + inline Cursor& operator+=(const T& rhs) noexcept + { + ptr = delta::utils::align_up(ptr + rhs, Alignment); + } + }; + + using tca_cursor_t = Cursor; + + void ThreadContextManager_Initialize(uint32_t totalThreads, uint32_t pageSize); + void ThreadContextManager_Shutdown(); +} diff --git a/Engine/src/delta/core/Worker.cpp b/Engine/src/delta/core/Worker.cpp deleted file mode 100644 index 4331851..0000000 --- a/Engine/src/delta/core/Worker.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2026 Jakub Bączyk - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "Worker.h" -#include -#include - -namespace delta::core -{ - using ThreadHandle = delta::platform::ThreadHandle; - using ThreadCreateInfo = delta::platform::ThreadCreateInfo; - - using SemaphoreHandle = delta::platform::SemaphoreHandle; - - static uint32_t s_WorkerCount; - static ThreadHandle* s_Threads; - - static void WorkerProc(void* args) - { - WorkerExecutionContext* ctx = reinterpret_cast(args); - ThreadContext_SetCurrent((GenericExecutionContext*)ctx); - - task_t task; - payload_t payload; - DependencyCounter& depCounter = reinterpret_cast(*ctx->taskQueue.depCounterPtr); - while (!ctx->shouldClose.load(std::memory_order_acquire)) - { - // TODO: Figure out how to select a worker to steal some work from. - // I'll probably utilize modulo n cyclic groups. (algebra - group theory) - - if (TaskQueue_Pop(&ctx->taskQueue, &task, &payload)) - { - task(payload); - depCounter.count.fetch_sub(1, std::memory_order_release); - continue; - } - - ThreadArena_Reset(GetTransientArena()); - ctx->isAsleep.store(true, std::memory_order_release); - if (!ctx->shouldClose.load(std::memory_order_acquire)) - { - delta::platform::Sync_WaitSemaphore(ctx->sleepSemaphore); - } - - ctx->isAsleep.store(false, std::memory_order_release); - } - } - - void Worker_Init(uint32_t count) - { - s_WorkerCount = count; - - // TODO: Take a look at native thread api and figure out how this could be done better - // TODO: Set thread affinity mask - s_Threads = new(delta::core::AllocationType::PERSISTENT) ThreadHandle[count]; - ThreadCreateInfo* cs = new(delta::core::AllocationType::TRANSIENT) ThreadCreateInfo[count]; - - for (uint32_t i = 0; i < count; i++) - { - // looping through thread indices, workers start from ix=1 - ThreadCreateInfo& info = cs[i]; - ThreadHandle& handle = s_Threads[i]; - auto* ctx = ThreadContext_GetForIndex(i + 1); - info.fn = WorkerProc; - info.args = (void*)ctx; - handle = delta::platform::Thread_Create(&info); - ctx->threadHandle = handle; - delta::platform::Thread_AssignPhysicalCore(handle, i + 1); - delta::platform::Thread_SetName(handle, "Worker"); - } - } - - void Worker_Shutdown() - { - delta::platform::Thread_JoinMultiple(s_Threads, s_WorkerCount); - } -} diff --git a/Engine/src/delta/core/Worker.h b/Engine/src/delta/core/Worker.h deleted file mode 100644 index 6ec2a8b..0000000 --- a/Engine/src/delta/core/Worker.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2026 Jakub Bączyk - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include - -namespace delta::core -{ - void Worker_Init(uint32_t count); - void Worker_Shutdown(); -} diff --git a/Engine/src/delta/core/engine.cpp b/Engine/src/delta/core/engine.cpp index 35477ea..5df53e8 100644 --- a/Engine/src/delta/core/engine.cpp +++ b/Engine/src/delta/core/engine.cpp @@ -21,8 +21,7 @@ #include "EngineTypes.h" #include "MemoryConfig.h" -#include "ThreadContext.h" -#include "Worker.h" +#include "ThreadContextManager.h" namespace delta::core { @@ -38,11 +37,7 @@ namespace delta::core uint32_t totalThreads = osInfo->cpuPhysicalCoreCount; uint32_t pageSize = osInfo->osPageSize; delta::core::MemoryConfig_Initialize(memStatus.physicalInstalled, pageSize, totalThreads); - delta::core::ThreadContext_Initialize(totalThreads, pageSize); - - delta::platform::ThreadHandle th = delta::platform::Thread_GetCurrentHandle(); - delta::platform::Thread_AssignPhysicalCore(th, 0); - delta::core::Worker_Init(totalThreads-1); + delta::core::ThreadContextManager_Initialize(totalThreads); context.window = delta::platform::Window_Create(); delta::platform::Window_Show(context.window); @@ -56,14 +51,11 @@ namespace delta::core delta::platform::Window_ProcessEvents(); delta::platform::Sync_Sleep(10); - delta::core::ThreadArena_Reset(delta::core::GetTransientArena()); } void Shutdown(Context& context) { delta::core::Free(context.window); - delta::core::Worker_Shutdown(); - delta::core::ThreadContext_Shutdown(); delta::core::MemoryConfig_Shutdown(); } From 8f41ec7b9cc4b40e7c98483dca46cbacedab5909 Mon Sep 17 00:00:00 2001 From: YasInvolved Date: Fri, 10 Jul 2026 19:50:48 +0200 Subject: [PATCH 11/13] change naming convention a bit --- Engine/src/delta/core/MemoryConfig.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Engine/src/delta/core/MemoryConfig.h b/Engine/src/delta/core/MemoryConfig.h index 391e968..e92b631 100644 --- a/Engine/src/delta/core/MemoryConfig.h +++ b/Engine/src/delta/core/MemoryConfig.h @@ -44,35 +44,35 @@ namespace delta::core // Generic inline constexpr size_t VIRT_ZONE_SPACE_LENGTH = (1ull << 35); - inline constexpr PoolDescriptor generic_transientArena(0ull, (1ull << 30), (1ull << 26)); + inline constexpr PoolDescriptor generic_transientStorage(0ull, (1ull << 30), (1ull << 26)); // Index Registry - inline constexpr uint32_t VIRT_ZONE_GENERIC_TA_INDEX = 0u; + inline constexpr uint32_t VIRT_ZONE_GENERIC_TS_INDEX = 0u; - // -- MAIN -- - inline constexpr uint32_t VIRT_ZONE_MAIN_PS_INDEX = 1u; + // -- MASTER -- + inline constexpr uint32_t VIRT_ZONE_MASTER_PS_INDEX = 1u; // -- WORKER -- inline constexpr uint32_t VIRT_ZONE_WORKER_TQ_INDEX = 1u; inline constexpr uint32_t VIRT_ZONE_WORKER_CP_INDEX = 2u; inline constexpr uint32_t VIRT_ZONE_WORKER_IO_INDEX = 3u; - inline constexpr auto VIRT_MAP_MAIN = []() consteval { - auto permaStorage = PoolDescriptor(generic_transientArena, (1ull << 31), (1ull << 26)); + inline constexpr auto VIRT_MAP_MASTER = []() consteval { + auto permaStorage = PoolDescriptor(generic_transientStorage, (1ull << 31), (1ull << 26)); return delta::utils::StaticArray{ - generic_transientArena, + generic_transientStorage, permaStorage }; }(); inline constexpr auto VIRT_MAP_WORKER = []() consteval { - auto taskQueue = PoolDescriptor(generic_transientArena, (1ull << 16)); + auto taskQueue = PoolDescriptor(generic_transientStorage, (1ull << 16)); auto componentPool = PoolDescriptor(taskQueue, (1ull << 33), (1ull << 27)); auto io = PoolDescriptor(componentPool, (1ull << 30)); return delta::utils::StaticArray{ - generic_transientArena, + generic_transientStorage, taskQueue, componentPool, io @@ -91,7 +91,7 @@ namespace delta::core return sum; } - inline constexpr auto VIRT_MAIN_BASELINE = total_baseline(VIRT_MAP_MAIN); + inline constexpr auto VIRT_MASTER_BASELINE = total_baseline(VIRT_MAP_MASTER); inline constexpr auto VIRT_WORKER_BASELINE = total_baseline(VIRT_MAP_WORKER); } From c29d31875c0b44fd8665f90eae89e4c9eb822d02 Mon Sep 17 00:00:00 2001 From: YasInvolved Date: Fri, 10 Jul 2026 20:19:01 +0200 Subject: [PATCH 12/13] initialize new structures --- Engine/src/delta/core/EngineTypes.h | 12 ++-- .../src/delta/core/ThreadContextManager.cpp | 70 +++++++++++++++++-- Engine/src/delta/core/ThreadContextManager.h | 17 +++-- 3 files changed, 82 insertions(+), 17 deletions(-) diff --git a/Engine/src/delta/core/EngineTypes.h b/Engine/src/delta/core/EngineTypes.h index 67d7b7a..da613e2 100644 --- a/Engine/src/delta/core/EngineTypes.h +++ b/Engine/src/delta/core/EngineTypes.h @@ -25,11 +25,11 @@ namespace delta::core inline constexpr size_t THREADCTX_ALIGNMENT = 64ull; #define DLT_CORE_PAGECRD_FIELDS(Layout) \ - DLT_DEFAULT_FIELD_DEF(Layout, uint8_t*, base) \ + DLT_DEFAULT_FIELD_DEF(Layout, uintptr_t, base) \ DLT_DEFAULT_FIELD_DEF(Layout, size_t, size) #define DLT_CORE_THREADARENA_FIELDS(Layout) \ - DLT_DEFAULT_FIELD_DEF(Layout, uint8_t*, base) \ + DLT_DEFAULT_FIELD_DEF(Layout, uintptr_t, base) \ DLT_DEFAULT_FIELD_DEF(Layout, size_t, offset) \ DLT_DEFAULT_FIELD_DEF(Layout, size_t, reserved) \ DLT_DEFAULT_FIELD_DEF(Layout, size_t, size) @@ -41,13 +41,13 @@ namespace delta::core DLT_CORE_PAGECRD_FIELDS(Layout) \ DLT_RESOURCE_GROUP_CLOSE(Layout, pagecrd) \ \ - DLT_RESOURCE_GROUP_OPEN(Layout, persistentStorage) \ + DLT_RESOURCE_GROUP_OPEN(Layout, transientStorage) \ DLT_CORE_THREADARENA_FIELDS(Layout) \ - DLT_RESOURCE_GROUP_CLOSE(Layout, persistentStorage) \ + DLT_RESOURCE_GROUP_CLOSE(Layout, transientStorage) \ \ - DLT_RESOURCE_GROUP_OPEN(Layout, transientStorage) \ + DLT_RESOURCE_GROUP_OPEN(Layout, persistentStorage) \ DLT_CORE_THREADARENA_FIELDS(Layout) \ - DLT_RESOURCE_GROUP_CLOSE(Layout, transientStorage) + DLT_RESOURCE_GROUP_CLOSE(Layout, persistentStorage) #define DLT_CORE_WORKERTHREADCTX_FIELDS(Layout) \ DLT_DEFAULT_FIELD_DEF(Layout, uint32_t, threadId) \ diff --git a/Engine/src/delta/core/ThreadContextManager.cpp b/Engine/src/delta/core/ThreadContextManager.cpp index 816dffb..2c0f81e 100644 --- a/Engine/src/delta/core/ThreadContextManager.cpp +++ b/Engine/src/delta/core/ThreadContextManager.cpp @@ -43,6 +43,32 @@ namespace delta::core return true; } + static DLT_FORCE_INLINE bool InitializeWorker(uintptr_t& cursor, uint32_t ix) + { + constexpr auto WORKER_TS_DESC = MemoryMap::VIRT_MAP_WORKER[MemoryMap::VIRT_ZONE_GENERIC_TS_INDEX]; + + g_WorkerThreadCtx.threadId[ix] = 0xBADBEEFu; + + g_WorkerThreadCtx.pagecrd.base[ix] = cursor; + g_WorkerThreadCtx.pagecrd.size[ix] = MemoryMap::VIRT_ZONE_SPACE_LENGTH; + + auto& tsBase = g_WorkerThreadCtx.transientStorage.base[ix]; + tsBase = cursor + WORKER_TS_DESC.offset; + g_WorkerThreadCtx.transientStorage.offset[ix] = 0ull; + g_WorkerThreadCtx.transientStorage.reserved[ix] = WORKER_TS_DESC.baseline; + g_WorkerThreadCtx.transientStorage.size[ix] = WORKER_TS_DESC.size; + + void* p = delta::platform::Memory_Commit(reinterpret_cast(tsBase), WORKER_TS_DESC.baseline); + if (!p) + return false; + + if (!delta::platform::Memory_Lock(reinterpret_cast(tsBase), WORKER_TS_DESC.baseline)) + return false; + + cursor += MemoryMap::VIRT_ZONE_SPACE_LENGTH; + return true; +; } + void ThreadContextManager_Initialize(uint32_t totalThreads, uint32_t pageSize) { const uint32_t workers = totalThreads - 1; @@ -50,18 +76,48 @@ namespace delta::core const size_t ctxArraySize = delta::utils::align_up(workers * sizeof(WorkerThreadContextAoS), pageSize); const size_t reservationSize = ctxArraySize + addrSpaceSize; - void* addrSpace = delta::platform::Memory_Reserve(reservationSize); - if (!addrSpace) + const void* begin = delta::platform::Memory_Reserve(reservationSize); + const uintptr_t ctxArray = reinterpret_cast(begin); + const uintptr_t addrSpace = ctxArray + ctxArraySize; + { - std::cout << "[DeltaEngine-Critical] Failed to reserve virtual address space\n"; - std::abort(); + tca_cursor_t cursor(ctxArray); + if (!InitializeContextArray(cursor, ctxArraySize, workers)) + { + std::cout << "[DeltaEngine-Critical] Failed to setup thread context array\n"; + std::abort(); + } + + assert(cursor.cast() - ctxArray <= ctxArraySize); } + // initialize contexts (starting from master) + uintptr_t cursor = addrSpace; + + constexpr auto MASTER_TS = MemoryMap::VIRT_MAP_MASTER[MemoryMap::VIRT_ZONE_GENERIC_TS_INDEX]; + constexpr auto MASTER_PS = MemoryMap::VIRT_MAP_MASTER[MemoryMap::VIRT_ZONE_MASTER_PS_INDEX]; + g_MasterThreadCtx.threadId = delta::platform::Thread_GetCurrentId(); + g_MasterThreadCtx.pagecrd.base = cursor; + g_MasterThreadCtx.pagecrd.size = MemoryMap::VIRT_ZONE_SPACE_LENGTH; + + g_MasterThreadCtx.transientStorage.base = cursor + MASTER_TS.offset; + g_MasterThreadCtx.transientStorage.offset = 0ull; + g_MasterThreadCtx.transientStorage.reserved = MASTER_TS.baseline; + g_MasterThreadCtx.transientStorage.size = MASTER_TS.size; + + g_MasterThreadCtx.persistentStorage.base = cursor + MASTER_PS.offset; + g_MasterThreadCtx.persistentStorage.offset = 0ull; + g_MasterThreadCtx.persistentStorage.reserved = MASTER_PS.baseline; + g_MasterThreadCtx.persistentStorage.size = MASTER_PS.size; + cursor += MemoryMap::VIRT_ZONE_SPACE_LENGTH; + + // now workers + constexpr auto WORKER_TS = MemoryMap::VIRT_MAP_WORKER[MemoryMap::VIRT_ZONE_GENERIC_TS_INDEX]; + for (uint32_t i = 0; i < workers; i++) { - tca_cursor_t cursor(addrSpace); - if (!InitializeContextArray(cursor, ctxArraySize, workers)) + if (!InitializeWorker(cursor, i)) { - std::cout << "[DeltaEngine-Critical] Failed to initialize Thread Context Array\n"; + std::cout << "[DeltaEngine-Critical] Failed to initialize worker " << i << "!\n"; std::abort(); } } diff --git a/Engine/src/delta/core/ThreadContextManager.h b/Engine/src/delta/core/ThreadContextManager.h index b2c07f9..36ddd97 100644 --- a/Engine/src/delta/core/ThreadContextManager.h +++ b/Engine/src/delta/core/ThreadContextManager.h @@ -7,22 +7,31 @@ namespace delta::core template struct Cursor { - Cursor(void* _ptr) - : ptr(reinterpret_cast(_ptr)) - { } + Cursor() = delete; - uintptr_t ptr; + inline Cursor(uintptr_t _ptr) + : ptr(_ptr) + {} + uintptr_t ptr; + template inline operator T* () const noexcept { return reinterpret_cast(ptr); } + template + inline T cast() noexcept + { + return reinterpret_cast(ptr); + } + template inline Cursor& operator+=(const T& rhs) noexcept { ptr = delta::utils::align_up(ptr + rhs, Alignment); + return *this; } }; From 630662ea05621f0b33c4bd53e152506f5f2a352d Mon Sep 17 00:00:00 2001 From: YasInvolved Date: Fri, 10 Jul 2026 20:22:45 +0200 Subject: [PATCH 13/13] update memory map --- Engine/src/delta/core/MemoryConfig.h | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/Engine/src/delta/core/MemoryConfig.h b/Engine/src/delta/core/MemoryConfig.h index e92b631..3c79f6e 100644 --- a/Engine/src/delta/core/MemoryConfig.h +++ b/Engine/src/delta/core/MemoryConfig.h @@ -41,9 +41,9 @@ namespace delta::core size_t baseline; }; - // Generic inline constexpr size_t VIRT_ZONE_SPACE_LENGTH = (1ull << 35); + // Generic inline constexpr PoolDescriptor generic_transientStorage(0ull, (1ull << 30), (1ull << 26)); // Index Registry @@ -53,9 +53,7 @@ namespace delta::core inline constexpr uint32_t VIRT_ZONE_MASTER_PS_INDEX = 1u; // -- WORKER -- - inline constexpr uint32_t VIRT_ZONE_WORKER_TQ_INDEX = 1u; - inline constexpr uint32_t VIRT_ZONE_WORKER_CP_INDEX = 2u; - inline constexpr uint32_t VIRT_ZONE_WORKER_IO_INDEX = 3u; + // empty for now inline constexpr auto VIRT_MAP_MASTER = []() consteval { auto permaStorage = PoolDescriptor(generic_transientStorage, (1ull << 31), (1ull << 26)); @@ -67,15 +65,8 @@ namespace delta::core }(); inline constexpr auto VIRT_MAP_WORKER = []() consteval { - auto taskQueue = PoolDescriptor(generic_transientStorage, (1ull << 16)); - auto componentPool = PoolDescriptor(taskQueue, (1ull << 33), (1ull << 27)); - auto io = PoolDescriptor(componentPool, (1ull << 30)); - return delta::utils::StaticArray{ - generic_transientStorage, - taskQueue, - componentPool, - io + generic_transientStorage }; }();