diff --git a/Template_Windows/Template_Windows.vcxproj b/Template_Windows/Template_Windows.vcxproj index 256726128..b03e1aaf4 100644 --- a/Template_Windows/Template_Windows.vcxproj +++ b/Template_Windows/Template_Windows.vcxproj @@ -73,7 +73,7 @@ true true $(SolutionDir)BUILD\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) - UseLinkTimeCodeGeneration + UseFastLinkTimeCodeGeneration diff --git a/Tests/Tests.vcxproj b/Tests/Tests.vcxproj index 22b6960de..ab232b5b4 100644 --- a/Tests/Tests.vcxproj +++ b/Tests/Tests.vcxproj @@ -76,7 +76,7 @@ true true $(SolutionDir)BUILD\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) - UseLinkTimeCodeGeneration + UseFastLinkTimeCodeGeneration diff --git a/WickedEngine/wiApplication.cpp b/WickedEngine/wiApplication.cpp index f48e8a3f1..063f582de 100644 --- a/WickedEngine/wiApplication.cpp +++ b/WickedEngine/wiApplication.cpp @@ -52,6 +52,11 @@ namespace wi wi::initializer::InitializeComponentsAsync(); alwaysactive = wi::arguments::HasArgument("alwaysactive"); + + // Note: lua is always initialized immediately on main thread by wi::initializer, so this is safe to do: + assert(wi::initializer::IsInitializeFinished(wi::initializer::INITIALIZED_SYSTEM_LUA)); + Luna::push_global(wi::lua::GetLuaState(), "main", this); + Luna::push_global(wi::lua::GetLuaState(), "application", this); } void Application::ActivatePath(RenderPath* component, float fadeSeconds, wi::Color fadeColor) @@ -114,8 +119,6 @@ namespace wi if (!startup_script) { startup_script = true; - Luna::push_global(wi::lua::GetLuaState(), "main", this); - Luna::push_global(wi::lua::GetLuaState(), "application", this); std::string startup_lua_filename = wi::helper::GetCurrentPath() + "/startup.lua"; if (wi::helper::FileExists(startup_lua_filename)) { @@ -512,6 +515,10 @@ namespace wi { params.cursor = wi::font::Draw(std::to_string(wi::renderer::GetShaderErrorCount()) + " shader compilation errors! Check the backlog for more information!\n", params, cmd); } + if (wi::backlog::GetUnseenLogLevelMax() >= wi::backlog::LogLevel::Error) + { + params.cursor = wi::font::Draw("Errors found, check the backlog for more information!", params, cmd); + } if (infoDisplay.colorgrading_helper) { diff --git a/WickedEngine/wiInitializer.cpp b/WickedEngine/wiInitializer.cpp index a1c0de84d..9787ae40d 100644 --- a/WickedEngine/wiInitializer.cpp +++ b/WickedEngine/wiInitializer.cpp @@ -7,24 +7,28 @@ namespace wi::initializer { - static bool initializationStarted = false; + static std::atomic_bool initializationStarted{ false }; static wi::jobsystem::context ctx; static wi::Timer timer; static std::atomic_bool systems[INITIALIZED_SYSTEM_COUNT]{}; void InitializeComponentsImmediate() { - if (!initializationStarted) + if (IsInitializeFinished()) + return; + if (!initializationStarted.load()) { InitializeComponentsAsync(); } - wi::jobsystem::Wait(ctx); + WaitForInitializationsToFinish(); } void InitializeComponentsAsync() { + if (IsInitializeFinished()) + return; timer.record(); - initializationStarted = true; + initializationStarted.store(true); std::string ss; ss += "\n[wi::initializer] Initializing Wicked Engine, please wait...\n"; @@ -57,11 +61,11 @@ namespace wi::initializer wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::gpusortlib::Initialize(); systems[INITIALIZED_SYSTEM_GPUSORTLIB].store(true); }); wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::GPUBVH::Initialize(); systems[INITIALIZED_SYSTEM_GPUBVH].store(true); }); wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::physics::Initialize(); systems[INITIALIZED_SYSTEM_PHYSICS].store(true); }); - wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::audio::Initialize(); systems[INITIALIZED_SYSTEM_AUDIO].store(true); }); wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::TrailRenderer::Initialize(); systems[INITIALIZED_SYSTEM_TRAILRENDERER].store(true); }); - // Initialize this immediately: + // Initialize these immediately: wi::lua::Initialize(); systems[INITIALIZED_SYSTEM_LUA].store(true); + wi::audio::Initialize(); systems[INITIALIZED_SYSTEM_AUDIO].store(true); std::thread([] { wi::jobsystem::Wait(ctx); @@ -74,11 +78,16 @@ namespace wi::initializer { if (system == INITIALIZED_SYSTEM_COUNT) { - return initializationStarted && !wi::jobsystem::IsBusy(ctx); + return initializationStarted.load() && !wi::jobsystem::IsBusy(ctx); } else { return systems[system].load(); } } + + void WaitForInitializationsToFinish() + { + wi::jobsystem::Wait(ctx); + } } diff --git a/WickedEngine/wiInitializer.h b/WickedEngine/wiInitializer.h index dadb42a92..7088bd8ce 100644 --- a/WickedEngine/wiInitializer.h +++ b/WickedEngine/wiInitializer.h @@ -29,4 +29,6 @@ namespace wi::initializer // Check if systems have been initialized or not // system : specify to check a specific system, or leave default to check all systems bool IsInitializeFinished(INITIALIZED_SYSTEM system = INITIALIZED_SYSTEM_COUNT); + // Wait for all system initializations to finish + void WaitForInitializationsToFinish(); } diff --git a/WickedEngine/wiJobSystem.cpp b/WickedEngine/wiJobSystem.cpp index 773c19c98..f6fc13a51 100644 --- a/WickedEngine/wiJobSystem.cpp +++ b/WickedEngine/wiJobSystem.cpp @@ -30,6 +30,32 @@ namespace wi::jobsystem uint32_t groupJobOffset; uint32_t groupJobEnd; uint32_t sharedmemory_size; + inline void execute() + { + JobArgs args; + args.groupID = groupID; + if (sharedmemory_size > 0) + { + thread_local static wi::vector shared_allocation_data; + shared_allocation_data.reserve(sharedmemory_size); + args.sharedmemory = shared_allocation_data.data(); + } + else + { + args.sharedmemory = nullptr; + } + + for (uint32_t j = groupJobOffset; j < groupJobEnd; ++j) + { + args.jobIndex = j; + args.groupIndex = j - groupJobOffset; + args.isFirstJobInGroup = (j == groupJobOffset); + args.isLastJobInGroup = (j == groupJobEnd - 1); + task(args); + } + + ctx->counter.fetch_sub(1); + } }; struct JobQueue { @@ -72,29 +98,7 @@ namespace wi::jobsystem JobQueue& job_queue = jobQueuePerThread[startingQueue % numThreads]; while (job_queue.pop_front(job)) { - JobArgs args; - args.groupID = job.groupID; - if (job.sharedmemory_size > 0) - { - thread_local static wi::vector shared_allocation_data; - shared_allocation_data.reserve(job.sharedmemory_size); - args.sharedmemory = shared_allocation_data.data(); - } - else - { - args.sharedmemory = nullptr; - } - - for (uint32_t j = job.groupJobOffset; j < job.groupJobEnd; ++j) - { - args.jobIndex = j; - args.groupIndex = j - job.groupJobOffset; - args.isFirstJobInGroup = (j == job.groupJobOffset); - args.isLastJobInGroup = (j == job.groupJobEnd - 1); - job.task(args); - } - - job.ctx->counter.fetch_sub(1); + job.execute(); } startingQueue++; // go to next queue } @@ -305,6 +309,8 @@ namespace wi::jobsystem void Execute(context& ctx, const std::function& task) { + PriorityResources& res = internal_state.resources[int(ctx.priority)]; + // Context state is updated: ctx.counter.fetch_add(1); @@ -316,7 +322,13 @@ namespace wi::jobsystem job.groupJobEnd = 1; job.sharedmemory_size = 0; - PriorityResources& res = internal_state.resources[int(ctx.priority)]; + if (res.numThreads <= 1) + { + // If job system is not yet initialized, or only has one threads, job will be executed immediately here instead of thread: + job.execute(); + return; + } + res.jobQueuePerThread[res.nextQueue.fetch_add(1) % res.numThreads].push_back(job); res.wakeCondition.notify_one(); } @@ -346,10 +358,21 @@ namespace wi::jobsystem job.groupJobOffset = groupID * groupSize; job.groupJobEnd = std::min(job.groupJobOffset + groupSize, jobCount); - res.jobQueuePerThread[res.nextQueue.fetch_add(1) % res.numThreads].push_back(job); + if (res.numThreads <= 1) + { + // If job system is not yet initialized, or only has one threads, job will be executed immediately here instead of thread: + job.execute(); + } + else + { + res.jobQueuePerThread[res.nextQueue.fetch_add(1) % res.numThreads].push_back(job); + } } - res.wakeCondition.notify_all(); + if (res.numThreads > 1) + { + res.wakeCondition.notify_all(); + } } uint32_t DispatchGroupCount(uint32_t jobCount, uint32_t groupSize) diff --git a/WickedEngine/wiLua.cpp b/WickedEngine/wiLua.cpp index 638147021..b9ebaf6fe 100644 --- a/WickedEngine/wiLua.cpp +++ b/WickedEngine/wiLua.cpp @@ -202,6 +202,9 @@ namespace wi::lua void Initialize() { + if (lua_internal().m_luaState != nullptr) + return; // already initialized + wi::Timer timer; lua_internal().m_luaState = luaL_newstate(); diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index f892c38ee..edf7c9d22 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 71; // minor bug fixes, alterations, refactors, updates - const int revision = 520; + const int revision = 521; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);