ソースを参照

Make the SceneGraph and ScriptManager singletons

Panagiotis Christopoulos Charitos 2 年 前
コミット
86ab244a97
80 ファイル変更384 行追加784 行削除
  1. 17 27
      AnKi/Core/App.cpp
  2. 0 21
      AnKi/Core/App.h
  3. 6 3
      AnKi/Core/Common.h
  4. 1 3
      AnKi/Core/DeveloperConsole.cpp
  5. 1 1
      AnKi/Core/DeveloperConsole.h
  6. 0 1
      AnKi/Renderer/Common.h
  7. 1 1
      AnKi/Renderer/RtShadows.cpp
  8. 3 3
      AnKi/Renderer/ShadowMapping.cpp
  9. 16 7
      AnKi/Scene/Common.h
  10. 2 2
      AnKi/Scene/Components/CameraComponent.cpp
  11. 6 10
      AnKi/Scene/Components/DecalComponent.cpp
  12. 0 3
      AnKi/Scene/Components/DecalComponent.h
  13. 7 7
      AnKi/Scene/Components/FogDensityComponent.cpp
  14. 2 2
      AnKi/Scene/Components/FogDensityComponent.h
  15. 6 10
      AnKi/Scene/Components/GlobalIlluminationProbeComponent.cpp
  16. 0 2
      AnKi/Scene/Components/GlobalIlluminationProbeComponent.h
  17. 4 8
      AnKi/Scene/Components/JointComponent.cpp
  18. 0 2
      AnKi/Scene/Components/JointComponent.h
  19. 4 5
      AnKi/Scene/Components/LensFlareComponent.cpp
  20. 0 1
      AnKi/Scene/Components/LensFlareComponent.h
  21. 36 41
      AnKi/Scene/Components/LightComponent.cpp
  22. 0 3
      AnKi/Scene/Components/LightComponent.h
  23. 16 17
      AnKi/Scene/Components/ModelComponent.cpp
  24. 1 1
      AnKi/Scene/Components/ModelComponent.h
  25. 18 21
      AnKi/Scene/Components/ParticleEmitterComponent.cpp
  26. 2 2
      AnKi/Scene/Components/ParticleEmitterComponent.h
  27. 9 13
      AnKi/Scene/Components/ReflectionProbeComponent.cpp
  28. 0 2
      AnKi/Scene/Components/ReflectionProbeComponent.h
  29. 0 5
      AnKi/Scene/Components/SceneComponent.cpp
  30. 0 2
      AnKi/Scene/Components/SceneComponent.h
  31. 4 7
      AnKi/Scene/Components/ScriptComponent.cpp
  32. 0 1
      AnKi/Scene/Components/ScriptComponent.h
  33. 6 10
      AnKi/Scene/Components/SkinComponent.cpp
  34. 2 2
      AnKi/Scene/Components/SkinComponent.h
  35. 3 3
      AnKi/Scene/Components/SkyboxComponent.cpp
  36. 8 14
      AnKi/Scene/Components/TriggerComponent.cpp
  37. 3 3
      AnKi/Scene/Components/TriggerComponent.h
  38. 5 5
      AnKi/Scene/Components/UiComponent.cpp
  39. 2 2
      AnKi/Scene/Components/UiComponent.h
  40. 14 24
      AnKi/Scene/ContiguousArrayAllocator.cpp
  41. 7 9
      AnKi/Scene/ContiguousArrayAllocator.h
  42. 1 6
      AnKi/Scene/Events/AnimationEvent.cpp
  43. 0 2
      AnKi/Scene/Events/AnimationEvent.h
  44. 2 32
      AnKi/Scene/Events/Event.cpp
  45. 4 25
      AnKi/Scene/Events/Event.h
  46. 2 19
      AnKi/Scene/Events/EventManager.cpp
  47. 2 19
      AnKi/Scene/Events/EventManager.h
  48. 1 1
      AnKi/Scene/Events/JitterMoveEvent.cpp
  49. 0 6
      AnKi/Scene/Events/JitterMoveEvent.h
  50. 1 1
      AnKi/Scene/Events/LightEvent.cpp
  51. 0 6
      AnKi/Scene/Events/LightEvent.h
  52. 3 8
      AnKi/Scene/Events/ScriptEvent.cpp
  53. 2 2
      AnKi/Scene/Events/ScriptEvent.h
  54. 3 6
      AnKi/Scene/Frustum.cpp
  55. 2 4
      AnKi/Scene/Frustum.h
  56. 7 11
      AnKi/Scene/Octree.h
  57. 13 17
      AnKi/Scene/SceneGraph.cpp
  58. 13 32
      AnKi/Scene/SceneGraph.h
  59. 7 34
      AnKi/Scene/SceneNode.cpp
  60. 5 25
      AnKi/Scene/SceneNode.h
  61. 2 2
      AnKi/Scene/SoftwareRasterizer.cpp
  62. 1 18
      AnKi/Scene/SoftwareRasterizer.h
  63. 1 2
      AnKi/Scene/Visibility.cpp
  64. 17 1
      AnKi/Script/Common.h
  65. 11 43
      AnKi/Script/LuaBinder.cpp
  66. 1 31
      AnKi/Script/LuaBinder.h
  67. 1 1
      AnKi/Script/Renderer.cpp
  68. 1 3
      AnKi/Script/Scene.cpp
  69. 0 19
      AnKi/Script/ScriptEnvironment.cpp
  70. 0 21
      AnKi/Script/ScriptEnvironment.h
  71. 12 8
      AnKi/Script/ScriptManager.cpp
  72. 16 32
      AnKi/Script/ScriptManager.h
  73. 1 1
      Samples/Common/SampleApp.cpp
  74. 18 17
      Samples/PhysicsPlayground/Main.cpp
  75. 1 1
      Samples/SimpleScene/Main.cpp
  76. 3 3
      Samples/SkeletalAnimation/Main.cpp
  77. 1 1
      Samples/Sponza/Main.cpp
  78. 3 3
      Sandbox/Main.cpp
  79. 9 9
      Tests/Script/LuaBinder.cpp
  80. 5 6
      Tools/Image/ImageViewerMain.cpp

+ 17 - 27
AnKi/Core/App.cpp

@@ -118,10 +118,8 @@ void App::cleanup()
 	m_statsUi.reset(nullptr);
 	m_console.reset(nullptr);
 
-	deleteInstance(m_mainPool, m_scene);
-	m_scene = nullptr;
-	deleteInstance(m_mainPool, m_script);
-	m_script = nullptr;
+	SceneGraph::freeSingleton();
+	ScriptManager::freeSingleton();
 	deleteInstance(m_mainPool, m_renderer);
 	m_renderer = nullptr;
 	UiManager::freeSingleton();
@@ -141,6 +139,7 @@ void App::cleanup()
 	CoreTracer::freeSingleton();
 #endif
 
+	GlobalFrameIndex::freeSingleton();
 	ConfigSet::freeSingleton();
 
 	m_settingsDir.destroy();
@@ -222,6 +221,8 @@ Error App::initInternal(AllocAlignedCallback allocCb, void* allocCbUserData)
 		ConfigSet::getSingleton().setGrVsync(false);
 	}
 
+	GlobalFrameIndex::allocateSingleton();
+
 	//
 	// Core tracer
 	//
@@ -325,37 +326,25 @@ Error App::initInternal(AllocAlignedCallback allocCb, void* allocCbUserData)
 		UVec2(NativeWindow::getSingleton().getWidth(), NativeWindow::getSingleton().getHeight());
 	renderInit.m_allocCallback = m_mainPool.getAllocationCallback();
 	renderInit.m_allocCallbackUserData = m_mainPool.getAllocationCallbackUserData();
-	renderInit.m_globTimestamp = &m_globalTimestamp;
 	m_renderer = newInstance<MainRenderer>(m_mainPool);
 	ANKI_CHECK(m_renderer->init(renderInit));
 
 	//
 	// Script
 	//
-	m_script = newInstance<ScriptManager>(m_mainPool);
-	ANKI_CHECK(m_script->init(m_mainPool.getAllocationCallback(), m_mainPool.getAllocationCallbackUserData()));
+	ScriptManager::allocateSingleton(m_mainPool.getAllocationCallback(), m_mainPool.getAllocationCallbackUserData());
 
 	//
 	// Scene
 	//
-	m_scene = newInstance<SceneGraph>(m_mainPool);
-
-	SceneGraphInitInfo sceneInit;
-	sceneInit.m_allocCallback = m_mainPool.getAllocationCallback();
-	sceneInit.m_allocCallbackData = m_mainPool.getAllocationCallbackUserData();
-	sceneInit.m_globalTimestamp = &m_globalTimestamp;
-	sceneInit.m_scriptManager = m_script;
-	ANKI_CHECK(m_scene->init(sceneInit));
-
-	// Inform the script engine about some subsystems
-	m_script->setRenderer(m_renderer);
-	m_script->setSceneGraph(m_scene);
+	ANKI_CHECK(SceneGraph::allocateSingleton().init(m_mainPool.getAllocationCallback(),
+													m_mainPool.getAllocationCallbackUserData()));
 
 	//
 	// Misc
 	//
 	ANKI_CHECK(UiManager::getSingleton().newInstance<StatsUi>(m_statsUi));
-	ANKI_CHECK(UiManager::getSingleton().newInstance<DeveloperConsole>(m_console, m_script));
+	ANKI_CHECK(UiManager::getSingleton().newInstance<DeveloperConsole>(m_console));
 
 	ANKI_CORE_LOGI("Application initialized");
 
@@ -441,10 +430,10 @@ Error App::mainLoop()
 			// User update
 			ANKI_CHECK(userMainLoop(quit, crntTime - prevUpdateTime));
 
-			ANKI_CHECK(m_scene->update(prevUpdateTime, crntTime));
+			ANKI_CHECK(SceneGraph::getSingleton().update(prevUpdateTime, crntTime));
 
 			RenderQueue rqueue;
-			m_scene->doVisibilityTests(rqueue);
+			SceneGraph::getSingleton().doVisibilityTests(rqueue);
 
 			// Inject stats UI
 			DynamicArrayRaii<UiQueueElement> newUiElementArr(&m_mainPool);
@@ -525,9 +514,9 @@ Error App::mainLoop()
 				StatsUiInput in;
 				in.m_cpuFrameTime = frameTime - grTime;
 				in.m_rendererTime = m_renderer->getStats().m_renderingCpuTime;
-				in.m_sceneUpdateTime = m_scene->getStats().m_updateTime;
-				in.m_visibilityTestsTime = m_scene->getStats().m_visibilityTestsTime;
-				in.m_physicsTime = m_scene->getStats().m_physicsUpdate;
+				in.m_sceneUpdateTime = SceneGraph::getSingleton().getStats().m_updateTime;
+				in.m_visibilityTestsTime = SceneGraph::getSingleton().getStats().m_visibilityTestsTime;
+				in.m_physicsTime = SceneGraph::getSingleton().getStats().m_physicsUpdate;
 
 				in.m_gpuFrameTime = m_renderer->getStats().m_renderingGpuTime;
 
@@ -571,11 +560,12 @@ Error App::mainLoop()
 			}
 #endif
 
-			++m_globalTimestamp;
+			++GlobalFrameIndex::getSingleton().m_value;
 
 			if(benchmarkMode) [[unlikely]]
 			{
-				if(m_globalTimestamp >= ConfigSet::getSingleton().getCoreBenchmarkModeFrameCount())
+				if(GlobalFrameIndex::getSingleton().m_value
+				   >= ConfigSet::getSingleton().getCoreBenchmarkModeFrameCount())
 				{
 					quit = true;
 				}

+ 0 - 21
AnKi/Core/App.h

@@ -13,10 +13,7 @@
 namespace anki {
 
 // Forward
-class GrManager;
 class MainRenderer;
-class SceneGraph;
-class ScriptManager;
 class UiQueueElement;
 class RenderQueue;
 
@@ -45,11 +42,6 @@ public:
 		return m_mainPool;
 	}
 
-	Timestamp getGlobalTimestamp() const
-	{
-		return m_globalTimestamp;
-	}
-
 	/// Run the main loop.
 	Error mainLoop();
 
@@ -60,21 +52,11 @@ public:
 		return Error::kNone;
 	}
 
-	SceneGraph& getSceneGraph()
-	{
-		return *m_scene;
-	}
-
 	MainRenderer& getMainRenderer()
 	{
 		return *m_renderer;
 	}
 
-	ScriptManager& getScriptManager()
-	{
-		return *m_script;
-	}
-
 	void setDisplayDeveloperConsole(Bool display)
 	{
 		m_consoleEnabled = display;
@@ -90,14 +72,11 @@ private:
 
 	// Sybsystems
 	MainRenderer* m_renderer = nullptr;
-	SceneGraph* m_scene = nullptr;
-	ScriptManager* m_script = nullptr;
 
 	// Misc
 	UiImmediateModeBuilderPtr m_statsUi;
 	UiImmediateModeBuilderPtr m_console;
 	Bool m_consoleEnabled = false;
-	Timestamp m_globalTimestamp = 1;
 	CoreString m_settingsDir; ///< The path that holds the configuration
 	CoreString m_cacheDir; ///< This is used as a cache
 	U64 m_resourceCompletedAsyncTaskCount = 0;

+ 6 - 3
AnKi/Core/Common.h

@@ -44,9 +44,12 @@ public:
 	}
 };
 
-using CoreString = BaseStringRaii<SingletonMemoryPoolWrapper<CoreMemoryPool>>;
+class GlobalFrameIndex : public MakeSingleton<GlobalFrameIndex>
+{
+public:
+	Timestamp m_value = 1;
+};
 
-template<typename T>
-using CoreDynamicArray = DynamicArrayRaii<T, U32, SingletonMemoryPoolWrapper<CoreMemoryPool>>;
+ANKI_DEFINE_SUBMODULE_UTIL_CONTAINERS(Core, CoreMemoryPool)
 
 } // end namespace anki

+ 1 - 3
AnKi/Core/DeveloperConsole.cpp

@@ -19,7 +19,7 @@ DeveloperConsole::~DeveloperConsole()
 	}
 }
 
-Error DeveloperConsole::init(ScriptManager* scriptManager)
+Error DeveloperConsole::init()
 {
 	zeroMemory(m_inputText);
 
@@ -28,8 +28,6 @@ Error DeveloperConsole::init(ScriptManager* scriptManager)
 	// Add a new callback to the logger
 	Logger::getSingleton().addMessageHandler(this, loggerCallback);
 
-	ANKI_CHECK(m_scriptEnv.init(scriptManager));
-
 	return Error::kNone;
 }
 

+ 1 - 1
AnKi/Core/DeveloperConsole.h

@@ -23,7 +23,7 @@ public:
 
 	~DeveloperConsole();
 
-	Error init(ScriptManager* scriptManager);
+	Error init();
 
 	void build(CanvasPtr ctx) override;
 

+ 0 - 1
AnKi/Renderer/Common.h

@@ -75,7 +75,6 @@ inline constexpr Array<Format, kGBufferColorRenderTargetCount> kGBufferColorRend
 class RendererExternalSubsystems
 {
 public:
-	Timestamp* m_globTimestamp = nullptr;
 };
 
 /// Rendering context.

+ 1 - 1
AnKi/Renderer/RtShadows.cpp

