SceneGraph.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Scene/SceneGraph.h>
  6. #include <AnKi/Scene/RenderStateBucket.h>
  7. #include <AnKi/Physics/PhysicsWorld.h>
  8. #include <AnKi/Resource/ResourceManager.h>
  9. #include <AnKi/Util/CVarSet.h>
  10. #include <AnKi/Core/StatsSet.h>
  11. #include <AnKi/Util/Tracer.h>
  12. #include <AnKi/Util/HighRezTimer.h>
  13. #include <AnKi/Core/App.h>
  14. #include <AnKi/Scene/StatsUiNode.h>
  15. #include <AnKi/Scene/DeveloperConsoleUiNode.h>
  16. #include <AnKi/Scene/Components/BodyComponent.h>
  17. #include <AnKi/Scene/Components/CameraComponent.h>
  18. #include <AnKi/Scene/Components/DecalComponent.h>
  19. #include <AnKi/Scene/Components/FogDensityComponent.h>
  20. #include <AnKi/Scene/Components/GlobalIlluminationProbeComponent.h>
  21. #include <AnKi/Scene/Components/JointComponent.h>
  22. #include <AnKi/Scene/Components/LensFlareComponent.h>
  23. #include <AnKi/Scene/Components/LightComponent.h>
  24. #include <AnKi/Scene/Components/MoveComponent.h>
  25. #include <AnKi/Scene/Components/ParticleEmitterComponent.h>
  26. #include <AnKi/Scene/Components/PlayerControllerComponent.h>
  27. #include <AnKi/Scene/Components/ReflectionProbeComponent.h>
  28. #include <AnKi/Scene/Components/ScriptComponent.h>
  29. #include <AnKi/Scene/Components/SkinComponent.h>
  30. #include <AnKi/Scene/Components/SkyboxComponent.h>
  31. #include <AnKi/Scene/Components/TriggerComponent.h>
  32. #include <AnKi/Scene/Components/UiComponent.h>
  33. #include <AnKi/Scene/Components/MeshComponent.h>
  34. #include <AnKi/Scene/Components/MaterialComponent.h>
  35. namespace anki {
  36. ANKI_SVAR(SceneUpdateTime, StatCategory::kTime, "All scene update", StatFlag::kMilisecond | StatFlag::kShowAverage | StatFlag::kMainThreadUpdates)
  37. ANKI_SVAR(SceneComponentsUpdated, StatCategory::kScene, "Scene components updated per frame", StatFlag::kZeroEveryFrame)
  38. ANKI_SVAR(SceneNodesUpdated, StatCategory::kScene, "Scene nodes updated per frame", StatFlag::kZeroEveryFrame)
  39. constexpr U32 kUpdateNodeBatchSize = 10;
  40. class SceneGraph::UpdateSceneNodesCtx
  41. {
  42. public:
  43. IntrusiveList<SceneNode>::Iterator m_crntNode;
  44. SpinLock m_crntNodeLock;
  45. Second m_prevUpdateTime;
  46. Second m_crntTime;
  47. DynamicArray<SceneNode*, MemoryPoolPtrWrapper<StackMemoryPool>> m_nodesForDeletion;
  48. UpdateSceneNodesCtx()
  49. : m_nodesForDeletion(&SceneGraph::getSingleton().m_framePool)
  50. {
  51. }
  52. };
  53. SceneGraph::SceneGraph()
  54. {
  55. }
  56. SceneGraph::~SceneGraph()
  57. {
  58. while(!m_nodesForRegistration.isEmpty())
  59. {
  60. deleteInstance(SceneMemoryPool::getSingleton(), m_nodesForRegistration.popBack());
  61. }
  62. while(!m_nodes.isEmpty())
  63. {
  64. deleteInstance(SceneMemoryPool::getSingleton(), m_nodes.popBack());
  65. }
  66. #define ANKI_CAT_TYPE(arrayName, gpuSceneType, id, cvarName) GpuSceneArrays::arrayName::freeSingleton();
  67. #include <AnKi/Scene/GpuSceneArrays.def.h>
  68. RenderStateBucketContainer::freeSingleton();
  69. }
  70. Error SceneGraph::init(AllocAlignedCallback allocCallback, void* allocCallbackData)
  71. {
  72. SceneMemoryPool::allocateSingleton(allocCallback, allocCallbackData);
  73. m_framePool.init(allocCallback, allocCallbackData, 1_MB, 2.0, 0, true, "SceneGraphFramePool");
  74. // Init the default main camera
  75. m_defaultMainCam = newSceneNode<SceneNode>("mainCamera");
  76. CameraComponent* camc = m_defaultMainCam->newComponent<CameraComponent>();
  77. camc->setPerspective(0.1f, 1000.0f, toRad(60.0f), (1080.0f / 1920.0f) * toRad(60.0f));
  78. m_mainCam = m_defaultMainCam;
  79. #define ANKI_CAT_TYPE(arrayName, gpuSceneType, id, cvarName) GpuSceneArrays::arrayName::allocateSingleton(U32(cvarName));
  80. #include <AnKi/Scene/GpuSceneArrays.def.h>
  81. RenderStateBucketContainer::allocateSingleton();
  82. // Construct a few common nodex
  83. if(g_cvarCoreDisplayStats > 0)
  84. {
  85. StatsUiNode* statsNode = newSceneNode<StatsUiNode>("_StatsUi");
  86. statsNode->setFpsOnly(g_cvarCoreDisplayStats == 1);
  87. }
  88. newSceneNode<DeveloperConsoleUiNode>("_DevConsole");
  89. return Error::kNone;
  90. }
  91. SceneNode& SceneGraph::findSceneNode(const CString& name)
  92. {
  93. SceneNode* node = tryFindSceneNode(name);
  94. ANKI_ASSERT(node);
  95. return *node;
  96. }
  97. SceneNode* SceneGraph::tryFindSceneNode(const CString& name)
  98. {
  99. // Search registered nodes
  100. auto it = m_nodesDict.find(name);
  101. if(it != m_nodesDict.getEnd())
  102. {
  103. return *it;
  104. }
  105. // Didn't found it, search those up for registration
  106. LockGuard lock(m_nodesForRegistrationMtx);
  107. for(SceneNode& node : m_nodesForRegistration)
  108. {
  109. if(node.getName() == name)
  110. {
  111. return &node;
  112. }
  113. }
  114. return nullptr;
  115. }
  116. void SceneGraph::update(Second prevUpdateTime, Second crntTime)
  117. {
  118. ANKI_ASSERT(m_mainCam);
  119. ANKI_TRACE_SCOPED_EVENT(SceneUpdate);
  120. const Second startUpdateTime = HighRezTimer::getCurrentTime();
  121. // Reset the framepool
  122. m_framePool.reset();
  123. // Register new nodes
  124. while(!m_nodesForRegistration.isEmpty())
  125. {
  126. SceneNode* node = m_nodesForRegistration.popFront();
  127. // Add to dict if it has a name
  128. if(node->getName())
  129. {
  130. if(tryFindSceneNode(node->getName()))
  131. {
  132. ANKI_SCENE_LOGE("Node with the same name already exists. New node will not be searchable: %s", node->getName().cstr());
  133. }
  134. else
  135. {
  136. m_nodesDict.emplace(node->getName(), node);
  137. }
  138. }
  139. // Add to list
  140. m_nodes.pushBack(node);
  141. ++m_nodesCount;
  142. }
  143. // Update physics
  144. PhysicsWorld::getSingleton().update(crntTime - prevUpdateTime);
  145. // Before the update wake some threads with dummy work
  146. for(U i = 0; i < 2; i++)
  147. {
  148. CoreThreadJobManager::getSingleton().dispatchTask([]([[maybe_unused]] U32 tid) {});
  149. }
  150. // Update events and scene nodes
  151. UpdateSceneNodesCtx updateCtx;
  152. {
  153. ANKI_TRACE_SCOPED_EVENT(SceneNodesUpdate);
  154. m_events.updateAllEvents(prevUpdateTime, crntTime);
  155. updateCtx.m_crntNode = m_nodes.getBegin();
  156. updateCtx.m_prevUpdateTime = prevUpdateTime;
  157. updateCtx.m_crntTime = crntTime;
  158. for(U i = 0; i < CoreThreadJobManager::getSingleton().getThreadCount(); i++)
  159. {
  160. CoreThreadJobManager::getSingleton().dispatchTask([this, &updateCtx]([[maybe_unused]] U32 tid) {
  161. updateNodes(updateCtx);
  162. });
  163. }
  164. CoreThreadJobManager::getSingleton().waitForAllTasksToFinish();
  165. }
  166. // Cleanup
  167. for(SceneNode* node : updateCtx.m_nodesForDeletion)
  168. {
  169. // Remove from the graph
  170. m_nodes.erase(node);
  171. ANKI_ASSERT(m_nodesCount > 0);
  172. --m_nodesCount;
  173. if(m_mainCam != m_defaultMainCam && m_mainCam == node)
  174. {
  175. m_mainCam = m_defaultMainCam;
  176. }
  177. // Remove from dict
  178. if(node->getName())
  179. {
  180. auto it = m_nodesDict.find(node->getName());
  181. ANKI_ASSERT(it != m_nodesDict.getEnd());
  182. if(*it == node)
  183. {
  184. m_nodesDict.erase(it);
  185. }
  186. }
  187. deleteInstance(SceneMemoryPool::getSingleton(), node);
  188. }
  189. updateCtx.m_nodesForDeletion.destroy();
  190. #define ANKI_CAT_TYPE(arrayName, gpuSceneType, id, cvarName) GpuSceneArrays::arrayName::getSingleton().flush();
  191. #include <AnKi/Scene/GpuSceneArrays.def.h>
  192. g_svarSceneUpdateTime.set((HighRezTimer::getCurrentTime() - startUpdateTime) * 1000.0);
  193. }
  194. void SceneGraph::updateNode(Second prevTime, Second crntTime, SceneNode& node)
  195. {
  196. ANKI_TRACE_INC_COUNTER(SceneNodeUpdated, 1);
  197. // Components update
  198. SceneComponentUpdateInfo componentUpdateInfo(prevTime, crntTime);
  199. componentUpdateInfo.m_framePool = &m_framePool;
  200. U32 sceneComponentUpdatedCount = 0;
  201. node.iterateComponents([&](SceneComponent& comp) {
  202. componentUpdateInfo.m_node = &node;
  203. Bool updated = false;
  204. comp.update(componentUpdateInfo, updated);
  205. if(updated)
  206. {
  207. ANKI_TRACE_INC_COUNTER(SceneComponentUpdated, 1);
  208. comp.setTimestamp(GlobalFrameIndex::getSingleton().m_value);
  209. ++sceneComponentUpdatedCount;
  210. }
  211. });
  212. // Update children
  213. node.visitChildrenMaxDepth(0, [&](SceneNode& child) {
  214. updateNode(prevTime, crntTime, child);
  215. return true;
  216. });
  217. // Frame update
  218. {
  219. if(sceneComponentUpdatedCount)
  220. {
  221. node.setComponentMaxTimestamp(GlobalFrameIndex::getSingleton().m_value);
  222. g_svarSceneComponentsUpdated.increment(sceneComponentUpdatedCount);
  223. g_svarSceneNodesUpdated.increment(1);
  224. }
  225. else
  226. {
  227. // No components or nothing updated, don't change the timestamp
  228. }
  229. node.frameUpdate(prevTime, crntTime);
  230. }
  231. }
  232. void SceneGraph::updateNodes(UpdateSceneNodesCtx& ctx)
  233. {
  234. ANKI_TRACE_SCOPED_EVENT(SceneNodeUpdate);
  235. IntrusiveList<SceneNode>::ConstIterator end = m_nodes.getEnd();
  236. Bool quit = false;
  237. while(!quit)
  238. {
  239. // Fetch a batch of scene nodes that don't have parent
  240. Array<SceneNode*, kUpdateNodeBatchSize> batch;
  241. U batchSize = 0;
  242. {
  243. LockGuard<SpinLock> lock(ctx.m_crntNodeLock);
  244. while(1)
  245. {
  246. if(batchSize == batch.getSize())
  247. {
  248. break;
  249. }
  250. if(ctx.m_crntNode == end)
  251. {
  252. quit = true;
  253. break;
  254. }
  255. SceneNode& node = *ctx.m_crntNode;
  256. if(node.isMarkedForDeletion())
  257. {
  258. ctx.m_nodesForDeletion.emplaceBack(&node);
  259. }
  260. else if(node.getParent() == nullptr)
  261. {
  262. batch[batchSize++] = &node;
  263. }
  264. else
  265. {
  266. // Ignore
  267. }
  268. ++ctx.m_crntNode;
  269. }
  270. }
  271. // Process nodes
  272. for(U i = 0; i < batchSize; ++i)
  273. {
  274. updateNode(ctx.m_prevUpdateTime, ctx.m_crntTime, *batch[i]);
  275. }
  276. }
  277. }
  278. LightComponent* SceneGraph::getDirectionalLight() const
  279. {
  280. LightComponent* out = (m_dirLights.getSize()) ? m_dirLights[0] : nullptr;
  281. if(out)
  282. {
  283. ANKI_ASSERT(out->getLightComponentType() == LightComponentType::kDirectional);
  284. }
  285. return out;
  286. }
  287. } // end namespace anki