From 971cb4a86edaf96c4dfd895649443886c51a1877 Mon Sep 17 00:00:00 2001 From: turanszkij Date: Sat, 3 Nov 2018 19:28:24 +0000 Subject: [PATCH] using wiJobSystem for initialization; refactors; --- CONTRIBUTING.md | 3 +- Documentation/WickedEngine-Documentation.md | 50 ++++++++++- WickedEngine/MainComponent.cpp | 4 - WickedEngine/MainComponent.h | 2 - WickedEngine/WickedEngine.h | 25 +++--- WickedEngine/WickedEngine_SHARED.vcxitems | 2 + .../WickedEngine_SHARED.vcxitems.filters | 30 ++++--- WickedEngine/wiInitializer.cpp | 66 +++++--------- WickedEngine/wiInitializer.h | 2 - WickedEngine/wiJobSystem.cpp | 87 +++++++++++++++++++ WickedEngine/wiJobSystem.h | 17 ++++ WickedEngine/wiRenderer.cpp | 32 +++---- WickedEngine/wiVersion.cpp | 2 +- 13 files changed, 225 insertions(+), 97 deletions(-) create mode 100644 WickedEngine/wiJobSystem.cpp create mode 100644 WickedEngine/wiJobSystem.h diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 62845585c..2f099a272 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,8 +13,7 @@ Here are some guidelines on contributing. You can submit a pull request with you - prefer having braces on their own line when writing loops, branches, functions or whatever - unit of time should be seconds - use std::string to store strings -- avoid using c++ stl containers if possible (std::vector is acceptable, or unordered_map, but use them sparingly) -- avoid new and malloc and allocating on general purpose heap wherever you can. Especially avoid it in frequently called code! Note that by default, c++ std:: lib will allocate on heap. +- avoid new and malloc and allocating on general purpose heap wherever you can. Especially avoid it in frequently called code - you can use auto keyword, but aim for as small scope as possible - using auto keyword for iterators is encouraged - aim to write const-correct code diff --git a/Documentation/WickedEngine-Documentation.md b/Documentation/WickedEngine-Documentation.md index dcb79222c..cb8140b59 100644 --- a/Documentation/WickedEngine-Documentation.md +++ b/Documentation/WickedEngine-Documentation.md @@ -42,7 +42,7 @@ Order of execution: - Implements a compute shader based path tracing solution. In a static scene, the rendering will converge to ground truth. ## System -You can find out more about the Entity-Component system under ENGINE/System filter in the solution. +You can find out more about the Entity-Component system and other engine-level systems under ENGINE/System filter in the solution. - wiECS - This is the core entity-component relationship handler class: ComponentManager @@ -51,7 +51,16 @@ You can find out more about the Entity-Component system under ENGINE/System filt - wiSceneSystem - This contains Scene, a class that is responsible of holding and managing everything in the world - - There are also all of the Component types, like TransformComponent, MeshCOmponent, etc. + - There are also all of the Component types, like TransformComponent, MeshComponent, etc. + +- wiJobSystem + - Manages the execution of concurrent tasks + +- wiInitializer + - Initializes all engine systems + +- wiWindowRegistration + - This is a platform specific utility to manage the native display window ## Physics You can find the physics system related functionality under ENGINE/Physics filter in the solution. @@ -84,3 +93,40 @@ You can see a quickstart guide on the following picture regarding the most commo ![InformationSheet](information_sheet.png) +## Helpers +A collection of engine-level helper classes + +- wiArchive + - This is used for serializing binary data +- wiHelper + - Many helper utility functions, like screenshot, readfile, messagebox, splitpath, sleep, etc... +- wiMath + - Math related helper functions, like lerp, triangleArea, HueToRGB, etc... +- wiProfiler + - A timer utility that can measure CPU and GPU timings and used across the engine +- wiRandom + - random number generator +- ... + +## Input +The input interface can be found here + +- wiInputManager + - This manages all inputs + - There are several functions, such as down(), press(), etc. to check button states. + +## Network +TODO: Rewrite the networking systems + +## Scripting +This is the place for the Lua scipt interface. The systems that are bound to Lua have the name of the system prefixed by _BindLua. + +- wiLua + - The Lua scripting interface + +## Tools +This is the place for tools that use engine-level systems + +- wiBackLog + - Used to log any messages by any system, from any thread. It can draw itself to the screen. It can execute Lua scripts. + diff --git a/WickedEngine/MainComponent.cpp b/WickedEngine/MainComponent.cpp index f17afeb33..a5189c307 100644 --- a/WickedEngine/MainComponent.cpp +++ b/WickedEngine/MainComponent.cpp @@ -284,10 +284,6 @@ void MainComponent::Compose() #endif ss << endl; } - if (infoDisplay.initstats) - { - ss << "System init time: " << wiInitializer::GetInitializationTimeInSeconds() << " sec" << endl; - } if (infoDisplay.resolution) { ss << "Resolution: " << wiRenderer::GetDevice()->GetScreenWidth() << " x " << wiRenderer::GetDevice()->GetScreenHeight() << endl; diff --git a/WickedEngine/MainComponent.h b/WickedEngine/MainComponent.h index 4d8472a2f..581eb680d 100644 --- a/WickedEngine/MainComponent.h +++ b/WickedEngine/MainComponent.h @@ -81,8 +81,6 @@ public: bool cpuinfo = false; // display resolution info bool resolution = false; - // display engine initialization time - bool initstats = false; // text size int size = -1; }; diff --git a/WickedEngine/WickedEngine.h b/WickedEngine/WickedEngine.h index 91ebf5b20..fc900605b 100644 --- a/WickedEngine/WickedEngine.h +++ b/WickedEngine/WickedEngine.h @@ -8,6 +8,19 @@ #include "CommonInclude.h" +// High-level interface: +#include "RenderPath.h" +#include "RenderPath2D.h" +#include "RenderPath3D.h" +#include "RenderPath3D_Forward.h" +#include "RenderPath3D_Deferred.h" +#include "RenderPath3D_TiledForward.h" +#include "RenderPath3D_TiledDeferred.h" +#include "RenderPath3D_PathTracing.h" +#include "LoadingScreen.h" +#include "MainComponent.h" + +// Engine-level systems #include "wiVersion.h" #include "wiRenderTarget.h" #include "wiDepthTarget.h" @@ -55,17 +68,7 @@ #include "wiStartupArguments.h" #include "wiGPUBVH.h" #include "wiGPUSortLib.h" - -#include "RenderPath.h" -#include "RenderPath2D.h" -#include "RenderPath3D.h" -#include "RenderPath3D_Forward.h" -#include "RenderPath3D_Deferred.h" -#include "RenderPath3D_TiledForward.h" -#include "RenderPath3D_TiledDeferred.h" -#include "RenderPath3D_PathTracing.h" -#include "LoadingScreen.h" -#include "MainComponent.h" +#include "wiJobSystem.h" #ifdef _WIN32 diff --git a/WickedEngine/WickedEngine_SHARED.vcxitems b/WickedEngine/WickedEngine_SHARED.vcxitems index 0756021cd..521d979fb 100644 --- a/WickedEngine/WickedEngine_SHARED.vcxitems +++ b/WickedEngine/WickedEngine_SHARED.vcxitems @@ -340,6 +340,7 @@ + @@ -680,6 +681,7 @@ + diff --git a/WickedEngine/WickedEngine_SHARED.vcxitems.filters b/WickedEngine/WickedEngine_SHARED.vcxitems.filters index c6f6c06b6..abdc36fd3 100644 --- a/WickedEngine/WickedEngine_SHARED.vcxitems.filters +++ b/WickedEngine/WickedEngine_SHARED.vcxitems.filters @@ -903,9 +903,6 @@ ENGINE\Graphics - - ENGINE\Helpers - ENGINE\Helpers @@ -951,9 +948,6 @@ ENGINE\Helpers - - ENGINE\Helpers - ENGINE\Input @@ -1149,6 +1143,15 @@ ENGINE\High level interface + + ENGINE\System + + + ENGINE\System + + + ENGINE\System + @@ -1814,9 +1817,6 @@ ENGINE\Helpers - - ENGINE\Helpers - ENGINE\Input @@ -1892,9 +1892,6 @@ ENGINE\Graphics - - ENGINE\Helpers - ENGINE\Scripting\LuaBindings @@ -1946,6 +1943,15 @@ ENGINE\High level interface + + ENGINE\System + + + ENGINE\System + + + ENGINE\System + diff --git a/WickedEngine/wiInitializer.cpp b/WickedEngine/wiInitializer.cpp index c7fc8d456..489e1709d 100644 --- a/WickedEngine/wiInitializer.cpp +++ b/WickedEngine/wiInitializer.cpp @@ -8,64 +8,40 @@ using namespace std; namespace wiInitializer { - static bool finished = false; - static float initializationTime = 0; + bool initializationStarted = false; void InitializeComponentsImmediate() { - if (finished) - { - return; - } - - wiTimer timer; - timer.record(); - - wiBackLog::post("\n[wiInitializer] Initializing Wicked Engine, please wait...\n"); - - wiFont::Initialize(); - wiImage::Initialize(); - wiTextureHelper::Initialize(); - wiRenderer::Initialize(); - wiSceneSystem::wiHairParticle::Initialize(); - wiSceneSystem::wiEmittedParticle::Initialize(); - wiCpuInfo::Initialize(); - wiLensFlare::Initialize(); - wiOcean::Initialize(); - wiWidget::LoadShaders(); - wiGPUSortLib::LoadShaders(); - wiGPUBVH::LoadShaders(); - wiPhysicsEngine::Initialize(); - wiSoundEffect::Initialize(); - wiMusic::Initialize(); - - initializationTime = (float)(timer.elapsed() / 1000.0); - - finished = true; - + InitializeComponentsAsync(); + wiJobSystem::Wait(); } void InitializeComponentsAsync() { - if (finished) - { - return; - } + initializationStarted = true; - std::thread([] { + wiBackLog::post("\n[wiInitializer] Initializing Wicked Engine, please wait...\n"); - InitializeComponentsImmediate(); + wiJobSystem::Initialize(); - }).detach(); + wiJobSystem::Execute([] { wiFont::Initialize(); }); + wiJobSystem::Execute([] { wiImage::Initialize(); }); + wiJobSystem::Execute([] { wiRenderer::Initialize(); }); + wiJobSystem::Execute([] { wiSoundEffect::Initialize(); wiMusic::Initialize(); }); + wiJobSystem::Execute([] { wiCpuInfo::Initialize(); }); + wiJobSystem::Execute([] { wiTextureHelper::Initialize(); }); + wiJobSystem::Execute([] { wiSceneSystem::wiHairParticle::Initialize(); }); + wiJobSystem::Execute([] { wiSceneSystem::wiEmittedParticle::Initialize(); }); + wiJobSystem::Execute([] { wiLensFlare::Initialize(); }); + wiJobSystem::Execute([] { wiOcean::Initialize(); }); + wiJobSystem::Execute([] { wiWidget::LoadShaders(); }); + wiJobSystem::Execute([] { wiGPUSortLib::LoadShaders(); }); + wiJobSystem::Execute([] { wiGPUBVH::LoadShaders(); }); + wiJobSystem::Execute([] { wiPhysicsEngine::Initialize(); }); } bool IsInitializeFinished() { - return finished; - } - - float GetInitializationTimeInSeconds() - { - return initializationTime; + return initializationStarted && !wiJobSystem::IsBusy(); } } \ No newline at end of file diff --git a/WickedEngine/wiInitializer.h b/WickedEngine/wiInitializer.h index 32c52736c..5e4f2a4c6 100644 --- a/WickedEngine/wiInitializer.h +++ b/WickedEngine/wiInitializer.h @@ -9,8 +9,6 @@ namespace wiInitializer void InitializeComponentsAsync(); // Check if systems have been initialized or not bool IsInitializeFinished(); - // Check the time it took to initialize systems - float GetInitializationTimeInSeconds(); } diff --git a/WickedEngine/wiJobSystem.cpp b/WickedEngine/wiJobSystem.cpp new file mode 100644 index 000000000..60eca04e4 --- /dev/null +++ b/WickedEngine/wiJobSystem.cpp @@ -0,0 +1,87 @@ +#include "wiJobSystem.h" +#include "wiSpinLock.h" +#include "wiBackLog.h" + +#include +#include +#include +#include + +namespace wiJobSystem +{ + struct Job + { + std::function func; + + Job() {} + Job(const std::function& func) :func(func) {} + }; + std::deque jobPool; + wiSpinLock jobLock; + std::atomic executionMask = 0; + + void Initialize() + { + unsigned int numCores = std::thread::hardware_concurrency(); + numCores = min(numCores, 64); // execution mask is 64 bits + + for (unsigned int threadID = 0; threadID < numCores; ++threadID) + { + std::thread([threadID] { + + while (true) + { + Job job; + bool working = false; + const uint64_t threadMask = 1ull << threadID; + + jobLock.lock(); + { + if (!jobPool.empty()) + { + executionMask.fetch_or(threadMask); // mark this thread as working + working = true; + job = std::move(jobPool.front()); + jobPool.pop_front(); + } + } + jobLock.unlock(); + + if (working) + { + job.func(); // execute job + executionMask.fetch_and(~threadMask); // mark this thread as idle + } + else + { + std::this_thread::yield(); + } + } + + }).detach(); + } + + std::stringstream ss(""); + ss << "wiJobSystem Initialized with " << numCores << " threads"; + wiBackLog::post(ss.str().c_str()); + } + + void Execute(const std::function& func) + { + jobLock.lock(); + jobPool.push_back(Job(std::move(func))); + jobLock.unlock(); + } + + bool IsBusy() + { + return executionMask.load() > 0; + } + + void Wait() + { + jobLock.lock(); + while (IsBusy()) {} + jobLock.unlock(); + } +} diff --git a/WickedEngine/wiJobSystem.h b/WickedEngine/wiJobSystem.h new file mode 100644 index 000000000..439584686 --- /dev/null +++ b/WickedEngine/wiJobSystem.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +namespace wiJobSystem +{ + void Initialize(); + + // Add a job to execute asynchronously + void Execute(const std::function& func); + + // Check if any threads are working currently or not + bool IsBusy(); + + // Wait until all threads become idle + void Wait(); +} diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index f32f658c2..74f7dfcac 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -48,23 +48,23 @@ namespace wiRenderer GraphicsDevice* graphicsDevice = nullptr; -static Sampler *samplers[SSLOT_COUNT] = {}; -static VertexShader *vertexShaders[VSTYPE_LAST] = {}; -static PixelShader *pixelShaders[PSTYPE_LAST] = {}; -static GeometryShader *geometryShaders[GSTYPE_LAST] = {}; -static HullShader *hullShaders[HSTYPE_LAST] = {}; -static DomainShader *domainShaders[DSTYPE_LAST] = {}; -static ComputeShader *computeShaders[CSTYPE_LAST] = {}; -static VertexLayout *vertexLayouts[VLTYPE_LAST] = {}; -static RasterizerState *rasterizers[RSTYPE_LAST] = {}; -static DepthStencilState *depthStencils[DSSTYPE_LAST] = {}; -static BlendState *blendStates[BSTYPE_LAST] = {}; -static GPUBuffer *constantBuffers[CBTYPE_LAST] = {}; -static GPUBuffer *resourceBuffers[RBTYPE_LAST] = {}; -static Texture *textures[TEXTYPE_LAST] = {}; -static Sampler *customsamplers[SSTYPE_LAST] = {}; +Sampler *samplers[SSLOT_COUNT] = {}; +VertexShader *vertexShaders[VSTYPE_LAST] = {}; +PixelShader *pixelShaders[PSTYPE_LAST] = {}; +GeometryShader *geometryShaders[GSTYPE_LAST] = {}; +HullShader *hullShaders[HSTYPE_LAST] = {}; +DomainShader *domainShaders[DSTYPE_LAST] = {}; +ComputeShader *computeShaders[CSTYPE_LAST] = {}; +VertexLayout *vertexLayouts[VLTYPE_LAST] = {}; +RasterizerState *rasterizers[RSTYPE_LAST] = {}; +DepthStencilState *depthStencils[DSSTYPE_LAST] = {}; +BlendState *blendStates[BSTYPE_LAST] = {}; +GPUBuffer *constantBuffers[CBTYPE_LAST] = {}; +GPUBuffer *resourceBuffers[RBTYPE_LAST] = {}; +Texture *textures[TEXTYPE_LAST] = {}; +Sampler *customsamplers[SSTYPE_LAST] = {}; -static string SHADERPATH = "shaders/"; +string SHADERPATH = "shaders/"; LinearAllocator frameAllocators[GRAPHICSTHREAD_COUNT]; GPURingBuffer dynamicVertexBufferPools[GRAPHICSTHREAD_COUNT] = {}; diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 26498fddd..e080e1dd2 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wiVersion // minor features, major updates const int minor = 22; // minor bug fixes, alterations, refactors, updates - const int revision = 0; + const int revision = 1; long GetVersion()