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..7a29f01 100644 --- a/Engine/include/delta/platform/os.h +++ b/Engine/include/delta/platform/os.h @@ -15,34 +15,21 @@ */ #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; - }; - + // 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); + 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/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/core/engine.cpp b/Engine/src/delta/core/engine.cpp index bfdcdc7..8790ef9 100644 --- a/Engine/src/delta/core/engine.cpp +++ b/Engine/src/delta/core/engine.cpp @@ -43,18 +43,25 @@ 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(); + delta::platform::Window_Show(context.window); + delta::platform::Window_Win32_Update(context.window); } 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_internal.h b/Engine/src/delta/platform/os_internal.h index ac6c713..c9332be 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,12 +48,15 @@ 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); void Sync_WaitSemaphore(SemaphoreHandle sem); void Sync_Sleep(uint32_t milliseconds); + + // Window API + WindowHandle Window_Create(); + void Window_Win32_Update(WindowHandle window); + void Window_ProcessEvents(); + void Window_Destroy(WindowHandle 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 +} diff --git a/Engine/src/delta/platform/os_win32.cpp b/Engine/src/delta/platform/os_win32.cpp index df4806b..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; @@ -152,11 +155,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); @@ -419,6 +429,146 @@ 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) + { + case WM_CLOSE: + // DestroyWindow(hwnd); + return 0; + default: + return DefWindowProcA(hwnd, umesg, wparam, lparam); + } + } + + WindowHandle Window_Create() + { + assert(s_hInstance); + WindowHandle window = new(delta::Engine::AllocationType::PERSISTENT) Window(); + + int nCmdShow = (s_StartupInfo.dwFlags & STARTF_USESHOWWINDOW) ? s_StartupInfo.wShowWindow : SW_SHOWDEFAULT; + + const WNDCLASSEXA wc = + { + .cbSize = sizeof(WNDCLASSEXA), + .style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC, + .lpfnWndProc = DltWindowProc, + .cbClsExtra = 0, + .cbWndExtra = 0, + .hInstance = s_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) }; + static constexpr DWORD windowStyle = WS_OVERLAPPEDWINDOW; + + 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, + s_hInstance, + nullptr + ); + + if (!window->hwnd) + { + return nullptr; + } + + return window; + } + + void Window_Win32_Update(WindowHandle window) + { + UpdateWindow(window->hwnd); + } + + 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(WindowHandle window) + { + DestroyWindow(window->hwnd); + UnregisterClassA(MAIN_WND_CLASS_NAME, s_hInstance); + } + + void Window_SetTitle(WindowHandle window, const char* newTitle) + { + 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 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)