@@ -529,7 +529,7 @@ void RtShadows::runDenoise(const RenderingContext& ctx, RenderPassWorkContext& r
 
 	RtShadowsDenoiseUniforms unis;
 	unis.invViewProjMat = ctx.m_matrices.m_invertedViewProjectionJitter;
-	unis.time = F32(*getExternalSubsystems().m_globTimestamp);
+	unis.time = F32(GlobalFrameIndex::getSingleton().m_value);
 	cmdb->setPushConstants(&unis, sizeof(unis));
 
 	dispatchPPCompute(cmdb, 8, 8, m_r->getInternalResolution().x() / 2, m_r->getInternalResolution().y() / 2);

+ 3 - 3
AnKi/Renderer/ShadowMapping.cpp

@@ -213,7 +213,7 @@ Bool ShadowMapping::allocateAtlasTiles(U64 lightUuid, U32 faceCount, const U64*
 	for(U i = 0; i < faceCount; ++i)
 	{
 		Array<U32, 4> tileViewport;
-		subResults[i] = m_tileAlloc.allocate(*getExternalSubsystems().m_globTimestamp, faceTimestamps[i], lightUuid,
+		subResults[i] = m_tileAlloc.allocate(GlobalFrameIndex::getSingleton().m_value, faceTimestamps[i], lightUuid,
 											 faceIndices[i], drawcallsCount[i], hierarchies[i], tileViewport);
 
 		if(subResults[i] == TileAllocatorResult::kAllocationFailed)
@@ -270,7 +270,7 @@ void ShadowMapping::processLights(RenderingContext& ctx, U32& threadCountForPass
 	{
 		Array<U32, 4> tileViewport;
 		[[maybe_unused]] const TileAllocatorResult res = m_tileAlloc.allocate(
-			*getExternalSubsystems().m_globTimestamp, 1, kMaxU64, 0, 1, kPointLightMaxTileAllocHierarchy, tileViewport);
+			GlobalFrameIndex::getSingleton().m_value, 1, kMaxU64, 0, 1, kPointLightMaxTileAllocHierarchy, tileViewport);
 
 		emptyTileViewport = UVec4(tileViewport);
 
@@ -310,7 +310,7 @@ void ShadowMapping::processLights(RenderingContext& ctx, U32& threadCountForPass
 			{
 				// Cascade with drawcalls, will need tiles
 
-				timestamps[activeCascades] = *getExternalSubsystems().m_globTimestamp; // This light is always updated
+				timestamps[activeCascades] = GlobalFrameIndex::getSingleton().m_value; // This light is always updated
 				cascadeIndices[activeCascades] = cascade;
 				drawcallCounts[activeCascades] = 1; // Doesn't matter
 

+ 16 - 7
AnKi/Scene/Common.h

@@ -32,6 +32,22 @@ class PhysicsWorld;
 #define ANKI_SCENE_LOGW(...) ANKI_LOG("SCEN", kWarning, __VA_ARGS__)
 #define ANKI_SCENE_LOGF(...) ANKI_LOG("SCEN", kFatal, __VA_ARGS__)
 
+class SceneMemoryPool : public HeapMemoryPool, public MakeSingleton<SceneMemoryPool>
+{
+	template<typename>
+	friend class MakeSingleton;
+
+private:
+	SceneMemoryPool(AllocAlignedCallback allocCb, void* allocCbUserData)
+		: HeapMemoryPool(allocCb, allocCbUserData, "SceneMemPool")
+	{
+	}
+
+	~SceneMemoryPool() = default;
+};
+
+ANKI_DEFINE_SUBMODULE_UTIL_CONTAINERS(Scene, SceneMemoryPool)
+
 #define ANKI_SCENE_ASSERT(expression) \
 	std::invoke([&]() -> Bool { \
 		const Bool ok = (expression); \
@@ -41,13 +57,6 @@ class PhysicsWorld;
 		} \
 		return ok; \
 	})
-
-class SceneGraphExternalSubsystems
-{
-public:
-	ScriptManager* m_scriptManager = nullptr;
-	const Timestamp* m_globalTimestamp = nullptr;
-};
 /// @}
 
 } // end namespace anki

+ 2 - 2
AnKi/Scene/Components/CameraComponent.cpp

@@ -17,7 +17,7 @@ CameraComponent::CameraComponent(SceneNode* node)
 	const ConfigSet& config = ConfigSet::getSingleton();
 
 	// Init main frustum
-	m_frustum.init(FrustumType::kPerspective, &node->getMemoryPool());
+	m_frustum.init(FrustumType::kPerspective);
 
 	m_frustum.setLodDistance(0, config.getLod0MaxDistance());
 	m_frustum.setLodDistance(1, config.getLod1MaxDistance());
@@ -41,7 +41,7 @@ CameraComponent::CameraComponent(SceneNode* node)
 
 	if(m_usesExtendedFrustum)
 	{
-		m_extendedFrustum.init(FrustumType::kOrthographic, &node->getMemoryPool());
+		m_extendedFrustum.init(FrustumType::kOrthographic);
 
 		const F32 dist = config.getSceneRayTracingExtendedFrustumDistance();
 

+ 6 - 10
AnKi/Scene/Components/DecalComponent.cpp

@@ -12,22 +12,18 @@ namespace anki {
 
 DecalComponent::DecalComponent(SceneNode* node)
 	: SceneComponent(node, getStaticClassId())
-	, m_node(node)
 	, m_spatial(this)
 {
 	m_gpuSceneIndex =
-		node->getSceneGraph().getAllGpuSceneContiguousArrays().allocate(GpuSceneContiguousArrayType::kDecals);
+		SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().allocate(GpuSceneContiguousArrayType::kDecals);
 }
 
 DecalComponent::~DecalComponent()
 {
-	m_spatial.removeFromOctree(m_node->getSceneGraph().getOctree());
-}
+	m_spatial.removeFromOctree(SceneGraph::getSingleton().getOctree());
 
-void DecalComponent::onDestroy(SceneNode& node)
-{
-	node.getSceneGraph().getAllGpuSceneContiguousArrays().deferredFree(GpuSceneContiguousArrayType::kDecals,
-																	   m_gpuSceneIndex);
+	SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().deferredFree(GpuSceneContiguousArrayType::kDecals,
+																			 m_gpuSceneIndex);
 }
 
 void DecalComponent::setLayer(CString fname, F32 blendFactor, LayerType type)
@@ -95,12 +91,12 @@ Error DecalComponent::update(SceneComponentUpdateInfo& info, Bool& updated)
 		gpuDecal.m_obbExtend = m_obb.getExtend().xyz();
 
 		const PtrSize offset = m_gpuSceneIndex * sizeof(GpuSceneDecal)
-							   + info.m_node->getSceneGraph().getAllGpuSceneContiguousArrays().getArrayBase(
+							   + SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().getArrayBase(
 								   GpuSceneContiguousArrayType::kDecals);
 		GpuSceneMicroPatcher::getSingleton().newCopy(*info.m_framePool, offset, sizeof(gpuDecal), &gpuDecal);
 	}
 
-	const Bool spatialUpdated = m_spatial.update(info.m_node->getSceneGraph().getOctree());
+	const Bool spatialUpdated = m_spatial.update(SceneGraph::getSingleton().getOctree());
 	updated = updated || spatialUpdated;
 
 	return Error::kNone;

+ 0 - 3
AnKi/Scene/Components/DecalComponent.h

@@ -86,7 +86,6 @@ private:
 		U32 m_bindlessTextureIndex = kMaxU32;
 	};
 
-	SceneNode* m_node;
 	Spatial m_spatial;
 
 	Array<Layer, U(LayerType::kCount)> m_layers;
@@ -101,8 +100,6 @@ private:
 	void setLayer(CString fname, F32 blendFactor, LayerType type);
 
 	Error update(SceneComponentUpdateInfo& info, Bool& updated);
-
-	void onDestroy(SceneNode& node);
 };
 /// @}
 

+ 7 - 7
AnKi/Scene/Components/FogDensityComponent.cpp

@@ -13,16 +13,16 @@ FogDensityComponent::FogDensityComponent(SceneNode* node)
 	: SceneComponent(node, getStaticClassId())
 	, m_spatial(this)
 {
-	m_gpuSceneIndex = node->getSceneGraph().getAllGpuSceneContiguousArrays().allocate(
+	m_gpuSceneIndex = SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().allocate(
 		GpuSceneContiguousArrayType::kFogDensityVolumes);
 }
 
-void FogDensityComponent::onDestroy(SceneNode& node)
+FogDensityComponent ::~FogDensityComponent()
 {
-	m_spatial.removeFromOctree(node.getSceneGraph().getOctree());
+	m_spatial.removeFromOctree(SceneGraph::getSingleton().getOctree());
 
-	node.getSceneGraph().getAllGpuSceneContiguousArrays().deferredFree(GpuSceneContiguousArrayType::kFogDensityVolumes,
-																	   m_gpuSceneIndex);
+	SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().deferredFree(
+		GpuSceneContiguousArrayType::kFogDensityVolumes, m_gpuSceneIndex);
 }
 
 Error FogDensityComponent::update(SceneComponentUpdateInfo& info, Bool& updated)
@@ -62,12 +62,12 @@ Error FogDensityComponent::update(SceneComponentUpdateInfo& info, Bool& updated)
 		gpuVolume.m_density = m_density;
 
 		const PtrSize offset = m_gpuSceneIndex * sizeof(GpuSceneFogDensityVolume)
-							   + info.m_node->getSceneGraph().getAllGpuSceneContiguousArrays().getArrayBase(
+							   + SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().getArrayBase(
 								   GpuSceneContiguousArrayType::kFogDensityVolumes);
 		GpuSceneMicroPatcher::getSingleton().newCopy(*info.m_framePool, offset, sizeof(gpuVolume), &gpuVolume);
 	}
 
-	const Bool spatialUpdated = m_spatial.update(info.m_node->getSceneGraph().getOctree());
+	const Bool spatialUpdated = m_spatial.update(SceneGraph::getSingleton().getOctree());
 	updated = updated || spatialUpdated;
 
 	return Error::kNone;

+ 2 - 2
AnKi/Scene/Components/FogDensityComponent.h

@@ -26,6 +26,8 @@ public:
 
 	FogDensityComponent(SceneNode* node);
 
+	~FogDensityComponent();
+
 	void setBoxVolumeSize(Vec3 sizeXYZ)
 	{
 		sizeXYZ = sizeXYZ.max(Vec3(kMinShapeSize));
@@ -114,8 +116,6 @@ private:
 	Bool m_dirty = true;
 
 	Error update(SceneComponentUpdateInfo& info, Bool& updated);
-
-	void onDestroy(SceneNode& node);
 };
 
 } // end namespace anki

+ 6 - 10
AnKi/Scene/Components/GlobalIlluminationProbeComponent.cpp

@@ -18,7 +18,7 @@ GlobalIlluminationProbeComponent::GlobalIlluminationProbeComponent(SceneNode* no
 {
 	for(U32 i = 0; i < 6; ++i)
 	{
-		m_frustums[i].init(FrustumType::kPerspective, &node->getMemoryPool());
+		m_frustums[i].init(FrustumType::kPerspective);
 		m_frustums[i].setPerspective(kClusterObjectFrustumNearPlane, 100.0f, kPi / 2.0f, kPi / 2.0f);
 		m_frustums[i].setWorldTransform(
 			Transform(node->getWorldTransform().getOrigin(), Frustum::getOmnidirectionalFrustumRotations()[i], 1.0f));
@@ -26,7 +26,7 @@ GlobalIlluminationProbeComponent::GlobalIlluminationProbeComponent(SceneNode* no
 		m_frustums[i].update();
 	}
 
-	m_gpuSceneIndex = node->getSceneGraph().getAllGpuSceneContiguousArrays().allocate(
+	m_gpuSceneIndex = SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().allocate(
 		GpuSceneContiguousArrayType::kGlobalIlluminationProbes);
 
 	const Error err = ResourceManager::getSingleton().loadResource("ShaderBinaries/ClearTextureCompute.ankiprogbin",
@@ -39,13 +39,9 @@ GlobalIlluminationProbeComponent::GlobalIlluminationProbeComponent(SceneNode* no
 
 GlobalIlluminationProbeComponent::~GlobalIlluminationProbeComponent()
 {
-}
-
-void GlobalIlluminationProbeComponent::onDestroy(SceneNode& node)
-{
-	m_spatial.removeFromOctree(node.getSceneGraph().getOctree());
+	m_spatial.removeFromOctree(SceneGraph::getSingleton().getOctree());
 
-	node.getSceneGraph().getAllGpuSceneContiguousArrays().deferredFree(
+	SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().deferredFree(
 		GpuSceneContiguousArrayType::kGlobalIlluminationProbes, m_gpuSceneIndex);
 }
 
@@ -128,7 +124,7 @@ Error GlobalIlluminationProbeComponent::update(SceneComponentUpdateInfo& info, B
 		gpuProbe.m_fadeDistance = m_fadeDistance;
 
 		const PtrSize offset = m_gpuSceneIndex * sizeof(GpuSceneGlobalIlluminationProbe)
-							   + info.m_node->getSceneGraph().getAllGpuSceneContiguousArrays().getArrayBase(
+							   + SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().getArrayBase(
 								   GpuSceneContiguousArrayType::kGlobalIlluminationProbes);
 		GpuSceneMicroPatcher::getSingleton().newCopy(*info.m_framePool, offset, sizeof(gpuProbe), &gpuProbe);
 	}
@@ -173,7 +169,7 @@ Error GlobalIlluminationProbeComponent::update(SceneComponentUpdateInfo& info, B
 		updated = updated || frustumUpdated;
 	}
 
-	const Bool spatialUpdated = m_spatial.update(info.m_node->getSceneGraph().getOctree());
+	const Bool spatialUpdated = m_spatial.update(SceneGraph::getSingleton().getOctree());
 	updated = updated || spatialUpdated;
 
 	return Error::kNone;

+ 0 - 2
AnKi/Scene/Components/GlobalIlluminationProbeComponent.h

@@ -133,8 +133,6 @@ private:
 	}
 
 	Error update(SceneComponentUpdateInfo& info, Bool& updated);
-
-	void onDestroy(SceneNode& node);
 };
 /// @}
 

+ 4 - 8
AnKi/Scene/Components/JointComponent.cpp

@@ -18,17 +18,13 @@ public:
 };
 
 JointComponent::~JointComponent()
-{
-}
-
-void JointComponent::onDestroy(SceneNode& node)
 {
 	while(!m_jointList.isEmpty())
 	{
 		JointNode* jnode = &m_jointList.getFront();
 		m_jointList.popFront();
 
-		deleteInstance(node.getMemoryPool(), jnode);
+		deleteInstance(SceneMemoryPool::getSingleton(), jnode);
 	}
 }
 
@@ -66,7 +62,7 @@ void JointComponent::newJoint(const Vec3& relPosFactor, F32 breakingImpulse, TAr
 																				 std::forward<TArgs>(args)...);
 		joint->setBreakingImpulseThreshold(breakingImpulse);
 
-		JointNode* newNode = newInstance<JointNode>(m_node->getMemoryPool());
+		JointNode* newNode = newInstance<JointNode>(SceneMemoryPool::getSingleton());
 		newNode->m_joint = std::move(joint);
 		m_jointList.pushBack(newNode);
 	}
@@ -99,7 +95,7 @@ void JointComponent::newPoint2PointJoint2(const Vec3& relPosFactorA, const Vec3&
 			bodycA->getPhysicsBody(), relPosA, bodycB->getPhysicsBody(), relPosB);
 		joint->setBreakingImpulseThreshold(breakingImpulse);
 
-		JointNode* newNode = newInstance<JointNode>(m_node->getMemoryPool());
+		JointNode* newNode = newInstance<JointNode>(SceneMemoryPool::getSingleton());
 		newNode->m_joint = std::move(joint);
 		newNode->m_parentNode = m_node->getParent();
 		m_jointList.pushBack(newNode);
@@ -126,7 +122,7 @@ Error JointComponent::update(SceneComponentUpdateInfo& info, Bool& updated)
 			if(joint.m_parentNode != info.m_node->getParent() || joint.m_joint->isBroken())
 			{
 				m_jointList.erase(&joint);
-				deleteInstance(info.m_node->getMemoryPool(), &joint);
+				deleteInstance(SceneMemoryPool::getSingleton(), &joint);
 				erasedOne = true;
 				updated = true;
 				break;

+ 0 - 2
AnKi/Scene/Components/JointComponent.h

@@ -53,8 +53,6 @@ private:
 
 	Error update(SceneComponentUpdateInfo& info, Bool& updated);
 
-	void onDestroy(SceneNode& node);
-
 	void onOtherComponentRemovedOrAdded(SceneComponent* other, Bool added);
 };
 /// @}

+ 4 - 5
AnKi/Scene/Components/LensFlareComponent.cpp

@@ -12,14 +12,13 @@ namespace anki {
 
 LensFlareComponent::LensFlareComponent(SceneNode* node)
 	: SceneComponent(node, getStaticClassId())
-	, m_node(node)
 	, m_spatial(this)
 {
 }
 
 LensFlareComponent::~LensFlareComponent()
 {
-	m_spatial.removeFromOctree(m_node->getSceneGraph().getOctree());
+	m_spatial.removeFromOctree(SceneGraph::getSingleton().getOctree());
 }
 
 void LensFlareComponent::loadImageResource(CString filename)
@@ -49,15 +48,15 @@ Error LensFlareComponent::update(SceneComponentUpdateInfo& info, Bool& updated)
 		m_spatial.setBoundingShape(aabb);
 	}
 
-	const Bool spatialUpdated = m_spatial.update(info.m_node->getSceneGraph().getOctree());
+	const Bool spatialUpdated = m_spatial.update(SceneGraph::getSingleton().getOctree());
 	updated = updated || spatialUpdated;
 
 	return Error::kNone;
 }
 
-void LensFlareComponent::onDestroy(SceneNode& node)
+void LensFlareComponent::onDestroy([[maybe_unused]] SceneNode& node)
 {
-	m_spatial.removeFromOctree(node.getSceneGraph().getOctree());
+	m_spatial.removeFromOctree(SceneGraph::getSingleton().getOctree());
 }
 
 } // end namespace anki

+ 0 - 1
AnKi/Scene/Components/LensFlareComponent.h

@@ -80,7 +80,6 @@ private:
 
 	Vec4 m_colorMul = Vec4(1.0f); ///< Color multiplier.
 
-	SceneNode* m_node;
 	ImageResourcePtr m_image; ///< Array of textures.
 
 	Spatial m_spatial;

+ 36 - 41
AnKi/Scene/Components/LightComponent.cpp

@@ -18,8 +18,7 @@ namespace anki {
 
 LightComponent::LightComponent(SceneNode* node)
 	: SceneComponent(node, getStaticClassId())
-	, m_node(node)
-	, m_uuid(node->getSceneGraph().getNewUuid())
+	, m_uuid(SceneGraph::getSingleton().getNewUuid())
 	, m_spatial(this)
 	, m_type(LightComponentType::kPoint)
 {
@@ -32,6 +31,26 @@ LightComponent::LightComponent(SceneNode* node)
 
 LightComponent::~LightComponent()
 {
+	deleteArray(SceneMemoryPool::getSingleton(), m_frustums, m_frustumCount);
+	m_spatial.removeFromOctree(SceneGraph::getSingleton().getOctree());
+
+	if(m_gpuSceneLightIndex != kMaxU32)
+	{
+		if(m_type == LightComponentType::kPoint)
+		{
+			SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().deferredFree(
+				GpuSceneContiguousArrayType::kPointLights, m_gpuSceneLightIndex);
+		}
+		else if(m_type == LightComponentType::kSpot)
+		{
+			SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().deferredFree(
+				GpuSceneContiguousArrayType::kSpotLights, m_gpuSceneLightIndex);
+		}
+		else
+		{
+			ANKI_ASSERT(0);
+		}
+	}
 }
 
 void LightComponent::setLightComponentType(LightComponentType type)
@@ -53,7 +72,7 @@ void LightComponent::setLightComponentType(LightComponentType type)
 
 	if(m_typeChanged && m_gpuSceneLightIndex != kMaxU32)
 	{
-		m_node->getSceneGraph().getAllGpuSceneContiguousArrays().deferredFree(
+		SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().deferredFree(
 			(m_type == LightComponentType::kPoint) ? GpuSceneContiguousArrayType::kPointLights
 												   : GpuSceneContiguousArrayType::kSpotLights,
 			m_gpuSceneLightIndex);
@@ -62,13 +81,13 @@ void LightComponent::setLightComponentType(LightComponentType type)
 
 	if(m_gpuSceneLightIndex == kMaxU32 && type == LightComponentType::kPoint)
 	{
-		m_gpuSceneLightIndex = m_node->getSceneGraph().getAllGpuSceneContiguousArrays().allocate(
+		m_gpuSceneLightIndex = SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().allocate(
 			GpuSceneContiguousArrayType::kPointLights);
 	}
 	else if(m_gpuSceneLightIndex == kMaxU32 && type == LightComponentType::kSpot)
 	{
-		m_gpuSceneLightIndex =
-			m_node->getSceneGraph().getAllGpuSceneContiguousArrays().allocate(GpuSceneContiguousArrayType::kSpotLights);
+		m_gpuSceneLightIndex = SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().allocate(
+			GpuSceneContiguousArrayType::kSpotLights);
 	}
 
 	m_type = type;
@@ -98,13 +117,13 @@ Error LightComponent::update(SceneComponentUpdateInfo& info, Bool& updated)
 			if(m_frustums == nullptr || m_frustumCount != 6) [[unlikely]]
 			{
 				// Allocate, initialize and update the frustums, just do everything to avoid bugs
-				deleteArray(info.m_node->getMemoryPool(), m_frustums, m_frustumCount);
-				m_frustums = newArray<Frustum>(info.m_node->getMemoryPool(), 6);
+				deleteArray(SceneMemoryPool::getSingleton(), m_frustums, m_frustumCount);
+				m_frustums = newArray<Frustum>(SceneMemoryPool::getSingleton(), 6);
 				m_frustumCount = 6;
 
 				for(U32 i = 0; i < 6; i++)
 				{
-					m_frustums[i].init(FrustumType::kPerspective, &info.m_node->getMemoryPool());
+					m_frustums[i].init(FrustumType::kPerspective);
 					m_frustums[i].setPerspective(kClusterObjectFrustumNearPlane, m_point.m_radius, kPi / 2.0f,
 												 kPi / 2.0f);
 					m_frustums[i].setWorldTransform(Transform(m_worldTransform.getOrigin(),
@@ -136,7 +155,7 @@ Error LightComponent::update(SceneComponentUpdateInfo& info, Bool& updated)
 		gpuLight.m_squareRadiusOverOne = 1.0f / (m_point.m_radius * m_point.m_radius);
 		gpuLight.m_shadow = m_shadow;
 		const PtrSize offset = m_gpuSceneLightIndex * sizeof(GpuScenePointLight)
-							   + info.m_node->getSceneGraph().getAllGpuSceneContiguousArrays().getArrayBase(
+							   + SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().getArrayBase(
 								   GpuSceneContiguousArrayType::kPointLights);
 		GpuSceneMicroPatcher::getSingleton().newCopy(*info.m_framePool, offset, sizeof(gpuLight), &gpuLight);
 	}
@@ -166,11 +185,11 @@ Error LightComponent::update(SceneComponentUpdateInfo& info, Bool& updated)
 			if(m_frustums == nullptr || m_frustumCount != 1) [[unlikely]]
 			{
 				// Allocate, initialize and update the frustums, just do everything to avoid bugs
-				deleteArray(info.m_node->getMemoryPool(), m_frustums, m_frustumCount);
-				m_frustums = newArray<Frustum>(info.m_node->getMemoryPool(), 1);
+				deleteArray(SceneMemoryPool::getSingleton(), m_frustums, m_frustumCount);
+				m_frustums = newArray<Frustum>(SceneMemoryPool::getSingleton(), 1);
 				m_frustumCount = 1;
 
-				m_frustums[0].init(FrustumType::kPerspective, &info.m_node->getMemoryPool());
+				m_frustums[0].init(FrustumType::kPerspective);
 				m_frustums[0].setPerspective(kClusterObjectFrustumNearPlane, m_spot.m_distance, m_spot.m_outerAngle,
 											 m_spot.m_outerAngle);
 				m_frustums[0].setWorldTransform(m_worldTransform);
@@ -205,17 +224,17 @@ Error LightComponent::update(SceneComponentUpdateInfo& info, Bool& updated)
 		gpuLight.m_outerCos = cos(m_spot.m_outerAngle / 2.0f);
 		gpuLight.m_innerCos = cos(m_spot.m_innerAngle / 2.0f);
 		const PtrSize offset = m_gpuSceneLightIndex * sizeof(GpuSceneSpotLight)
-							   + info.m_node->getSceneGraph().getAllGpuSceneContiguousArrays().getArrayBase(
+							   + SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().getArrayBase(
 								   GpuSceneContiguousArrayType::kSpotLights);
 		GpuSceneMicroPatcher::getSingleton().newCopy(*info.m_framePool, offset, sizeof(gpuLight), &gpuLight);
 	}
 	else if(m_type == LightComponentType::kDirectional)
 	{
 		// Update the scene bounds always
-		info.m_node->getSceneGraph().getOctree().getActualSceneBounds(m_dir.m_sceneMin, m_dir.m_sceneMax);
+		SceneGraph::getSingleton().getOctree().getActualSceneBounds(m_dir.m_sceneMin, m_dir.m_sceneMax);
 	}
 
-	const Bool spatialUpdated = m_spatial.update(info.m_node->getSceneGraph().getOctree());
+	const Bool spatialUpdated = m_spatial.update(SceneGraph::getSingleton().getOctree());
 	updated = updated || spatialUpdated;
 
 	if(m_shadow)
@@ -373,7 +392,7 @@ void LightComponent::setupDirectionalLightQueueElement(const Frustum& primaryFru
 			const F32 bottom = plane.getOffset();
 
 			Frustum& cascadeFrustum = cascadeFrustums[i];
-			cascadeFrustum.init(FrustumType::kOrthographic, nullptr);
+			cascadeFrustum.init(FrustumType::kOrthographic);
 			cascadeFrustum.setOrthographic(kClusterObjectFrustumNearPlane, far, right, left, top, bottom);
 			cascadeFrustum.setWorldTransform(cascadeTransform);
 			[[maybe_unused]] const Bool updated = cascadeFrustum.update();
@@ -386,28 +405,4 @@ void LightComponent::setupDirectionalLightQueueElement(const Frustum& primaryFru
 	}
 }
 
-void LightComponent::onDestroy(SceneNode& node)
-{
-	deleteArray(node.getMemoryPool(), m_frustums, m_frustumCount);
-	m_spatial.removeFromOctree(node.getSceneGraph().getOctree());
-
-	if(m_gpuSceneLightIndex != kMaxU32)
-	{
-		if(m_type == LightComponentType::kPoint)
-		{
-			node.getSceneGraph().getAllGpuSceneContiguousArrays().deferredFree(
-				GpuSceneContiguousArrayType::kPointLights, m_gpuSceneLightIndex);
-		}
-		else if(m_type == LightComponentType::kSpot)
-		{
-			node.getSceneGraph().getAllGpuSceneContiguousArrays().deferredFree(GpuSceneContiguousArrayType::kSpotLights,
-																			   m_gpuSceneLightIndex);
-		}
-		else
-		{
-			ANKI_ASSERT(0);
-		}
-	}
-}
-
 } // end namespace anki

+ 0 - 3
AnKi/Scene/Components/LightComponent.h

@@ -152,7 +152,6 @@ public:
 										   WeakArray<Frustum> cascadeFrustums) const;
 
 private:
-	SceneNode* m_node;
 	U64 m_uuid;
 	Vec4 m_diffColor = Vec4(0.5f);
 	Transform m_worldTransform = Transform::getIdentity();
@@ -198,8 +197,6 @@ private:
 	U8 m_frustumCount : 4 = 0; ///< The size of m_frustums array.
 
 	Error update(SceneComponentUpdateInfo& info, Bool& updated);
-
-	void onDestroy(SceneNode& node);
 };
 /// @}
 

+ 16 - 17
AnKi/Scene/Components/ModelComponent.cpp

@@ -18,8 +18,8 @@ ModelComponent::ModelComponent(SceneNode* node)
 	, m_node(node)
 	, m_spatial(this)
 {
-	m_gpuSceneTransformsIndex = U32(
-		node->getSceneGraph().getAllGpuSceneContiguousArrays().allocate(GpuSceneContiguousArrayType::kTransformPairs));
+	m_gpuSceneTransformsIndex = U32(SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().allocate(
+		GpuSceneContiguousArrayType::kTransformPairs));
 }
 
 ModelComponent::~ModelComponent()
@@ -30,17 +30,15 @@ ModelComponent::~ModelComponent()
 	{
 		if(patch.m_gpuSceneMeshLodsIndex != kMaxU32)
 		{
-			m_node->getSceneGraph().getAllGpuSceneContiguousArrays().deferredFree(
+			SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().deferredFree(
 				GpuSceneContiguousArrayType::kMeshLods, patch.m_gpuSceneMeshLodsIndex);
 		}
 	}
 
-	m_node->getSceneGraph().getAllGpuSceneContiguousArrays().deferredFree(GpuSceneContiguousArrayType::kTransformPairs,
-																		  m_gpuSceneTransformsIndex);
+	SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().deferredFree(
+		GpuSceneContiguousArrayType::kTransformPairs, m_gpuSceneTransformsIndex);
 
-	m_patchInfos.destroy(m_node->getMemoryPool());
-
-	m_spatial.removeFromOctree(m_node->getSceneGraph().getOctree());
+	m_spatial.removeFromOctree(SceneGraph::getSingleton().getOctree());
 }
 
 void ModelComponent::loadModelResource(CString filename)
@@ -63,16 +61,17 @@ void ModelComponent::loadModelResource(CString filename)
 	{
 		if(patch.m_gpuSceneMeshLodsIndex != kMaxU32)
 		{
-			m_node->getSceneGraph().getAllGpuSceneContiguousArrays().deferredFree(
+			SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().deferredFree(
 				GpuSceneContiguousArrayType::kMeshLods, patch.m_gpuSceneMeshLodsIndex);
 		}
 	}
 
-	m_patchInfos.resize(m_node->getMemoryPool(), modelPatchCount);
+	m_patchInfos.resize(modelPatchCount);
 	for(U32 i = 0; i < modelPatchCount; ++i)
 	{
-		m_patchInfos[i].m_gpuSceneMeshLodsIndex = U32(
-			m_node->getSceneGraph().getAllGpuSceneContiguousArrays().allocate(GpuSceneContiguousArrayType::kMeshLods));
+		m_patchInfos[i].m_gpuSceneMeshLodsIndex =
+			U32(SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().allocate(
+				GpuSceneContiguousArrayType::kMeshLods));
 	}
 
 	U32 uniformsSize = 0;
@@ -177,7 +176,7 @@ Error ModelComponent::update(SceneComponentUpdateInfo& info, Bool& updated)
 			}
 
 			const PtrSize offset = m_patchInfos[i].m_gpuSceneMeshLodsIndex * sizeof(meshLods)
-								   + info.m_node->getSceneGraph().getAllGpuSceneContiguousArrays().getArrayBase(
+								   + SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().getArrayBase(
 									   GpuSceneContiguousArrayType::kMeshLods);
 			GpuSceneMicroPatcher::getSingleton().newCopy(*info.m_framePool, offset, meshLods.getSizeInBytes(),
 														 &meshLods[0]);
@@ -209,7 +208,7 @@ Error ModelComponent::update(SceneComponentUpdateInfo& info, Bool& updated)
 		trfs[1] = Mat3x4(info.m_node->getPreviousWorldTransform());
 
 		const PtrSize offset = m_gpuSceneTransformsIndex * sizeof(trfs)
-							   + info.m_node->getSceneGraph().getAllGpuSceneContiguousArrays().getArrayBase(
+							   + SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().getArrayBase(
 								   GpuSceneContiguousArrayType::kTransformPairs);
 		GpuSceneMicroPatcher::getSingleton().newCopy(*info.m_framePool, offset, sizeof(trfs), &trfs[0]);
 	}
@@ -233,7 +232,7 @@ Error ModelComponent::update(SceneComponentUpdateInfo& info, Bool& updated)
 		m_spatial.setBoundingShape(aabbWorld);
 	}
 
-	const Bool spatialUpdated = m_spatial.update(info.m_node->getSceneGraph().getOctree());
+	const Bool spatialUpdated = m_spatial.update(SceneGraph::getSingleton().getOctree());
 	updated = updated || spatialUpdated;
 
 	return Error::kNone;
@@ -294,7 +293,7 @@ void ModelComponent::setupRenderableQueueElements(U32 lod, RenderingTechnique te
 		ModelRenderingInfo modelInf;
 		patch.getRenderingInfo(key, modelInf);
 
-		AllGpuSceneContiguousArrays& gpuArrays = m_node->getSceneGraph().getAllGpuSceneContiguousArrays();
+		AllGpuSceneContiguousArrays& gpuArrays = SceneGraph::getSingleton().getAllGpuSceneContiguousArrays();
 
 		queueElem.m_program = modelInf.m_program.get();
 		queueElem.m_worldTransformsOffset = U32(m_gpuSceneTransformsIndex * sizeof(Mat3x4) * 2
@@ -366,7 +365,7 @@ void ModelComponent::setupRayTracingInstanceQueueElements(U32 lod, RenderingTech
 
 		const ModelPatch& patch = m_model->getModelPatches()[i];
 
-		AllGpuSceneContiguousArrays& gpuArrays = m_node->getSceneGraph().getAllGpuSceneContiguousArrays();
+		AllGpuSceneContiguousArrays& gpuArrays = SceneGraph::getSingleton().getAllGpuSceneContiguousArrays();
 
 		ModelRayTracingInfo modelInf;
 		patch.getRayTracingInfo(key, modelInf);

+ 1 - 1
AnKi/Scene/Components/ModelComponent.h

@@ -66,7 +66,7 @@ private:
 
 	SegregatedListsGpuMemoryPoolToken m_gpuSceneUniforms;
 	U32 m_gpuSceneTransformsIndex = kMaxU32;
-	DynamicArray<PatchInfo> m_patchInfos;
+	SceneDynamicArray<PatchInfo> m_patchInfos;
 
 	Bool m_dirty : 1 = true;
 	Bool m_castsShadow : 1 = false;

+ 18 - 21
AnKi/Scene/Components/ParticleEmitterComponent.cpp

@@ -202,9 +202,6 @@ ParticleEmitterComponent::ParticleEmitterComponent(SceneNode* node)
 
 ParticleEmitterComponent::~ParticleEmitterComponent()
 {
-	m_simpleParticles.destroy(m_node->getMemoryPool());
-	m_physicsParticles.destroy(m_node->getMemoryPool());
-
 	GpuSceneMemoryPool& gpuScenePool = GpuSceneMemoryPool::getSingleton();
 	gpuScenePool.deferredFree(m_gpuScenePositions);
 	gpuScenePool.deferredFree(m_gpuSceneScales);
@@ -213,11 +210,11 @@ ParticleEmitterComponent::~ParticleEmitterComponent()
 
 	if(m_gpuSceneIndex != kMaxU32)
 	{
-		m_node->getSceneGraph().getAllGpuSceneContiguousArrays().deferredFree(
+		SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().deferredFree(
 			GpuSceneContiguousArrayType::kParticleEmitters, m_gpuSceneIndex);
 	}
 
-	m_spatial.removeFromOctree(m_node->getSceneGraph().getOctree());
+	m_spatial.removeFromOctree(SceneGraph::getSingleton().getOctree());
 }
 
 void ParticleEmitterComponent::loadParticleEmitterResource(CString filename)
@@ -237,8 +234,8 @@ void ParticleEmitterComponent::loadParticleEmitterResource(CString filename)
 	m_resourceUpdated = true;
 
 	// Cleanup
-	m_simpleParticles.destroy(m_node->getMemoryPool());
-	m_physicsParticles.destroy(m_node->getMemoryPool());
+	m_simpleParticles.destroy();
+	m_physicsParticles.destroy();
 	GpuSceneMemoryPool& gpuScenePool = GpuSceneMemoryPool::getSingleton();
 	gpuScenePool.deferredFree(m_gpuScenePositions);
 	gpuScenePool.deferredFree(m_gpuSceneScales);
@@ -247,7 +244,7 @@ void ParticleEmitterComponent::loadParticleEmitterResource(CString filename)
 
 	if(m_gpuSceneIndex != kMaxU32)
 	{
-		m_node->getSceneGraph().getAllGpuSceneContiguousArrays().deferredFree(
+		SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().deferredFree(
 			GpuSceneContiguousArrayType::kParticleEmitters, m_gpuSceneIndex);
 	}
 
@@ -261,16 +258,16 @@ void ParticleEmitterComponent::loadParticleEmitterResource(CString filename)
 		PhysicsBodyInitInfo binit;
 		binit.m_shape = std::move(collisionShape);
 
-		m_physicsParticles.resizeStorage(m_node->getMemoryPool(), m_props.m_maxNumOfParticles);
+		m_physicsParticles.resizeStorage(m_props.m_maxNumOfParticles);
 		for(U32 i = 0; i < m_props.m_maxNumOfParticles; i++)
 		{
 			binit.m_mass = getRandomRange(m_props.m_particle.m_minMass, m_props.m_particle.m_maxMass);
-			m_physicsParticles.emplaceBack(m_node->getMemoryPool(), binit, this);
+			m_physicsParticles.emplaceBack(binit, this);
 		}
 	}
 	else
 	{
-		m_simpleParticles.create(m_node->getMemoryPool(), m_props.m_maxNumOfParticles);
+		m_simpleParticles.create(m_props.m_maxNumOfParticles);
 	}
 
 	// GPU scene allocations
@@ -280,7 +277,7 @@ void ParticleEmitterComponent::loadParticleEmitterResource(CString filename)
 	gpuScenePool.allocate(m_particleEmitterResource->getMaterial()->getPrefilledLocalUniforms().getSizeInBytes(),
 						  alignof(U32), m_gpuSceneUniforms);
 
-	m_gpuSceneIndex = m_node->getSceneGraph().getAllGpuSceneContiguousArrays().allocate(
+	m_gpuSceneIndex = SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().allocate(
 		GpuSceneContiguousArrayType::kParticleEmitters);
 }
 
@@ -311,7 +308,7 @@ Error ParticleEmitterComponent::update(SceneComponentUpdateInfo& info, Bool& upd
 	}
 
 	m_spatial.setBoundingShape(aabbWorld);
-	m_spatial.update(info.m_node->getSceneGraph().getOctree());
+	m_spatial.update(SceneGraph::getSingleton().getOctree());
 
 	// Upload to the GPU scene
 	GpuSceneMicroPatcher& patcher = GpuSceneMicroPatcher::getSingleton();
@@ -331,7 +328,7 @@ Error ParticleEmitterComponent::update(SceneComponentUpdateInfo& info, Bool& upd
 		particles.m_vertexOffsets[U32(VertexStreamId::kParticleScale)] = U32(m_gpuSceneScales.m_offset);
 
 		const PtrSize offset = m_gpuSceneIndex * sizeof(GpuSceneParticleEmitter)
-							   + info.m_node->getSceneGraph().getAllGpuSceneContiguousArrays().getArrayBase(
+							   + SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().getArrayBase(
 								   GpuSceneContiguousArrayType::kParticleEmitters);
 		patcher.newCopy(*info.m_framePool, offset, sizeof(GpuSceneParticleEmitter), &particles);
 
@@ -356,12 +353,12 @@ void ParticleEmitterComponent::simulate(Second prevUpdateTime, Second crntTime,
 	Vec3 aabbMax(kMinF32);
 	m_aliveParticleCount = 0;
 
-	positions = static_cast<Vec3*>(
-		m_node->getFrameMemoryPool().allocate(m_props.m_maxNumOfParticles * sizeof(Vec3), alignof(Vec3)));
-	scales = static_cast<F32*>(
-		m_node->getFrameMemoryPool().allocate(m_props.m_maxNumOfParticles * sizeof(F32), alignof(F32)));
-	alphas = static_cast<F32*>(
-		m_node->getFrameMemoryPool().allocate(m_props.m_maxNumOfParticles * sizeof(F32), alignof(F32)));
+	positions = static_cast<Vec3*>(SceneGraph::getSingleton().getFrameMemoryPool().allocate(
+		m_props.m_maxNumOfParticles * sizeof(Vec3), alignof(Vec3)));
+	scales = static_cast<F32*>(SceneGraph::getSingleton().getFrameMemoryPool().allocate(
+		m_props.m_maxNumOfParticles * sizeof(F32), alignof(F32)));
+	alphas = static_cast<F32*>(SceneGraph::getSingleton().getFrameMemoryPool().allocate(
+		m_props.m_maxNumOfParticles * sizeof(F32), alignof(F32)));
 
 	F32 maxParticleSize = -1.0f;
 
@@ -471,7 +468,7 @@ void ParticleEmitterComponent::setupRenderableQueueElements(RenderingTechnique t
 	el->m_worldTransformsOffset = 0;
 	el->m_uniformsOffset = U32(m_gpuSceneUniforms.m_offset);
 	el->m_geometryOffset = U32(m_gpuSceneIndex * sizeof(GpuSceneParticleEmitter)
-							   + m_node->getSceneGraph().getAllGpuSceneContiguousArrays().getArrayBase(
+							   + SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().getArrayBase(
 								   GpuSceneContiguousArrayType::kParticleEmitters));
 	el->m_boneTransformsOffset = 0;
 	el->m_vertexCount = 6 * m_aliveParticleCount;

+ 2 - 2
AnKi/Scene/Components/ParticleEmitterComponent.h

@@ -58,8 +58,8 @@ private:
 	Spatial m_spatial;
 
 	ParticleEmitterResourcePtr m_particleEmitterResource;
-	DynamicArray<SimpleParticle> m_simpleParticles;
-	DynamicArray<PhysicsParticle> m_physicsParticles;
+	SceneDynamicArray<SimpleParticle> m_simpleParticles;
+	SceneDynamicArray<PhysicsParticle> m_physicsParticles;
 	Second m_timeLeftForNextEmission = 0.0;
 	U32 m_aliveParticleCount = 0;
 

+ 9 - 13
AnKi/Scene/Components/ReflectionProbeComponent.cpp

@@ -19,7 +19,7 @@ ReflectionProbeComponent::ReflectionProbeComponent(SceneNode* node)
 
 	for(U32 i = 0; i < 6; ++i)
 	{
-		m_frustums[i].init(FrustumType::kPerspective, &node->getMemoryPool());
+		m_frustums[i].init(FrustumType::kPerspective);
 		m_frustums[i].setPerspective(kClusterObjectFrustumNearPlane, 100.0f, kPi / 2.0f, kPi / 2.0f);
 		m_frustums[i].setWorldTransform(
 			Transform(m_worldPos.xyz0(), Frustum::getOmnidirectionalFrustumRotations()[i], 1.0f));
@@ -27,12 +27,16 @@ ReflectionProbeComponent::ReflectionProbeComponent(SceneNode* node)
 		m_frustums[i].update();
 	}
 
-	m_gpuSceneIndex =
-		node->getSceneGraph().getAllGpuSceneContiguousArrays().allocate(GpuSceneContiguousArrayType::kReflectionProbes);
+	m_gpuSceneIndex = SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().allocate(
+		GpuSceneContiguousArrayType::kReflectionProbes);
 }
 
 ReflectionProbeComponent::~ReflectionProbeComponent()
 {
+	m_spatial.removeFromOctree(SceneGraph::getSingleton().getOctree());
+
+	SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().deferredFree(
+		GpuSceneContiguousArrayType::kReflectionProbes, m_gpuSceneIndex);
 }
 
 Error ReflectionProbeComponent::update(SceneComponentUpdateInfo& info, Bool& updated)
@@ -102,13 +106,13 @@ Error ReflectionProbeComponent::update(SceneComponentUpdateInfo& info, Bool& upd
 		gpuProbe.m_aabbMax = aabbWorld.getMax().xyz();
 
 		const PtrSize offset = m_gpuSceneIndex * sizeof(GpuSceneReflectionProbe)
-							   + info.m_node->getSceneGraph().getAllGpuSceneContiguousArrays().getArrayBase(
+							   + SceneGraph::getSingleton().getAllGpuSceneContiguousArrays().getArrayBase(
 								   GpuSceneContiguousArrayType::kReflectionProbes);
 		GpuSceneMicroPatcher::getSingleton().newCopy(*info.m_framePool, offset, sizeof(gpuProbe), &gpuProbe);
 	}
 
 	// Update spatial and frustums
-	const Bool spatialUpdated = m_spatial.update(info.m_node->getSceneGraph().getOctree());
+	const Bool spatialUpdated = m_spatial.update(SceneGraph::getSingleton().getOctree());
 	updated = updated || spatialUpdated;
 
 	for(U32 i = 0; i < 6; ++i)
@@ -120,12 +124,4 @@ Error ReflectionProbeComponent::update(SceneComponentUpdateInfo& info, Bool& upd
 	return Error::kNone;
 }
 
-void ReflectionProbeComponent::onDestroy(SceneNode& node)
-{
-	m_spatial.removeFromOctree(node.getSceneGraph().getOctree());
-
-	node.getSceneGraph().getAllGpuSceneContiguousArrays().deferredFree(GpuSceneContiguousArrayType::kReflectionProbes,
-																	   m_gpuSceneIndex);
-}
-
 } // end namespace anki

+ 0 - 2
AnKi/Scene/Components/ReflectionProbeComponent.h

@@ -91,8 +91,6 @@ private:
 	Bool m_reflectionNeedsRefresh = true;
 
 	Error update(SceneComponentUpdateInfo& info, Bool& updated);
-
-	void onDestroy(SceneNode& node);
 };
 /// @}
 

+ 0 - 5
AnKi/Scene/Components/SceneComponent.cpp

@@ -111,9 +111,4 @@ const SceneComponentRtti& SceneComponent::getClassRtti(U8 classId)
 	return *g_rttis[classId];
 }
 
-SceneGraphExternalSubsystems& SceneComponent::getExternalSubsystems(const SceneNode& node)
-{
-	return node.getExternalSubsystems();
-}
-
 } // namespace anki

+ 0 - 2
AnKi/Scene/Components/SceneComponent.h

@@ -163,8 +163,6 @@ public:
 	}
 
 protected:
-	ANKI_PURE static SceneGraphExternalSubsystems& getExternalSubsystems(const SceneNode& node);
-
 	/// Pseudo-virtual
 	void onDestroy([[maybe_unused]] SceneNode& node)
 	{

+ 4 - 7
AnKi/Scene/Components/ScriptComponent.cpp

@@ -14,14 +14,13 @@ namespace anki {
 
 ScriptComponent::ScriptComponent(SceneNode* node)
 	: SceneComponent(node, getStaticClassId())
-	, m_node(node)
 {
 	ANKI_ASSERT(node);
 }
 
 ScriptComponent::~ScriptComponent()
 {
-	deleteInstance(m_node->getMemoryPool(), m_env);
+	deleteInstance(SceneMemoryPool::getSingleton(), m_env);
 }
 
 void ScriptComponent::loadScriptResource(CString fname)
@@ -34,8 +33,7 @@ void ScriptComponent::loadScriptResource(CString fname)
 	ScriptEnvironment* newEnv = nullptr;
 	if(!err)
 	{
-		newEnv = newInstance<ScriptEnvironment>(m_node->getMemoryPool());
-		err = newEnv->init(getExternalSubsystems(*m_node).m_scriptManager);
+		newEnv = newInstance<ScriptEnvironment>(SceneMemoryPool::getSingleton());
 	}
 
 	// Exec the script
@@ -48,19 +46,18 @@ void ScriptComponent::loadScriptResource(CString fname)
 	if(err)
 	{
 		ANKI_SCENE_LOGE("Failed to load the script");
-		deleteInstance(m_node->getMemoryPool(), newEnv);
+		deleteInstance(SceneMemoryPool::getSingleton(), newEnv);
 	}
 	else
 	{
 		m_script = std::move(rsrc);
-		deleteInstance(m_node->getMemoryPool(), m_env);
+		deleteInstance(SceneMemoryPool::getSingleton(), m_env);
 		m_env = newEnv;
 	}
 }
 
 Error ScriptComponent::update(SceneComponentUpdateInfo& info, Bool& updated)
 {
-	ANKI_ASSERT(info.m_node == m_node);
 	updated = false;
 	if(m_env == nullptr)
 	{

+ 0 - 1
AnKi/Scene/Components/ScriptComponent.h

@@ -32,7 +32,6 @@ public:
 	}
 
 private:
-	SceneNode* m_node;
 	ScriptResourcePtr m_script;
 	ScriptEnvironment* m_env = nullptr;
 

+ 6 - 10
AnKi/Scene/Components/SkinComponent.cpp

@@ -21,10 +21,6 @@ SkinComponent::SkinComponent(SceneNode* node)
 
 SkinComponent::~SkinComponent()
 {
-	m_boneTrfs[0].destroy(m_node->getMemoryPool());
-	m_boneTrfs[1].destroy(m_node->getMemoryPool());
-	m_animationTrfs.destroy(m_node->getMemoryPool());
-
 	GpuSceneMemoryPool::getSingleton().deferredFree(m_boneTransformsGpuSceneOffset);
 }
 
@@ -43,16 +39,16 @@ void SkinComponent::loadSkeletonResource(CString fname)
 	m_skeleton = std::move(rsrc);
 
 	// Cleanup
-	m_boneTrfs[0].destroy(m_node->getMemoryPool());
-	m_boneTrfs[1].destroy(m_node->getMemoryPool());
-	m_animationTrfs.destroy(m_node->getMemoryPool());
+	m_boneTrfs[0].destroy();
+	m_boneTrfs[1].destroy();
+	m_animationTrfs.destroy();
 	GpuSceneMemoryPool::getSingleton().deferredFree(m_boneTransformsGpuSceneOffset);
 
 	// Create
 	const U32 boneCount = m_skeleton->getBones().getSize();
-	m_boneTrfs[0].create(m_node->getMemoryPool(), boneCount, Mat3x4::getIdentity());
-	m_boneTrfs[1].create(m_node->getMemoryPool(), boneCount, Mat3x4::getIdentity());
-	m_animationTrfs.create(m_node->getMemoryPool(), boneCount, {Vec3(0.0f), Quat::getIdentity(), 1.0f});
+	m_boneTrfs[0].create(boneCount, Mat3x4::getIdentity());
+	m_boneTrfs[1].create(boneCount, Mat3x4::getIdentity());
+	m_animationTrfs.create(boneCount, {Vec3(0.0f), Quat::getIdentity(), 1.0f});
 
 	GpuSceneMemoryPool::getSingleton().allocate(sizeof(Mat4) * boneCount * 2, 4, m_boneTransformsGpuSceneOffset);
 }

+ 2 - 2
AnKi/Scene/Components/SkinComponent.h

@@ -103,8 +103,8 @@ private:
 
 	SceneNode* m_node;
 	SkeletonResourcePtr m_skeleton;
-	Array<DynamicArray<Mat3x4>, 2> m_boneTrfs;
-	DynamicArray<Trf> m_animationTrfs;
+	Array<SceneDynamicArray<Mat3x4>, 2> m_boneTrfs;
+	SceneDynamicArray<Trf> m_animationTrfs;
 	Aabb m_boneBoundingVolume = Aabb(Vec3(-1.0f), Vec3(1.0f));
 	Array<Track, kMaxAnimationTracks> m_tracks;
 	Second m_absoluteTime = 0.0;

+ 3 - 3
AnKi/Scene/Components/SkyboxComponent.cpp

@@ -23,7 +23,7 @@ SkyboxComponent::SkyboxComponent(SceneNode* node)
 
 SkyboxComponent::~SkyboxComponent()
 {
-	m_spatial.removeFromOctree(m_node->getSceneGraph().getOctree());
+	m_spatial.removeFromOctree(SceneGraph::getSingleton().getOctree());
 }
 
 void SkyboxComponent::loadImageResource(CString filename)
@@ -40,9 +40,9 @@ void SkyboxComponent::loadImageResource(CString filename)
 	m_type = SkyboxType::kImage2D;
 }
 
-Error SkyboxComponent::update(SceneComponentUpdateInfo& info, Bool& updated)
+Error SkyboxComponent::update([[maybe_unused]] SceneComponentUpdateInfo& info, Bool& updated)
 {
-	updated = m_spatial.update(info.m_node->getSceneGraph().getOctree());
+	updated = m_spatial.update(SceneGraph::getSingleton().getOctree());
 	return Error::kNone;
 }
 

+ 8 - 14
AnKi/Scene/Components/TriggerComponent.cpp

@@ -27,13 +27,12 @@ public:
 		if(!m_enterUpdated)
 		{
 			m_enterUpdated = true;
-			m_comp->m_bodiesEnter.destroy(m_comp->m_node->getMemoryPool());
+			m_comp->m_bodiesEnter.destroy();
 		}
 
 		m_updated = true;
 
-		m_comp->m_bodiesEnter.emplaceBack(m_comp->m_node->getMemoryPool(),
-										  static_cast<BodyComponent*>(obj.getUserData()));
+		m_comp->m_bodiesEnter.emplaceBack(static_cast<BodyComponent*>(obj.getUserData()));
 	}
 
 	void onTriggerInside([[maybe_unused]] PhysicsTrigger& trigger, PhysicsFilteredObject& obj)
@@ -42,13 +41,12 @@ public:
 		if(!m_insideUpdated)
 		{
 			m_insideUpdated = true;
-			m_comp->m_bodiesInside.destroy(m_comp->m_node->getMemoryPool());
+			m_comp->m_bodiesInside.destroy();
 		}
 
 		m_updated = true;
 
-		m_comp->m_bodiesInside.emplaceBack(m_comp->m_node->getMemoryPool(),
-										   static_cast<BodyComponent*>(obj.getUserData()));
+		m_comp->m_bodiesInside.emplaceBack(static_cast<BodyComponent*>(obj.getUserData()));
 	}
 
 	void onTriggerExit([[maybe_unused]] PhysicsTrigger& trigger, PhysicsFilteredObject& obj)
@@ -57,13 +55,12 @@ public:
 		if(!m_exitUpdated)
 		{
 			m_exitUpdated = true;
-			m_comp->m_bodiesExit.destroy(m_comp->m_node->getMemoryPool());
+			m_comp->m_bodiesExit.destroy();
 		}
 
 		m_updated = true;
 
-		m_comp->m_bodiesExit.emplaceBack(m_comp->m_node->getMemoryPool(),
-										 static_cast<BodyComponent*>(obj.getUserData()));
+		m_comp->m_bodiesExit.emplaceBack(static_cast<BodyComponent*>(obj.getUserData()));
 	}
 };
 
@@ -72,16 +69,13 @@ TriggerComponent::TriggerComponent(SceneNode* node)
 	, m_node(node)
 {
 	ANKI_ASSERT(node);
-	m_callbacks = newInstance<MyPhysicsTriggerProcessContactCallback>(m_node->getMemoryPool());
+	m_callbacks = newInstance<MyPhysicsTriggerProcessContactCallback>(SceneMemoryPool::getSingleton());
 	m_callbacks->m_comp = this;
 }
 
 TriggerComponent::~TriggerComponent()
 {
-	deleteInstance(m_node->getMemoryPool(), m_callbacks);
-	m_bodiesEnter.destroy(m_node->getMemoryPool());
-	m_bodiesInside.destroy(m_node->getMemoryPool());
-	m_bodiesExit.destroy(m_node->getMemoryPool());
+	deleteInstance(SceneMemoryPool::getSingleton(), m_callbacks);
 }
 
 void TriggerComponent::setSphereVolumeRadius(F32 radius)

+ 3 - 3
AnKi/Scene/Components/TriggerComponent.h

@@ -49,9 +49,9 @@ private:
 	SceneNode* m_node;
 	PhysicsCollisionShapePtr m_shape;
 	PhysicsTriggerPtr m_trigger;
-	DynamicArray<BodyComponent*> m_bodiesEnter;
-	DynamicArray<BodyComponent*> m_bodiesInside;
-	DynamicArray<BodyComponent*> m_bodiesExit;
+	SceneDynamicArray<BodyComponent*> m_bodiesEnter;
+	SceneDynamicArray<BodyComponent*> m_bodiesInside;
+	SceneDynamicArray<BodyComponent*> m_bodiesExit;
 	MyPhysicsTriggerProcessContactCallback* m_callbacks = nullptr;
 
 	Error update(SceneComponentUpdateInfo& info, Bool& updated);

+ 5 - 5
AnKi/Scene/Components/UiComponent.cpp

@@ -9,15 +9,15 @@
 
 namespace anki {
 
-Error UiComponent::updateReal(SceneComponentUpdateInfo& info, Bool& updated)
+UiComponent ::~UiComponent()
 {
-	updated = m_spatial.update(info.m_node->getSceneGraph().getOctree());
-	return Error::kNone;
+	m_spatial.removeFromOctree(SceneGraph::getSingleton().getOctree());
 }
 
-void UiComponent::onDestroy(SceneNode& node)
+Error UiComponent::updateReal([[maybe_unused]] SceneComponentUpdateInfo& info, Bool& updated)
 {
-	m_spatial.removeFromOctree(node.getSceneGraph().getOctree());
+	updated = m_spatial.update(SceneGraph::getSingleton().getOctree());
+	return Error::kNone;
 }
 
 } // end namespace anki

+ 2 - 2
AnKi/Scene/Components/UiComponent.h

@@ -28,6 +28,8 @@ public:
 		m_spatial.setUpdatesOctreeBounds(false);
 	}
 
+	~UiComponent();
+
 	void init(UiQueueElementDrawCallback callback, void* userData)
 	{
 		ANKI_ASSERT(callback != nullptr);
@@ -50,8 +52,6 @@ private:
 	Spatial m_spatial;
 
 	Error updateReal(SceneComponentUpdateInfo& info, Bool& updated);
-
-	void onDestroy(SceneNode& node);
 };
 /// @}
 

+ 14 - 24
AnKi/Scene/ContiguousArrayAllocator.cpp

@@ -10,19 +10,16 @@
 
 namespace anki {
 
-void AllGpuSceneContiguousArrays::ContiguousArrayAllocator::destroy(HeapMemoryPool* cpuPool)
+void AllGpuSceneContiguousArrays::ContiguousArrayAllocator::destroy()
 {
 	for(U32 i = 0; i < kMaxFramesInFlight; ++i)
 	{
-		collectGarbage(i, cpuPool);
+		collectGarbage(i);
 	}
 }
 
-AllGpuSceneContiguousArrays::Index
-AllGpuSceneContiguousArrays::ContiguousArrayAllocator::allocateObject(HeapMemoryPool* cpuPool)
+AllGpuSceneContiguousArrays::Index AllGpuSceneContiguousArrays::ContiguousArrayAllocator::allocateObject()
 {
-	ANKI_ASSERT(cpuPool);
-
 	LockGuard lock(m_mtx);
 
 	if(m_poolToken.m_offset == kMaxPtrSize)
@@ -32,7 +29,7 @@ AllGpuSceneContiguousArrays::ContiguousArrayAllocator::allocateObject(HeapMemory
 		GpuSceneMemoryPool::getSingleton().allocate(m_objectSize * m_initialArraySize, alignment, m_poolToken);
 		m_nextSlotIndex = 0;
 
-		m_freeSlotStack.create(*cpuPool, m_initialArraySize);
+		m_freeSlotStack.create(m_initialArraySize);
 		for(U32 i = 0; i < m_initialArraySize; ++i)
 		{
 			m_freeSlotStack[i] = i;
@@ -51,21 +48,16 @@ AllGpuSceneContiguousArrays::ContiguousArrayAllocator::allocateObject(HeapMemory
 	return idx;
 }
 
-void AllGpuSceneContiguousArrays::ContiguousArrayAllocator::deferredFree(U32 crntFrameIdx, HeapMemoryPool* cpuPool,
-																		 Index index)
+void AllGpuSceneContiguousArrays::ContiguousArrayAllocator::deferredFree(U32 crntFrameIdx, Index index)
 {
-	ANKI_ASSERT(cpuPool);
-
 	LockGuard lock(m_mtx);
 
 	ANKI_ASSERT(index < m_freeSlotStack.getSize());
-	m_garbage[crntFrameIdx].emplaceBack(*cpuPool, index);
+	m_garbage[crntFrameIdx].emplaceBack(index);
 }
 
-void AllGpuSceneContiguousArrays::ContiguousArrayAllocator::collectGarbage(U32 newFrameIdx, HeapMemoryPool* cpuPool)
+void AllGpuSceneContiguousArrays::ContiguousArrayAllocator::collectGarbage(U32 newFrameIdx)
 {
-	ANKI_ASSERT(cpuPool);
-
 	LockGuard lock(m_mtx);
 
 	if(m_garbage[newFrameIdx].getSize() == 0) [[likely]]
@@ -81,7 +73,7 @@ void AllGpuSceneContiguousArrays::ContiguousArrayAllocator::collectGarbage(U32 n
 		m_freeSlotStack[m_nextSlotIndex] = idx;
 	}
 
-	m_garbage[newFrameIdx].destroy(*cpuPool);
+	m_garbage[newFrameIdx].destroy();
 
 	// Sort so we can keep memory close to the beginning of the array for better cache behaviour
 	std::sort(m_freeSlotStack.getBegin() + m_nextSlotIndex, m_freeSlotStack.getEnd());
@@ -98,14 +90,12 @@ void AllGpuSceneContiguousArrays::ContiguousArrayAllocator::collectGarbage(U32 n
 	{
 		ANKI_ASSERT(m_nextSlotIndex == 0);
 		GpuSceneMemoryPool::getSingleton().deferredFree(m_poolToken);
-		m_freeSlotStack.destroy(*cpuPool);
+		m_freeSlotStack.destroy();
 	}
 }
 
-void AllGpuSceneContiguousArrays::init(SceneGraph* scene)
+void AllGpuSceneContiguousArrays::init()
 {
-	m_scene = scene;
-
 	const ConfigSet& cfg = ConfigSet::getSingleton();
 	constexpr F32 kGrowRate = 2.0;
 
@@ -133,19 +123,19 @@ void AllGpuSceneContiguousArrays::destroy()
 {
 	for(GpuSceneContiguousArrayType type : EnumIterable<GpuSceneContiguousArrayType>())
 	{
-		m_allocs[type].destroy(&m_scene->m_pool);
+		m_allocs[type].destroy();
 	}
 }
 
 AllGpuSceneContiguousArrays::Index AllGpuSceneContiguousArrays::allocate(GpuSceneContiguousArrayType type)
 {
-	const U32 idx = m_allocs[type].allocateObject(&m_scene->m_pool);
+	const U32 idx = m_allocs[type].allocateObject();
 	return idx;
 }
 
 void AllGpuSceneContiguousArrays::deferredFree(GpuSceneContiguousArrayType type, Index idx)
 {
-	m_allocs[type].deferredFree(m_frame, &m_scene->m_pool, idx);
+	m_allocs[type].deferredFree(m_frame, idx);
 }
 
 void AllGpuSceneContiguousArrays::endFrame()
@@ -154,7 +144,7 @@ void AllGpuSceneContiguousArrays::endFrame()
 
 	for(GpuSceneContiguousArrayType type : EnumIterable<GpuSceneContiguousArrayType>())
 	{
-		m_allocs[type].collectGarbage(m_frame, &m_scene->m_pool);
+		m_allocs[type].collectGarbage(m_frame);
 	}
 }
 

+ 7 - 9
AnKi/Scene/ContiguousArrayAllocator.h

@@ -36,7 +36,7 @@ class AllGpuSceneContiguousArrays
 public:
 	using Index = U32;
 
-	void init(SceneGraph* scene);
+	void init();
 
 	void destroy();
 
@@ -94,19 +94,19 @@ private:
 			m_initialArraySize = initialArraySize;
 		}
 
-		void destroy(HeapMemoryPool* cpuPool);
+		void destroy();
 
 		/// Allocate a new object and return its index in the array.
 		/// @note It's thread-safe against itself, deferredFree and endFrame.
-		Index allocateObject(HeapMemoryPool* cpuPool);
+		Index allocateObject();
 
 		/// Safely free an index allocated by allocateObject.
 		/// @note It's thread-safe against itself, allocateObject and endFrame.
-		void deferredFree(U32 crntFrameIdx, HeapMemoryPool* cpuPool, Index index);
+		void deferredFree(U32 crntFrameIdx, Index index);
 
 		/// Call this every frame.
 		/// @note It's thread-safe against itself, deferredFree and allocateObject.
-		void collectGarbage(U32 newFrameIdx, HeapMemoryPool* cpuPool);
+		void collectGarbage(U32 newFrameIdx);
 
 		PtrSize getArrayBase() const
 		{
@@ -122,9 +122,9 @@ private:
 	private:
 		SegregatedListsGpuMemoryPoolToken m_poolToken;
 
-		DynamicArray<Index> m_freeSlotStack;
+		SceneDynamicArray<Index> m_freeSlotStack;
 
-		Array<DynamicArray<Index>, kMaxFramesInFlight> m_garbage;
+		Array<SceneDynamicArray<Index>, kMaxFramesInFlight> m_garbage;
 
 		mutable SpinLock m_mtx;
 
@@ -135,8 +135,6 @@ private:
 		U32 m_nextSlotIndex = 0;
 	};
 
-	SceneGraph* m_scene = nullptr;
-
 	Array<ContiguousArrayAllocator, U32(GpuSceneContiguousArrayType::kCount)> m_allocs;
 
 	U8 m_frame = 0;

+ 1 - 6
AnKi/Scene/Events/AnimationEvent.cpp

@@ -10,11 +10,6 @@
 
 namespace anki {
 
-AnimationEvent::AnimationEvent(EventManager* manager)
-	: Event(manager)
-{
-}
-
 Error AnimationEvent::init(CString animationFilename, CString channelName, SceneNode* movableSceneNode)
 {
 	ANKI_ASSERT(movableSceneNode);
@@ -38,7 +33,7 @@ Error AnimationEvent::init(CString animationFilename, CString channelName, Scene
 
 	Event::init(m_anim->getStartingTime(), m_anim->getDuration());
 	m_reanimate = true;
-	m_associatedNodes.emplaceBack(getMemoryPool(), movableSceneNode);
+	m_associatedNodes.emplaceBack(movableSceneNode);
 
 	return Error::kNone;
 }

+ 0 - 2
AnKi/Scene/Events/AnimationEvent.h

@@ -17,8 +17,6 @@ namespace anki {
 class AnimationEvent : public Event
 {
 public:
-	AnimationEvent(EventManager* manager);
-
 	Error init(CString animationFilename, CString channel, SceneNode* movableSceneNode);
 
 	/// Implements Event::update

+ 2 - 32
AnKi/Scene/Events/Event.cpp

@@ -10,16 +10,6 @@
 
 namespace anki {
 
-Event::Event(EventManager* manager)
-	: m_manager(manager)
-{
-}
-
-Event::~Event()
-{
-	m_associatedNodes.destroy(getMemoryPool());
-}
-
 void Event::init(Second startTime, Second duration)
 {
 	m_startTime = startTime;
@@ -31,16 +21,6 @@ void Event::init(Second startTime, Second duration)
 	}
 }
 
-HeapMemoryPool& Event::getMemoryPool() const
-{
-	return m_manager->getSceneGraph().getMemoryPool();
-}
-
-void Event::setMarkedForDeletion()
-{
-	m_manager->markEventForDeletion(this);
-}
-
 Second Event::getDelta(Second crntTime) const
 {
 	const Second d = crntTime - m_startTime; // delta
@@ -48,19 +28,9 @@ Second Event::getDelta(Second crntTime) const
 	return dp;
 }
 
-SceneGraph& Event::getSceneGraph()
-{
-	return m_manager->getSceneGraph();
-}
-
-const SceneGraph& Event::getSceneGraph() const
-{
-	return m_manager->getSceneGraph();
-}
-
-SceneGraphExternalSubsystems& Event::getExternalSubsystems() const
+void Event::setMarkedForDeletion()
 {
-	return m_manager->getSceneGraph().m_subsystems;
+	SceneGraph::getSingleton().getEventManager().markEventForDeletion(this);
 }
 
 } // end namespace anki

+ 4 - 25
AnKi/Scene/Events/Event.h

@@ -20,26 +20,9 @@ class Event : public IntrusiveListEnabled<Event>
 	friend class EventManager;
 
 public:
-	/// Constructor
-	Event(EventManager* manager);
+	Event() = default;
 
-	virtual ~Event();
-
-	HeapMemoryPool& getMemoryPool() const;
-
-	EventManager& getEventManager()
-	{
-		return *m_manager;
-	}
-
-	const EventManager& getEventManager() const
-	{
-		return *m_manager;
-	}
-
-	SceneGraph& getSceneGraph();
-
-	const SceneGraph& getSceneGraph() const;
+	virtual ~Event() = default;
 
 	Second getStartTime() const
 	{
@@ -84,7 +67,7 @@ public:
 	void addAssociatedSceneNode(SceneNode* node)
 	{
 		ANKI_ASSERT(node);
-		m_associatedNodes.emplaceBack(getMemoryPool(), node);
+		m_associatedNodes.emplaceBack(node);
 	}
 
 	/// This method should be implemented by the derived classes
@@ -101,15 +84,13 @@ public:
 	}
 
 protected:
-	EventManager* m_manager = nullptr;
-
 	Second m_startTime = 0.0;
 	Second m_duration = 0.0;
 
 	Bool m_markedForDeletion = false;
 	Bool m_reanimate = false;
 
-	DynamicArray<SceneNode*> m_associatedNodes;
+	SceneDynamicArray<SceneNode*> m_associatedNodes;
 
 	/// @param startTime The time the event will start. If it's < 0 then start the event now.
 	/// @param duration The duration of the event.
@@ -118,8 +99,6 @@ protected:
 	/// Return the u between current time and when the event started
 	/// @return A number [0.0, 1.0]
 	Second getDelta(Second crntTime) const;
-
-	SceneGraphExternalSubsystems& getExternalSubsystems() const;
 };
 /// @}
 

+ 2 - 19
AnKi/Scene/Events/EventManager.cpp

@@ -24,23 +24,6 @@ EventManager::~EventManager()
 	deleteEventsMarkedForDeletion(false);
 }
 
-Error EventManager::init(SceneGraph* scene)
-{
-	ANKI_ASSERT(scene);
-	m_scene = scene;
-	return Error::kNone;
-}
-
-HeapMemoryPool& EventManager::getMemoryPool() const
-{
-	return m_scene->getMemoryPool();
-}
-
-StackMemoryPool& EventManager::getFrameMemoryPool() const
-{
-	return m_scene->getFrameMemoryPool();
-}
-
 Error EventManager::updateAllEvents(Second prevUpdateTime, Second crntTime)
 {
 	Error err = Error::kNone;
@@ -128,7 +111,7 @@ void EventManager::deleteEventsMarkedForDeletion(Bool fullCleanup)
 	if(fullCleanup)
 	{
 		// Gather in an array because we can't call setMarkedForDeletion while iterating m_events
-		DynamicArrayRaii<Event*> markedForDeletion(&getFrameMemoryPool());
+		DynamicArrayRaii<Event*> markedForDeletion(&SceneGraph::getSingleton().getFrameMemoryPool());
 		for(Event& event : m_events)
 		{
 			for(SceneNode* node : event.m_associatedNodes)
@@ -153,7 +136,7 @@ void EventManager::deleteEventsMarkedForDeletion(Bool fullCleanup)
 		Event* event = &m_eventsMarkedForDeletion.getFront();
 		m_eventsMarkedForDeletion.popFront();
 
-		deleteInstance(getMemoryPool(), event);
+		deleteInstance(SceneMemoryPool::getSingleton(), event);
 	}
 }
 

+ 2 - 19
AnKi/Scene/Events/EventManager.h

@@ -21,31 +21,16 @@ public:
 	EventManager();
 	~EventManager();
 
-	Error init(SceneGraph* scene);
-
-	SceneGraph& getSceneGraph()
-	{
-		return *m_scene;
-	}
-
-	const SceneGraph& getSceneGraph() const
-	{
-		return *m_scene;
-	}
-
-	HeapMemoryPool& getMemoryPool() const;
-	StackMemoryPool& getFrameMemoryPool() const;
-
 	/// Create a new event
 	/// @note It's thread-safe against itself.
 	template<typename T, typename... Args>
 	Error newEvent(T*& event, Args... args)
 	{
-		event = newInstance<T>(getMemoryPool(), this);
+		event = newInstance<T>(SceneMemoryPool::getSingleton());
 		Error err = event->init(std::forward<Args>(args)...);
 		if(err)
 		{
-			deleteInstance(getMemoryPool(), event);
+			deleteInstance(SceneMemoryPool::getSingleton(), event);
 		}
 		else
 		{
@@ -65,8 +50,6 @@ public:
 	void markEventForDeletion(Event* event);
 
 private:
-	SceneGraph* m_scene = nullptr;
-
 	IntrusiveList<Event> m_events;
 	IntrusiveList<Event> m_eventsMarkedForDeletion;
 	Mutex m_mtx;

+ 1 - 1
AnKi/Scene/Events/JitterMoveEvent.cpp

@@ -13,7 +13,7 @@ Error JitterMoveEvent::init(Second startTime, Second duration, SceneNode* node)
 {
 	ANKI_ASSERT(node);
 	Event::init(startTime, duration);
-	m_associatedNodes.emplaceBack(getMemoryPool(), node);
+	m_associatedNodes.emplaceBack(node);
 	m_originalPos = node->getWorldTransform().getOrigin();
 
 	return Error::kNone;

+ 0 - 6
AnKi/Scene/Events/JitterMoveEvent.h

@@ -17,12 +17,6 @@ namespace anki {
 class JitterMoveEvent : public Event
 {
 public:
-	/// Constructor
-	JitterMoveEvent(EventManager* manager)
-		: Event(manager)
-	{
-	}
-
 	Error init(Second startTime, Second duration, SceneNode* movableSceneNode);
 
 	/// Implements Event::update

+ 1 - 1
AnKi/Scene/Events/LightEvent.cpp

@@ -12,7 +12,7 @@ namespace anki {
 Error LightEvent::init(Second startTime, Second duration, SceneNode* light)
 {
 	Event::init(startTime, duration);
-	m_associatedNodes.emplaceBack(getMemoryPool(), light);
+	m_associatedNodes.emplaceBack(light);
 
 	LightComponent& lightc = light->getFirstComponentOfType<LightComponent>();
 

+ 0 - 6
AnKi/Scene/Events/LightEvent.h

@@ -17,12 +17,6 @@ namespace anki {
 class LightEvent : public Event
 {
 public:
-	/// Create
-	LightEvent(EventManager* manager)
-		: Event(manager)
-	{
-	}
-
 	Error init(Second startTime, Second duration, SceneNode* light);
 
 	/// Implements Event::update

+ 3 - 8
AnKi/Scene/Events/ScriptEvent.cpp

@@ -13,25 +13,20 @@
 
 namespace anki {
 
-ScriptEvent::ScriptEvent(EventManager* manager)
-	: Event(manager)
+ScriptEvent::ScriptEvent()
 {
 }
 
 ScriptEvent::~ScriptEvent()
 {
-	m_script.destroy(getMemoryPool());
 }
 
 Error ScriptEvent::init(Second startTime, Second duration, CString script)
 {
 	Event::init(startTime, duration);
 
-	// Create the env
-	ANKI_CHECK(m_env.init(getExternalSubsystems().m_scriptManager));
-
 	// Do the rest
-	StringRaii extension(&getMemoryPool());
+	StringRaii extension(&SceneMemoryPool::getSingleton());
 	getFilepathExtension(script, extension);
 
 	if(!extension.isEmpty() && extension == "lua")
@@ -45,7 +40,7 @@ Error ScriptEvent::init(Second startTime, Second duration, CString script)
 	else
 	{
 		// It's a string
-		m_script.create(getMemoryPool(), script);
+		m_script = script;
 
 		// Exec the script
 		ANKI_CHECK(m_env.evalString(m_script.toCString()));

+ 2 - 2
AnKi/Scene/Events/ScriptEvent.h

@@ -29,7 +29,7 @@ namespace anki {
 class ScriptEvent : public Event
 {
 public:
-	ScriptEvent(EventManager* manager);
+	ScriptEvent();
 
 	~ScriptEvent();
 
@@ -42,7 +42,7 @@ public:
 
 private:
 	ScriptResourcePtr m_scriptRsrc;
-	String m_script;
+	SceneString m_script;
 	ScriptEnvironment m_env;
 };
 /// @}

+ 3 - 6
AnKi/Scene/Frustum.cpp

@@ -19,7 +19,7 @@ Array<Mat3x4, 6> Frustum::m_omnidirectionalRotations = {
 Frustum::Frustum()
 {
 	// Set some default values
-	init(FrustumType::kPerspective, nullptr);
+	init(FrustumType::kPerspective);
 	for(U i = 0; i < m_maxLodDistances.getSize(); ++i)
 	{
 		const F32 dist = (m_common.m_far - m_common.m_near) / F32(kMaxLodCount + 1);
@@ -31,13 +31,11 @@ Frustum::Frustum()
 
 Frustum::~Frustum()
 {
-	m_depthMap.destroy(*m_pool);
 }
 
-void Frustum::init(FrustumType type, HeapMemoryPool* pool)
+void Frustum::init(FrustumType type)
 {
 	ANKI_ASSERT(type < FrustumType::kCount);
-	m_pool = pool;
 	m_frustumType = type;
 	setNear(kDefaultNear);
 	setFar(kDefaultFar);
@@ -203,13 +201,12 @@ Bool Frustum::update()
 
 void Frustum::setCoverageBuffer(F32* depths, U32 width, U32 height)
 {
-	ANKI_ASSERT(m_pool);
 	ANKI_ASSERT(depths && width > 0 && height > 0);
 
 	const U32 elemCount = width * height;
 	if(m_depthMap.getSize() != elemCount) [[unlikely]]
 	{
-		m_depthMap.resize(*m_pool, elemCount);
+		m_depthMap.resize(elemCount);
 	}
 
 	if(depths && elemCount > 0) [[likely]]

+ 2 - 4
AnKi/Scene/Frustum.h

@@ -23,7 +23,7 @@ public:
 
 	~Frustum();
 
-	void init(FrustumType type, HeapMemoryPool* pool);
+	void init(FrustumType type);
 
 	void setPerspective(F32 near, F32 far, F32 fovX, F32 fovY)
 	{
@@ -356,8 +356,6 @@ private:
 	static constexpr F32 kDefaultFar = 100.0f;
 	static constexpr F32 kDefaultFovAngle = toRad(45.0f);
 
-	HeapMemoryPool* m_pool = nullptr;
-
 	union
 	{
 		Perspective m_perspective;
@@ -386,7 +384,7 @@ private:
 	F32 m_earlyZDistance = 0.0f;
 
 	// Coverage buffer stuff
-	DynamicArray<F32> m_depthMap;
+	SceneDynamicArray<F32> m_depthMap;
 	U32 m_depthMapWidth = 0;
 	U32 m_depthMapHeight = 0;
 

+ 7 - 11
AnKi/Scene/Octree.h

@@ -40,10 +40,7 @@ class Octree
 	friend class OctreePlaceable;
 
 public:
-	Octree(HeapMemoryPool* pool)
-		: m_pool(pool)
-	{
-	}
+	Octree() = default;
 
 	Octree(const Octree&) = delete; // Non-copyable
 
@@ -198,7 +195,6 @@ private:
 	};
 	ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS_FRIEND(LeafMask)
 
-	HeapMemoryPool* m_pool;
 	U32 m_maxDepth = 0;
 	Vec3 m_sceneAabbMin = Vec3(0.0f);
 	Vec3 m_sceneAabbMax = Vec3(0.0f);
@@ -217,38 +213,38 @@ private:
 
 	Leaf* newLeaf()
 	{
-		return m_leafAlloc.newInstance(*m_pool);
+		return m_leafAlloc.newInstance(SceneMemoryPool::getSingleton());
 	}
 
 	void releaseLeaf(Leaf* leaf)
 	{
-		m_leafAlloc.deleteInstance(*m_pool, leaf);
+		m_leafAlloc.deleteInstance(SceneMemoryPool::getSingleton(), leaf);
 	}
 
 	PlaceableNode* newPlaceableNode(OctreePlaceable* placeable)
 	{
 		ANKI_ASSERT(placeable);
-		PlaceableNode* out = m_placeableNodeAlloc.newInstance(*m_pool);
+		PlaceableNode* out = m_placeableNodeAlloc.newInstance(SceneMemoryPool::getSingleton());
 		out->m_placeable = placeable;
 		return out;
 	}
 
 	void releasePlaceableNode(PlaceableNode* placeable)
 	{
-		m_placeableNodeAlloc.deleteInstance(*m_pool, placeable);
+		m_placeableNodeAlloc.deleteInstance(SceneMemoryPool::getSingleton(), placeable);
 	}
 
 	LeafNode* newLeafNode(Leaf* leaf)
 	{
 		ANKI_ASSERT(leaf);
-		LeafNode* out = m_leafNodeAlloc.newInstance(*m_pool);
+		LeafNode* out = m_leafNodeAlloc.newInstance(SceneMemoryPool::getSingleton());
 		out->m_leaf = leaf;
 		return out;
 	}
 
 	void releaseLeafNode(LeafNode* node)
 	{
-		m_leafNodeAlloc.deleteInstance(*m_pool, node);
+		m_leafNodeAlloc.deleteInstance(SceneMemoryPool::getSingleton(), node);
 	}
 
 	void placeRecursive(const Aabb& volume, OctreePlaceable* placeable, Leaf* parent, U32 depth);

+ 13 - 17
AnKi/Scene/SceneGraph.cpp

@@ -45,22 +45,21 @@ SceneGraph::~SceneGraph()
 
 	if(m_octree)
 	{
-		deleteInstance(m_pool, m_octree);
+		deleteInstance(SceneMemoryPool::getSingleton(), m_octree);
 	}
 
 	m_gpuSceneAllocators.destroy();
+
+	SceneMemoryPool::freeSingleton();
 }
 
-Error SceneGraph::init(const SceneGraphInitInfo& initInfo)
+Error SceneGraph::init(AllocAlignedCallback allocCallback, void* allocCallbackData)
 {
-	m_subsystems = initInfo;
-
-	m_pool.init(initInfo.m_allocCallback, initInfo.m_allocCallbackData);
-	m_framePool.init(initInfo.m_allocCallback, initInfo.m_allocCallbackData, 1 * 1024 * 1024);
+	SceneMemoryPool::allocateSingleton(allocCallback, allocCallbackData);
 
-	ANKI_CHECK(m_events.init(this));
+	m_framePool.init(allocCallback, allocCallbackData, 1 * 1024 * 1024);
 
-	m_octree = newInstance<Octree>(m_pool, &m_pool);
+	m_octree = newInstance<Octree>(SceneMemoryPool::getSingleton());
 	m_octree->init(m_sceneMin, m_sceneMax, ConfigSet::getSingleton().getSceneOctreeMaxDepth());
 
 	// Init the default main camera
@@ -69,7 +68,7 @@ Error SceneGraph::init(const SceneGraphInitInfo& initInfo)
 	camc->setPerspective(0.1f, 1000.0f, toRad(60.0f), (1080.0f / 1920.0f) * toRad(60.0f));
 	m_mainCam = m_defaultMainCam;
 
-	m_gpuSceneAllocators.init(this);
+	m_gpuSceneAllocators.init();
 
 	return Error::kNone;
 }
@@ -87,7 +86,7 @@ Error SceneGraph::registerNode(SceneNode* node)
 			return Error::kUserData;
 		}
 
-		m_nodesDict.emplace(m_pool, node->getName(), node);
+		m_nodesDict.emplace(node->getName(), node);
 	}
 
 	// Add to vector
@@ -113,7 +112,7 @@ void SceneGraph::unregisterNode(SceneNode* node)
 	{
 		auto it = m_nodesDict.find(node->getName());
 		ANKI_ASSERT(it != m_nodesDict.getEnd());
-		m_nodesDict.erase(m_pool, it);
+		m_nodesDict.erase(it);
 	}
 }
 
@@ -147,7 +146,7 @@ void SceneGraph::deleteNodesMarkedForDeletion()
 			{
 				// Delete node
 				unregisterNode(&node);
-				deleteInstance(m_pool, &node);
+				deleteInstance(SceneMemoryPool::getSingleton(), &node);
 				m_objectsMarkedForDeletionCount.fetchSub(1);
 				found = true;
 				break;
@@ -167,9 +166,6 @@ Error SceneGraph::update(Second prevUpdateTime, Second crntTime)
 
 	m_stats.m_updateTime = HighRezTimer::getCurrentTime();
 
-	m_timestamp = *m_subsystems.m_globalTimestamp;
-	ANKI_ASSERT(m_timestamp > 0);
-
 	// Reset the framepool
 	m_framePool.reset();
 
@@ -252,7 +248,7 @@ Error SceneGraph::updateNode(Second prevTime, Second crntTime, SceneNode& node)
 		if(updated)
 		{
 			ANKI_TRACE_INC_COUNTER(SceneComponentUpdated, 1);
-			comp.setTimestamp(node.getSceneGraph().m_timestamp);
+			comp.setTimestamp(GlobalFrameIndex::getSingleton().m_value);
 			atLeastOneComponentUpdated = true;
 		}
 	});
@@ -270,7 +266,7 @@ Error SceneGraph::updateNode(Second prevTime, Second crntTime, SceneNode& node)
 	{
 		if(atLeastOneComponentUpdated)
 		{
-			node.setComponentMaxTimestamp(node.getSceneGraph().m_timestamp);
+			node.setComponentMaxTimestamp(GlobalFrameIndex::getSingleton().m_value);
 		}
 		else
 		{

+ 13 - 32
AnKi/Scene/SceneGraph.h

@@ -31,37 +31,19 @@ public:
 	Second m_physicsUpdate ANKI_DEBUG_CODE(= 0.0);
 };
 
-class SceneGraphInitInfo : public SceneGraphExternalSubsystems
-{
-public:
-	AllocAlignedCallback m_allocCallback = nullptr;
-	void* m_allocCallbackData = nullptr;
-};
-
 /// The scene graph that  all the scene entities
-class SceneGraph
+class SceneGraph : public MakeSingleton<SceneGraph>
 {
+	template<typename>
+	friend class MakeSingleton;
+
 	friend class SceneNode;
 	friend class UpdateSceneNodesTask;
 	friend class Event;
 	friend class AllGpuSceneContiguousArrays;
 
 public:
-	SceneGraph();
-
-	~SceneGraph();
-
-	Error init(const SceneGraphInitInfo& initInfo);
-
-	Timestamp getGlobalTimestamp() const
-	{
-		return m_timestamp;
-	}
-
-	HeapMemoryPool& getMemoryPool() const
-	{
-		return m_pool;
-	}
+	Error init(AllocAlignedCallback allocCallback, void* allocCallbackData);
 
 	StackMemoryPool& getFrameMemoryPool() const
 	{
@@ -80,7 +62,7 @@ public:
 	void setActiveCameraNode(SceneNode* cam)
 	{
 		m_mainCam = cam;
-		m_activeCameraChangeTimestamp = getGlobalTimestamp();
+		m_activeCameraChangeTimestamp = GlobalFrameIndex::getSingleton().m_value;
 	}
 	Timestamp getActiveCameraNodeChangeTimestamp() const
 	{
@@ -179,16 +161,11 @@ public:
 private:
 	class UpdateSceneNodesCtx;
 
-	Timestamp m_timestamp = 0; ///< Cached timestamp
-
-	SceneGraphExternalSubsystems m_subsystems;
-
-	mutable HeapMemoryPool m_pool;
 	mutable StackMemoryPool m_framePool;
 
 	IntrusiveList<SceneNode> m_nodes;
 	U32 m_nodesCount = 0;
-	HashMap<CString, SceneNode*> m_nodesDict;
+	GrHashMap<CString, SceneNode*> m_nodesDict;
 
 	SceneNode* m_mainCam = nullptr;
 	Timestamp m_activeCameraChangeTimestamp = 0;
@@ -209,6 +186,10 @@ private:
 
 	AllGpuSceneContiguousArrays m_gpuSceneAllocators;
 
+	SceneGraph();
+
+	~SceneGraph();
+
 	/// Put a node in the appropriate containers
 	Error registerNode(SceneNode* node);
 	void unregisterNode(SceneNode* node);
@@ -228,7 +209,7 @@ inline Error SceneGraph::newSceneNode(const CString& name, Node*& node, Args&&..
 {
 	Error err = Error::kNone;
 
-	node = newInstance<Node>(m_pool, this, name);
+	node = newInstance<Node>(SceneMemoryPool::getSingleton(), name);
 	if(node)
 	{
 		err = node->init(std::forward<Args>(args)...);
@@ -249,7 +230,7 @@ inline Error SceneGraph::newSceneNode(const CString& name, Node*& node, Args&&..
 
 		if(node)
 		{
-			deleteInstance(m_pool, node);
+			deleteInstance(SceneMemoryPool::getSingleton(), node);
 			node = nullptr;
 		}
 	}

+ 7 - 34
AnKi/Scene/SceneNode.cpp

@@ -10,13 +10,12 @@
 
 namespace anki {
 
-SceneNode::SceneNode(SceneGraph* scene, CString name)
-	: m_scene(scene)
-	, m_uuid(scene->getNewUuid())
+SceneNode::SceneNode(CString name)
+	: m_uuid(SceneGraph::getSingleton().getNewUuid())
 {
 	if(name)
 	{
-		m_name.create(getMemoryPool(), name);
+		m_name = name;
 	}
 
 	// Add the implicit MoveComponent
@@ -25,19 +24,15 @@ SceneNode::SceneNode(SceneGraph* scene, CString name)
 
 SceneNode::~SceneNode()
 {
-	HeapMemoryPool& pool = getMemoryPool();
-
 	for(SceneComponent* comp : m_components)
 	{
 		comp->onDestroyReal(*this);
 		g_sceneComponentCallbacks.m_destructor[comp->getClassId()](*comp);
 
-		pool.free(comp);
+		SceneMemoryPool::getSingleton().free(comp);
 	}
 
-	Base::destroy(pool);
-	m_name.destroy(pool);
-	m_components.destroy(pool);
+	Base::destroy(SceneMemoryPool::getSingleton());
 }
 
 void SceneNode::setMarkedForDeletion()
@@ -46,7 +41,7 @@ void SceneNode::setMarkedForDeletion()
 	if(!getMarkedForDeletion())
 	{
 		m_markedForDeletion = true;
-		m_scene->increaseObjectsMarkedForDeletion();
+		SceneGraph::getSingleton().increaseObjectsMarkedForDeletion();
 	}
 
 	[[maybe_unused]] const Error err = visitChildren([](SceneNode& obj) -> Error {
@@ -55,28 +50,6 @@ void SceneNode::setMarkedForDeletion()
 	});
 }
 
-Timestamp SceneNode::getGlobalTimestamp() const
-{
-	return m_scene->getGlobalTimestamp();
-}
-
-HeapMemoryPool& SceneNode::getMemoryPool() const
-{
-	ANKI_ASSERT(m_scene);
-	return m_scene->getMemoryPool();
-}
-
-StackMemoryPool& SceneNode::getFrameMemoryPool() const
-{
-	ANKI_ASSERT(m_scene);
-	return m_scene->getFrameMemoryPool();
-}
-
-SceneGraphExternalSubsystems& SceneNode::getExternalSubsystems() const
-{
-	return m_scene->m_subsystems;
-}
-
 void SceneNode::newComponentInternal(SceneComponent* newc)
 {
 	m_componentTypeMask |= 1 << newc->getClassId();
@@ -93,7 +66,7 @@ void SceneNode::newComponentInternal(SceneComponent* newc)
 		newc->onOtherComponentRemovedOrAddedReal(other, true);
 	}
 
-	m_components.emplaceBack(getMemoryPool(), newc);
+	m_components.emplaceBack(newc);
 
 	// Sort based on update weight
 	std::sort(m_components.getBegin(), m_components.getEnd(), [](const SceneComponent* a, const SceneComponent* b) {

+ 5 - 25
AnKi/Scene/SceneNode.h

@@ -31,7 +31,7 @@ public:
 	/// The one and only constructor.
 	/// @param scene The owner scene.
 	/// @param name The unique name of the node. If it's empty the the node is not searchable.
-	SceneNode(SceneGraph* scene, CString name);
+	SceneNode(CString name);
 
 	/// Unregister node
 	virtual ~SceneNode();
@@ -42,16 +42,6 @@ public:
 		return Error::kNone;
 	}
 
-	SceneGraph& getSceneGraph()
-	{
-		return *m_scene;
-	}
-
-	const SceneGraph& getSceneGraph() const
-	{
-		return *m_scene;
-	}
-
 	/// Return the name. It may be empty for nodes that we don't want to track.
 	CString getName() const
 	{
@@ -70,8 +60,6 @@ public:
 
 	void setMarkedForDeletion();
 
-	Timestamp getGlobalTimestamp() const;
-
 	Timestamp getComponentMaxTimestamp() const
 	{
 		return m_maxComponentTimestamp;
@@ -83,13 +71,9 @@ public:
 		m_maxComponentTimestamp = maxComponentTimestamp;
 	}
 
-	HeapMemoryPool& getMemoryPool() const;
-
-	StackMemoryPool& getFrameMemoryPool() const;
-
 	void addChild(SceneNode* obj)
 	{
-		Base::addChild(getMemoryPool(), obj);
+		Base::addChild(SceneMemoryPool::getSingleton(), obj);
 	}
 
 	/// This is called by the scenegraph every frame after all component updates. By default it does nothing.
@@ -388,20 +372,16 @@ public:
 	template<typename TComponent>
 	TComponent* newComponent()
 	{
-		TComponent* comp = newInstance<TComponent>(getMemoryPool(), this);
+		TComponent* comp = newInstance<TComponent>(SceneMemoryPool::getSingleton(), this);
 		newComponentInternal(comp);
 		return comp;
 	}
 
-protected:
-	SceneGraphExternalSubsystems& getExternalSubsystems() const;
-
 private:
-	SceneGraph* m_scene = nullptr;
 	U64 m_uuid;
-	String m_name; ///< A unique name.
+	SceneString m_name; ///< A unique name.
 
-	DynamicArray<SceneComponent*> m_components;
+	GrDynamicArray<SceneComponent*> m_components;
 
 	U32 m_componentTypeMask = 0;
 

+ 2 - 2
AnKi/Scene/SoftwareRasterizer.cpp

@@ -26,8 +26,8 @@ void SoftwareRasterizer::prepare(const Mat4& mv, const Mat4& p, U32 width, U32 h
 	U32 size = width * height;
 	if(m_zbuffer.getSize() < size)
 	{
-		m_zbuffer.destroy(*m_pool);
-		m_zbuffer.create(*m_pool, size);
+		m_zbuffer.destroy();
+		m_zbuffer.create(size);
 	}
 	memset(&m_zbuffer[0], 0xFF, sizeof(m_zbuffer[0]) * size);
 }

+ 1 - 18
AnKi/Scene/SoftwareRasterizer.h

@@ -19,22 +19,6 @@ namespace anki {
 class SoftwareRasterizer
 {
 public:
-	SoftwareRasterizer()
-	{
-	}
-
-	~SoftwareRasterizer()
-	{
-		m_zbuffer.destroy(*m_pool);
-	}
-
-	/// Initialize.
-	void init(BaseMemoryPool* pool)
-	{
-		ANKI_ASSERT(pool);
-		m_pool = pool;
-	}
-
 	/// Prepare for rendering. Call it before every draw.
 	void prepare(const Mat4& mv, const Mat4& p, U32 width, U32 height);
 
@@ -55,7 +39,6 @@ public:
 	Bool visibilityTest(const Aabb& aabb) const;
 
 private:
-	BaseMemoryPool* m_pool = nullptr;
 	Mat4 m_mv; ///< ModelView.
 	Mat4 m_p; ///< Projection.
 	Mat4 m_mvp;
@@ -63,7 +46,7 @@ private:
 	Array<Plane, 6> m_planesW; ///< In world space.
 	U32 m_width;
 	U32 m_height;
-	DynamicArray<Atomic<U32>> m_zbuffer;
+	SceneDynamicArray<Atomic<U32>> m_zbuffer;
 
 	/// @param tri In clip space.
 	void rasterizeTriangle(const Vec4* tri);

+ 1 - 2
AnKi/Scene/Visibility.cpp

@@ -199,7 +199,6 @@ void FillRasterizerWithCoverageTask::fill()
 	if(true)
 	{
 		m_frcCtx->m_r = newInstance<SoftwareRasterizer>(pool);
-		m_frcCtx->m_r->init(&pool);
 		m_frcCtx->m_r->prepare(
 			Mat4(m_frcCtx->m_frustum.m_frustum->getPreviousViewMatrix(1), Vec4(0.0f, 0.0f, 0.0f, 1.0f)),
 			m_frcCtx->m_frustum.m_frustum->getPreviousProjectionMatrix(1), width, height);
@@ -643,7 +642,7 @@ void VisibilityTestTask::test(ThreadHive& hive, U32 taskId)
 
 	if(testedFrustum.getUpdatedThisFrame())
 	{
-		m_frcCtx->m_queueViews[taskId].m_timestamp = m_frcCtx->m_visCtx->m_scene->getGlobalTimestamp();
+		m_frcCtx->m_queueViews[taskId].m_timestamp = GlobalFrameIndex::getSingleton().m_value;
 	}
 	else
 	{

+ 17 - 1
AnKi/Script/Common.h

@@ -5,7 +5,7 @@
 
 #pragma once
 
-#include <AnKi/Util/Ptr.h>
+#include <AnKi/Util/MemoryPool.h>
 
 namespace anki {
 
@@ -19,4 +19,20 @@ class ScriptEnvironment;
 #define ANKI_SCRIPT_LOGW(...) ANKI_LOG("SCRI", kWarning, __VA_ARGS__)
 #define ANKI_SCRIPT_LOGF(...) ANKI_LOG("SCRI", kFatal, __VA_ARGS__)
 
+class ScriptMemoryPool : public HeapMemoryPool, public MakeSingleton<ScriptMemoryPool>
+{
+	template<typename>
+	friend class MakeSingleton;
+
+private:
+	ScriptMemoryPool(AllocAlignedCallback allocCb, void* allocCbUserData)
+		: HeapMemoryPool(allocCb, allocCbUserData, "ScriptMemPool")
+	{
+	}
+
+	~ScriptMemoryPool() = default;
+};
+
+ANKI_DEFINE_SUBMODULE_UTIL_CONTAINERS(Script, ScriptMemoryPool)
+
 } // end namespace anki

+ 11 - 43
AnKi/Script/LuaBinder.cpp

@@ -35,6 +35,11 @@ static int luaPanic(lua_State* l)
 
 LuaBinder::LuaBinder()
 {
+	m_l = lua_newstate(luaAllocCallback, this);
+	luaL_openlibs(m_l);
+	lua_atpanic(m_l, &luaPanic);
+
+	wrapModules(m_l);
 }
 
 LuaBinder::~LuaBinder()
@@ -43,37 +48,20 @@ LuaBinder::~LuaBinder()
 	{
 		lua_close(m_l);
 	}
-	m_userDataSigToDataInfo.destroy(*m_pool);
-}
-
-Error LuaBinder::init(HeapMemoryPool* pool, LuaBinderOtherSystems* otherSystems)
-{
-	ANKI_ASSERT(otherSystems && pool);
-	m_otherSystems = otherSystems;
-	m_pool = pool;
-
-	m_l = lua_newstate(luaAllocCallback, this);
-	luaL_openlibs(m_l);
-	lua_atpanic(m_l, &luaPanic);
-
-	wrapModules(m_l);
-
-	return Error::kNone;
 }
 
-void* LuaBinder::luaAllocCallback(void* userData, void* ptr, PtrSize osize, PtrSize nsize)
+void* LuaBinder::luaAllocCallback([[maybe_unused]] void* userData, void* ptr, PtrSize osize, PtrSize nsize)
 {
 	ANKI_ASSERT(userData);
 
 #if 1
-	LuaBinder& binder = *reinterpret_cast<LuaBinder*>(userData);
 	void* out = nullptr;
 
 	if(nsize == 0)
 	{
 		if(ptr != nullptr)
 		{
-			binder.m_pool->free(ptr);
+			ScriptMemoryPool::getSingleton().free(ptr);
 		}
 	}
 	else
@@ -82,7 +70,7 @@ void* LuaBinder::luaAllocCallback(void* userData, void* ptr, PtrSize osize, PtrS
 
 		if(ptr == nullptr)
 		{
-			out = binder.m_pool->allocate(nsize, 16);
+			out = ScriptMemoryPool::getSingleton().allocate(nsize, 16);
 		}
 		else if(nsize <= osize)
 		{
@@ -92,9 +80,9 @@ void* LuaBinder::luaAllocCallback(void* userData, void* ptr, PtrSize osize, PtrS
 		{
 			// realloc
 
-			out = binder.m_pool->allocate(nsize, 16);
+			out = ScriptMemoryPool::getSingleton().allocate(nsize, 16);
 			memcpy(out, ptr, osize);
-			binder.m_pool->free(ptr);
+			ScriptMemoryPool::getSingleton().free(ptr);
 		}
 	}
 #else
@@ -146,7 +134,7 @@ void LuaBinder::createClass(lua_State* l, const LuaUserDataTypeInfo* typeInfo)
 	lua_getallocf(l, &ud);
 	ANKI_ASSERT(ud);
 	LuaBinder& binder = *static_cast<LuaBinder*>(ud);
-	binder.m_userDataSigToDataInfo.emplace(*binder.m_pool, typeInfo->m_signature, typeInfo);
+	binder.m_userDataSigToDataInfo.emplace(typeInfo->m_signature, typeInfo);
 }
 
 void LuaBinder::pushLuaCFuncMethod(lua_State* l, const char* name, lua_CFunction luafunc)
@@ -253,26 +241,6 @@ Error LuaBinder::checkArgsCount(lua_State* l, I argsCount)
 	return Error::kNone;
 }
 
-void* LuaBinder::luaAlloc(lua_State* l, size_t size, U32 alignment)
-{
-	void* ud;
-	lua_getallocf(l, &ud);
-	ANKI_ASSERT(ud);
-	LuaBinder* binder = static_cast<LuaBinder*>(ud);
-
-	return binder->m_pool->allocate(size, alignment);
-}
-
-void LuaBinder::luaFree(lua_State* l, void* ptr)
-{
-	void* ud;
-	lua_getallocf(l, &ud);
-	ANKI_ASSERT(ud);
-	LuaBinder* binder = static_cast<LuaBinder*>(ud);
-
-	binder->m_pool->free(ptr);
-}
-
 void LuaBinder::serializeGlobals(lua_State* l, LuaBinderSerializeGlobalsCallback& callback)
 {
 	ANKI_ASSERT(l);

+ 1 - 31
AnKi/Script/LuaBinder.h

@@ -137,15 +137,6 @@ public:
 	virtual void write(const void* data, PtrSize dataSize) = 0;
 };
 
-/// A list of systems that the LuaBinder should be aware of.
-/// @memberof LuaBinder
-class LuaBinderOtherSystems
-{
-public:
-	SceneGraph* m_sceneGraph;
-	MainRenderer* m_renderer;
-};
-
 /// Lua binder class. A wrapper on top of LUA
 class LuaBinder
 {
@@ -158,25 +149,12 @@ public:
 
 	LuaBinder& operator=(const LuaBinder&) = delete; // Non-copyable
 
-	Error init(HeapMemoryPool* pool, LuaBinderOtherSystems* otherSystems);
-
 	lua_State* getLuaState()
 	{
 		ANKI_ASSERT(m_l);
 		return m_l;
 	}
 
-	HeapMemoryPool& getMemoryPool() const
-	{
-		return *m_pool;
-	}
-
-	LuaBinderOtherSystems& getOtherSystems()
-	{
-		ANKI_ASSERT(m_otherSystems);
-		return *m_otherSystems;
-	}
-
 	/// Expose a variable to the lua state
 	template<typename T>
 	static void exposeVariable(lua_State* state, CString name, T* y)
@@ -250,17 +228,9 @@ public:
 	/// typeName. That is supposed to be faster.
 	static Error checkUserData(lua_State* l, I32 stackIdx, const LuaUserDataTypeInfo& typeInfo, LuaUserData*& out);
 
-	/// Allocate memory.
-	static void* luaAlloc(lua_State* l, size_t size, U32 alignment);
-
-	/// Free memory.
-	static void luaFree(lua_State* l, void* ptr);
-
 private:
-	LuaBinderOtherSystems* m_otherSystems;
-	HeapMemoryPool* m_pool = nullptr;
 	lua_State* m_l = nullptr;
-	HashMap<I64, const LuaUserDataTypeInfo*> m_userDataSigToDataInfo;
+	ScriptHashMap<I64, const LuaUserDataTypeInfo*> m_userDataSigToDataInfo;
 
 	static void* luaAllocCallback(void* userData, void* ptr, PtrSize osize, PtrSize nsize);
 

+ 1 - 1
AnKi/Script/Renderer.cpp

@@ -16,7 +16,7 @@ static MainRenderer* getMainRenderer(lua_State* l)
 	LuaBinder* binder = nullptr;
 	lua_getallocf(l, reinterpret_cast<void**>(&binder));
 
-	MainRenderer* r = binder->getOtherSystems().m_renderer;
+	MainRenderer* r = nullptr; // TODO glob: fix it
 	ANKI_ASSERT(r);
 	return r;
 }

+ 1 - 3
AnKi/Script/Scene.cpp

@@ -48,9 +48,7 @@ static SceneGraph* getSceneGraph(lua_State* l)
 	LuaBinder* binder = nullptr;
 	lua_getallocf(l, reinterpret_cast<void**>(&binder));
 
-	SceneGraph* scene = binder->getOtherSystems().m_sceneGraph;
-	ANKI_ASSERT(scene);
-	return scene;
+	return &SceneGraph::getSingleton();
 }
 
 static EventManager* getEventManager(lua_State* l)

+ 0 - 19
AnKi/Script/ScriptEnvironment.cpp

@@ -1,19 +0,0 @@
-// Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <AnKi/Script/ScriptEnvironment.h>
-#include <AnKi/Script/ScriptManager.h>
-
-namespace anki {
-
-Error ScriptEnvironment::init(ScriptManager* manager)
-{
-	ANKI_ASSERT(!isInitialized());
-	ANKI_ASSERT(manager);
-	m_manager = manager;
-	return m_thread.init(&m_manager->getMemoryPool(), &m_manager->getOtherSystems());
-}
-
-} // end namespace anki

+ 0 - 21
AnKi/Script/ScriptEnvironment.h

@@ -16,56 +16,35 @@ namespace anki {
 class ScriptEnvironment
 {
 public:
-	ScriptEnvironment()
-	{
-	}
-
-	~ScriptEnvironment()
-	{
-	}
-
-	Error init(ScriptManager* manager);
-
-	Bool isInitialized() const
-	{
-		return m_manager != nullptr;
-	}
-
 	/// Expose a variable to the scripting engine.
 	template<typename T>
 	void exposeVariable(const char* name, T* y)
 	{
-		ANKI_ASSERT(isInitialized());
 		LuaBinder::exposeVariable<T>(m_thread.getLuaState(), name, y);
 	}
 
 	/// Evaluate a string
 	Error evalString(const CString& str)
 	{
-		ANKI_ASSERT(isInitialized());
 		return LuaBinder::evalString(m_thread.getLuaState(), str);
 	}
 
 	void serializeGlobals(LuaBinderSerializeGlobalsCallback& callback)
 	{
-		ANKI_ASSERT(isInitialized());
 		LuaBinder::serializeGlobals(m_thread.getLuaState(), callback);
 	}
 
 	void deserializeGlobals(const void* data, PtrSize dataSize)
 	{
-		ANKI_ASSERT(isInitialized());
 		LuaBinder::deserializeGlobals(m_thread.getLuaState(), data, dataSize);
 	}
 
 	lua_State& getLuaState()
 	{
-		ANKI_ASSERT(isInitialized());
 		return *m_thread.getLuaState();
 	}
 
 private:
-	ScriptManager* m_manager = nullptr;
 	LuaBinder m_thread;
 };
 /// @}

+ 12 - 8
AnKi/Script/ScriptManager.cpp

@@ -9,24 +9,28 @@
 
 namespace anki {
 
-ScriptManager::ScriptManager()
+ScriptManager::PoolInit::PoolInit(AllocAlignedCallback allocCb, void* allocCbData)
 {
+	ANKI_SCRIPT_LOGI("Initializing scripting engine...");
+
+	ScriptMemoryPool::allocateSingleton(allocCb, allocCbData);
 }
 
-ScriptManager::~ScriptManager()
+ScriptManager::PoolInit ::~PoolInit()
 {
 	ANKI_SCRIPT_LOGI("Destroying scripting engine...");
+
+	ScriptMemoryPool::freeSingleton();
 }
 
-Error ScriptManager::init(AllocAlignedCallback allocCb, void* allocCbData)
+ScriptManager::ScriptManager(AllocAlignedCallback allocCb, void* allocCbData)
+	: m_poolInit(allocCb, allocCbData)
 {
 	ANKI_SCRIPT_LOGI("Initializing scripting engine...");
+}
 
-	m_pool.init(allocCb, allocCbData);
-
-	ANKI_CHECK(m_lua.init(&m_pool, &m_otherSystems));
-
-	return Error::kNone;
+ScriptManager::~ScriptManager()
+{
 }
 
 } // end namespace anki

+ 16 - 32
AnKi/Script/ScriptManager.h

@@ -9,38 +9,16 @@
 
 namespace anki {
 
-// Forward
-class SceneGraph;
-class MainRenderer;
-
 /// @addtogroup script
 /// @{
 
 /// The scripting manager.
-class ScriptManager
+class ScriptManager : public MakeSingleton<ScriptManager>
 {
-public:
-	ScriptManager();
-	~ScriptManager();
-
-	/// Create the script manager.
-	Error init(AllocAlignedCallback allocCb, void* allocCbData);
-
-	void setRenderer(MainRenderer* renderer)
-	{
-		m_otherSystems.m_renderer = renderer;
-	}
-
-	void setSceneGraph(SceneGraph* scene)
-	{
-		m_otherSystems.m_sceneGraph = scene;
-	}
-
-	LuaBinderOtherSystems& getOtherSystems()
-	{
-		return m_otherSystems;
-	}
+	template<typename>
+	friend class MakeSingleton;
 
+public:
 	/// Expose a variable to the scripting engine.
 	template<typename T>
 	void exposeVariable(const char* name, T* y)
@@ -61,16 +39,22 @@ public:
 		return m_lua;
 	}
 
-	ANKI_INTERNAL HeapMemoryPool& getMemoryPool() const
+private:
+	class PoolInit
 	{
-		return m_pool;
-	}
+	public:
+		PoolInit(AllocAlignedCallback allocCb, void* allocCbData);
 
-private:
-	LuaBinderOtherSystems m_otherSystems;
-	mutable HeapMemoryPool m_pool;
+		~PoolInit();
+	};
+
+	PoolInit m_poolInit;
 	LuaBinder m_lua;
 	Mutex n_luaMtx;
+
+	ScriptManager(AllocAlignedCallback allocCb, void* allocCbData);
+
+	~ScriptManager();
 };
 /// @}
 

+ 1 - 1
Samples/Common/SampleApp.cpp

@@ -46,7 +46,7 @@ Error SampleApp::userMainLoop(Bool& quit, Second elapsedTime)
 	constexpr F32 MOUSE_SENSITIVITY = 5.0f;
 	quit = false;
 
-	SceneGraph& scene = getSceneGraph();
+	SceneGraph& scene = SceneGraph::getSingleton();
 	Renderer& renderer = getMainRenderer().getOffscreenRenderer();
 	Input& in = Input::getSingleton();
 

+ 18 - 17
Samples/PhysicsPlayground/Main.cpp

@@ -23,7 +23,7 @@ function onKilled(event, prevTime, crntTime)
 end
 	)";
 	ScriptEvent* event;
-	ANKI_CHECK(node->getSceneGraph().getEventManager().newEvent(event, -1, 10.0, script));
+	ANKI_CHECK(SceneGraph::getSingleton().getEventManager().newEvent(event, -1, 10.0, script));
 	event->addAssociatedSceneNode(node);
 
 	return Error::kNone;
@@ -63,7 +63,7 @@ function onKilled(event, prevTime, crntTime)
 end
 	)";
 	ScriptEvent* event;
-	ANKI_CHECK(node->getSceneGraph().getEventManager().newEvent(event, -1, 10.0, script));
+	ANKI_CHECK(SceneGraph::getSingleton().getEventManager().newEvent(event, -1, 10.0, script));
 	event->addAssociatedSceneNode(node);
 
 	return Error::kNone;
@@ -110,16 +110,16 @@ Error MyApp::sampleExtraInit()
 {
 	ScriptResourcePtr script;
 	ANKI_CHECK(ResourceManager::getSingleton().loadResource("Assets/Scene.lua", script));
-	ANKI_CHECK(getScriptManager().evalString(script->getSource()));
+	ANKI_CHECK(ScriptManager::getSingleton().evalString(script->getSource()));
 
 	// Create the player
 	if(1)
 	{
-		SceneNode& cam = getSceneGraph().getActiveCameraNode();
+		SceneNode& cam = SceneGraph::getSingleton().getActiveCameraNode();
 		cam.setLocalTransform(Transform(Vec4(0.0, 2.0, 5.0, 0.0), Mat3x4::getIdentity(), 1.0));
 
 		SceneNode* player;
-		ANKI_CHECK(getSceneGraph().newSceneNode("player", player));
+		ANKI_CHECK(SceneGraph::getSingleton().newSceneNode("player", player));
 		PlayerControllerComponent* playerc = player->newComponent<PlayerControllerComponent>();
 		playerc->moveToPosition(Vec3(0.0f, 2.5f, 0.0f));
 		playerc->getPhysicsPlayerController().setMaterialMask(PhysicsMaterialBit::kStaticGeometry);
@@ -130,7 +130,7 @@ Error MyApp::sampleExtraInit()
 	// Create a body component with joint
 	{
 		SceneNode* monkey;
-		ANKI_CHECK(getSceneGraph().newSceneNode("monkey_p2p", monkey));
+		ANKI_CHECK(SceneGraph::getSingleton().newSceneNode("monkey_p2p", monkey));
 		ModelComponent* modelc = monkey->newComponent<ModelComponent>();
 		modelc->loadModelResource("Assets/Suzanne_dynamic_36043dae41fe12d5.ankimdl");
 
@@ -151,7 +151,7 @@ Error MyApp::sampleExtraInit()
 		for(U32 i = 0; i < LINKS; ++i)
 		{
 			SceneNode* monkey;
-			ANKI_CHECK(getSceneGraph().newSceneNode(
+			ANKI_CHECK(SceneGraph::getSingleton().newSceneNode(
 				StringRaii(&getMemoryPool()).sprintf("monkey_chain%u", i).toCString(), monkey));
 			monkey->newComponent<ModelComponent>()->loadModelResource(
 				"Assets/Suzanne_dynamic_36043dae41fe12d5.ankimdl");
@@ -186,7 +186,7 @@ Error MyApp::sampleExtraInit()
 	// Trigger
 	{
 		SceneNode* node;
-		ANKI_CHECK(getSceneGraph().newSceneNode("trigger", node));
+		ANKI_CHECK(SceneGraph::getSingleton().newSceneNode("trigger", node));
 		TriggerComponent* triggerc = node->newComponent<TriggerComponent>();
 		triggerc->setSphereVolumeRadius(1.8f);
 		node->setLocalTransform(Transform(Vec4(1.0f, 0.5f, 0.0f, 0.0f), Mat3x4::getIdentity(), 1.0f));
@@ -272,7 +272,7 @@ Error MyApp::userMainLoop(Bool& quit, [[maybe_unused]] Second elapsedTime)
 
 	// Move player
 	{
-		SceneNode& player = getSceneGraph().findSceneNode("player");
+		SceneNode& player = SceneGraph::getSingleton().findSceneNode("player");
 		PlayerControllerComponent& playerc = player.getFirstComponentOfType<PlayerControllerComponent>();
 
 		if(Input::getSingleton().getKey(KeyCode::kR))
@@ -340,10 +340,10 @@ Error MyApp::userMainLoop(Bool& quit, [[maybe_unused]] Second elapsedTime)
 
 		static U32 instance = 0;
 
-		Transform camTrf = getSceneGraph().getActiveCameraNode().getWorldTransform();
+		Transform camTrf = SceneGraph::getSingleton().getActiveCameraNode().getWorldTransform();
 
 		SceneNode* monkey;
-		ANKI_CHECK(getSceneGraph().newSceneNode(
+		ANKI_CHECK(SceneGraph::getSingleton().newSceneNode(
 			StringRaii(&getMemoryPool()).sprintf("FireMonkey%u", instance++).toCString(), monkey));
 		ModelComponent* modelc = monkey->newComponent<ModelComponent>();
 		modelc->loadModelResource("Assets/Suzanne_dynamic_36043dae41fe12d5.ankimdl");
@@ -363,7 +363,7 @@ Error MyApp::userMainLoop(Bool& quit, [[maybe_unused]] Second elapsedTime)
 
 	if(Input::getSingleton().getMouseButton(MouseButton::kRight) == 1)
 	{
-		Transform camTrf = getSceneGraph().getActiveCameraNode().getWorldTransform();
+		Transform camTrf = SceneGraph::getSingleton().getActiveCameraNode().getWorldTransform();
 		Vec3 from = camTrf.getOrigin().xyz();
 		Vec3 to = from + -camTrf.getRotation().getZAxis() * 100.0f;
 
@@ -390,8 +390,9 @@ Error MyApp::userMainLoop(Bool& quit, [[maybe_unused]] Second elapsedTime)
 			// Create an obj
 			static U32 id = 0;
 			SceneNode* monkey;
-			ANKI_CHECK(getSceneGraph().newSceneNode(
-				StringRaii(&getSceneGraph().getFrameMemoryPool()).sprintf("decal%u", id++).toCString(), monkey));
+			ANKI_CHECK(SceneGraph::getSingleton().newSceneNode(
+				StringRaii(&SceneGraph::getSingleton().getFrameMemoryPool()).sprintf("decal%u", id++).toCString(),
+				monkey));
 			ModelComponent* modelc = monkey->newComponent<ModelComponent>();
 			modelc->loadModelResource("Assets/Suzanne_dynamic_36043dae41fe12d5.ankimdl");
 			monkey->setLocalTransform(trf);
@@ -408,11 +409,11 @@ Error MyApp::userMainLoop(Bool& quit, [[maybe_unused]] Second elapsedTime)
 			for(U i = 0; i < 1; ++i)
 			{
 				static int id = 0;
-				StringRaii name(&getSceneGraph().getFrameMemoryPool());
+				StringRaii name(&SceneGraph::getSingleton().getFrameMemoryPool());
 				name.sprintf("fog%u", id++);
 
 				SceneNode* fogNode;
-				ANKI_CHECK(getSceneGraph().newSceneNode(name.toCString(), fogNode));
+				ANKI_CHECK(SceneGraph::getSingleton().newSceneNode(name.toCString(), fogNode));
 				FogDensityComponent* fogComp = fogNode->newComponent<FogDensityComponent>();
 				fogComp->setSphereVolumeRadius(2.1f);
 				fogComp->setDensity(15.0f);
@@ -427,7 +428,7 @@ Error MyApp::userMainLoop(Bool& quit, [[maybe_unused]] Second elapsedTime)
 
 	if(0)
 	{
-		SceneNode& node = getSceneGraph().findSceneNode("trigger");
+		SceneNode& node = SceneGraph::getSingleton().findSceneNode("trigger");
 		TriggerComponent& comp = node.getFirstComponentOfType<TriggerComponent>();
 
 		for(U32 i = 0; i < comp.getBodyComponentsEnter().getSize(); ++i)

+ 1 - 1
Samples/SimpleScene/Main.cpp

@@ -15,7 +15,7 @@ public:
 	{
 		ScriptResourcePtr script;
 		ANKI_CHECK(ResourceManager::getSingleton().loadResource("Assets/Scene.lua", script));
-		ANKI_CHECK(getScriptManager().evalString(script->getSource()));
+		ANKI_CHECK(ScriptManager::getSingleton().evalString(script->getSource()));
 
 		return Error::kNone;
 	}

+ 3 - 3
Samples/SkeletalAnimation/Main.cpp

@@ -18,7 +18,7 @@ public:
 	{
 		ScriptResourcePtr script;
 		ANKI_CHECK(ResourceManager::getSingleton().loadResource("Assets/Scene.lua", script));
-		ANKI_CHECK(getScriptManager().evalString(script->getSource()));
+		ANKI_CHECK(ScriptManager::getSingleton().evalString(script->getSource()));
 
 		ANKI_CHECK(
 			ResourceManager::getSingleton().loadResource("Assets/float.001_ccb9eb33e30c8fa4.ankianim", m_floatAnim));
@@ -27,7 +27,7 @@ public:
 		AnimationPlayInfo animInfo;
 		animInfo.m_startTime = 2.0;
 		animInfo.m_repeatTimes = -1.0;
-		getSceneGraph()
+		SceneGraph::getSingleton()
 			.findSceneNode("droid.001")
 			.getFirstComponentOfType<SkinComponent>()
 			.playAnimation(0, m_floatAnim, animInfo);
@@ -45,7 +45,7 @@ public:
 			animInfo.m_repeatTimes = 3.0;
 			animInfo.m_blendInTime = 0.5;
 			animInfo.m_blendOutTime = 0.35;
-			getSceneGraph()
+			SceneGraph::getSingleton()
 				.findSceneNode("droid.001")
 				.getFirstComponentOfType<SkinComponent>()
 				.playAnimation(1, m_waveAnim, animInfo);

+ 1 - 1
Samples/Sponza/Main.cpp

@@ -15,7 +15,7 @@ public:
 	{
 		ScriptResourcePtr script;
 		ANKI_CHECK(ResourceManager::getSingleton().loadResource("Assets/Scene.lua", script));
-		ANKI_CHECK(getScriptManager().evalString(script->getSource()));
+		ANKI_CHECK(ScriptManager::getSingleton().evalString(script->getSource()));
 
 		return Error::kNone;
 	}

+ 3 - 3
Sandbox/Main.cpp

@@ -61,7 +61,7 @@ Error MyApp::init(int argc, char* argv[])
 #else
 	ANKI_CHECK(resources.loadResource(argv[1], script));
 #endif
-	ANKI_CHECK(getScriptManager().evalString(script->getSource()));
+	ANKI_CHECK(ScriptManager::getSingleton().evalString(script->getSource()));
 
 	// ANKI_CHECK(renderer.getFinalComposite().loadColorGradingTexture(
 	//	"textures/color_gradient_luts/forge_lut.ankitex"));
@@ -87,7 +87,7 @@ Error MyApp::userMainLoop(Bool& quit, Second elapsedTime)
 {
 	quit = false;
 
-	SceneGraph& scene = getSceneGraph();
+	SceneGraph& scene = SceneGraph::getSingleton();
 	Input& in = Input::getSingleton();
 	Renderer& renderer = getMainRenderer().getOffscreenRenderer();
 
@@ -419,7 +419,7 @@ Error MyApp::userMainLoop(Bool& quit, Second elapsedTime)
 		quit = true;
 	}
 
-	if(m_profile && getGlobalTimestamp() == 1000)
+	if(m_profile && GlobalFrameIndex::getSingleton().m_value == 1000)
 	{
 		quit = true;
 		return Error::kNone;

+ 9 - 9
Tests/Script/LuaBinder.cpp

@@ -9,9 +9,8 @@
 
 ANKI_TEST(Script, LuaBinder)
 {
-	ScriptManager sm;
+	ScriptManager& sm = ScriptManager::allocateSingleton(allocAligned, nullptr);
 
-	ANKI_TEST_EXPECT_NO_ERR(sm.init(allocAligned, nullptr));
 	Vec4 v4(2.0, 3.0, 4.0, 5.0);
 	Vec3 v3(1.1f, 2.2f, 3.3f);
 
@@ -37,15 +36,15 @@ v3:setZ(0.1)
 
 	ANKI_TEST_EXPECT_EQ(v4, Vec4(6, 12, 0, 5.5));
 	ANKI_TEST_EXPECT_EQ(v3, Vec3(1.1f, 2.2f, 0.1f));
+
+	ScriptManager::freeSingleton();
 }
 
 ANKI_TEST(Script, LuaBinderThreads)
 {
-	ScriptManager sm;
-	ANKI_TEST_EXPECT_NO_ERR(sm.init(allocAligned, nullptr));
+	ScriptManager& sm = ScriptManager::allocateSingleton(allocAligned, nullptr);
 
 	ScriptEnvironment env;
-	ANKI_TEST_EXPECT_NO_ERR(env.init(&sm));
 
 	static const char* script = R"(
 vec = Vec4.new(0, 0, 0, 0)
@@ -64,15 +63,15 @@ myFunc()
 
 	ANKI_TEST_EXPECT_NO_ERR(env.evalString(script1));
 	ANKI_TEST_EXPECT_NO_ERR(env.evalString(script1));
+
+	ScriptManager::freeSingleton();
 }
 
 ANKI_TEST(Script, LuaBinderSerialize)
 {
-	ScriptManager sm;
-	ANKI_TEST_EXPECT_NO_ERR(sm.init(allocAligned, nullptr));
+	ScriptManager& sm = ScriptManager::allocateSingleton(allocAligned, nullptr);
 
 	ScriptEnvironment env;
-	ANKI_TEST_EXPECT_NO_ERR(env.init(&sm));
 
 	static const char* script = R"(
 num = 123.4
@@ -98,7 +97,6 @@ vec = Vec3.new(1, 2, 3)
 	env.serializeGlobals(callback);
 
 	ScriptEnvironment env2;
-	ANKI_TEST_EXPECT_NO_ERR(env2.init(&sm));
 
 	env2.deserializeGlobals(&callback.m_buff[0], callback.m_offset);
 
@@ -109,4 +107,6 @@ print(vec:getX(), vec:getY(), vec:getZ())
 )";
 
 	ANKI_TEST_EXPECT_NO_ERR(env2.evalString(script2));
+
+	ScriptManager::freeSingleton();
 }

+ 5 - 6
Tools/Image/ImageViewerMain.cpp

@@ -12,8 +12,8 @@ class TextureViewerUiNode : public SceneNode
 public:
 	ImageResourcePtr m_imageResource;
 
-	TextureViewerUiNode(SceneGraph* scene, CString name)
-		: SceneNode(scene, name)
+	TextureViewerUiNode(CString name)
+		: SceneNode(name)
 	{
 		UiComponent* uic = newComponent<UiComponent>();
 		uic->init(
@@ -118,7 +118,7 @@ private:
 
 		// Mips combo
 		{
-			StringListRaii mipLabels(&getFrameMemoryPool());
+			UiStringList mipLabels;
 			for(U32 mip = 0; mip < grTex.getMipmapCount(); ++mip)
 			{
 				mipLabels.pushBackSprintf("Mip %u (%u x %u)", mip, grTex.getWidth() >> mip, grTex.getHeight() >> mip);
@@ -158,7 +158,7 @@ private:
 		// Depth
 		if(grTex.getTextureType() == TextureType::k3D)
 		{
-			StringListRaii labels(&getFrameMemoryPool());
+			UiStringList labels;
 			for(U32 d = 0; d < grTex.getDepth(); ++d)
 			{
 				labels.pushBackSprintf("Depth %u", d);
@@ -294,9 +294,8 @@ public:
 		NativeWindow::getSingleton().setWindowTitle(title);
 
 		// Create the node
-		SceneGraph& scene = getSceneGraph();
 		TextureViewerUiNode* node;
-		ANKI_CHECK(scene.newSceneNode("TextureViewer", node));
+		ANKI_CHECK(SceneGraph::getSingleton().newSceneNode("TextureViewer", node));
 		node->m_imageResource = std::move(image);
 
 		return Error::kNone;