diff --git a/src/core/application.cpp b/src/core/application.cpp index fec2ca5f..8e0d6c6b 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -59,6 +59,15 @@ #ifdef __linux__ #include #include +#elif defined(_WIN32) +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#elif defined(__APPLE__) +#include +#include +#include #endif namespace wowee { @@ -238,11 +247,10 @@ void Application::run() { LOG_INFO("Starting main loop"); // Pin main thread to a dedicated CPU core to reduce scheduling jitter -#ifdef __linux__ { int numCores = static_cast(std::thread::hardware_concurrency()); if (numCores >= 2) { - // Use core 0 for the main thread (typically the highest-clocked core) +#ifdef __linux__ cpu_set_t cpuset; CPU_ZERO(&cpuset); CPU_SET(0, &cpuset); @@ -252,9 +260,31 @@ void Application::run() { } else { LOG_WARNING("Failed to pin main thread to CPU core 0 (error ", rc, ")"); } +#elif defined(_WIN32) + DWORD_PTR mask = 1; // Core 0 + DWORD_PTR prev = SetThreadAffinityMask(GetCurrentThread(), mask); + if (prev != 0) { + LOG_INFO("Main thread pinned to CPU core 0 (", numCores, " cores available)"); + } else { + LOG_WARNING("Failed to pin main thread to CPU core 0 (error ", GetLastError(), ")"); + } +#elif defined(__APPLE__) + // macOS doesn't support hard pinning — use affinity tags to hint + // that the main thread should stay on its own core group + thread_affinity_policy_data_t policy = { 1 }; // tag 1 = main thread group + kern_return_t kr = thread_policy_set( + pthread_mach_thread_np(pthread_self()), + THREAD_AFFINITY_POLICY, + reinterpret_cast(&policy), + THREAD_AFFINITY_POLICY_COUNT); + if (kr == KERN_SUCCESS) { + LOG_INFO("Main thread affinity tag set (", numCores, " cores available)"); + } else { + LOG_WARNING("Failed to set main thread affinity tag (error ", kr, ")"); + } +#endif } } -#endif const bool frameProfileEnabled = envFlagEnabled("WOWEE_FRAME_PROFILE", false); if (frameProfileEnabled) { diff --git a/src/rendering/terrain_manager.cpp b/src/rendering/terrain_manager.cpp index 3dbd2bd6..5caeab9d 100644 --- a/src/rendering/terrain_manager.cpp +++ b/src/rendering/terrain_manager.cpp @@ -25,6 +25,15 @@ #ifdef __linux__ #include #include +#elif defined(_WIN32) +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#elif defined(__APPLE__) +#include +#include +#include #endif namespace wowee { @@ -922,19 +931,33 @@ bool TerrainManager::advanceFinalization(FinalizingTile& ft) { void TerrainManager::workerLoop() { // Keep worker threads off core 0 (reserved for main thread) -#ifdef __linux__ { int numCores = static_cast(std::thread::hardware_concurrency()); if (numCores >= 2) { +#ifdef __linux__ cpu_set_t cpuset; CPU_ZERO(&cpuset); for (int i = 1; i < numCores; i++) { CPU_SET(i, &cpuset); } pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); +#elif defined(_WIN32) + DWORD_PTR mask = 0; + for (int i = 1; i < numCores && i < 64; i++) { + mask |= (static_cast(1) << i); + } + SetThreadAffinityMask(GetCurrentThread(), mask); +#elif defined(__APPLE__) + // Use affinity tag 2 for workers (separate from main thread tag 1) + thread_affinity_policy_data_t policy = { 2 }; + thread_policy_set( + pthread_mach_thread_np(pthread_self()), + THREAD_AFFINITY_POLICY, + reinterpret_cast(&policy), + THREAD_AFFINITY_POLICY_COUNT); +#endif } } -#endif LOG_INFO("Terrain worker thread started"); while (workerRunning.load()) {