Browse Source

Make the GrManager a singleton

Panagiotis Christopoulos Charitos 2 years ago
parent
commit
e1b6dbe779
100 changed files with 700 additions and 1063 deletions
  1. 13 23
      AnKi/Core/App.cpp
  2. 0 1
      AnKi/Core/App.h
  3. 12 17
      AnKi/Core/GpuMemoryPools.cpp
  4. 3 8
      AnKi/Core/GpuMemoryPools.h
  5. 3 4
      AnKi/Gr/AccelerationStructure.h
  6. 3 3
      AnKi/Gr/Buffer.h
  7. 0 4
      AnKi/Gr/CMakeLists.txt
  8. 3 3
      AnKi/Gr/CommandBuffer.h
  9. 6 0
      AnKi/Gr/Common.cpp
  10. 23 1
      AnKi/Gr/Common.h
  11. 3 3
      AnKi/Gr/Fence.h
  12. 3 3
      AnKi/Gr/Framebuffer.h
  13. 13 16
      AnKi/Gr/GrManager.h
  14. 4 10
      AnKi/Gr/GrObject.cpp
  15. 1 14
      AnKi/Gr/GrObject.h
  16. 3 3
      AnKi/Gr/GrUpscaler.h
  17. 3 3
      AnKi/Gr/OcclusionQuery.h
  18. 21 39
      AnKi/Gr/RenderGraph.cpp
  19. 14 14
      AnKi/Gr/RenderGraph.h
  20. 3 3
      AnKi/Gr/Sampler.h
  21. 3 3
      AnKi/Gr/Shader.h
  22. 3 3
      AnKi/Gr/ShaderProgram.h
  23. 3 3
      AnKi/Gr/Texture.h
  24. 3 3
      AnKi/Gr/TextureView.h
  25. 3 3
      AnKi/Gr/TimestampQuery.h
  26. 22 32
      AnKi/Gr/Utils/SegregatedListsGpuMemoryPool.cpp
  27. 7 16
      AnKi/Gr/Utils/SegregatedListsGpuMemoryPool.h
  28. 10 20
      AnKi/Gr/Utils/StackGpuMemoryPool.cpp
  29. 2 3
      AnKi/Gr/Utils/StackGpuMemoryPool.h
  30. 3 3
      AnKi/Gr/Vulkan/AccelerationStructure.cpp
  31. 15 14
      AnKi/Gr/Vulkan/AccelerationStructureImpl.cpp
  32. 4 7
      AnKi/Gr/Vulkan/AccelerationStructureImpl.h
  33. 3 3
      AnKi/Gr/Vulkan/Buffer.cpp
  34. 8 10
      AnKi/Gr/Vulkan/BufferImpl.cpp
  35. 8 11
      AnKi/Gr/Vulkan/BufferImpl.h
  36. 5 6
      AnKi/Gr/Vulkan/CommandBuffer.cpp
  37. 23 35
      AnKi/Gr/Vulkan/CommandBufferFactory.cpp
  38. 12 13
      AnKi/Gr/Vulkan/CommandBufferFactory.h
  39. 0 26
      AnKi/Gr/Vulkan/CommandBufferFactory.inl.h
  40. 1 1
      AnKi/Gr/Vulkan/CommandBufferImpl.cpp
  41. 3 4
      AnKi/Gr/Vulkan/CommandBufferImpl.h
  42. 11 0
      AnKi/Gr/Vulkan/Common.cpp
  43. 3 0
      AnKi/Gr/Vulkan/Common.h
  44. 34 16
      AnKi/Gr/Vulkan/DeferredBarrierFactory.h
  45. 0 52
      AnKi/Gr/Vulkan/DeferredBarrierFactory.inl.h
  46. 47 70
      AnKi/Gr/Vulkan/DescriptorSet.cpp
  47. 3 5
      AnKi/Gr/Vulkan/DescriptorSet.h
  48. 2 2
      AnKi/Gr/Vulkan/Fence.cpp
  49. 10 8
      AnKi/Gr/Vulkan/FenceFactory.cpp
  50. 4 16
      AnKi/Gr/Vulkan/FenceFactory.h
  51. 4 9
      AnKi/Gr/Vulkan/FenceFactory.inl.h
  52. 3 4
      AnKi/Gr/Vulkan/FenceImpl.h
  53. 8 12
      AnKi/Gr/Vulkan/FrameGarbageCollector.cpp
  54. 4 7
      AnKi/Gr/Vulkan/FrameGarbageCollector.h
  55. 3 3
      AnKi/Gr/Vulkan/Framebuffer.cpp
  56. 7 9
      AnKi/Gr/Vulkan/FramebufferImpl.cpp
  57. 4 5
      AnKi/Gr/Vulkan/FramebufferImpl.h
  58. 15 20
      AnKi/Gr/Vulkan/GpuMemoryManager.cpp
  59. 2 6
      AnKi/Gr/Vulkan/GpuMemoryManager.h
  60. 29 36
      AnKi/Gr/Vulkan/GrManager.cpp
  61. 40 40
      AnKi/Gr/Vulkan/GrManagerImpl.cpp
  62. 3 3
      AnKi/Gr/Vulkan/GrUpscaler.cpp
  63. 1 1
      AnKi/Gr/Vulkan/GrUpscalerImpl.cpp
  64. 3 4
      AnKi/Gr/Vulkan/GrUpscalerImpl.h
  65. 1 12
      AnKi/Gr/Vulkan/MicroObjectRecycler.h
  66. 10 12
      AnKi/Gr/Vulkan/MicroObjectRecycler.inl.h
  67. 3 3
      AnKi/Gr/Vulkan/OcclusionQuery.cpp
  68. 1 1
      AnKi/Gr/Vulkan/OcclusionQueryImpl.cpp
  69. 3 4
      AnKi/Gr/Vulkan/OcclusionQueryImpl.h
  70. 14 6
      AnKi/Gr/Vulkan/Pipeline.cpp
  71. 4 13
      AnKi/Gr/Vulkan/Pipeline.h
  72. 16 17
      AnKi/Gr/Vulkan/PipelineCache.cpp
  73. 4 4
      AnKi/Gr/Vulkan/PipelineCache.h
  74. 4 4
      AnKi/Gr/Vulkan/PipelineLayout.cpp
  75. 1 11
      AnKi/Gr/Vulkan/PipelineLayout.h
  76. 4 4
      AnKi/Gr/Vulkan/QueryFactory.cpp
  77. 1 6
      AnKi/Gr/Vulkan/QueryFactory.h
  78. 3 3
      AnKi/Gr/Vulkan/Sampler.cpp
  79. 9 28
      AnKi/Gr/Vulkan/SamplerFactory.cpp
  80. 1 13
      AnKi/Gr/Vulkan/SamplerFactory.h
  81. 3 4
      AnKi/Gr/Vulkan/SamplerImpl.h
  82. 0 13
      AnKi/Gr/Vulkan/SemaphoreFactory.h
  83. 4 9
      AnKi/Gr/Vulkan/SemaphoreFactory.inl.h
  84. 3 3
      AnKi/Gr/Vulkan/Shader.cpp
  85. 7 12
      AnKi/Gr/Vulkan/ShaderImpl.cpp
  86. 4 5
      AnKi/Gr/Vulkan/ShaderImpl.h
  87. 3 3
      AnKi/Gr/Vulkan/ShaderProgram.cpp
  88. 20 25
      AnKi/Gr/Vulkan/ShaderProgramImpl.cpp
  89. 5 6
      AnKi/Gr/Vulkan/ShaderProgramImpl.h
  90. 20 36
      AnKi/Gr/Vulkan/SwapchainFactory.cpp
  91. 5 5
      AnKi/Gr/Vulkan/SwapchainFactory.h
  92. 3 3
      AnKi/Gr/Vulkan/Texture.cpp
  93. 12 12
      AnKi/Gr/Vulkan/TextureImpl.cpp
  94. 4 5
      AnKi/Gr/Vulkan/TextureImpl.h
  95. 3 3
      AnKi/Gr/Vulkan/TextureView.cpp
  96. 3 4
      AnKi/Gr/Vulkan/TextureViewImpl.h
  97. 3 3
      AnKi/Gr/Vulkan/TimestampQuery.cpp
  98. 1 1
      AnKi/Gr/Vulkan/TimestampQueryImpl.cpp
  99. 3 4
      AnKi/Gr/Vulkan/TimestampQueryImpl.h
  100. 0 47
      AnKi/Gr/Vulkan/VulkanObject.cpp

+ 13 - 23
AnKi/Core/App.cpp

@@ -133,8 +133,7 @@ void App::cleanup()
 	GpuSceneMemoryPool::freeSingleton();
 	CoreThreadHive::freeSingleton();
 	MaliHwCounters::freeSingleton();
-	GrManager::deleteInstance(m_gr);
-	m_gr = nullptr;
+	GrManager::freeSingleton();
 	Input::freeSingleton();
 	NativeWindow::freeSingleton();
 
@@ -264,13 +263,12 @@ Error App::initInternal(AllocAlignedCallback allocCb, void* allocCbUserData)
 	grInit.m_allocCallback = m_mainPool.getAllocationCallback();
 	grInit.m_allocCallbackUserData = m_mainPool.getAllocationCallbackUserData();
 	grInit.m_cacheDirectory = m_cacheDir.toCString();
-
-	ANKI_CHECK(GrManager::newInstance(grInit, m_gr));
+	ANKI_CHECK(GrManager::allocateSingleton().init(grInit));
 
 	//
 	// Mali HW counters
 	//
-	if(m_gr->getDeviceCapabilities().m_gpuVendor == GpuVendor::kArm
+	if(GrManager::getSingleton().getDeviceCapabilities().m_gpuVendor == GpuVendor::kArm
 	   && ConfigSet::getSingleton().getCoreMaliHwCounters())
 	{
 		MaliHwCounters::allocateSingleton();
@@ -279,9 +277,9 @@ Error App::initInternal(AllocAlignedCallback allocCb, void* allocCbUserData)
 	//
 	// GPU mem
 	//
-	UnifiedGeometryMemoryPool::allocateSingleton().init(m_gr);
-	GpuSceneMemoryPool::allocateSingleton().init(m_gr);
-	RebarStagingGpuMemoryPool::allocateSingleton().init(m_gr);
+	UnifiedGeometryMemoryPool::allocateSingleton().init();
+	GpuSceneMemoryPool::allocateSingleton().init();
+	RebarStagingGpuMemoryPool::allocateSingleton().init();
 
 	//
 	// Physics
@@ -305,20 +303,14 @@ Error App::initInternal(AllocAlignedCallback allocCb, void* allocCbUserData)
 	ConfigSet::getSingleton().setRsrcDataPaths(shadersPath);
 #endif
 
-	ResourceManagerInitInfo rinit;
-	rinit.m_grManager = m_gr;
-	rinit.m_allocCallback = m_mainPool.getAllocationCallback();
-	rinit.m_allocCallbackData = m_mainPool.getAllocationCallbackUserData();
-	ANKI_CHECK(ResourceManager::allocateSingleton().init(rinit));
+	ANKI_CHECK(ResourceManager::allocateSingleton().init(m_mainPool.getAllocationCallback(),
+														 m_mainPool.getAllocationCallbackUserData()));
 
 	//
 	// UI
 	//
-	UiManagerInitInfo uiInitInfo;
-	uiInitInfo.m_allocCallback = m_mainPool.getAllocationCallback();
-	uiInitInfo.m_allocCallbackUserData = m_mainPool.getAllocationCallbackUserData();
-	uiInitInfo.m_grManager = m_gr;
-	ANKI_CHECK(UiManager::allocateSingleton().init(uiInitInfo));
+	ANKI_CHECK(UiManager::allocateSingleton().init(m_mainPool.getAllocationCallback(),
+												   m_mainPool.getAllocationCallbackUserData()));
 
 	//
 	// GPU scene
@@ -333,7 +325,6 @@ 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_grManager = m_gr;
 	renderInit.m_globTimestamp = &m_globalTimestamp;
 	m_renderer = newInstance<MainRenderer>(m_mainPool);
 	ANKI_CHECK(m_renderer->init(renderInit));
@@ -354,7 +345,6 @@ Error App::initInternal(AllocAlignedCallback allocCb, void* allocCbUserData)
 	sceneInit.m_allocCallbackData = m_mainPool.getAllocationCallbackUserData();
 	sceneInit.m_globalTimestamp = &m_globalTimestamp;
 	sceneInit.m_scriptManager = m_script;
-	sceneInit.m_grManager = m_gr;
 	ANKI_CHECK(m_scene->init(sceneInit));
 
 	// Inform the script engine about some subsystems
@@ -461,7 +451,7 @@ Error App::mainLoop()
 			injectUiElements(newUiElementArr, rqueue);
 
 			// Render
-			TexturePtr presentableTex = m_gr->acquireNextPresentableTexture();
+			TexturePtr presentableTex = GrManager::getSingleton().acquireNextPresentableTexture();
 			m_renderer->setStatsEnabled(ConfigSet::getSingleton().getCoreDisplayStats() > 0 || benchmarkMode
 #if ANKI_ENABLE_TRACE
 										|| Tracer::getSingleton().getEnabled()
@@ -480,7 +470,7 @@ Error App::mainLoop()
 				grTime = HighRezTimer::getCurrentTime();
 			}
 
-			m_gr->swapBuffers();
+			GrManager::getSingleton().swapBuffers();
 
 			if(benchmarkMode || ConfigSet::getSingleton().getCoreDisplayStats() > 0) [[unlikely]]
 			{
@@ -554,7 +544,7 @@ Error App::mainLoop()
 				in.m_cpuAllocationCount = m_memStats.m_allocCount.load();
 				in.m_cpuFreeCount = m_memStats.m_freeCount.load();
 
-				const GrManagerStats grStats = m_gr->getStats();
+				const GrManagerStats grStats = GrManager::getSingleton().getStats();
 				UnifiedGeometryMemoryPool::getSingleton().getStats(
 					in.m_unifiedGometryExternalFragmentation, in.m_unifiedGeometryAllocated, in.m_unifiedGeometryTotal);
 				GpuSceneMemoryPool::getSingleton().getStats(in.m_gpuSceneExternalFragmentation, in.m_gpuSceneAllocated,

+ 0 - 1
AnKi/Core/App.h

@@ -89,7 +89,6 @@ private:
 	HeapMemoryPool m_mainPool; // TODO glob: rm
 
 	// Sybsystems
-	GrManager* m_gr = nullptr;
 	MainRenderer* m_renderer = nullptr;
 	SceneGraph* m_scene = nullptr;
 	ScriptManager* m_script = nullptr;

+ 12 - 17
AnKi/Core/GpuMemoryPools.cpp

@@ -12,10 +12,8 @@
 
 namespace anki {
 
-void UnifiedGeometryMemoryPool::init(GrManager* gr)
+void UnifiedGeometryMemoryPool::init()
 {
-	ANKI_ASSERT(gr);
-
 	const PtrSize poolSize = ConfigSet::getSingleton().getCoreGlobalVertexMemorySize();
 
 	const Array classes = {1_KB, 8_KB, 32_KB, 128_KB, 512_KB, 4_MB, 8_MB, 16_MB, poolSize};
@@ -23,12 +21,12 @@ void UnifiedGeometryMemoryPool::init(GrManager* gr)
 	BufferUsageBit buffUsage = BufferUsageBit::kVertex | BufferUsageBit::kIndex | BufferUsageBit::kTransferDestination
 							   | (BufferUsageBit::kAllTexture & BufferUsageBit::kAllRead);
 
-	if(gr->getDeviceCapabilities().m_rayTracingEnabled)
+	if(GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled)
 	{
 		buffUsage |= BufferUsageBit::kAccelerationStructureBuild;
 	}
 
-	m_pool.init(gr, &CoreMemoryPool::getSingleton(), buffUsage, classes, poolSize, "UnifiedGeometry", false);
+	m_pool.init(buffUsage, classes, poolSize, "UnifiedGeometry", false);
 
 	// Allocate something dummy to force creating the GPU buffer
 	SegregatedListsGpuMemoryPoolToken token;
@@ -36,43 +34,40 @@ void UnifiedGeometryMemoryPool::init(GrManager* gr)
 	deferredFree(token);
 }
 
-void GpuSceneMemoryPool::init(GrManager* gr)
+void GpuSceneMemoryPool::init()
 {
-	ANKI_ASSERT(gr);
-
 	const PtrSize poolSize = ConfigSet::getSingleton().getCoreGpuSceneInitialSize();
 
 	const Array classes = {32_B, 64_B, 128_B, 256_B, poolSize};
 
 	BufferUsageBit buffUsage = BufferUsageBit::kAllStorage | BufferUsageBit::kTransferDestination;
 
-	m_pool.init(gr, &CoreMemoryPool::getSingleton(), buffUsage, classes, poolSize, "GpuScene", true);
+	m_pool.init(buffUsage, classes, poolSize, "GpuScene", true);
 }
 
 RebarStagingGpuMemoryPool::~RebarStagingGpuMemoryPool()
 {
-	GrManager& gr = m_buffer->getManager();
-
-	gr.finish();
+	GrManager::getSingleton().finish();
 
 	m_buffer->unmap();
 	m_buffer.reset(nullptr);
 }
 
-void RebarStagingGpuMemoryPool::init(GrManager* gr)
+void RebarStagingGpuMemoryPool::init()
 {
 	BufferInitInfo buffInit("ReBar");
 	buffInit.m_mapAccess = BufferMapAccessBit::kWrite;
 	buffInit.m_size = ConfigSet::getSingleton().getCoreRebarGpuMemorySize();
 	buffInit.m_usage = BufferUsageBit::kAllUniform | BufferUsageBit::kAllStorage | BufferUsageBit::kVertex
 					   | BufferUsageBit::kIndex | BufferUsageBit::kShaderBindingTable;
-	m_buffer = gr->newBuffer(buffInit);
+	m_buffer = GrManager::getSingleton().newBuffer(buffInit);
 
 	m_bufferSize = buffInit.m_size;
 
-	m_alignment = gr->getDeviceCapabilities().m_uniformBufferBindOffsetAlignment;
-	m_alignment = max(m_alignment, gr->getDeviceCapabilities().m_storageBufferBindOffsetAlignment);
-	m_alignment = max(m_alignment, gr->getDeviceCapabilities().m_sbtRecordAlignment);
+	m_alignment = GrManager::getSingleton().getDeviceCapabilities().m_uniformBufferBindOffsetAlignment;
+	m_alignment =
+		max(m_alignment, GrManager::getSingleton().getDeviceCapabilities().m_storageBufferBindOffsetAlignment);
+	m_alignment = max(m_alignment, GrManager::getSingleton().getDeviceCapabilities().m_sbtRecordAlignment);
 
 	m_mappedMem = static_cast<U8*>(m_buffer->map(0, kMaxPtrSize, BufferMapAccessBit::kWrite));
 }

+ 3 - 8
AnKi/Core/GpuMemoryPools.h

@@ -27,7 +27,7 @@ public:
 
 	UnifiedGeometryMemoryPool& operator=(const UnifiedGeometryMemoryPool&) = delete; // Non-copyable
 
-	void init(GrManager* gr);
+	void init();
 
 	void allocate(PtrSize size, U32 alignment, SegregatedListsGpuMemoryPoolToken& token)
 	{
@@ -73,7 +73,7 @@ public:
 
 	GpuSceneMemoryPool& operator=(const GpuSceneMemoryPool&) = delete; // Non-copyable
 
-	void init(GrManager* gr);
+	void init();
 
 	void allocate(PtrSize size, U32 alignment, SegregatedListsGpuMemoryPoolToken& token)
 	{
@@ -100,11 +100,6 @@ public:
 		m_pool.getStats(externalFragmentation, userAllocatedSize, totalSize);
 	}
 
-	GrManager& getGrManager()
-	{
-		return m_pool.getGrManager();
-	}
-
 private:
 	SegregatedListsGpuMemoryPool m_pool;
 
@@ -153,7 +148,7 @@ public:
 
 	RebarStagingGpuMemoryPool& operator=(const RebarStagingGpuMemoryPool&) = delete; // Non-copyable
 
-	void init(GrManager* gr);
+	void init();
 
 	PtrSize endFrame();
 

+ 3 - 4
AnKi/Gr/AccelerationStructure.h

@@ -125,8 +125,8 @@ protected:
 	AccelerationStructureType m_type = AccelerationStructureType::kCount;
 
 	/// Construct.
-	AccelerationStructure(GrManager* manager, CString name)
-		: GrObject(manager, kClassType, name)
+	AccelerationStructure(CString name)
+		: GrObject(kClassType, name)
 	{
 	}
 
@@ -137,8 +137,7 @@ protected:
 
 private:
 	/// Allocate and initialize a new instance.
-	[[nodiscard]] static AccelerationStructure* newInstance(GrManager* manager,
-															const AccelerationStructureInitInfo& init);
+	[[nodiscard]] static AccelerationStructure* newInstance(const AccelerationStructureInitInfo& init);
 };
 /// @}
 

+ 3 - 3
AnKi/Gr/Buffer.h

@@ -113,8 +113,8 @@ protected:
 	U64 m_gpuAddress = 0;
 
 	/// Construct.
-	Buffer(GrManager* manager, CString name)
-		: GrObject(manager, kClassType, name)
+	Buffer(CString name)
+		: GrObject(kClassType, name)
 	{
 	}
 
@@ -125,7 +125,7 @@ protected:
 
 private:
 	/// Allocate and initialize a new instance.
-	[[nodiscard]] static Buffer* newInstance(GrManager* manager, const BufferInitInfo& init);
+	[[nodiscard]] static Buffer* newInstance(const BufferInitInfo& init);
 };
 /// @}
 

+ 0 - 4
AnKi/Gr/CMakeLists.txt

@@ -72,7 +72,6 @@ if(VULKAN)
 		Vulkan/TextureViewImpl.cpp
 		Vulkan/TimestampQuery.cpp
 		Vulkan/TimestampQueryImpl.cpp
-		Vulkan/VulkanObject.cpp
 		Vulkan/FrameGarbageCollector.cpp
 		Vulkan/GrUpscaler.cpp
 		Vulkan/GrUpscalerImpl.cpp)
@@ -81,12 +80,10 @@ if(VULKAN)
 		Vulkan/AccelerationStructureImpl.h
 		Vulkan/BufferImpl.h
 		Vulkan/CommandBufferFactory.h
-		Vulkan/CommandBufferFactory.inl.h
 		Vulkan/CommandBufferImpl.h
 		Vulkan/CommandBufferImpl.inl.h
 		Vulkan/Common.h
 		Vulkan/DeferredBarrierFactory.h
-		Vulkan/DeferredBarrierFactory.inl.h
 		Vulkan/DescriptorSet.h
 		Vulkan/FenceFactory.h
 		Vulkan/FenceFactory.inl.h
@@ -112,7 +109,6 @@ if(VULKAN)
 		Vulkan/TextureImpl.h
 		Vulkan/TextureViewImpl.h
 		Vulkan/TimestampQueryImpl.h
-		Vulkan/VulkanObject.h
 		Vulkan/GrUpscalerImpl.h)
 
 	if(ANKI_HEADLESS)

+ 3 - 3
AnKi/Gr/CommandBuffer.h

@@ -437,8 +437,8 @@ public:
 
 protected:
 	/// Construct.
-	CommandBuffer(GrManager* manager, CString name)
-		: GrObject(manager, kClassType, name)
+	CommandBuffer(CString name)
+		: GrObject(kClassType, name)
 	{
 	}
 
@@ -449,7 +449,7 @@ protected:
 
 private:
 	/// Allocate and initialize a new instance.
-	[[nodiscard]] static CommandBuffer* newInstance(GrManager* manager, const CommandBufferInitInfo& init);
+	[[nodiscard]] static CommandBuffer* newInstance(const CommandBufferInitInfo& init);
 };
 /// @}
 

+ 6 - 0
AnKi/Gr/Common.cpp

@@ -4,6 +4,7 @@
 // http://www.anki3d.org/LICENSE
 
 #include <AnKi/Gr/Common.h>
+#include <AnKi/Gr/GrObject.h>
 #include <AnKi/Math.h>
 
 namespace anki {
@@ -18,6 +19,11 @@ inline constexpr ShaderVariableDataTypeInfo kShaderVariableDataTypeInfos[] = {
 #undef ANKI_SVDT_MACRO_OPAQUE
 };
 
+void GrObjectDeleter::operator()(GrObject* ptr)
+{
+	deleteInstance(GrMemoryPool::getSingleton(), ptr);
+}
+
 const ShaderVariableDataTypeInfo& getShaderVariableDataTypeInfo(ShaderVariableDataType type)
 {
 	ANKI_ASSERT(type > ShaderVariableDataType::kNone && type < ShaderVariableDataType::kCount);

+ 23 - 1
AnKi/Gr/Common.h

@@ -39,6 +39,22 @@ class GrUpscalerInitInfo;
 #define ANKI_GR_LOGF(...) ANKI_LOG("GR", kFatal, __VA_ARGS__)
 #define ANKI_GR_LOGV(...) ANKI_LOG("GR", kVerbose, __VA_ARGS__)
 
+class GrMemoryPool : public HeapMemoryPool, public MakeSingleton<GrMemoryPool>
+{
+	template<typename>
+	friend class MakeSingleton;
+
+private:
+	GrMemoryPool(AllocAlignedCallback allocCb, void* allocCbUserData)
+		: HeapMemoryPool(allocCb, allocCbUserData, "GrMemPool")
+	{
+	}
+
+	~GrMemoryPool() = default;
+};
+
+ANKI_DEFINE_SUBMODULE_UTIL_CONTAINERS(Gr, GrMemoryPool)
+
 // Some constants
 constexpr U32 kMaxVertexAttributes = 8;
 constexpr U32 kMaxColorRenderTargets = 4;
@@ -52,9 +68,15 @@ constexpr U32 kMaxBindlessReadonlyTextureBuffers = 512;
 /// The number of commands in a command buffer that make it a small batch command buffer.
 constexpr U32 kCommandBufferSmallBatchMaxCommands = 100;
 
+class GrObjectDeleter
+{
+public:
+	void operator()(GrObject* ptr);
+};
+
 /// Smart pointer for resources.
 template<typename T>
-using GrObjectPtrT = IntrusivePtr<T, DefaultPtrDeleter<GrObject>>;
+using GrObjectPtrT = IntrusivePtr<T, GrObjectDeleter>;
 
 using GrObjectPtr = GrObjectPtrT<GrObject>;
 

+ 3 - 3
AnKi/Gr/Fence.h

@@ -27,8 +27,8 @@ public:
 
 protected:
 	/// Construct.
-	Fence(GrManager* manager, CString name)
-		: GrObject(manager, kClassType, name)
+	Fence(CString name)
+		: GrObject(kClassType, name)
 	{
 	}
 
@@ -39,7 +39,7 @@ protected:
 
 private:
 	/// Allocate and initialize a new instance.
-	[[nodiscard]] static Fence* newInstance(GrManager* manager);
+	[[nodiscard]] static Fence* newInstance();
 };
 /// @}
 

+ 3 - 3
AnKi/Gr/Framebuffer.h

@@ -119,8 +119,8 @@ public:
 
 protected:
 	/// Construct.
-	Framebuffer(GrManager* manager, CString name)
-		: GrObject(manager, kClassType, name)
+	Framebuffer(CString name)
+		: GrObject(kClassType, name)
 	{
 	}
 
@@ -130,7 +130,7 @@ protected:
 	}
 
 private:
-	[[nodiscard]] static Framebuffer* newInstance(GrManager* manager, const FramebufferInitInfo& init);
+	[[nodiscard]] static Framebuffer* newInstance(const FramebufferInitInfo& init);
 };
 /// @}
 

+ 13 - 16
AnKi/Gr/GrManager.h

@@ -42,14 +42,13 @@ public:
 };
 
 /// The graphics manager, owner of all graphics objects.
-class GrManager
+class GrManager : public MakeSingletonPtr<GrManager>
 {
-public:
-	/// Create.
-	static Error newInstance(GrManagerInitInfo& init, GrManager*& gr);
+	template<typename>
+	friend class MakeSingletonPtr;
 
-	/// Destroy.
-	static void deleteInstance(GrManager* gr);
+public:
+	Error init(GrManagerInitInfo& init);
 
 	const GpuDeviceCapabilities& getDeviceCapabilities() const
 	{
@@ -85,11 +84,6 @@ public:
 
 	GrManagerStats getStats() const;
 
-	ANKI_INTERNAL HeapMemoryPool& getMemoryPool() const
-	{
-		return m_pool;
-	}
-
 	ANKI_INTERNAL CString getCacheDirectory() const
 	{
 		return m_cacheDir.toCString();
@@ -101,11 +95,7 @@ public:
 	}
 
 protected:
-	/// Keep it first to get deleted last. It's mutable because its methods are thread-safe and we want to use it in
-	/// const methods.
-	mutable HeapMemoryPool m_pool;
-
-	String m_cacheDir;
+	GrString m_cacheDir;
 	Atomic<U64> m_uuidIndex = {1};
 	GpuDeviceCapabilities m_capabilities;
 
@@ -113,6 +103,13 @@ protected:
 
 	virtual ~GrManager();
 };
+
+template<>
+template<>
+GrManager& MakeSingletonPtr<GrManager>::allocateSingleton<>();
+
+template<>
+void MakeSingletonPtr<GrManager>::freeSingleton();
 /// @}
 
 } // end namespace anki

+ 4 - 10
AnKi/Gr/GrObject.cpp

@@ -8,9 +8,8 @@
 
 namespace anki {
 
-GrObject::GrObject(GrManager* manager, GrObjectType type, CString name)
-	: m_manager(manager)
-	, m_uuid(m_manager->getNewUuid())
+GrObject::GrObject(GrObjectType type, CString name)
+	: m_uuid(GrManager::getSingleton().getNewUuid())
 	, m_refcount(0)
 	, m_type(type)
 {
@@ -19,7 +18,7 @@ GrObject::GrObject(GrManager* manager, GrObjectType type, CString name)
 		name = "N/A";
 	}
 
-	m_name = static_cast<Char*>(manager->getMemoryPool().allocate(name.getLength() + 1, alignof(Char)));
+	m_name = static_cast<Char*>(GrMemoryPool::getSingleton().allocate(name.getLength() + 1, alignof(Char)));
 	memcpy(m_name, &name[0], name.getLength() + 1);
 }
 
@@ -27,13 +26,8 @@ GrObject::~GrObject()
 {
 	if(m_name)
 	{
-		m_manager->getMemoryPool().free(m_name);
+		GrMemoryPool::getSingleton().free(m_name);
 	}
 }
 
-HeapMemoryPool& GrObject::getMemoryPool() const
-{
-	return m_manager->getMemoryPool();
-}
-
 } // end namespace anki

+ 1 - 14
AnKi/Gr/GrObject.h

@@ -39,7 +39,7 @@ enum class GrObjectType : U8
 class GrObject
 {
 public:
-	GrObject(GrManager* manager, GrObjectType type, CString name);
+	GrObject(GrObjectType type, CString name);
 
 	GrObject(const GrObject&) = delete; // Non-copyable
 
@@ -52,18 +52,6 @@ public:
 		return m_type;
 	}
 
-	GrManager& getManager()
-	{
-		return *m_manager;
-	}
-
-	const GrManager& getManager() const
-	{
-		return *m_manager;
-	}
-
-	HeapMemoryPool& getMemoryPool() const;
-
 	void retain() const
 	{
 		m_refcount.fetchAdd(1);
@@ -87,7 +75,6 @@ public:
 	}
 
 private:
-	GrManager* m_manager;
 	Char* m_name = nullptr;
 	U64 m_uuid;
 	mutable Atomic<I32> m_refcount;

+ 3 - 3
AnKi/Gr/GrUpscaler.h

@@ -60,8 +60,8 @@ protected:
 	GrUpscalerType m_upscalerType = GrUpscalerType::kCount;
 
 	/// Construct.
-	GrUpscaler(GrManager* manager, CString name)
-		: GrObject(manager, kClassType, name)
+	GrUpscaler(CString name)
+		: GrObject(kClassType, name)
 	{
 	}
 
@@ -72,7 +72,7 @@ protected:
 
 private:
 	/// Allocate and initialize a new instance.
-	[[nodiscard]] static GrUpscaler* newInstance(GrManager* manager, const GrUpscalerInitInfo& initInfo);
+	[[nodiscard]] static GrUpscaler* newInstance(const GrUpscalerInitInfo& initInfo);
 };
 /// @}
 

+ 3 - 3
AnKi/Gr/OcclusionQuery.h

@@ -25,8 +25,8 @@ public:
 
 protected:
 	/// Construct.
-	OcclusionQuery(GrManager* manager, CString name)
-		: GrObject(manager, kClassType, name)
+	OcclusionQuery(CString name)
+		: GrObject(kClassType, name)
 	{
 	}
 
@@ -37,7 +37,7 @@ protected:
 
 private:
 	/// Allocate and initialize a new instance.
-	[[nodiscard]] static OcclusionQuery* newInstance(GrManager* manager);
+	[[nodiscard]] static OcclusionQuery* newInstance();
 };
 /// @}
 

+ 21 - 39
AnKi/Gr/RenderGraph.cpp

@@ -260,37 +260,19 @@ void FramebufferDescription::bake()
 	ANKI_ASSERT(m_hash != 0 && m_hash != 1);
 }
 
-RenderGraph::RenderGraph(GrManager* manager, CString name)
-	: GrObject(manager, kClassType, name)
+RenderGraph::RenderGraph(CString name)
+	: GrObject(kClassType, name)
 {
-	ANKI_ASSERT(manager);
 }
 
 RenderGraph::~RenderGraph()
 {
 	ANKI_ASSERT(m_ctx == nullptr);
-
-	while(!m_renderTargetCache.isEmpty())
-	{
-		auto it = m_renderTargetCache.getBegin();
-		RenderTargetCacheEntry& entry = *it;
-		entry.m_textures.destroy(getMemoryPool());
-		m_renderTargetCache.erase(getMemoryPool(), it);
-	}
-
-	m_fbCache.destroy(getMemoryPool());
-
-	for(auto& it : m_importedRenderTargets)
-	{
-		it.m_surfOrVolLastUsages.destroy(getMemoryPool());
-	}
-
-	m_importedRenderTargets.destroy(getMemoryPool());
 }
 
-RenderGraph* RenderGraph::newInstance(GrManager* manager)
+RenderGraph* RenderGraph::newInstance()
 {
-	return anki::newInstance<RenderGraph>(manager->getMemoryPool(), manager, "N/A");
+	return anki::newInstance<RenderGraph>(GrMemoryPool::getSingleton(), "N/A");
 }
 
 void RenderGraph::reset()
@@ -329,8 +311,8 @@ void RenderGraph::reset()
 			else
 			{
 				// Not found, create
-				it = m_importedRenderTargets.emplace(getMemoryPool(), hash);
-				it->m_surfOrVolLastUsages.create(getMemoryPool(), surfOrVolumeCount);
+				it = m_importedRenderTargets.emplace(hash);
+				it->m_surfOrVolLastUsages.create(surfOrVolumeCount);
 			}
 
 			// Update the usage
@@ -382,7 +364,7 @@ TexturePtr RenderGraph::getOrCreateRenderTarget(const TextureInitInfo& initInf,
 	{
 		// Didn't found the entry, create a new one
 
-		auto it2 = m_renderTargetCache.emplace(getMemoryPool(), hash);
+		auto it2 = m_renderTargetCache.emplace(hash);
 		entry = &(*it2);
 	}
 	else
@@ -404,10 +386,10 @@ TexturePtr RenderGraph::getOrCreateRenderTarget(const TextureInitInfo& initInf,
 	{
 		// Create it
 
-		tex = getManager().newTexture(initInf);
+		tex = GrManager::getSingleton().newTexture(initInf);
 
 		ANKI_ASSERT(entry->m_texturesInUse == entry->m_textures.getSize());
-		entry->m_textures.resize(getMemoryPool(), entry->m_textures.getSize() + 1);
+		entry->m_textures.resize(entry->m_textures.getSize() + 1);
 		entry->m_textures[entry->m_textures.getSize() - 1] = tex;
 		++entry->m_texturesInUse;
 	}
@@ -477,7 +459,7 @@ FramebufferPtr RenderGraph::getOrCreateFramebuffer(const FramebufferDescription&
 			// Create texture view
 			TextureViewInitInfo viewInit(m_ctx->m_rts[rtHandles[i].m_idx].m_texture,
 										 TextureSubresourceInfo(inAtt.m_surface), "RenderGraph");
-			TextureViewPtr view = getManager().newTextureView(viewInit);
+			TextureViewPtr view = GrManager::getSingleton().newTextureView(viewInit);
 
 			outAtt.m_textureView = std::move(view);
 		}
@@ -496,7 +478,7 @@ FramebufferPtr RenderGraph::getOrCreateFramebuffer(const FramebufferDescription&
 			// Create texture view
 			TextureViewInitInfo viewInit(m_ctx->m_rts[rtHandles[kMaxColorRenderTargets].m_idx].m_texture,
 										 TextureSubresourceInfo(inAtt.m_surface, inAtt.m_aspect), "RenderGraph");
-			TextureViewPtr view = getManager().newTextureView(viewInit);
+			TextureViewPtr view = GrManager::getSingleton().newTextureView(viewInit);
 
 			outAtt.m_textureView = std::move(view);
 		}
@@ -505,7 +487,7 @@ FramebufferPtr RenderGraph::getOrCreateFramebuffer(const FramebufferDescription&
 		{
 			TextureViewInitInfo viewInit(m_ctx->m_rts[rtHandles[kMaxColorRenderTargets + 1].m_idx].m_texture,
 										 fbDescr.m_shadingRateAttachmentSurface, "RenderGraph SRI");
-			TextureViewPtr view = getManager().newTextureView(viewInit);
+			TextureViewPtr view = GrManager::getSingleton().newTextureView(viewInit);
 
 			fbInit.m_shadingRateImage.m_texelWidth = fbDescr.m_shadingRateAttachmentTexelWidth;
 			fbInit.m_shadingRateImage.m_texelHeight = fbDescr.m_shadingRateAttachmentTexelHeight;
@@ -516,8 +498,8 @@ FramebufferPtr RenderGraph::getOrCreateFramebuffer(const FramebufferDescription&
 		fbInit.setName(name);
 
 		// Create
-		fb = getManager().newFramebuffer(fbInit);
-		m_fbCache.emplace(getMemoryPool(), hash, fb);
+		fb = GrManager::getSingleton().newFramebuffer(fbInit);
+		m_fbCache.emplace(hash, fb);
 	}
 
 	return fb;
@@ -880,7 +862,7 @@ void RenderGraph::initBatches()
 		{
 			CommandBufferInitInfo cmdbInit;
 			cmdbInit.m_flags = CommandBufferFlag::kGeneralWork;
-			CommandBufferPtr cmdb = getManager().newCommandBuffer(cmdbInit);
+			CommandBufferPtr cmdb = GrManager::getSingleton().newCommandBuffer(cmdbInit);
 
 			m_ctx->m_graphicsCmdbs.emplaceBack(*m_ctx->m_pool, cmdb);
 
@@ -890,7 +872,7 @@ void RenderGraph::initBatches()
 			if(setTimestamp) [[unlikely]]
 			{
 				setTimestamp = false;
-				TimestampQueryPtr query = getManager().newTimestampQuery();
+				TimestampQueryPtr query = GrManager::getSingleton().newTimestampQuery();
 				TimestampQuery* pQuery = query.get();
 				cmdb->resetTimestampQueries({&pQuery, 1});
 				cmdb->writeTimestamp(query);
@@ -1267,7 +1249,7 @@ void RenderGraph::runSecondLevel(U32 threadIdx)
 		if(threadIdx < size)
 		{
 			ANKI_ASSERT(!p.m_secondLevelCmdbs[threadIdx].isCreated());
-			p.m_secondLevelCmdbs[threadIdx] = getManager().newCommandBuffer(p.m_secondLevelCmdbInitInfo);
+			p.m_secondLevelCmdbs[threadIdx] = GrManager::getSingleton().newCommandBuffer(p.m_secondLevelCmdbInitInfo);
 
 			ctx.m_commandBuffer = p.m_secondLevelCmdbs[threadIdx];
 			ctx.m_secondLevelCommandBufferCount = size;
@@ -1383,7 +1365,7 @@ void RenderGraph::flush()
 		{
 			// Write a timestamp before the last flush
 
-			TimestampQueryPtr query = getManager().newTimestampQuery();
+			TimestampQueryPtr query = GrManager::getSingleton().newTimestampQuery();
 			TimestampQuery* pQuery = query.get();
 			m_ctx->m_graphicsCmdbs[i]->resetTimestampQueries({&pQuery, 1});
 			m_ctx->m_graphicsCmdbs[i]->writeTimestamp(query);
@@ -1428,10 +1410,10 @@ void RenderGraph::periodicCleanup()
 			rtsCleanedCount += entry.m_textures.getSize() - entry.m_texturesInUse;
 
 			// New array
-			DynamicArray<TexturePtr> newArray;
+			GrDynamicArray<TexturePtr> newArray;
 			if(entry.m_texturesInUse > 0)
 			{
-				newArray.create(getMemoryPool(), entry.m_texturesInUse);
+				newArray.create(entry.m_texturesInUse);
 			}
 
 			// Populate the new array
@@ -1441,7 +1423,7 @@ void RenderGraph::periodicCleanup()
 			}
 
 			// Destroy the old array and the rest of the textures
-			entry.m_textures.destroy(getMemoryPool());
+			entry.m_textures.destroy();
 
 			// Move new array
 			entry.m_textures = std::move(newArray);

+ 14 - 14
AnKi/Gr/RenderGraph.h

@@ -132,7 +132,7 @@ public:
 		TexturePtr tex = getTexture(handle);
 		TextureViewInitInfo viewInit(tex, "TmpRenderGraph"); // Use the whole texture
 		getRenderTargetState(handle, viewInit, tex);
-		return m_commandBuffer->getManager().newTextureView(viewInit);
+		return GrManager::getSingleton().newTextureView(viewInit);
 	}
 
 	/// Convenience method.
@@ -142,7 +142,7 @@ public:
 		TexturePtr tex;
 		getRenderTargetState(handle, subresource, tex);
 		TextureViewInitInfo viewInit(tex, subresource, "TmpRenderGraph");
-		TextureViewPtr view = m_commandBuffer->getManager().newTextureView(viewInit);
+		TextureViewPtr view = GrManager::getSingleton().newTextureView(viewInit);
 		m_commandBuffer->bindTextureAndSampler(set, binding, view, sampler);
 	}
 
@@ -152,7 +152,7 @@ public:
 		TexturePtr tex;
 		getRenderTargetState(handle, subresource, tex);
 		TextureViewInitInfo viewInit(tex, subresource, "TmpRenderGraph");
-		TextureViewPtr view = m_commandBuffer->getManager().newTextureView(viewInit);
+		TextureViewPtr view = GrManager::getSingleton().newTextureView(viewInit);
 		m_commandBuffer->bindTexture(set, binding, view);
 	}
 
@@ -162,7 +162,7 @@ public:
 		TexturePtr tex = getTexture(handle);
 		TextureViewInitInfo viewInit(tex); // Use the whole texture
 		getRenderTargetState(handle, viewInit, tex);
-		TextureViewPtr view = m_commandBuffer->getManager().newTextureView(viewInit);
+		TextureViewPtr view = GrManager::getSingleton().newTextureView(viewInit);
 		m_commandBuffer->bindTextureAndSampler(set, binding, view, sampler);
 	}
 
@@ -172,7 +172,7 @@ public:
 		TexturePtr tex = getTexture(handle);
 		TextureViewInitInfo viewInit(tex); // Use the whole texture
 		getRenderTargetState(handle, viewInit, tex);
-		TextureViewPtr view = m_commandBuffer->getManager().newTextureView(viewInit);
+		TextureViewPtr view = GrManager::getSingleton().newTextureView(viewInit);
 		m_commandBuffer->bindTexture(set, binding, view, arrayIdx);
 	}
 
@@ -183,7 +183,7 @@ public:
 		TexturePtr tex;
 		getRenderTargetState(handle, subresource, tex);
 		TextureViewInitInfo viewInit(tex, subresource, "TmpRenderGraph");
-		TextureViewPtr view = m_commandBuffer->getManager().newTextureView(viewInit);
+		TextureViewPtr view = GrManager::getSingleton().newTextureView(viewInit);
 		m_commandBuffer->bindImage(set, binding, view, arrayIdx);
 	}
 
@@ -199,7 +199,7 @@ public:
 		const TextureSubresourceInfo subresource;
 		getRenderTargetState(handle, subresource, tex);
 		TextureViewInitInfo viewInit(tex, subresource, "TmpRenderGraph");
-		TextureViewPtr view = m_commandBuffer->getManager().newTextureView(viewInit);
+		TextureViewPtr view = GrManager::getSingleton().newTextureView(viewInit);
 		m_commandBuffer->bindImage(set, binding, view, arrayIdx);
 	}
 
@@ -701,7 +701,7 @@ private:
 	class RenderTargetCacheEntry
 	{
 	public:
-		DynamicArray<TexturePtr> m_textures;
+		GrDynamicArray<TexturePtr> m_textures;
 		U32 m_texturesInUse = 0;
 	};
 
@@ -709,12 +709,12 @@ private:
 	class ImportedRenderTargetInfo
 	{
 	public:
-		DynamicArray<TextureUsageBit> m_surfOrVolLastUsages; ///< Last TextureUsageBit of the imported RT.
+		GrDynamicArray<TextureUsageBit> m_surfOrVolLastUsages; ///< Last TextureUsageBit of the imported RT.
 	};
 
-	HashMap<U64, RenderTargetCacheEntry> m_renderTargetCache; ///< Non-imported render targets.
-	HashMap<U64, FramebufferPtr> m_fbCache; ///< Framebuffer cache.
-	HashMap<U64, ImportedRenderTargetInfo> m_importedRenderTargets;
+	GrHashMap<U64, RenderTargetCacheEntry> m_renderTargetCache; ///< Non-imported render targets.
+	GrHashMap<U64, FramebufferPtr> m_fbCache; ///< Framebuffer cache.
+	GrHashMap<U64, ImportedRenderTargetInfo> m_importedRenderTargets;
 
 	BakeContext* m_ctx = nullptr;
 	U64 m_version = 0;
@@ -728,11 +728,11 @@ private:
 		U8 m_nextTimestamp = 0;
 	} m_statistics;
 
-	RenderGraph(GrManager* manager, CString name);
+	RenderGraph(CString name);
 
 	~RenderGraph();
 
-	[[nodiscard]] static RenderGraph* newInstance(GrManager* manager);
+	[[nodiscard]] static RenderGraph* newInstance();
 
 	BakeContext* newContext(const RenderGraphDescription& descr, StackMemoryPool& pool);
 	void initRenderPassesAndSetDeps(const RenderGraphDescription& descr, StackMemoryPool& pool);

+ 3 - 3
AnKi/Gr/Sampler.h

@@ -55,8 +55,8 @@ public:
 
 protected:
 	/// Construct.
-	Sampler(GrManager* manager, CString name)
-		: GrObject(manager, kClassType, name)
+	Sampler(CString name)
+		: GrObject(kClassType, name)
 	{
 	}
 
@@ -67,7 +67,7 @@ protected:
 
 private:
 	/// Allocate and initialize a new instance.
-	[[nodiscard]] static Sampler* newInstance(GrManager* manager, const SamplerInitInfo& init);
+	[[nodiscard]] static Sampler* newInstance(const SamplerInitInfo& init);
 };
 /// @}
 

+ 3 - 3
AnKi/Gr/Shader.h

@@ -101,8 +101,8 @@ protected:
 	ShaderType m_shaderType = ShaderType::kCount;
 
 	/// Construct.
-	Shader(GrManager* manager, CString name)
-		: GrObject(manager, kClassType, name)
+	Shader(CString name)
+		: GrObject(kClassType, name)
 	{
 	}
 
@@ -113,7 +113,7 @@ protected:
 
 private:
 	/// Allocate and initialize a new instance.
-	[[nodiscard]] static Shader* newInstance(GrManager* manager, const ShaderInitInfo& init);
+	[[nodiscard]] static Shader* newInstance(const ShaderInitInfo& init);
 };
 /// @}
 

+ 3 - 3
AnKi/Gr/ShaderProgram.h

@@ -73,8 +73,8 @@ public:
 
 protected:
 	/// Construct.
-	ShaderProgram(GrManager* manager, CString name)
-		: GrObject(manager, kClassType, name)
+	ShaderProgram(CString name)
+		: GrObject(kClassType, name)
 	{
 	}
 
@@ -85,7 +85,7 @@ protected:
 
 private:
 	/// Allocate and initialize a new instance.
-	[[nodiscard]] static ShaderProgram* newInstance(GrManager* manager, const ShaderProgramInitInfo& init);
+	[[nodiscard]] static ShaderProgram* newInstance(const ShaderProgramInitInfo& init);
 };
 /// @}
 

+ 3 - 3
AnKi/Gr/Texture.h

@@ -254,8 +254,8 @@ protected:
 	DepthStencilAspectBit m_aspect = DepthStencilAspectBit::kNone;
 
 	/// Construct.
-	Texture(GrManager* manager, CString name)
-		: GrObject(manager, kClassType, name)
+	Texture(CString name)
+		: GrObject(kClassType, name)
 	{
 	}
 
@@ -266,7 +266,7 @@ protected:
 
 private:
 	/// Allocate and initialize a new instance.
-	[[nodiscard]] static Texture* newInstance(GrManager* manager, const TextureInitInfo& init);
+	[[nodiscard]] static Texture* newInstance(const TextureInitInfo& init);
 };
 /// @}
 

+ 3 - 3
AnKi/Gr/TextureView.h

@@ -97,8 +97,8 @@ protected:
 	TextureSubresourceInfo m_subresource;
 
 	/// Construct.
-	TextureView(GrManager* manager, CString name)
-		: GrObject(manager, kClassType, name)
+	TextureView(CString name)
+		: GrObject(kClassType, name)
 	{
 		m_subresource.m_depthStencilAspect = DepthStencilAspectBit::kNone;
 
@@ -127,7 +127,7 @@ protected:
 
 private:
 	/// Allocate and initialize a new instance.
-	[[nodiscard]] static TextureView* newInstance(GrManager* manager, const TextureViewInitInfo& init);
+	[[nodiscard]] static TextureView* newInstance(const TextureViewInitInfo& init);
 };
 /// @}
 

+ 3 - 3
AnKi/Gr/TimestampQuery.h

@@ -25,8 +25,8 @@ public:
 
 protected:
 	/// Construct.
-	TimestampQuery(GrManager* manager, CString name)
-		: GrObject(manager, kClassType, name)
+	TimestampQuery(CString name)
+		: GrObject(kClassType, name)
 	{
 	}
 
@@ -37,7 +37,7 @@ protected:
 
 private:
 	/// Allocate and initialize a new instance.
-	[[nodiscard]] static TimestampQuery* newInstance(GrManager* manager);
+	[[nodiscard]] static TimestampQuery* newInstance();
 };
 /// @}
 

+ 22 - 32
AnKi/Gr/Utils/SegregatedListsGpuMemoryPool.cpp

@@ -42,32 +42,28 @@ public:
 		m_parent->deleteChunk(chunk);
 	}
 
-	BaseMemoryPool& getMemoryPool() const
+	static constexpr PtrSize getMinSizeAlignment()
 	{
-		return *m_parent->m_pool;
+		return 4;
 	}
 
-	static constexpr PtrSize getMinSizeAlignment()
+	BaseMemoryPool& getMemoryPool() const
 	{
-		return 4;
+		return GrMemoryPool::getSingleton();
 	}
 	/// @}
 };
 
-void SegregatedListsGpuMemoryPool::init(GrManager* gr, BaseMemoryPool* pool, BufferUsageBit gpuBufferUsage,
-										ConstWeakArray<PtrSize> classUpperSizes, PtrSize initialGpuBufferSize,
-										CString bufferName, Bool allowCoWs)
+void SegregatedListsGpuMemoryPool::init(BufferUsageBit gpuBufferUsage, ConstWeakArray<PtrSize> classUpperSizes,
+										PtrSize initialGpuBufferSize, CString bufferName, Bool allowCoWs)
 {
 	ANKI_ASSERT(!isInitialized());
-	ANKI_ASSERT(gr && pool);
-	m_gr = gr;
-	m_pool = pool;
 
 	ANKI_ASSERT(gpuBufferUsage != BufferUsageBit::kNone);
 	m_bufferUsage = gpuBufferUsage;
 
 	ANKI_ASSERT(classUpperSizes.getSize() > 0);
-	m_classes.create(*m_pool, classUpperSizes.getSize());
+	m_classes.create(classUpperSizes.getSize());
 	for(U32 i = 0; i < m_classes.getSize(); ++i)
 	{
 		m_classes[i] = classUpperSizes[i];
@@ -76,9 +72,9 @@ void SegregatedListsGpuMemoryPool::init(GrManager* gr, BaseMemoryPool* pool, Buf
 	ANKI_ASSERT(initialGpuBufferSize > 0);
 	m_initialBufferSize = initialGpuBufferSize;
 
-	m_bufferName.create(*m_pool, bufferName);
+	m_bufferName.create(bufferName);
 
-	m_builder = newInstance<Builder>(*m_pool);
+	m_builder = newInstance<Builder>(GrMemoryPool::getSingleton());
 	m_builder->getInterface().m_parent = this;
 
 	m_frame = 0;
@@ -93,29 +89,23 @@ void SegregatedListsGpuMemoryPool::destroy()
 		return;
 	}
 
-	m_gr->finish();
-	m_gr = nullptr;
+	GrManager::getSingleton().finish();
 
-	for(DynamicArray<SegregatedListsGpuMemoryPoolToken>& arr : m_garbage)
+	for(GrDynamicArray<SegregatedListsGpuMemoryPoolToken>& arr : m_garbage)
 	{
 		for(const SegregatedListsGpuMemoryPoolToken& token : arr)
 		{
 			m_builder->free(static_cast<Chunk*>(token.m_chunk), token.m_chunkOffset, token.m_size);
 		}
-
-		arr.destroy(*m_pool);
 	}
 
-	m_classes.destroy(*m_pool);
-	deleteInstance(*m_pool, m_builder);
+	deleteInstance(GrMemoryPool::getSingleton(), m_builder);
 	m_gpuBuffer.reset(nullptr);
-	m_bufferName.destroy(*m_pool);
 
 	for(Chunk* chunk : m_deletedChunks)
 	{
-		deleteInstance(*m_pool, chunk);
+		deleteInstance(GrMemoryPool::getSingleton(), chunk);
 	}
-	m_deletedChunks.destroy(*m_pool);
 }
 
 Error SegregatedListsGpuMemoryPool::allocateChunk(Chunk*& newChunk, PtrSize& chunkSize)
@@ -129,9 +119,9 @@ Error SegregatedListsGpuMemoryPool::allocateChunk(Chunk*& newChunk, PtrSize& chu
 		BufferInitInfo buffInit(m_bufferName);
 		buffInit.m_size = m_initialBufferSize;
 		buffInit.m_usage = m_bufferUsage | BufferUsageBit::kAllTransfer;
-		m_gpuBuffer = m_gr->newBuffer(buffInit);
+		m_gpuBuffer = GrManager::getSingleton().newBuffer(buffInit);
 
-		newChunk = newInstance<Chunk>(*m_pool);
+		newChunk = newInstance<Chunk>(GrMemoryPool::getSingleton());
 		newChunk->m_offsetInGpuBuffer = 0;
 	}
 	else if(m_deletedChunks.getSize() > 0)
@@ -139,7 +129,7 @@ Error SegregatedListsGpuMemoryPool::allocateChunk(Chunk*& newChunk, PtrSize& chu
 		// We already have a deleted chunk, use that
 
 		newChunk = m_deletedChunks.getBack();
-		m_deletedChunks.popBack(*m_pool);
+		m_deletedChunks.popBack();
 	}
 	else if(m_allowCoWs)
 	{
@@ -151,12 +141,12 @@ Error SegregatedListsGpuMemoryPool::allocateChunk(Chunk*& newChunk, PtrSize& chu
 		BufferInitInfo buffInit(m_bufferName);
 		buffInit.m_size = m_gpuBuffer->getSize() * 2;
 		buffInit.m_usage = m_bufferUsage | BufferUsageBit::kAllTransfer;
-		BufferPtr newBuffer = m_gr->newBuffer(buffInit);
+		BufferPtr newBuffer = GrManager::getSingleton().newBuffer(buffInit);
 
 		// Do the copy
 		CommandBufferInitInfo cmdbInit("SegregatedListsGpuMemoryPool CoW");
 		cmdbInit.m_flags = CommandBufferFlag::kSmallBatch;
-		CommandBufferPtr cmdb = m_gr->newCommandBuffer(cmdbInit);
+		CommandBufferPtr cmdb = GrManager::getSingleton().newCommandBuffer(cmdbInit);
 
 		Array<BufferBarrierInfo, 2> barriers;
 		barriers[0].m_buffer = m_gpuBuffer.get();
@@ -176,7 +166,7 @@ Error SegregatedListsGpuMemoryPool::allocateChunk(Chunk*& newChunk, PtrSize& chu
 		cmdb->flush();
 
 		// Create the new chunk
-		newChunk = newInstance<Chunk>(*m_pool);
+		newChunk = newInstance<Chunk>(GrMemoryPool::getSingleton());
 		newChunk->m_offsetInGpuBuffer = m_gpuBuffer->getSize();
 
 		// Switch the buffers
@@ -195,7 +185,7 @@ Error SegregatedListsGpuMemoryPool::allocateChunk(Chunk*& newChunk, PtrSize& chu
 
 void SegregatedListsGpuMemoryPool::deleteChunk(Chunk* chunk)
 {
-	m_deletedChunks.emplaceBack(*m_pool, chunk);
+	m_deletedChunks.emplaceBack(chunk);
 }
 
 void SegregatedListsGpuMemoryPool::allocate(PtrSize size, U32 alignment, SegregatedListsGpuMemoryPoolToken& token)
@@ -233,7 +223,7 @@ void SegregatedListsGpuMemoryPool::deferredFree(SegregatedListsGpuMemoryPoolToke
 
 	{
 		LockGuard lock(m_lock);
-		m_garbage[m_frame].emplaceBack(*m_pool, token);
+		m_garbage[m_frame].emplaceBack(token);
 	}
 
 	token = {};
@@ -256,7 +246,7 @@ void SegregatedListsGpuMemoryPool::endFrame()
 		m_allocatedSize -= token.m_size;
 	}
 
-	m_garbage[m_frame].destroy(*m_pool);
+	m_garbage[m_frame].destroy();
 }
 
 void SegregatedListsGpuMemoryPool::getStats(F32& externalFragmentation, PtrSize& userAllocatedSize,

+ 7 - 16
AnKi/Gr/Utils/SegregatedListsGpuMemoryPool.h

@@ -54,9 +54,8 @@ public:
 
 	SegregatedListsGpuMemoryPool& operator=(const SegregatedListsGpuMemoryPool&) = delete;
 
-	void init(GrManager* gr, BaseMemoryPool* pool, BufferUsageBit gpuBufferUsage,
-			  ConstWeakArray<PtrSize> classUpperSizes, PtrSize initialGpuBufferSize, CString bufferName,
-			  Bool allowCoWs);
+	void init(BufferUsageBit gpuBufferUsage, ConstWeakArray<PtrSize> classUpperSizes, PtrSize initialGpuBufferSize,
+			  CString bufferName, Bool allowCoWs);
 
 	void destroy();
 
@@ -82,23 +81,15 @@ public:
 	/// @note It's thread-safe.
 	void getStats(F32& externalFragmentation, PtrSize& userAllocatedSize, PtrSize& totalSize) const;
 
-	GrManager& getGrManager()
-	{
-		ANKI_ASSERT(m_gr);
-		return *m_gr;
-	}
-
 private:
 	class BuilderInterface;
 	class Chunk;
 	using Builder = SegregatedListsAllocatorBuilder<Chunk, BuilderInterface, DummyMutex>;
 
-	GrManager* m_gr = nullptr;
-	mutable BaseMemoryPool* m_pool = nullptr;
 	BufferUsageBit m_bufferUsage = BufferUsageBit::kNone;
-	DynamicArray<PtrSize> m_classes;
+	GrDynamicArray<PtrSize> m_classes;
 	PtrSize m_initialBufferSize = 0;
-	String m_bufferName;
+	GrString m_bufferName;
 
 	mutable Mutex m_lock;
 
@@ -106,9 +97,9 @@ private:
 	BufferPtr m_gpuBuffer;
 	PtrSize m_allocatedSize = 0;
 
-	DynamicArray<Chunk*> m_deletedChunks;
+	GrDynamicArray<Chunk*> m_deletedChunks;
 
-	Array<DynamicArray<SegregatedListsGpuMemoryPoolToken>, kMaxFramesInFlight> m_garbage;
+	Array<GrDynamicArray<SegregatedListsGpuMemoryPoolToken>, kMaxFramesInFlight> m_garbage;
 	U8 m_frame = 0;
 	Bool m_allowCoWs = true;
 
@@ -117,7 +108,7 @@ private:
 
 	Bool isInitialized() const
 	{
-		return m_gr != nullptr;
+		return m_bufferUsage != BufferUsageBit::kNone;
 	}
 };
 /// @}

+ 10 - 20
AnKi/Gr/Utils/StackGpuMemoryPool.cpp

@@ -25,23 +25,16 @@ public:
 class StackGpuMemoryPool::BuilderInterface
 {
 public:
-	GrManager* m_gr = nullptr;
-	BaseMemoryPool* m_cpuPool = nullptr;
 	PtrSize m_initialSize = 0;
 	F64 m_scale = 0.0;
 	PtrSize m_bias = 0;
-	String m_bufferName;
+	GrString m_bufferName;
 	U32 m_alignment = 0;
 	BufferUsageBit m_bufferUsage = BufferUsageBit::kNone;
 	BufferMapAccessBit m_bufferMap = BufferMapAccessBit::kNone;
 	U8 m_chunkCount = 0;
 	Bool m_allowToGrow = false;
 
-	~BuilderInterface()
-	{
-		m_bufferName.destroy(*m_cpuPool);
-	}
-
 	// Builder interface stuff:
 	U32 getMaxAlignment() const
 	{
@@ -76,13 +69,13 @@ public:
 			return Error::kOutOfMemory;
 		}
 
-		Chunk* chunk = newInstance<Chunk>(*m_cpuPool);
+		Chunk* chunk = newInstance<Chunk>(GrMemoryPool::getSingleton());
 
 		BufferInitInfo buffInit(m_bufferName);
 		buffInit.m_size = size;
 		buffInit.m_usage = m_bufferUsage;
 		buffInit.m_mapAccess = m_bufferMap;
-		chunk->m_buffer = m_gr->newBuffer(buffInit);
+		chunk->m_buffer = GrManager::getSingleton().newBuffer(buffInit);
 
 		if(!!m_bufferMap)
 		{
@@ -102,7 +95,7 @@ public:
 			chunk->m_buffer->unmap();
 		}
 
-		deleteInstance(*m_cpuPool, chunk);
+		deleteInstance(GrMemoryPool::getSingleton(), chunk);
 	}
 
 	void recycleChunk([[maybe_unused]] Chunk& out)
@@ -120,27 +113,24 @@ StackGpuMemoryPool::~StackGpuMemoryPool()
 {
 	if(m_builder)
 	{
-		BaseMemoryPool* cpuPool = m_builder->getInterface().m_cpuPool;
-		deleteInstance(*cpuPool, m_builder);
+		deleteInstance(GrMemoryPool::getSingleton(), m_builder);
 	}
 }
 
-void StackGpuMemoryPool::init(GrManager* gr, BaseMemoryPool* cpuPool, PtrSize initialSize, F64 nextChunkGrowScale,
-							  PtrSize nextChunkGrowBias, U32 alignment, BufferUsageBit bufferUsage,
-							  BufferMapAccessBit bufferMapping, Bool allowToGrow, CString bufferName)
+void StackGpuMemoryPool::init(PtrSize initialSize, F64 nextChunkGrowScale, PtrSize nextChunkGrowBias, U32 alignment,
+							  BufferUsageBit bufferUsage, BufferMapAccessBit bufferMapping, Bool allowToGrow,
+							  CString bufferName)
 {
 	ANKI_ASSERT(m_builder == nullptr);
 	ANKI_ASSERT(initialSize > 0 && alignment > 0);
 	ANKI_ASSERT(nextChunkGrowScale >= 1.0 && nextChunkGrowBias > 0);
 
-	m_builder = newInstance<Builder>(*cpuPool);
+	m_builder = newInstance<Builder>(GrMemoryPool::getSingleton());
 	BuilderInterface& inter = m_builder->getInterface();
-	inter.m_gr = gr;
-	inter.m_cpuPool = cpuPool;
 	inter.m_initialSize = initialSize;
 	inter.m_scale = nextChunkGrowScale;
 	inter.m_bias = nextChunkGrowBias;
-	inter.m_bufferName.create(*cpuPool, bufferName);
+	inter.m_bufferName.create(bufferName);
 	inter.m_alignment = alignment;
 	inter.m_bufferUsage = bufferUsage;
 	inter.m_bufferMap = bufferMapping;

+ 2 - 3
AnKi/Gr/Utils/StackGpuMemoryPool.h

@@ -25,9 +25,8 @@ public:
 
 	StackGpuMemoryPool& operator=(const StackGpuMemoryPool&) = delete; // Non-copyable
 
-	void init(GrManager* gr, BaseMemoryPool* cpuPool, PtrSize initialSize, F64 nextChunkGrowScale,
-			  PtrSize nextChunkGrowBias, U32 alignment, BufferUsageBit bufferUsage, BufferMapAccessBit bufferMapping,
-			  Bool allowToGrow, CString bufferName);
+	void init(PtrSize initialSize, F64 nextChunkGrowScale, PtrSize nextChunkGrowBias, U32 alignment,
+			  BufferUsageBit bufferUsage, BufferMapAccessBit bufferMapping, Bool allowToGrow, CString bufferName);
 
 	/// @note It's thread-safe against other allocate()
 	void allocate(PtrSize size, PtrSize& outOffset, Buffer*& buffer)

+ 3 - 3
AnKi/Gr/Vulkan/AccelerationStructure.cpp

@@ -9,14 +9,14 @@
 
 namespace anki {
 
-AccelerationStructure* AccelerationStructure::newInstance(GrManager* manager, const AccelerationStructureInitInfo& init)
+AccelerationStructure* AccelerationStructure::newInstance(const AccelerationStructureInitInfo& init)
 {
 	AccelerationStructureImpl* impl =
-		anki::newInstance<AccelerationStructureImpl>(manager->getMemoryPool(), manager, init.getName());
+		anki::newInstance<AccelerationStructureImpl>(GrMemoryPool::getSingleton(), init.getName());
 	const Error err = impl->init(init);
 	if(err)
 	{
-		deleteInstance(manager->getMemoryPool(), impl);
+		deleteInstance(GrMemoryPool::getSingleton(), impl);
 		impl = nullptr;
 	}
 	return impl;

+ 15 - 14
AnKi/Gr/Vulkan/AccelerationStructureImpl.cpp

@@ -10,11 +10,11 @@ namespace anki {
 
 AccelerationStructureImpl::~AccelerationStructureImpl()
 {
-	m_topLevelInfo.m_blas.destroy(getMemoryPool());
+	m_topLevelInfo.m_blas.destroy();
 
 	if(m_handle)
 	{
-		vkDestroyAccelerationStructureKHR(getDevice(), m_handle, nullptr);
+		vkDestroyAccelerationStructureKHR(getGrManagerImpl().getDevice(), m_handle, nullptr);
 	}
 }
 
@@ -24,6 +24,7 @@ Error AccelerationStructureImpl::init(const AccelerationStructureInitInfo& inf)
 
 	ANKI_ASSERT(inf.isValid());
 	m_type = inf.m_type;
+	const VkDevice vkdev = getGrManagerImpl().getDevice();
 
 	if(m_type == AccelerationStructureType::kBottomLevel)
 	{
@@ -55,15 +56,15 @@ Error AccelerationStructureImpl::init(const AccelerationStructureInitInfo& inf)
 		VkAccelerationStructureBuildSizesInfoKHR buildSizes = {};
 		const U32 primitiveCount = inf.m_bottomLevel.m_indexCount / 3;
 		buildSizes.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR;
-		vkGetAccelerationStructureBuildSizesKHR(getDevice(), VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
-												&buildInfo, &primitiveCount, &buildSizes);
+		vkGetAccelerationStructureBuildSizesKHR(vkdev, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &buildInfo,
+												&primitiveCount, &buildSizes);
 		m_scratchBufferSize = U32(buildSizes.buildScratchSize);
 
 		// Create the buffer that holds the AS memory
 		BufferInitInfo bufferInit(inf.getName());
 		bufferInit.m_usage = PrivateBufferUsageBit::kAccelerationStructure;
 		bufferInit.m_size = buildSizes.accelerationStructureSize;
-		m_asBuffer = getManager().newBuffer(bufferInit);
+		m_asBuffer = getGrManagerImpl().newBuffer(bufferInit);
 
 		// Create the AS
 		VkAccelerationStructureCreateInfoKHR asCi = {};
@@ -73,13 +74,13 @@ Error AccelerationStructureImpl::init(const AccelerationStructureInitInfo& inf)
 		asCi.offset = 0;
 		asCi.size = buildSizes.accelerationStructureSize;
 		asCi.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
-		ANKI_VK_CHECK(vkCreateAccelerationStructureKHR(getDevice(), &asCi, nullptr, &m_handle));
+		ANKI_VK_CHECK(vkCreateAccelerationStructureKHR(vkdev, &asCi, nullptr, &m_handle));
 
 		// Get its address
 		VkAccelerationStructureDeviceAddressInfoKHR addressInfo = {};
 		addressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR;
 		addressInfo.accelerationStructure = m_handle;
-		m_deviceAddress = vkGetAccelerationStructureDeviceAddressKHR(getDevice(), &addressInfo);
+		m_deviceAddress = vkGetAccelerationStructureDeviceAddressKHR(vkdev, &addressInfo);
 
 		// Almost finalize the build info
 		buildInfo.dstAccelerationStructure = m_handle;
@@ -90,13 +91,13 @@ Error AccelerationStructureImpl::init(const AccelerationStructureInitInfo& inf)
 	else
 	{
 		// Create the instances buffer
-		m_topLevelInfo.m_blas.resizeStorage(getMemoryPool(), inf.m_topLevel.m_instances.getSize());
+		m_topLevelInfo.m_blas.resizeStorage(inf.m_topLevel.m_instances.getSize());
 
 		BufferInitInfo buffInit("AS instances");
 		buffInit.m_size = sizeof(VkAccelerationStructureInstanceKHR) * inf.m_topLevel.m_instances.getSize();
 		buffInit.m_usage = PrivateBufferUsageBit::kAccelerationStructure;
 		buffInit.m_mapAccess = BufferMapAccessBit::kWrite;
-		m_topLevelInfo.m_instancesBuffer = getManager().newBuffer(buffInit);
+		m_topLevelInfo.m_instancesBuffer = getGrManagerImpl().newBuffer(buffInit);
 
 		VkAccelerationStructureInstanceKHR* instances = static_cast<VkAccelerationStructureInstanceKHR*>(
 			m_topLevelInfo.m_instancesBuffer->map(0, kMaxPtrSize, BufferMapAccessBit::kWrite));
@@ -116,7 +117,7 @@ Error AccelerationStructureImpl::init(const AccelerationStructureInitInfo& inf)
 			ANKI_ASSERT(outInst.accelerationStructureReference != 0);
 
 			// Hold the reference
-			m_topLevelInfo.m_blas.emplaceBack(getMemoryPool(), inf.m_topLevel.m_instances[i].m_bottomLevel);
+			m_topLevelInfo.m_blas.emplaceBack(inf.m_topLevel.m_instances[i].m_bottomLevel);
 		}
 
 		m_topLevelInfo.m_instancesBuffer->flush(0, kMaxPtrSize);
@@ -144,15 +145,15 @@ Error AccelerationStructureImpl::init(const AccelerationStructureInitInfo& inf)
 		VkAccelerationStructureBuildSizesInfoKHR buildSizes = {};
 		const U32 instanceCount = inf.m_topLevel.m_instances.getSize();
 		buildSizes.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR;
-		vkGetAccelerationStructureBuildSizesKHR(getDevice(), VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
-												&buildInfo, &instanceCount, &buildSizes);
+		vkGetAccelerationStructureBuildSizesKHR(vkdev, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &buildInfo,
+												&instanceCount, &buildSizes);
 		m_scratchBufferSize = U32(buildSizes.buildScratchSize);
 
 		// Create the buffer that holds the AS memory
 		BufferInitInfo bufferInit(inf.getName());
 		bufferInit.m_usage = PrivateBufferUsageBit::kAccelerationStructure;
 		bufferInit.m_size = buildSizes.accelerationStructureSize;
-		m_asBuffer = getManager().newBuffer(bufferInit);
+		m_asBuffer = getGrManagerImpl().newBuffer(bufferInit);
 
 		// Create the AS
 		VkAccelerationStructureCreateInfoKHR asCi = {};
@@ -162,7 +163,7 @@ Error AccelerationStructureImpl::init(const AccelerationStructureInitInfo& inf)
 		asCi.offset = 0;
 		asCi.size = buildSizes.accelerationStructureSize;
 		asCi.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
-		ANKI_VK_CHECK(vkCreateAccelerationStructureKHR(getDevice(), &asCi, nullptr, &m_handle));
+		ANKI_VK_CHECK(vkCreateAccelerationStructureKHR(vkdev, &asCi, nullptr, &m_handle));
 
 		// Almost finalize the build info
 		buildInfo.dstAccelerationStructure = m_handle;

+ 4 - 7
AnKi/Gr/Vulkan/AccelerationStructureImpl.h

@@ -6,7 +6,6 @@
 #pragma once
 
 #include <AnKi/Gr/AccelerationStructure.h>
-#include <AnKi/Gr/Vulkan/VulkanObject.h>
 #include <AnKi/Gr/Vulkan/GpuMemoryManager.h>
 
 namespace anki {
@@ -15,13 +14,11 @@ namespace anki {
 /// @{
 
 /// AccelerationStructure implementation.
-class AccelerationStructureImpl final :
-	public AccelerationStructure,
-	public VulkanObject<AccelerationStructure, AccelerationStructureImpl>
+class AccelerationStructureImpl final : public AccelerationStructure
 {
 public:
-	AccelerationStructureImpl(GrManager* manager, CString name)
-		: AccelerationStructure(manager, name)
+	AccelerationStructureImpl(CString name)
+		: AccelerationStructure(name)
 	{
 	}
 
@@ -65,7 +62,7 @@ private:
 	{
 	public:
 		BufferPtr m_instancesBuffer;
-		DynamicArray<AccelerationStructurePtr> m_blas;
+		GrDynamicArray<AccelerationStructurePtr> m_blas;
 	};
 
 	BufferPtr m_asBuffer;

+ 3 - 3
AnKi/Gr/Vulkan/Buffer.cpp

@@ -9,13 +9,13 @@
 
 namespace anki {
 
-Buffer* Buffer::newInstance(GrManager* manager, const BufferInitInfo& init)
+Buffer* Buffer::newInstance(const BufferInitInfo& init)
 {
-	BufferImpl* impl = anki::newInstance<BufferImpl>(manager->getMemoryPool(), manager, init.getName());
+	BufferImpl* impl = anki::newInstance<BufferImpl>(GrMemoryPool::getSingleton(), init.getName());
 	const Error err = impl->init(init);
 	if(err)
 	{
-		deleteInstance(manager->getMemoryPool(), impl);
+		deleteInstance(GrMemoryPool::getSingleton(), impl);
 		impl = nullptr;
 	}
 	return impl;

+ 8 - 10
AnKi/Gr/Vulkan/BufferImpl.cpp

@@ -12,13 +12,13 @@ BufferImpl::~BufferImpl()
 {
 	ANKI_ASSERT(!m_mapped);
 
-	BufferGarbage* garbage = anki::newInstance<BufferGarbage>(getMemoryPool());
+	BufferGarbage* garbage = anki::newInstance<BufferGarbage>(GrMemoryPool::getSingleton());
 	garbage->m_bufferHandle = m_handle;
 	garbage->m_memoryHandle = m_memHandle;
 
 	if(m_views.getSize())
 	{
-		garbage->m_viewHandles.create(getMemoryPool(), U32(m_views.getSize()));
+		garbage->m_viewHandles.create(U32(m_views.getSize()));
 
 		U32 count = 0;
 		for(auto it : m_views)
@@ -41,8 +41,6 @@ BufferImpl::~BufferImpl()
 		ANKI_VK_LOGW("Buffer needed invalidation but you never invalidated: %s", getName().cstr());
 	}
 #endif
-
-	m_views.destroy(getMemoryPool());
 }
 
 Error BufferImpl::init(const BufferInitInfo& inf)
@@ -78,12 +76,12 @@ Error BufferImpl::init(const BufferInitInfo& inf)
 	ci.queueFamilyIndexCount = getGrManagerImpl().getQueueFamilies().getSize();
 	ci.pQueueFamilyIndices = &getGrManagerImpl().getQueueFamilies()[0];
 	ci.sharingMode = (ci.queueFamilyIndexCount > 1) ? VK_SHARING_MODE_CONCURRENT : VK_SHARING_MODE_EXCLUSIVE;
-	ANKI_VK_CHECK(vkCreateBuffer(getDevice(), &ci, nullptr, &m_handle));
+	ANKI_VK_CHECK(vkCreateBuffer(getVkDevice(), &ci, nullptr, &m_handle));
 	getGrManagerImpl().trySetVulkanHandleName(inf.getName(), VK_OBJECT_TYPE_BUFFER, m_handle);
 
 	// Get mem requirements
 	VkMemoryRequirements req;
-	vkGetBufferMemoryRequirements(getDevice(), m_handle, &req);
+	vkGetBufferMemoryRequirements(getVkDevice(), m_handle, &req);
 	U32 memIdx = kMaxU32;
 	const Bool isDiscreteGpu = getGrManagerImpl().getDeviceCapabilities().m_discreteGpu;
 
@@ -198,7 +196,7 @@ Error BufferImpl::init(const BufferInitInfo& inf)
 	// Bind mem to buffer
 	{
 		ANKI_TRACE_SCOPED_EVENT(VkBindObject);
-		ANKI_VK_CHECK(vkBindBufferMemory(getDevice(), m_handle, m_memHandle.m_memory, m_memHandle.m_offset));
+		ANKI_VK_CHECK(vkBindBufferMemory(getVkDevice(), m_handle, m_memHandle.m_memory, m_memHandle.m_offset));
 	}
 
 	// Get GPU buffer address
@@ -207,7 +205,7 @@ Error BufferImpl::init(const BufferInitInfo& inf)
 		VkBufferDeviceAddressInfoKHR info = {};
 		info.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR;
 		info.buffer = m_handle;
-		m_gpuAddress = vkGetBufferDeviceAddressKHR(getDevice(), &info);
+		m_gpuAddress = vkGetBufferDeviceAddressKHR(getVkDevice(), &info);
 
 		if(m_gpuAddress == 0)
 		{
@@ -445,9 +443,9 @@ VkBufferView BufferImpl::getOrCreateBufferView(Format fmt, PtrSize offset, PtrSi
 	viewCreateInfo.range = range;
 
 	VkBufferView view;
-	ANKI_VK_CHECKF(vkCreateBufferView(getDevice(), &viewCreateInfo, nullptr, &view));
+	ANKI_VK_CHECKF(vkCreateBufferView(getVkDevice(), &viewCreateInfo, nullptr, &view));
 
-	m_views.emplace(getMemoryPool(), hash, view);
+	m_views.emplace(hash, view);
 
 	return view;
 }

+ 8 - 11
AnKi/Gr/Vulkan/BufferImpl.h

@@ -6,7 +6,6 @@
 #pragma once
 
 #include <AnKi/Gr/Buffer.h>
-#include <AnKi/Gr/Vulkan/VulkanObject.h>
 #include <AnKi/Gr/Vulkan/GpuMemoryManager.h>
 #include <AnKi/Util/HashMap.h>
 
@@ -16,13 +15,11 @@ namespace anki {
 /// @{
 
 /// Buffer implementation
-class BufferImpl final : public Buffer, public VulkanObject<Buffer, BufferImpl>
+class BufferImpl final : public Buffer
 {
 public:
-	BufferImpl(GrManager* manager, CString name)
-		: Buffer(manager, name)
-		, m_needsFlush(false)
-		, m_needsInvalidate(false)
+	BufferImpl(CString name)
+		: Buffer(name)
 	{
 	}
 
@@ -69,7 +66,7 @@ public:
 		if(m_needsFlush)
 		{
 			VkMappedMemoryRange vkrange = setVkMappedMemoryRange(offset, range);
-			ANKI_VK_CHECKF(vkFlushMappedMemoryRanges(getDevice(), 1, &vkrange));
+			ANKI_VK_CHECKF(vkFlushMappedMemoryRanges(getVkDevice(), 1, &vkrange));
 #if ANKI_EXTRA_CHECKS
 			m_flushCount.fetchAdd(1);
 #endif
@@ -82,7 +79,7 @@ public:
 		if(m_needsInvalidate)
 		{
 			VkMappedMemoryRange vkrange = setVkMappedMemoryRange(offset, range);
-			ANKI_VK_CHECKF(vkInvalidateMappedMemoryRanges(getDevice(), 1, &vkrange));
+			ANKI_VK_CHECKF(vkInvalidateMappedMemoryRanges(getVkDevice(), 1, &vkrange));
 #if ANKI_EXTRA_CHECKS
 			m_invalidateCount.fetchAdd(1);
 #endif
@@ -99,10 +96,10 @@ private:
 	VkMemoryPropertyFlags m_memoryFlags = 0;
 	PtrSize m_actualSize = 0;
 	PtrSize m_mappedMemoryRangeAlignment = 0; ///< Cache this value.
-	Bool m_needsFlush : 1;
-	Bool m_needsInvalidate : 1;
+	Bool m_needsFlush : 1 = false;
+	Bool m_needsInvalidate : 1 = false;
 
-	mutable HashMap<U64, VkBufferView> m_views; ///< Only for texture buffers.
+	mutable GrHashMap<U64, VkBufferView> m_views; ///< Only for texture buffers.
 	mutable RWMutex m_viewsMtx;
 
 #if ANKI_EXTRA_CHECKS

+ 5 - 6
AnKi/Gr/Vulkan/CommandBuffer.cpp

@@ -11,14 +11,14 @@
 
 namespace anki {
 
-CommandBuffer* CommandBuffer::newInstance(GrManager* manager, const CommandBufferInitInfo& init)
+CommandBuffer* CommandBuffer::newInstance(const CommandBufferInitInfo& init)
 {
 	ANKI_TRACE_SCOPED_EVENT(VkNewCommandBuffer);
-	CommandBufferImpl* impl = anki::newInstance<CommandBufferImpl>(manager->getMemoryPool(), manager, init.getName());
+	CommandBufferImpl* impl = anki::newInstance<CommandBufferImpl>(GrMemoryPool::getSingleton(), init.getName());
 	const Error err = impl->init(init);
 	if(err)
 	{
-		deleteInstance(manager->getMemoryPool(), impl);
+		deleteInstance(GrMemoryPool::getSingleton(), impl);
 		impl = nullptr;
 	}
 	return impl;
@@ -38,15 +38,14 @@ void CommandBuffer::flush(ConstWeakArray<FencePtr> waitFences, FencePtr* signalF
 		}
 
 		MicroSemaphorePtr signalSemaphore;
-		self.getGrManagerImpl().flushCommandBuffer(
+		getGrManagerImpl().flushCommandBuffer(
 			self.getMicroCommandBuffer(), self.renderedToDefaultFramebuffer(),
 			WeakArray<MicroSemaphorePtr>(waitSemaphores.getBegin(), waitFences.getSize()),
 			(signalFence) ? &signalSemaphore : nullptr);
 
 		if(signalFence)
 		{
-			FenceImpl* fenceImpl =
-				anki::newInstance<FenceImpl>(self.getGrManagerImpl().getMemoryPool(), &getManager(), "SignalFence");
+			FenceImpl* fenceImpl = anki::newInstance<FenceImpl>(GrMemoryPool::getSingleton(), "SignalFence");
 			fenceImpl->m_semaphore = signalSemaphore;
 			signalFence->reset(fenceImpl);
 		}

+ 23 - 35
AnKi/Gr/Vulkan/CommandBufferFactory.cpp

@@ -23,13 +23,19 @@ static VulkanQueueType getQueueTypeFromCommandBufferFlags(CommandBufferFlag flag
 	}
 }
 
+void MicroCommandBufferPtrDeleter::operator()(MicroCommandBuffer* ptr)
+{
+	ANKI_ASSERT(ptr);
+	ptr->m_threadAlloc->deleteCommandBuffer(ptr);
+}
+
 MicroCommandBuffer::~MicroCommandBuffer()
 {
 	reset();
 
 	if(m_handle)
 	{
-		vkFreeCommandBuffers(m_threadAlloc->m_factory->m_dev, m_threadAlloc->m_pools[m_queue], 1, &m_handle);
+		vkFreeCommandBuffers(getVkDevice(), m_threadAlloc->m_pools[m_queue], 1, &m_handle);
 		m_handle = {};
 
 		[[maybe_unused]] const U32 count = m_threadAlloc->m_factory->m_createdCmdBufferCount.fetchSub(1);
@@ -46,7 +52,7 @@ void MicroCommandBuffer::reset()
 
 	for(GrObjectType type : EnumIterable<GrObjectType>())
 	{
-		m_objectRefs[type].destroy(m_fastPool);
+		m_objectRefs[type].destroy();
 	}
 
 	m_fastPool.reset();
@@ -66,20 +72,7 @@ Error CommandBufferThreadAllocator::init()
 		ci.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
 		ci.queueFamilyIndex = m_factory->m_queueFamilies[qtype];
 
-		ANKI_VK_CHECK(vkCreateCommandPool(m_factory->m_dev, &ci, nullptr, &m_pools[qtype]));
-	}
-
-	for(U32 secondLevel = 0; secondLevel < 2; ++secondLevel)
-	{
-		for(U32 smallBatch = 0; smallBatch < 2; ++smallBatch)
-		{
-			for(VulkanQueueType queue : EnumIterable<VulkanQueueType>())
-			{
-				MicroObjectRecycler<MicroCommandBuffer>& recycler = m_recyclers[secondLevel][smallBatch][queue];
-
-				recycler.init(m_factory->m_pool);
-			}
-		}
+		ANKI_VK_CHECK(vkCreateCommandPool(getVkDevice(), &ci, nullptr, &m_pools[qtype]));
 	}
 
 	return Error::kNone;
@@ -102,7 +95,7 @@ void CommandBufferThreadAllocator::destroy()
 	{
 		if(pool)
 		{
-			vkDestroyCommandPool(m_factory->m_dev, pool, nullptr);
+			vkDestroyCommandPool(getVkDevice(), pool, nullptr);
 			pool = VK_NULL_HANDLE;
 		}
 	}
@@ -132,12 +125,17 @@ Error CommandBufferThreadAllocator::newCommandBuffer(CommandBufferFlag cmdbFlags
 
 		ANKI_TRACE_INC_COUNTER(VkCommandBufferCreate, 1);
 		VkCommandBuffer cmdb;
-		ANKI_VK_CHECK(vkAllocateCommandBuffers(m_factory->m_dev, &ci, &cmdb));
+		ANKI_VK_CHECK(vkAllocateCommandBuffers(getVkDevice(), &ci, &cmdb));
 
-		MicroCommandBuffer* newCmdb = newInstance<MicroCommandBuffer>(getMemoryPool(), this);
+		MicroCommandBuffer* newCmdb = newInstance<MicroCommandBuffer>(GrMemoryPool::getSingleton(), this);
 
-		newCmdb->m_fastPool.init(m_factory->m_pool->getAllocationCallback(),
-								 m_factory->m_pool->getAllocationCallbackUserData(), 256_KB, 2.0f);
+		newCmdb->m_fastPool.init(GrMemoryPool::getSingleton().getAllocationCallback(),
+								 GrMemoryPool::getSingleton().getAllocationCallbackUserData(), 256_KB, 2.0f);
+
+		for(DynamicArrayRaii<GrObjectPtr>& arr : newCmdb->m_objectRefs)
+		{
+			arr = DynamicArrayRaii<GrObjectPtr>(&newCmdb->m_fastPool);
+		}
 
 		newCmdb->m_handle = cmdb;
 		newCmdb->m_flags = cmdbFlags;
@@ -171,16 +169,6 @@ void CommandBufferThreadAllocator::deleteCommandBuffer(MicroCommandBuffer* ptr)
 	m_recyclers[secondLevel][smallBatch][ptr->m_queue].recycle(ptr);
 }
 
-Error CommandBufferFactory::init(HeapMemoryPool* pool, VkDevice dev, const VulkanQueueFamilies& queueFamilies)
-{
-	ANKI_ASSERT(pool && dev);
-
-	m_pool = pool;
-	m_dev = dev;
-	m_queueFamilies = queueFamilies;
-	return Error::kNone;
-}
-
 void CommandBufferFactory::destroy()
 {
 	// First trim the caches for all recyclers. This will release the primaries and populate the recyclers of
@@ -202,10 +190,10 @@ void CommandBufferFactory::destroy()
 	for(CommandBufferThreadAllocator* talloc : m_threadAllocs)
 	{
 		talloc->destroy();
-		deleteInstance(*m_pool, talloc);
+		deleteInstance(GrMemoryPool::getSingleton(), talloc);
 	}
 
-	m_threadAllocs.destroy(*m_pool);
+	m_threadAllocs.destroy();
 }
 
 Error CommandBufferFactory::newCommandBuffer(ThreadId tid, CommandBufferFlag cmdbFlags, MicroCommandBufferPtr& ptr)
@@ -245,9 +233,9 @@ Error CommandBufferFactory::newCommandBuffer(ThreadId tid, CommandBufferFlag cmd
 
 			if(alloc == nullptr)
 			{
-				alloc = newInstance<CommandBufferThreadAllocator>(*m_pool, this, tid);
+				alloc = newInstance<CommandBufferThreadAllocator>(GrMemoryPool::getSingleton(), this, tid);
 
-				m_threadAllocs.resize(*m_pool, m_threadAllocs.getSize() + 1);
+				m_threadAllocs.resize(m_threadAllocs.getSize() + 1);
 				m_threadAllocs[m_threadAllocs.getSize() - 1] = alloc;
 
 				// Sort for fast find

+ 12 - 13
AnKi/Gr/Vulkan/CommandBufferFactory.h

@@ -29,6 +29,10 @@ public:
 		: m_threadAlloc(allocator)
 	{
 		ANKI_ASSERT(allocator);
+		for(DynamicArrayRaii<GrObjectPtr>& arr : m_objectRefs)
+		{
+			arr = DynamicArrayRaii<GrObjectPtr>(&m_fastPool);
+		}
 	}
 
 	~MicroCommandBuffer();
@@ -60,8 +64,6 @@ public:
 		return m_fence;
 	}
 
-	HeapMemoryPool& getMemoryPool();
-
 	/// Interface method.
 	void onFenceDone()
 	{
@@ -109,7 +111,7 @@ private:
 	VkCommandBuffer m_handle = {};
 
 	MicroFencePtr m_fence;
-	Array<DynamicArray<GrObjectPtr>, U(GrObjectType::kCount)> m_objectRefs;
+	Array<DynamicArrayRaii<GrObjectPtr>, U(GrObjectType::kCount)> m_objectRefs;
 
 	// Cacheline boundary
 
@@ -120,7 +122,7 @@ private:
 
 	void reset();
 
-	void pushToArray(DynamicArray<GrObjectPtr>& arr, GrObject* grobj)
+	void pushToArray(DynamicArrayRaii<GrObjectPtr>& arr, GrObject* grobj)
 	{
 		ANKI_ASSERT(grobj);
 
@@ -137,7 +139,7 @@ private:
 		}
 
 		// Not found in the temp cache, add it
-		arr.emplaceBack(m_fastPool, grobj);
+		arr.emplaceBack(grobj);
 	}
 };
 
@@ -179,8 +181,6 @@ public:
 
 	void destroy();
 
-	HeapMemoryPool& getMemoryPool();
-
 	/// Request a new command buffer.
 	Error newCommandBuffer(CommandBufferFlag cmdbFlags, MicroCommandBufferPtr& ptr);
 
@@ -214,7 +214,10 @@ public:
 
 	CommandBufferFactory& operator=(const CommandBufferFactory&) = delete; // Non-copyable
 
-	Error init(HeapMemoryPool* pool, VkDevice dev, const VulkanQueueFamilies& queueFamilies);
+	void init(const VulkanQueueFamilies& queueFamilies)
+	{
+		m_queueFamilies = queueFamilies;
+	}
 
 	void destroy();
 
@@ -228,11 +231,9 @@ public:
 	}
 
 private:
-	HeapMemoryPool* m_pool = nullptr;
-	VkDevice m_dev = VK_NULL_HANDLE;
 	VulkanQueueFamilies m_queueFamilies;
 
-	DynamicArray<CommandBufferThreadAllocator*> m_threadAllocs;
+	GrDynamicArray<CommandBufferThreadAllocator*> m_threadAllocs;
 	RWMutex m_threadAllocMtx;
 
 	Atomic<U32> m_createdCmdBufferCount = {0};
@@ -240,5 +241,3 @@ private:
 /// @}
 
 } // end namespace anki
-
-#include <AnKi/Gr/Vulkan/CommandBufferFactory.inl.h>

+ 0 - 26
AnKi/Gr/Vulkan/CommandBufferFactory.inl.h

@@ -1,26 +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/Gr/Vulkan/CommandBufferFactory.h>
-
-namespace anki {
-
-inline HeapMemoryPool& MicroCommandBuffer::getMemoryPool()
-{
-	return m_threadAlloc->getMemoryPool();
-}
-
-inline void MicroCommandBufferPtrDeleter::operator()(MicroCommandBuffer* ptr)
-{
-	ANKI_ASSERT(ptr);
-	ptr->m_threadAlloc->deleteCommandBuffer(ptr);
-}
-
-inline HeapMemoryPool& CommandBufferThreadAllocator::getMemoryPool()
-{
-	return *m_factory->m_pool;
-}
-
-} // end namespace anki

+ 1 - 1
AnKi/Gr/Vulkan/CommandBufferImpl.cpp

@@ -512,7 +512,7 @@ void CommandBufferImpl::buildAccelerationStructureInternal(const AccelerationStr
 	BufferInitInfo bufferInit;
 	bufferInit.m_usage = PrivateBufferUsageBit::kAccelerationStructureBuildScratch;
 	bufferInit.m_size = asImpl.getBuildScratchBufferSize();
-	BufferPtr scratchBuff = getManager().newBuffer(bufferInit);
+	BufferPtr scratchBuff = getGrManagerImpl().newBuffer(bufferInit);
 
 	// Create the build info
 	VkAccelerationStructureBuildGeometryInfoKHR buildInfo;

+ 3 - 4
AnKi/Gr/Vulkan/CommandBufferImpl.h

@@ -6,7 +6,6 @@
 #pragma once
 
 #include <AnKi/Gr/CommandBuffer.h>
-#include <AnKi/Gr/Vulkan/VulkanObject.h>
 #include <AnKi/Gr/Vulkan/CommandBufferFactory.h>
 #include <AnKi/Gr/CommandBuffer.h>
 #include <AnKi/Gr/Texture.h>
@@ -29,12 +28,12 @@ class CommandBufferInitInfo;
 /// @{
 
 /// Command buffer implementation.
-class CommandBufferImpl final : public CommandBuffer, public VulkanObject<CommandBuffer, CommandBufferImpl>
+class CommandBufferImpl final : public CommandBuffer
 {
 public:
 	/// Default constructor
-	CommandBufferImpl(GrManager* manager, CString name)
-		: CommandBuffer(manager, name)
+	CommandBufferImpl(CString name)
+		: CommandBuffer(name)
 		, m_renderedToDefaultFb(false)
 		, m_finalized(false)
 		, m_empty(false)

+ 11 - 0
AnKi/Gr/Vulkan/Common.cpp

@@ -4,12 +4,23 @@
 // http://www.anki3d.org/LICENSE
 
 #include <AnKi/Gr/Vulkan/Common.h>
+#include <AnKi/Gr/Vulkan/GrManagerImpl.h>
 
 #define VOLK_IMPLEMENTATION
 #include <Volk/volk.h>
 
 namespace anki {
 
+GrManagerImpl& getGrManagerImpl()
+{
+	return static_cast<GrManagerImpl&>(GrManager::getSingleton());
+}
+
+VkDevice getVkDevice()
+{
+	return getGrManagerImpl().getDevice();
+}
+
 VkCompareOp convertCompareOp(CompareOperation ak)
 {
 	VkCompareOp out = VK_COMPARE_OP_NEVER;

+ 3 - 0
AnKi/Gr/Vulkan/Common.h

@@ -45,6 +45,9 @@ class GrManagerImpl;
 #define ANKI_VK_SELF(class_) class_& self = *static_cast<class_*>(this)
 #define ANKI_VK_SELF_CONST(class_) const class_& self = *static_cast<const class_*>(this)
 
+ANKI_PURE GrManagerImpl& getGrManagerImpl();
+ANKI_PURE VkDevice getVkDevice();
+
 enum class DescriptorType : U8
 {
 	kCombinedTextureSampler,

+ 34 - 16
AnKi/Gr/Vulkan/DeferredBarrierFactory.h

@@ -23,9 +23,23 @@ class MicroDeferredBarrier
 	friend class MicroDeferredBarrierPtrDeleter;
 
 public:
-	MicroDeferredBarrier(DeferredBarrierFactory* factory);
+	MicroDeferredBarrier(DeferredBarrierFactory* factory)
+		: m_factory(factory)
+	{
+		ANKI_ASSERT(factory);
+		VkEventCreateInfo ci = {};
+		ci.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
+		ANKI_VK_CHECKF(vkCreateEvent(getVkDevice(), &ci, nullptr, &m_handle));
+	}
 
-	~MicroDeferredBarrier();
+	~MicroDeferredBarrier()
+	{
+		if(m_handle)
+		{
+			vkDestroyEvent(getVkDevice(), m_handle, nullptr);
+			m_handle = VK_NULL_HANDLE;
+		}
+	}
 
 	const VkEvent& getHandle() const
 	{
@@ -48,8 +62,6 @@ public:
 		return m_refcount.load();
 	}
 
-	HeapMemoryPool& getMemoryPool();
-
 	void setFence(MicroFencePtr& f)
 	{
 		m_fence = f;
@@ -98,29 +110,35 @@ public:
 
 	DeferredBarrierFactory& operator=(const DeferredBarrierFactory&) = delete; // Non-copyable
 
-	void init(HeapMemoryPool* pool, VkDevice dev)
-	{
-		ANKI_ASSERT(pool && dev);
-		m_pool = pool;
-		m_dev = dev;
-	}
-
 	void destroy()
 	{
 		m_recycler.destroy();
 	}
 
-	MicroDeferredBarrierPtr newInstance();
+	MicroDeferredBarrierPtr newInstance()
+	{
+		MicroDeferredBarrier* out = m_recycler.findToReuse();
+
+		if(out == nullptr)
+		{
+			// Create a new one
+			out = anki::newInstance<MicroDeferredBarrier>(GrMemoryPool::getSingleton(), this);
+		}
+
+		return MicroDeferredBarrierPtr(out);
+	}
 
 private:
-	HeapMemoryPool* m_pool = nullptr;
-	VkDevice m_dev = VK_NULL_HANDLE;
 	MicroObjectRecycler<MicroDeferredBarrier> m_recycler;
 
 	void destroyBarrier(MicroDeferredBarrier* barrier);
 };
+
+inline void MicroDeferredBarrierPtrDeleter::operator()(MicroDeferredBarrier* s)
+{
+	ANKI_ASSERT(s);
+	s->m_factory->m_recycler.recycle(s);
+}
 /// @}
 
 } // end namespace anki
-
-#include <AnKi/Gr/Vulkan/DeferredBarrierFactory.inl.h>

+ 0 - 52
AnKi/Gr/Vulkan/DeferredBarrierFactory.inl.h

@@ -1,52 +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/Gr/Vulkan/DeferredBarrierFactory.h>
-
-namespace anki {
-
-inline MicroDeferredBarrier::MicroDeferredBarrier(DeferredBarrierFactory* factory)
-	: m_factory(factory)
-{
-	ANKI_ASSERT(factory);
-	VkEventCreateInfo ci = {};
-	ci.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
-	ANKI_VK_CHECKF(vkCreateEvent(factory->m_dev, &ci, nullptr, &m_handle));
-}
-
-inline MicroDeferredBarrier::~MicroDeferredBarrier()
-{
-	if(m_handle)
-	{
-		vkDestroyEvent(m_factory->m_dev, m_handle, nullptr);
-		m_handle = VK_NULL_HANDLE;
-	}
-}
-
-inline HeapMemoryPool& MicroDeferredBarrier::getMemoryPool()
-{
-	return *m_factory->m_pool;
-}
-
-inline void MicroDeferredBarrierPtrDeleter::operator()(MicroDeferredBarrier* s)
-{
-	ANKI_ASSERT(s);
-	s->m_factory->m_recycler.recycle(s);
-}
-
-inline MicroDeferredBarrierPtr DeferredBarrierFactory::newInstance()
-{
-	MicroDeferredBarrier* out = m_recycler.findToReuse();
-
-	if(out == nullptr)
-	{
-		// Create a new one
-		out = anki::newInstance<MicroDeferredBarrier>(*m_pool, this);
-	}
-
-	return MicroDeferredBarrierPtr(out);
-}
-
-} // end namespace anki

+ 47 - 70
AnKi/Gr/Vulkan/DescriptorSet.cpp

@@ -21,7 +21,7 @@ class DescriptorSetFactory::BindlessDescriptorSet
 public:
 	~BindlessDescriptorSet();
 
-	Error init(HeapMemoryPool* pool, VkDevice dev, const U32 bindlessTextureCount, U32 bindlessImageCount);
+	Error init(const U32 bindlessTextureCount, U32 bindlessImageCount);
 
 	/// Bind a sampled image.
 	/// @note It's thread-safe.
@@ -58,20 +58,18 @@ public:
 	}
 
 private:
-	HeapMemoryPool* m_memPool = nullptr;
-	VkDevice m_dev = VK_NULL_HANDLE;
 	VkDescriptorSetLayout m_layout = VK_NULL_HANDLE;
 	VkDescriptorPool m_dsPool = VK_NULL_HANDLE;
 	VkDescriptorSet m_dset = VK_NULL_HANDLE;
 	Mutex m_mtx;
 
-	DynamicArray<U16> m_freeTexIndices;
-	DynamicArray<U16> m_freeTexelBufferIndices;
+	GrDynamicArray<U16> m_freeTexIndices;
+	GrDynamicArray<U16> m_freeTexelBufferIndices;
 
 	U16 m_freeTexIndexCount = kMaxU16;
 	U16 m_freeTexelBufferIndexCount = kMaxU16;
 
-	void unbindCommon(U32 idx, DynamicArray<U16>& freeIndices, U16& freeIndexCount);
+	void unbindCommon(U32 idx, GrDynamicArray<U16>& freeIndices, U16& freeIndexCount);
 };
 
 /// Descriptor set internal class.
@@ -117,12 +115,12 @@ public:
 private:
 	const DSLayoutCacheEntry* m_layoutEntry; ///< Know your father.
 
-	DynamicArray<VkDescriptorPool> m_pools;
+	GrDynamicArray<VkDescriptorPool> m_pools;
 	U32 m_lastPoolDSCount = 0;
 	U32 m_lastPoolFreeDSCount = 0;
 
 	IntrusiveList<DS> m_list; ///< At the left of the list are the least used sets.
-	HashMap<U64, DS*> m_hashmap;
+	GrHashMap<U64, DS*> m_hashmap;
 
 	[[nodiscard]] const DS* tryFindSet(U64 hash);
 	Error newSet(U64 hash, const Array<AnyBindingExtended, kMaxBindingsPerDescriptorSet>& bindings,
@@ -134,7 +132,7 @@ private:
 class alignas(ANKI_CACHE_LINE_SIZE) DescriptorSetFactory::ThreadLocal
 {
 public:
-	DynamicArray<DSAllocator*> m_allocators;
+	GrDynamicArray<DSAllocator*> m_allocators;
 };
 
 /// Cache entry. It's built around a specific descriptor set layout.
@@ -178,28 +176,20 @@ DescriptorSetFactory::BindlessDescriptorSet::~BindlessDescriptorSet()
 
 	if(m_dsPool)
 	{
-		vkDestroyDescriptorPool(m_dev, m_dsPool, nullptr);
+		vkDestroyDescriptorPool(getVkDevice(), m_dsPool, nullptr);
 		m_dsPool = VK_NULL_HANDLE;
 		m_dset = VK_NULL_HANDLE;
 	}
 
 	if(m_layout)
 	{
-		vkDestroyDescriptorSetLayout(m_dev, m_layout, nullptr);
+		vkDestroyDescriptorSetLayout(getVkDevice(), m_layout, nullptr);
 		m_layout = VK_NULL_HANDLE;
 	}
-
-	m_freeTexIndices.destroy(*m_memPool);
-	m_freeTexelBufferIndices.destroy(*m_memPool);
 }
 
-Error DescriptorSetFactory::BindlessDescriptorSet::init(HeapMemoryPool* pool, VkDevice dev, U32 bindlessTextureCount,
-														U32 bindlessTextureBuffers)
+Error DescriptorSetFactory::BindlessDescriptorSet::init(U32 bindlessTextureCount, U32 bindlessTextureBuffers)
 {
-	ANKI_ASSERT(dev);
-	m_memPool = pool;
-	m_dev = dev;
-
 	// Create the layout
 	{
 		Array<VkDescriptorSetLayoutBinding, 2> bindings = {};
@@ -230,7 +220,7 @@ Error DescriptorSetFactory::BindlessDescriptorSet::init(HeapMemoryPool* pool, Vk
 		ci.pBindings = &bindings[0];
 		ci.pNext = &extraInfos;
 
-		ANKI_VK_CHECK(vkCreateDescriptorSetLayout(m_dev, &ci, nullptr, &m_layout));
+		ANKI_VK_CHECK(vkCreateDescriptorSetLayout(getVkDevice(), &ci, nullptr, &m_layout));
 	}
 
 	// Create the pool
@@ -248,7 +238,7 @@ Error DescriptorSetFactory::BindlessDescriptorSet::init(HeapMemoryPool* pool, Vk
 		ci.pPoolSizes = &sizes[0];
 		ci.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT;
 
-		ANKI_VK_CHECK(vkCreateDescriptorPool(m_dev, &ci, nullptr, &m_dsPool));
+		ANKI_VK_CHECK(vkCreateDescriptorPool(getVkDevice(), &ci, nullptr, &m_dsPool));
 	}
 
 	// Create the descriptor set
@@ -259,12 +249,12 @@ Error DescriptorSetFactory::BindlessDescriptorSet::init(HeapMemoryPool* pool, Vk
 		ci.descriptorSetCount = 1;
 		ci.pSetLayouts = &m_layout;
 
-		ANKI_VK_CHECK(vkAllocateDescriptorSets(m_dev, &ci, &m_dset));
+		ANKI_VK_CHECK(vkAllocateDescriptorSets(getVkDevice(), &ci, &m_dset));
 	}
 
 	// Init the free arrays
 	{
-		m_freeTexIndices.create(*m_memPool, bindlessTextureCount);
+		m_freeTexIndices.create(bindlessTextureCount);
 		m_freeTexIndexCount = U16(m_freeTexIndices.getSize());
 
 		for(U32 i = 0; i < m_freeTexIndices.getSize(); ++i)
@@ -272,7 +262,7 @@ Error DescriptorSetFactory::BindlessDescriptorSet::init(HeapMemoryPool* pool, Vk
 			m_freeTexIndices[i] = U16(m_freeTexIndices.getSize() - i - 1);
 		}
 
-		m_freeTexelBufferIndices.create(*m_memPool, bindlessTextureBuffers);
+		m_freeTexelBufferIndices.create(bindlessTextureBuffers);
 		m_freeTexelBufferIndexCount = U16(m_freeTexelBufferIndices.getSize());
 
 		for(U32 i = 0; i < m_freeTexelBufferIndices.getSize(); ++i)
@@ -312,7 +302,7 @@ U32 DescriptorSetFactory::BindlessDescriptorSet::bindTexture(const VkImageView v
 	write.dstArrayElement = idx;
 	write.pImageInfo = &imageInf;
 
-	vkUpdateDescriptorSets(m_dev, 1, &write, 0, nullptr);
+	vkUpdateDescriptorSets(getVkDevice(), 1, &write, 0, nullptr);
 
 	return idx;
 }
@@ -339,12 +329,12 @@ U32 DescriptorSetFactory::BindlessDescriptorSet::bindUniformTexelBuffer(VkBuffer
 	write.dstArrayElement = idx;
 	write.pTexelBufferView = &view;
 
-	vkUpdateDescriptorSets(m_dev, 1, &write, 0, nullptr);
+	vkUpdateDescriptorSets(getVkDevice(), 1, &write, 0, nullptr);
 
 	return idx;
 }
 
-void DescriptorSetFactory::BindlessDescriptorSet::unbindCommon(U32 idx, DynamicArray<U16>& freeIndices,
+void DescriptorSetFactory::BindlessDescriptorSet::unbindCommon(U32 idx, GrDynamicArray<U16>& freeIndices,
 															   U16& freeIndexCount)
 {
 	LockGuard<Mutex> lock(m_mtx);
@@ -367,23 +357,18 @@ void DescriptorSetFactory::BindlessDescriptorSet::unbindCommon(U32 idx, DynamicA
 
 DescriptorSetFactory::DSAllocator::~DSAllocator()
 {
-	HeapMemoryPool& pool = *m_layoutEntry->m_factory->m_pool;
-
 	while(!m_list.isEmpty())
 	{
 		DS* ds = &m_list.getFront();
 		m_list.popFront();
 
-		deleteInstance(pool, ds);
+		deleteInstance(GrMemoryPool::getSingleton(), ds);
 	}
 
 	for(VkDescriptorPool pool : m_pools)
 	{
-		vkDestroyDescriptorPool(m_layoutEntry->m_factory->m_dev, pool, nullptr);
+		vkDestroyDescriptorPool(getVkDevice(), pool, nullptr);
 	}
-	m_pools.destroy(pool);
-
-	m_hashmap.destroy(pool);
 }
 
 Error DescriptorSetFactory::DSAllocator::init()
@@ -415,11 +400,11 @@ Error DescriptorSetFactory::DSAllocator::createNewPool()
 
 	// Create
 	VkDescriptorPool pool;
-	ANKI_VK_CHECK(vkCreateDescriptorPool(m_layoutEntry->m_factory->m_dev, &ci, nullptr, &pool));
+	ANKI_VK_CHECK(vkCreateDescriptorPool(getVkDevice(), &ci, nullptr, &pool));
 	ANKI_TRACE_INC_COUNTER(VkDescriptorPoolCreate, 1);
 
 	// Push back
-	m_pools.resize(*m_layoutEntry->m_factory->m_pool, m_pools.getSize() + 1);
+	m_pools.resize(m_pools.getSize() + 1);
 	m_pools[m_pools.getSize() - 1] = pool;
 
 	return Error::kNone;
@@ -466,11 +451,11 @@ Error DescriptorSetFactory::DSAllocator::newSet(U64 hash,
 			// Found something, recycle
 			auto it2 = m_hashmap.find(set->m_hash);
 			ANKI_ASSERT(it2 != m_hashmap.getEnd());
-			m_hashmap.erase(*m_layoutEntry->m_factory->m_pool, it2);
+			m_hashmap.erase(it2);
 			m_list.erase(set);
 
 			m_list.pushBack(set);
-			m_hashmap.emplace(*m_layoutEntry->m_factory->m_pool, hash, set);
+			m_hashmap.emplace(hash, set);
 
 			out = set;
 			break;
@@ -497,14 +482,14 @@ Error DescriptorSetFactory::DSAllocator::newSet(U64 hash,
 		ci.descriptorSetCount = 1;
 
 		VkDescriptorSet handle;
-		[[maybe_unused]] VkResult rez = vkAllocateDescriptorSets(m_layoutEntry->m_factory->m_dev, &ci, &handle);
+		[[maybe_unused]] VkResult rez = vkAllocateDescriptorSets(getVkDevice(), &ci, &handle);
 		ANKI_ASSERT(rez == VK_SUCCESS && "That allocation can't fail");
 		ANKI_TRACE_INC_COUNTER(VkDescriptorSetCreate, 1);
 
-		out = newInstance<DS>(*m_layoutEntry->m_factory->m_pool);
+		out = newInstance<DS>(GrMemoryPool::getSingleton());
 		out->m_handle = handle;
 
-		m_hashmap.emplace(*m_layoutEntry->m_factory->m_pool, hash, out);
+		m_hashmap.emplace(hash, out);
 		m_list.pushBack(out);
 	}
 
@@ -658,15 +643,15 @@ void DescriptorSetFactory::DSAllocator::writeSet(
 	}
 
 	// Write
-	vkUpdateDescriptorSets(m_layoutEntry->m_factory->m_dev, writeInfos.getSize(),
-						   (writeInfos.getSize() > 0) ? &writeInfos[0] : nullptr, 0, nullptr);
+	vkUpdateDescriptorSets(getVkDevice(), writeInfos.getSize(), (writeInfos.getSize() > 0) ? &writeInfos[0] : nullptr,
+						   0, nullptr);
 }
 
 DSLayoutCacheEntry::~DSLayoutCacheEntry()
 {
 	if(m_layoutHandle)
 	{
-		vkDestroyDescriptorSetLayout(m_factory->m_dev, m_layoutHandle, nullptr);
+		vkDestroyDescriptorSetLayout(getVkDevice(), m_layoutHandle, nullptr);
 	}
 }
 
@@ -704,7 +689,7 @@ Error DSLayoutCacheEntry::init(const DescriptorBinding* bindings, U32 bindingCou
 	ci.bindingCount = bindingCount;
 	ci.pBindings = &vkBindings[0];
 
-	ANKI_VK_CHECK(vkCreateDescriptorSetLayout(m_factory->m_dev, &ci, nullptr, &m_layoutHandle));
+	ANKI_VK_CHECK(vkCreateDescriptorSetLayout(getVkDevice(), &ci, nullptr, &m_layoutHandle));
 
 	// Create the pool info
 	U32 poolSizeCount = 0;
@@ -753,24 +738,24 @@ Error DSLayoutCacheEntry::getOrCreateDSAllocator(DescriptorSetFactory::DSAllocat
 	DescriptorSetFactory::ThreadLocal* threadLocal = DescriptorSetFactory::m_threadLocal;
 	if(threadLocal == nullptr) [[unlikely]]
 	{
-		threadLocal = newInstance<DescriptorSetFactory::ThreadLocal>(*m_factory->m_pool);
+		threadLocal = newInstance<DescriptorSetFactory::ThreadLocal>(GrMemoryPool::getSingleton());
 		DescriptorSetFactory::m_threadLocal = threadLocal;
 
 		LockGuard<Mutex> lock(m_factory->m_allThreadLocalsMtx);
-		m_factory->m_allThreadLocals.emplaceBack(*m_factory->m_pool, threadLocal);
+		m_factory->m_allThreadLocals.emplaceBack(threadLocal);
 	}
 
 	// Get or create the allocator
 	if(m_index >= threadLocal->m_allocators.getSize()) [[unlikely]]
 	{
-		threadLocal->m_allocators.resize(*m_factory->m_pool, m_index + 1, nullptr);
-		alloc = newInstance<DescriptorSetFactory::DSAllocator>(*m_factory->m_pool, this);
+		threadLocal->m_allocators.resize(m_index + 1, nullptr);
+		alloc = newInstance<DescriptorSetFactory::DSAllocator>(GrMemoryPool::getSingleton(), this);
 		ANKI_CHECK(alloc->init());
 		threadLocal->m_allocators[m_index] = alloc;
 	}
 	else if(threadLocal->m_allocators[m_index] == nullptr) [[unlikely]]
 	{
-		alloc = newInstance<DescriptorSetFactory::DSAllocator>(*m_factory->m_pool, this);
+		alloc = newInstance<DescriptorSetFactory::DSAllocator>(GrMemoryPool::getSingleton(), this);
 		ANKI_CHECK(alloc->init());
 		threadLocal->m_allocators[m_index] = alloc;
 	}
@@ -980,15 +965,10 @@ DescriptorSetFactory::~DescriptorSetFactory()
 {
 }
 
-Error DescriptorSetFactory::init(HeapMemoryPool* pool, VkDevice dev, U32 bindlessTextureCount,
-								 U32 bindlessTextureBuffers)
+Error DescriptorSetFactory::init(U32 bindlessTextureCount, U32 bindlessTextureBuffers)
 {
-	ANKI_ASSERT(pool);
-	m_pool = pool;
-	m_dev = dev;
-
-	m_bindless = newInstance<BindlessDescriptorSet>(*m_pool);
-	ANKI_CHECK(m_bindless->init(pool, dev, bindlessTextureCount, bindlessTextureBuffers));
+	m_bindless = newInstance<BindlessDescriptorSet>(GrMemoryPool::getSingleton());
+	ANKI_CHECK(m_bindless->init(bindlessTextureCount, bindlessTextureBuffers));
 	m_bindlessTextureCount = bindlessTextureCount;
 	m_bindlessUniformTexelBufferCount = bindlessTextureBuffers;
 
@@ -1001,25 +981,22 @@ void DescriptorSetFactory::destroy()
 	{
 		for(DSAllocator* alloc : threadLocal->m_allocators)
 		{
-			deleteInstance(*m_pool, alloc);
+			deleteInstance(GrMemoryPool::getSingleton(), alloc);
 		}
 
-		threadLocal->m_allocators.destroy(*m_pool);
-		deleteInstance(*m_pool, threadLocal);
+		deleteInstance(GrMemoryPool::getSingleton(), threadLocal);
 	}
-
-	m_allThreadLocals.destroy(*m_pool);
+	m_allThreadLocals.destroy();
 
 	for(DSLayoutCacheEntry* l : m_caches)
 	{
-		deleteInstance(*m_pool, l);
+		deleteInstance(GrMemoryPool::getSingleton(), l);
 	}
-
-	m_caches.destroy(*m_pool);
+	m_caches.destroy();
 
 	if(m_bindless)
 	{
-		deleteInstance(*m_pool, m_bindless);
+		deleteInstance(GrMemoryPool::getSingleton(), m_bindless);
 	}
 }
 
@@ -1095,10 +1072,10 @@ Error DescriptorSetFactory::newDescriptorSetLayout(const DescriptorSetLayoutInit
 
 		if(cache == nullptr)
 		{
-			cache = newInstance<DSLayoutCacheEntry>(*m_pool, this, m_caches.getSize());
+			cache = newInstance<DSLayoutCacheEntry>(GrMemoryPool::getSingleton(), this, m_caches.getSize());
 			ANKI_CHECK(cache->init(bindings.getBegin(), bindingCount, hash));
 
-			m_caches.emplaceBack(*m_pool, cache);
+			m_caches.emplaceBack(cache);
 		}
 
 		// Set the layout

+ 3 - 5
AnKi/Gr/Vulkan/DescriptorSet.h

@@ -361,7 +361,7 @@ public:
 	DescriptorSetFactory() = default;
 	~DescriptorSetFactory();
 
-	Error init(HeapMemoryPool* pool, VkDevice dev, U32 bindlessTextureCount, U32 bindlessTextureBuffers);
+	Error init(U32 bindlessTextureCount, U32 bindlessTextureBuffers);
 
 	void destroy();
 
@@ -397,14 +397,12 @@ private:
 	class ThreadLocal;
 
 	static thread_local ThreadLocal* m_threadLocal;
-	DynamicArray<ThreadLocal*> m_allThreadLocals;
+	GrDynamicArray<ThreadLocal*> m_allThreadLocals;
 	Mutex m_allThreadLocalsMtx;
 
-	HeapMemoryPool* m_pool = nullptr;
-	VkDevice m_dev = VK_NULL_HANDLE;
 	U64 m_frameCount = 0;
 
-	DynamicArray<DSLayoutCacheEntry*> m_caches;
+	GrDynamicArray<DSLayoutCacheEntry*> m_caches;
 	SpinLock m_cachesMtx; ///< Not a mutex because after a while there will be no reason to lock
 
 	BindlessDescriptorSet* m_bindless = nullptr;

+ 2 - 2
AnKi/Gr/Vulkan/Fence.cpp

@@ -9,9 +9,9 @@
 
 namespace anki {
 
-Fence* Fence::newInstance(GrManager* manager)
+Fence* Fence::newInstance()
 {
-	return anki::newInstance<FenceImpl>(manager->getMemoryPool(), manager, "N/A");
+	return anki::newInstance<FenceImpl>(GrMemoryPool::getSingleton(), "N/A");
 }
 
 Bool Fence::clientWait(Second seconds)

+ 10 - 8
AnKi/Gr/Vulkan/FenceFactory.cpp

@@ -9,12 +9,14 @@ namespace anki {
 
 void FenceFactory::destroy()
 {
+	LockGuard<Mutex> lock(m_mtx);
+
 	for(MicroFence* fence : m_fences)
 	{
-		deleteInstance(*m_pool, fence);
+		deleteInstance(GrMemoryPool::getSingleton(), fence);
 	}
 
-	m_fences.destroy(*m_pool);
+	m_fences.destroy();
 }
 
 MicroFence* FenceFactory::newFence()
@@ -27,13 +29,13 @@ MicroFence* FenceFactory::newFence()
 		for(U32 i = 0; i < m_fences.getSize(); ++i)
 		{
 			VkResult status;
-			ANKI_VK_CHECKF(status = vkGetFenceStatus(m_dev, m_fences[i]->getHandle()));
+			ANKI_VK_CHECKF(status = vkGetFenceStatus(getVkDevice(), m_fences[i]->getHandle()));
 			if(status == VK_SUCCESS)
 			{
 				out = m_fences[i];
 
 				// Pop it
-				m_fences.erase(*m_pool, m_fences.getBegin() + i);
+				m_fences.erase(m_fences.getBegin() + i);
 				break;
 			}
 			else if(status != VK_NOT_READY)
@@ -52,7 +54,7 @@ MicroFence* FenceFactory::newFence()
 
 			++m_aliveFenceCount;
 
-			if(m_aliveFenceCount > MAX_ALIVE_FENCES)
+			if(m_aliveFenceCount > kMaxAliveFences)
 			{
 				ANKI_VK_LOGW("Too many alive fences (%u). You may run out of file descriptors", m_aliveFenceCount);
 			}
@@ -62,12 +64,12 @@ MicroFence* FenceFactory::newFence()
 	if(out == nullptr)
 	{
 		// Create a new one
-		out = anki::newInstance<MicroFence>(*m_pool, this);
+		out = anki::newInstance<MicroFence>(GrMemoryPool::getSingleton(), this);
 	}
 	else
 	{
 		// Recycle
-		ANKI_VK_CHECKF(vkResetFences(m_dev, 1, &out->getHandle()));
+		ANKI_VK_CHECKF(vkResetFences(getVkDevice(), 1, &out->getHandle()));
 	}
 
 	ANKI_ASSERT(out->m_refcount.getNonAtomically() == 0);
@@ -79,7 +81,7 @@ void FenceFactory::deleteFence(MicroFence* fence)
 	ANKI_ASSERT(fence);
 
 	LockGuard<Mutex> lock(m_mtx);
-	m_fences.emplaceBack(*m_pool, fence);
+	m_fences.emplaceBack(fence);
 }
 
 } // end namespace anki

+ 4 - 16
AnKi/Gr/Vulkan/FenceFactory.h

@@ -46,8 +46,6 @@ public:
 		return m_refcount.fetchSub(1);
 	}
 
-	HeapMemoryPool& getMemoryPool();
-
 	void wait()
 	{
 		const Bool timeout = !clientWait(kMaxSecond);
@@ -85,21 +83,13 @@ class FenceFactory
 
 public:
 	/// Limit the alive fences to avoid having too many file descriptors used in Linux.
-	static constexpr U32 MAX_ALIVE_FENCES = 32;
+	static constexpr U32 kMaxAliveFences = 32;
 
-	FenceFactory()
-	{
-	}
+	FenceFactory() = default;
 
 	~FenceFactory()
 	{
-	}
-
-	void init(HeapMemoryPool* pool, VkDevice dev)
-	{
-		ANKI_ASSERT(pool && dev);
-		m_pool = pool;
-		m_dev = dev;
+		ANKI_ASSERT(m_fences.getSize() == 0);
 	}
 
 	void destroy();
@@ -111,9 +101,7 @@ public:
 	}
 
 private:
-	HeapMemoryPool* m_pool = nullptr;
-	VkDevice m_dev = VK_NULL_HANDLE;
-	DynamicArray<MicroFence*> m_fences;
+	GrDynamicArray<MicroFence*> m_fences;
 	U32 m_aliveFenceCount = 0;
 	Mutex m_mtx;
 

+ 4 - 9
AnKi/Gr/Vulkan/FenceFactory.inl.h

@@ -16,7 +16,7 @@ inline MicroFence::MicroFence(FenceFactory* f)
 	ci.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
 
 	ANKI_TRACE_INC_COUNTER(VkFenceCreate, 1);
-	ANKI_VK_CHECKF(vkCreateFence(m_factory->m_dev, &ci, nullptr, &m_handle));
+	ANKI_VK_CHECKF(vkCreateFence(getVkDevice(), &ci, nullptr, &m_handle));
 }
 
 inline MicroFence::~MicroFence()
@@ -24,20 +24,15 @@ inline MicroFence::~MicroFence()
 	if(m_handle)
 	{
 		ANKI_ASSERT(done());
-		vkDestroyFence(m_factory->m_dev, m_handle, nullptr);
+		vkDestroyFence(getVkDevice(), m_handle, nullptr);
 	}
 }
 
-inline HeapMemoryPool& MicroFence::getMemoryPool()
-{
-	return *m_factory->m_pool;
-}
-
 inline Bool MicroFence::done() const
 {
 	ANKI_ASSERT(m_handle);
 	VkResult status;
-	ANKI_VK_CHECKF(status = vkGetFenceStatus(m_factory->m_dev, m_handle));
+	ANKI_VK_CHECKF(status = vkGetFenceStatus(getVkDevice(), m_handle));
 	return status == VK_SUCCESS;
 }
 
@@ -56,7 +51,7 @@ inline Bool MicroFence::clientWait(Second seconds)
 		const F64 nsf = 1e+9 * seconds;
 		const U64 ns = U64(nsf);
 		VkResult res;
-		ANKI_VK_CHECKF(res = vkWaitForFences(m_factory->m_dev, 1, &m_handle, true, ns));
+		ANKI_VK_CHECKF(res = vkWaitForFences(getVkDevice(), 1, &m_handle, true, ns));
 
 		return res != VK_TIMEOUT;
 	}

+ 3 - 4
AnKi/Gr/Vulkan/FenceImpl.h

@@ -6,7 +6,6 @@
 #pragma once
 
 #include <AnKi/Gr/Fence.h>
-#include <AnKi/Gr/Vulkan/VulkanObject.h>
 #include <AnKi/Gr/Vulkan/SemaphoreFactory.h>
 
 namespace anki {
@@ -15,13 +14,13 @@ namespace anki {
 /// @{
 
 /// Buffer implementation
-class FenceImpl final : public Fence, public VulkanObject<Fence, FenceImpl>
+class FenceImpl final : public Fence
 {
 public:
 	MicroSemaphorePtr m_semaphore; ///< Yes, it's a timeline semaphore and not a VkFence.
 
-	FenceImpl(GrManager* manager, CString name)
-		: Fence(manager, name)
+	FenceImpl(CString name)
+		: Fence(name)
 	{
 	}
 

+ 8 - 12
AnKi/Gr/Vulkan/FrameGarbageCollector.cpp

@@ -21,8 +21,7 @@ void FrameGarbageCollector::collectGarbage()
 		return;
 	}
 
-	const VkDevice dev = m_gr->getDevice();
-	HeapMemoryPool& pool = m_gr->getMemoryPool();
+	const VkDevice dev = getVkDevice();
 
 	IntrusiveList<FrameGarbage> newFrames;
 	while(!m_frames.isEmpty())
@@ -47,13 +46,11 @@ void FrameGarbageCollector::collectGarbage()
 			{
 				vkDestroyImageView(dev, viewHandle, nullptr);
 			}
-			textureGarbage->m_viewHandles.destroy(pool);
 
 			for(U32 bindlessIndex : textureGarbage->m_bindlessIndices)
 			{
-				m_gr->getDescriptorSetFactory().unbindBindlessTexture(bindlessIndex);
+				getGrManagerImpl().getDescriptorSetFactory().unbindBindlessTexture(bindlessIndex);
 			}
-			textureGarbage->m_bindlessIndices.destroy(pool);
 
 			if(textureGarbage->m_imageHandle)
 			{
@@ -62,10 +59,10 @@ void FrameGarbageCollector::collectGarbage()
 
 			if(textureGarbage->m_memoryHandle)
 			{
-				m_gr->getGpuMemoryManager().freeMemory(textureGarbage->m_memoryHandle);
+				getGrManagerImpl().getGpuMemoryManager().freeMemory(textureGarbage->m_memoryHandle);
 			}
 
-			deleteInstance(pool, textureGarbage);
+			deleteInstance(GrMemoryPool::getSingleton(), textureGarbage);
 		}
 
 		// Dispose buffer garbage
@@ -77,7 +74,6 @@ void FrameGarbageCollector::collectGarbage()
 			{
 				vkDestroyBufferView(dev, view, nullptr);
 			}
-			bufferGarbage->m_viewHandles.destroy(pool);
 
 			if(bufferGarbage->m_bufferHandle)
 			{
@@ -86,13 +82,13 @@ void FrameGarbageCollector::collectGarbage()
 
 			if(bufferGarbage->m_memoryHandle)
 			{
-				m_gr->getGpuMemoryManager().freeMemory(bufferGarbage->m_memoryHandle);
+				getGrManagerImpl().getGpuMemoryManager().freeMemory(bufferGarbage->m_memoryHandle);
 			}
 
-			deleteInstance(pool, bufferGarbage);
+			deleteInstance(GrMemoryPool::getSingleton(), bufferGarbage);
 		}
 
-		deleteInstance(pool, &frame);
+		deleteInstance(GrMemoryPool::getSingleton(), &frame);
 	}
 
 	m_frames = std::move(newFrames);
@@ -106,7 +102,7 @@ FrameGarbageCollector::FrameGarbage& FrameGarbageCollector::getFrame()
 	}
 	else
 	{
-		FrameGarbage* newGarbage = newInstance<FrameGarbage>(m_gr->getMemoryPool());
+		FrameGarbage* newGarbage = newInstance<FrameGarbage>(GrMemoryPool::getSingleton());
 		m_frames.pushBack(newGarbage);
 	}
 

+ 4 - 7
AnKi/Gr/Vulkan/FrameGarbageCollector.h

@@ -20,8 +20,8 @@ namespace anki {
 class TextureGarbage : public IntrusiveListEnabled<TextureGarbage>
 {
 public:
-	DynamicArray<VkImageView> m_viewHandles;
-	DynamicArray<U32> m_bindlessIndices;
+	GrDynamicArray<VkImageView> m_viewHandles;
+	GrDynamicArray<U32> m_bindlessIndices;
 	VkImage m_imageHandle = VK_NULL_HANDLE;
 	GpuMemoryHandle m_memoryHandle;
 };
@@ -31,7 +31,7 @@ class BufferGarbage : public IntrusiveListEnabled<BufferGarbage>
 {
 public:
 	VkBuffer m_bufferHandle = VK_NULL_HANDLE;
-	DynamicArray<VkBufferView> m_viewHandles;
+	GrDynamicArray<VkBufferView> m_viewHandles;
 	GpuMemoryHandle m_memoryHandle;
 };
 
@@ -44,9 +44,8 @@ public:
 
 	~FrameGarbageCollector();
 
-	void init(GrManagerImpl* gr)
+	void init()
 	{
-		m_gr = gr;
 #if ANKI_EXTRA_CHECKS
 		m_initialized = true;
 #endif
@@ -73,8 +72,6 @@ private:
 		MicroFencePtr m_fence;
 	};
 
-	GrManagerImpl* m_gr = nullptr;
-
 	Mutex m_mtx;
 	IntrusiveList<FrameGarbage> m_frames;
 

+ 3 - 3
AnKi/Gr/Vulkan/Framebuffer.cpp

@@ -9,13 +9,13 @@
 
 namespace anki {
 
-Framebuffer* Framebuffer::newInstance(GrManager* manager, const FramebufferInitInfo& init)
+Framebuffer* Framebuffer::newInstance(const FramebufferInitInfo& init)
 {
-	FramebufferImpl* impl = anki::newInstance<FramebufferImpl>(manager->getMemoryPool(), manager, init.getName());
+	FramebufferImpl* impl = anki::newInstance<FramebufferImpl>(GrMemoryPool::getSingleton(), init.getName());
 	const Error err = impl->init(init);
 	if(err)
 	{
-		deleteInstance(manager->getMemoryPool(), impl);
+		deleteInstance(GrMemoryPool::getSingleton(), impl);
 		impl = nullptr;
 	}
 	return impl;

+ 7 - 9
AnKi/Gr/Vulkan/FramebufferImpl.cpp

@@ -14,21 +14,19 @@ FramebufferImpl::~FramebufferImpl()
 {
 	if(m_fbHandle)
 	{
-		vkDestroyFramebuffer(getDevice(), m_fbHandle, nullptr);
+		vkDestroyFramebuffer(getVkDevice(), m_fbHandle, nullptr);
 	}
 
 	for(auto it : m_renderpassHandles)
 	{
 		VkRenderPass rpass = it;
 		ANKI_ASSERT(rpass);
-		vkDestroyRenderPass(getDevice(), rpass, nullptr);
+		vkDestroyRenderPass(getVkDevice(), rpass, nullptr);
 	}
 
-	m_renderpassHandles.destroy(getMemoryPool());
-
 	if(m_compatibleRenderpassHandle)
 	{
-		vkDestroyRenderPass(getDevice(), m_compatibleRenderpassHandle, nullptr);
+		vkDestroyRenderPass(getVkDevice(), m_compatibleRenderpassHandle, nullptr);
 	}
 }
 
@@ -54,7 +52,7 @@ Error FramebufferImpl::init(const FramebufferInitInfo& init)
 
 	// Create a renderpass.
 	initRpassCreateInfo(init);
-	ANKI_VK_CHECK(vkCreateRenderPass2KHR(getDevice(), &m_rpassCi, nullptr, &m_compatibleRenderpassHandle));
+	ANKI_VK_CHECK(vkCreateRenderPass2KHR(getVkDevice(), &m_rpassCi, nullptr, &m_compatibleRenderpassHandle));
 	getGrManagerImpl().trySetVulkanHandleName(init.getName(), VK_OBJECT_TYPE_RENDER_PASS, m_compatibleRenderpassHandle);
 
 	// Create the FB
@@ -175,7 +173,7 @@ Error FramebufferImpl::initFbs(const FramebufferInitInfo& init)
 	ci.pAttachments = &imgViews[0];
 	ANKI_ASSERT(count == ci.attachmentCount);
 
-	ANKI_VK_CHECK(vkCreateFramebuffer(getDevice(), &ci, nullptr, &m_fbHandle));
+	ANKI_VK_CHECK(vkCreateFramebuffer(getVkDevice(), &ci, nullptr, &m_fbHandle));
 	getGrManagerImpl().trySetVulkanHandleName(init.getName(), VK_OBJECT_TYPE_FRAMEBUFFER, m_fbHandle);
 
 	return Error::kNone;
@@ -373,10 +371,10 @@ VkRenderPass FramebufferImpl::getRenderPassHandle(const Array<VkImageLayout, kMa
 				subpassDescr.pNext = &sriAttachmentInfo;
 			}
 
-			ANKI_VK_CHECKF(vkCreateRenderPass2KHR(getDevice(), &ci, nullptr, &out));
+			ANKI_VK_CHECKF(vkCreateRenderPass2KHR(getVkDevice(), &ci, nullptr, &out));
 			getGrManagerImpl().trySetVulkanHandleName(getName(), VK_OBJECT_TYPE_RENDER_PASS, out);
 
-			m_renderpassHandles.emplace(getMemoryPool(), hash, out);
+			m_renderpassHandles.emplace(hash, out);
 		}
 	}
 

+ 4 - 5
AnKi/Gr/Vulkan/FramebufferImpl.h

@@ -6,7 +6,6 @@
 #pragma once
 
 #include <AnKi/Gr/Framebuffer.h>
-#include <AnKi/Gr/Vulkan/VulkanObject.h>
 #include <AnKi/Gr/Vulkan/SwapchainFactory.h>
 #include <AnKi/Util/HashMap.h>
 #include <AnKi/Util/BitSet.h>
@@ -20,11 +19,11 @@ class FramebufferAttachmentInfo;
 /// @{
 
 /// Framebuffer implementation.
-class FramebufferImpl final : public Framebuffer, public VulkanObject<Framebuffer, FramebufferImpl>
+class FramebufferImpl final : public Framebuffer
 {
 public:
-	FramebufferImpl(GrManager* manager, CString name)
-		: Framebuffer(manager, name)
+	FramebufferImpl(CString name)
+		: Framebuffer(name)
 	{
 	}
 
@@ -132,7 +131,7 @@ private:
 
 	// VK objects
 	VkRenderPass m_compatibleRenderpassHandle = VK_NULL_HANDLE; ///< Compatible renderpass. Good for pipeline creation.
-	HashMap<U64, VkRenderPass> m_renderpassHandles;
+	GrHashMap<U64, VkRenderPass> m_renderpassHandles;
 	RWMutex m_renderpassHandlesMtx;
 	VkFramebuffer m_fbHandle = VK_NULL_HANDLE;
 

+ 15 - 20
AnKi/Gr/Vulkan/GpuMemoryManager.cpp

@@ -4,6 +4,7 @@
 // http://www.anki3d.org/LICENSE
 
 #include <AnKi/Gr/Vulkan/GpuMemoryManager.h>
+#include <AnKi/Gr/Vulkan/GrManagerImpl.h>
 
 namespace anki {
 
@@ -34,13 +35,13 @@ Error GpuMemoryManagerInterface::allocateChunk(U32 classIdx, GpuMemoryManagerChu
 	}
 
 	VkDeviceMemory memHandle;
-	if(vkAllocateMemory(m_parent->m_dev, &ci, nullptr, &memHandle) != VK_SUCCESS) [[unlikely]]
+	if(vkAllocateMemory(getVkDevice(), &ci, nullptr, &memHandle) != VK_SUCCESS) [[unlikely]]
 	{
 		ANKI_VK_LOGF("Out of GPU memory. Mem type index %u, size %zu", m_memTypeIdx,
 					 m_classInfos[classIdx].m_suballocationSize);
 	}
 
-	chunk = newInstance<GpuMemoryManagerChunk>(*m_parent->m_pool);
+	chunk = newInstance<GpuMemoryManagerChunk>(GrMemoryPool::getSingleton());
 	chunk->m_handle = memHandle;
 	chunk->m_size = m_classInfos[classIdx].m_chunkSize;
 
@@ -56,15 +57,15 @@ void GpuMemoryManagerInterface::freeChunk(GpuMemoryManagerChunk* chunk)
 
 	if(chunk->m_mappedAddress)
 	{
-		vkUnmapMemory(m_parent->m_dev, chunk->m_handle);
+		vkUnmapMemory(getVkDevice(), chunk->m_handle);
 	}
 
-	vkFreeMemory(m_parent->m_dev, chunk->m_handle, nullptr);
+	vkFreeMemory(getVkDevice(), chunk->m_handle, nullptr);
 
 	ANKI_ASSERT(m_allocatedMemory >= chunk->m_size);
 	m_allocatedMemory -= chunk->m_size;
 
-	deleteInstance(*m_parent->m_pool, chunk);
+	deleteInstance(GrMemoryPool::getSingleton(), chunk);
 }
 
 GpuMemoryManager::~GpuMemoryManager()
@@ -74,14 +75,11 @@ GpuMemoryManager::~GpuMemoryManager()
 void GpuMemoryManager::destroy()
 {
 	ANKI_VK_LOGV("Destroying memory manager");
-	m_callocs.destroy(*m_pool);
+	m_callocs.destroy();
 }
 
-void GpuMemoryManager::init(VkPhysicalDevice pdev, VkDevice dev, HeapMemoryPool* pool, Bool exposeBufferGpuAddress)
+void GpuMemoryManager::init(Bool exposeBufferGpuAddress)
 {
-	ANKI_ASSERT(pool && pdev);
-	ANKI_ASSERT(dev);
-
 	// Print some info
 	ANKI_VK_LOGV("Initializing memory manager");
 	for(const GpuMemoryManagerClassInfo& c : kClasses)
@@ -93,7 +91,7 @@ void GpuMemoryManager::init(VkPhysicalDevice pdev, VkDevice dev, HeapMemoryPool*
 	// Image buffer granularity
 	{
 		VkPhysicalDeviceProperties props;
-		vkGetPhysicalDeviceProperties(pdev, &props);
+		vkGetPhysicalDeviceProperties(getGrManagerImpl().getPhysicalDevice(), &props);
 		m_bufferImageGranularity = U32(props.limits.bufferImageGranularity);
 		ANKI_ASSERT(m_bufferImageGranularity > 0 && isPowerOfTwo(m_bufferImageGranularity));
 
@@ -116,12 +114,9 @@ void GpuMemoryManager::init(VkPhysicalDevice pdev, VkDevice dev, HeapMemoryPool*
 		}
 	}
 
-	vkGetPhysicalDeviceMemoryProperties(pdev, &m_memoryProperties);
-
-	m_pool = pool;
-	m_dev = dev;
+	vkGetPhysicalDeviceMemoryProperties(getGrManagerImpl().getPhysicalDevice(), &m_memoryProperties);
 
-	m_callocs.create(*pool, m_memoryProperties.memoryTypeCount);
+	m_callocs.create(m_memoryProperties.memoryTypeCount);
 	for(U32 memTypeIdx = 0; memTypeIdx < m_callocs.getSize(); ++memTypeIdx)
 	{
 		GpuMemoryManagerInterface& iface = m_callocs[memTypeIdx].getInterface();
@@ -157,7 +152,7 @@ void GpuMemoryManager::init(VkPhysicalDevice pdev, VkDevice dev, HeapMemoryPool*
 		}
 
 		// The interface is initialized, init the builder
-		m_callocs[memTypeIdx].init(m_pool);
+		m_callocs[memTypeIdx].init(&GrMemoryPool::getSingleton());
 	}
 }
 
@@ -191,7 +186,7 @@ void GpuMemoryManager::allocateMemoryDedicated(U32 memTypeIdx, PtrSize size, VkI
 	memoryAllocateInfo.memoryTypeIndex = memTypeIdx;
 
 	VkDeviceMemory mem;
-	ANKI_VK_CHECKF(vkAllocateMemory(m_dev, &memoryAllocateInfo, nullptr, &mem));
+	ANKI_VK_CHECKF(vkAllocateMemory(getVkDevice(), &memoryAllocateInfo, nullptr, &mem));
 
 	handle.m_memory = mem;
 	handle.m_offset = 0;
@@ -209,7 +204,7 @@ void GpuMemoryManager::freeMemory(GpuMemoryHandle& handle)
 
 	if(handle.isDedicated())
 	{
-		vkFreeMemory(m_dev, handle.m_memory, nullptr);
+		vkFreeMemory(getVkDevice(), handle.m_memory, nullptr);
 		[[maybe_unused]] const PtrSize prevSize = m_dedicatedAllocatedMemory.fetchSub(handle.m_size);
 		ANKI_ASSERT(prevSize >= handle.m_size);
 
@@ -234,7 +229,7 @@ void* GpuMemoryManager::getMappedAddress(GpuMemoryHandle& handle)
 
 	if(handle.m_chunk->m_mappedAddress == nullptr)
 	{
-		ANKI_VK_CHECKF(vkMapMemory(m_dev, handle.m_chunk->m_handle, 0, handle.m_chunk->m_size, 0,
+		ANKI_VK_CHECKF(vkMapMemory(getVkDevice(), handle.m_chunk->m_handle, 0, handle.m_chunk->m_size, 0,
 								   &handle.m_chunk->m_mappedAddress));
 	}
 

+ 2 - 6
AnKi/Gr/Vulkan/GpuMemoryManager.h

@@ -130,7 +130,7 @@ public:
 
 	GpuMemoryManager& operator=(const GpuMemoryManager&) = delete; // Non-copyable
 
-	void init(VkPhysicalDevice pdev, VkDevice dev, HeapMemoryPool* pool, Bool exposeBufferGpuAddress);
+	void init(Bool exposeBufferGpuAddress);
 
 	void destroy();
 
@@ -155,11 +155,7 @@ public:
 private:
 	using ClassAllocator = ClassAllocatorBuilder<GpuMemoryManagerChunk, GpuMemoryManagerInterface, Mutex>;
 
-	HeapMemoryPool* m_pool = nullptr;
-
-	VkDevice m_dev = VK_NULL_HANDLE;
-
-	DynamicArray<ClassAllocator> m_callocs;
+	GrDynamicArray<ClassAllocator> m_callocs;
 
 	VkPhysicalDeviceMemoryProperties m_memoryProperties = {};
 	U32 m_bufferImageGranularity = 0;

+ 29 - 36
AnKi/Gr/Vulkan/GrManager.cpp

@@ -22,52 +22,45 @@
 
 namespace anki {
 
-GrManager::GrManager()
+template<>
+template<>
+GrManager& MakeSingletonPtr<GrManager>::allocateSingleton<>()
 {
-}
+	ANKI_ASSERT(m_global == nullptr);
+	m_global = new GrManagerImpl;
 
-GrManager::~GrManager()
-{
-	// Destroy in reverse order
-	m_cacheDir.destroy(m_pool);
+#if ANKI_ENABLE_ASSERTIONS
+	++g_singletonsAllocated;
+#endif
+
+	return *m_global;
 }
 
-Error GrManager::newInstance(GrManagerInitInfo& init, GrManager*& gr)
+template<>
+void MakeSingletonPtr<GrManager>::freeSingleton()
 {
-	GrManagerImpl* impl = static_cast<GrManagerImpl*>(
-		init.m_allocCallback(init.m_allocCallbackUserData, nullptr, sizeof(GrManagerImpl), alignof(GrManagerImpl)));
-	callConstructor(*impl);
-
-	// Init
-	impl->m_pool.init(init.m_allocCallback, init.m_allocCallbackUserData);
-	impl->m_cacheDir.create(impl->m_pool, init.m_cacheDirectory);
-	Error err = impl->init(init);
-
-	if(err)
-	{
-		callDestructor(*impl);
-		init.m_allocCallback(init.m_allocCallbackUserData, impl, 0, 0);
-		gr = nullptr;
-	}
-	else
+	if(m_global)
 	{
-		gr = impl;
+		delete static_cast<GrManagerImpl*>(m_global);
+		m_global = nullptr;
+#if ANKI_ENABLE_ASSERTIONS
+		--g_singletonsAllocated;
+#endif
 	}
+}
 
-	return err;
+GrManager::GrManager()
+{
 }
 
-void GrManager::deleteInstance(GrManager* gr)
+GrManager::~GrManager()
 {
-	if(gr == nullptr)
-	{
-		return;
-	}
+}
 
-	AllocAlignedCallback callback = gr->m_pool.getAllocationCallback();
-	void* userData = gr->m_pool.getAllocationCallbackUserData();
-	gr->~GrManager();
-	callback(userData, gr, 0, 0);
+Error GrManager::init(GrManagerInitInfo& inf)
+{
+	ANKI_VK_SELF(GrManagerImpl);
+	return self.init(inf);
 }
 
 TexturePtr GrManager::acquireNextPresentableTexture()
@@ -111,7 +104,7 @@ GrManagerStats GrManager::getStats() const
 #define ANKI_NEW_GR_OBJECT(type) \
 	type##Ptr GrManager::new##type(const type##InitInfo& init) \
 	{ \
-		type##Ptr ptr(type::newInstance(this, init)); \
+		type##Ptr ptr(type::newInstance(init)); \
 		if(!ptr.isCreated()) [[unlikely]] \
 		{ \
 			ANKI_VK_LOGF("Failed to create a " ANKI_STRINGIZE(type) " object"); \
@@ -122,7 +115,7 @@ GrManagerStats GrManager::getStats() const
 #define ANKI_NEW_GR_OBJECT_NO_INIT_INFO(type) \
 	type##Ptr GrManager::new##type() \
 	{ \
-		type##Ptr ptr(type::newInstance(this)); \
+		type##Ptr ptr(type::newInstance()); \
 		if(!ptr.isCreated()) [[unlikely]] \
 		{ \
 			ANKI_VK_LOGF("Failed to create a " ANKI_STRINGIZE(type) " object"); \

+ 40 - 40
AnKi/Gr/Vulkan/GrManagerImpl.cpp

@@ -66,7 +66,7 @@ GrManagerImpl::~GrManagerImpl()
 	m_pplineLayoutFactory.destroy();
 	m_descrFactory.destroy();
 
-	m_pplineCache.destroy(m_device, m_physicalDevice, m_pool);
+	m_pplineCache.destroy();
 
 	m_fenceFactory.destroy();
 
@@ -99,8 +99,12 @@ GrManagerImpl::~GrManagerImpl()
 	}
 
 #if ANKI_PLATFORM_MOBILE
-	anki::deleteInstance(m_pool, m_globalCreatePipelineMtx);
+	anki::deleteInstance(GrMemoryPool::getSingleton(), m_globalCreatePipelineMtx);
 #endif
+
+	m_cacheDir.destroy();
+
+	GrMemoryPool::freeSingleton();
 }
 
 Error GrManagerImpl::init(const GrManagerInitInfo& init)
@@ -119,6 +123,10 @@ Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
 {
 	ANKI_VK_LOGI("Initializing Vulkan backend");
 
+	GrMemoryPool::allocateSingleton(init.m_allocCallback, init.m_allocCallbackUserData);
+
+	m_cacheDir = init.m_cacheDirectory;
+
 	ANKI_CHECK(initInstance());
 	ANKI_CHECK(initSurface());
 	ANKI_CHECK(initDevice());
@@ -135,27 +143,23 @@ Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
 		}
 	}
 
-	m_swapchainFactory.init(this, ConfigSet::getSingleton().getGrVsync());
+	m_swapchainFactory.init(ConfigSet::getSingleton().getGrVsync());
 
 	m_crntSwapchain = m_swapchainFactory.newInstance();
 
-	ANKI_CHECK(m_pplineCache.init(m_device, m_physicalDevice, init.m_cacheDirectory, m_pool));
+	ANKI_CHECK(m_pplineCache.init(init.m_cacheDirectory));
 
 	ANKI_CHECK(initMemory());
 
-	ANKI_CHECK(m_cmdbFactory.init(&m_pool, m_device, m_queueFamilyIndices));
+	m_cmdbFactory.init(m_queueFamilyIndices);
 
 	for(PerFrame& f : m_perFrame)
 	{
 		resetFrame(f);
 	}
 
-	m_fenceFactory.init(&m_pool, m_device);
-	m_semaphoreFactory.init(&m_pool, m_device);
-	m_samplerFactory.init(this);
-	m_barrierFactory.init(&m_pool, m_device);
-	m_occlusionQueryFactory.init(&m_pool, m_device, VK_QUERY_TYPE_OCCLUSION);
-	m_timestampQueryFactory.init(&m_pool, m_device, VK_QUERY_TYPE_TIMESTAMP);
+	m_occlusionQueryFactory.init(VK_QUERY_TYPE_OCCLUSION);
+	m_timestampQueryFactory.init(VK_QUERY_TYPE_TIMESTAMP);
 
 	// See if unaligned formats are supported
 	{
@@ -192,10 +196,9 @@ Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
 		}
 	}
 
-	ANKI_CHECK(m_descrFactory.init(&m_pool, m_device, kMaxBindlessTextures, kMaxBindlessReadonlyTextureBuffers));
-	m_pplineLayoutFactory.init(&m_pool, m_device);
+	ANKI_CHECK(m_descrFactory.init(kMaxBindlessTextures, kMaxBindlessReadonlyTextureBuffers));
 
-	m_frameGarbageCollector.init(this);
+	m_frameGarbageCollector.init();
 
 	return Error::kNone;
 }
@@ -224,14 +227,14 @@ Error GrManagerImpl::initInstance()
 	ci.pApplicationInfo = &app;
 
 	// Instance layers
-	DynamicArrayRaii<const char*> layersToEnable(&m_pool);
+	GrDynamicArray<const char*> layersToEnable;
 	{
 		U32 layerCount;
 		vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
 
 		if(layerCount)
 		{
-			DynamicArrayRaii<VkLayerProperties> layerProps(layerCount, &m_pool);
+			GrDynamicArray<VkLayerProperties> layerProps(layerCount);
 			vkEnumerateInstanceLayerProperties(&layerCount, &layerProps[0]);
 
 			ANKI_VK_LOGV("Found the following instance layers:");
@@ -263,8 +266,8 @@ Error GrManagerImpl::initInstance()
 	}
 
 	// Validation features
-	DynamicArrayRaii<VkValidationFeatureEnableEXT> enabledValidationFeatures(&m_pool);
-	DynamicArrayRaii<VkValidationFeatureDisableEXT> disabledValidationFeatures(&m_pool);
+	GrDynamicArray<VkValidationFeatureEnableEXT> enabledValidationFeatures;
+	GrDynamicArray<VkValidationFeatureDisableEXT> disabledValidationFeatures;
 	if(ConfigSet::getSingleton().getGrDebugPrintf())
 	{
 		enabledValidationFeatures.emplaceBack(VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT);
@@ -290,8 +293,8 @@ Error GrManagerImpl::initInstance()
 	}
 
 	// Extensions
-	DynamicArrayRaii<const char*> instExtensions(&m_pool);
-	DynamicArrayRaii<VkExtensionProperties> instExtensionInf(&m_pool);
+	GrDynamicArray<const char*> instExtensions;
+	GrDynamicArray<VkExtensionProperties> instExtensionInf;
 	U32 extCount = 0;
 	vkEnumerateInstanceExtensionProperties(nullptr, &extCount, nullptr);
 	if(extCount)
@@ -426,7 +429,7 @@ Error GrManagerImpl::initInstance()
 			return Error::kFunctionFailed;
 		}
 
-		DynamicArrayRaii<VkPhysicalDevice> physicalDevices(count, &m_pool);
+		GrDynamicArray<VkPhysicalDevice> physicalDevices(count);
 		ANKI_VK_CHECK(vkEnumeratePhysicalDevices(m_instance, &count, &physicalDevices[0]));
 
 		class Dev
@@ -436,7 +439,7 @@ Error GrManagerImpl::initInstance()
 			VkPhysicalDeviceProperties2 m_vkProps;
 		};
 
-		DynamicArrayRaii<Dev> devs(count, &m_pool);
+		GrDynamicArray<Dev> devs(count);
 		for(U32 devIdx = 0; devIdx < count; ++devIdx)
 		{
 			devs[devIdx].m_pdev = physicalDevices[devIdx];
@@ -554,7 +557,7 @@ Error GrManagerImpl::initInstance()
 	{
 		// Calling vkCreateGraphicsPipeline from multiple threads crashes qualcomm's compiler
 		ANKI_VK_LOGI("Enabling workaround for vkCreateGraphicsPipeline crashing when called from multiple threads");
-		m_globalCreatePipelineMtx = anki::newInstance<Mutex>(m_pool);
+		m_globalCreatePipelineMtx = anki::newInstance<Mutex>(GrMemoryPool::getSingleton());
 	}
 #endif
 
@@ -570,7 +573,7 @@ Error GrManagerImpl::initDevice()
 	vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &count, nullptr);
 	ANKI_VK_LOGI("Number of queue families: %u", count);
 
-	DynamicArrayRaii<VkQueueFamilyProperties> queueInfos(&m_pool);
+	GrDynamicArray<VkQueueFamilyProperties> queueInfos;
 	queueInfos.create(count);
 	vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &count, &queueInfos[0]);
 
@@ -640,8 +643,8 @@ Error GrManagerImpl::initDevice()
 	U32 extCount = 0;
 	vkEnumerateDeviceExtensionProperties(m_physicalDevice, nullptr, &extCount, nullptr);
 
-	DynamicArrayRaii<VkExtensionProperties> extensionInfos(&m_pool); // Keep it alive in the stack
-	DynamicArrayRaii<const char*> extensionsToEnable(&m_pool);
+	GrDynamicArray<VkExtensionProperties> extensionInfos; // Keep it alive in the stack
+	GrDynamicArray<const char*> extensionsToEnable;
 	if(extCount)
 	{
 		extensionInfos.create(extCount);
@@ -1165,8 +1168,7 @@ Error GrManagerImpl::initMemory()
 					 ANKI_FORMAT_U32(m_memoryProperties.memoryTypes[i].propertyFlags));
 	}
 
-	m_gpuMemManager.init(m_physicalDevice, m_device, &m_pool,
-						 !!(m_extensions & VulkanExtensions::kKHR_buffer_device_address));
+	m_gpuMemManager.init(!!(m_extensions & VulkanExtensions::kKHR_buffer_device_address));
 
 	return Error::kNone;
 }
@@ -1492,7 +1494,7 @@ void GrManagerImpl::trySetVulkanHandleName(CString name, VkObjectType type, U64
 VkBool32 GrManagerImpl::debugReportCallbackEXT(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
 											   [[maybe_unused]] VkDebugUtilsMessageTypeFlagsEXT messageTypes,
 											   const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
-											   void* pUserData)
+											   [[maybe_unused]] void* pUserData)
 {
 #if ANKI_PLATFORM_MOBILE
 	if(pCallbackData->messageIdNumber == 101294395)
@@ -1505,8 +1507,7 @@ VkBool32 GrManagerImpl::debugReportCallbackEXT(VkDebugUtilsMessageSeverityFlagBi
 #endif
 
 	// Get all names of affected objects
-	GrManagerImpl* self = static_cast<GrManagerImpl*>(pUserData);
-	StringRaii objectNames(&self->m_pool);
+	GrString objectNames;
 	if(pCallbackData->objectCount)
 	{
 		for(U32 i = 0; i < pCallbackData->objectCount; ++i)
@@ -1561,8 +1562,7 @@ Error GrManagerImpl::printPipelineShaderInfoInternal(VkPipeline ppline, CString
 		if(!m_shaderStatsFile.isOpen())
 		{
 			ANKI_CHECK(m_shaderStatsFile.open(
-				StringRaii(&m_pool).sprintf("%s/../ppline_stats.csv", m_cacheDir.cstr()).toCString(),
-				FileOpenFlag::kWrite));
+				GrString().sprintf("%s/../ppline_stats.csv", m_cacheDir.cstr()).toCString(), FileOpenFlag::kWrite));
 
 			ANKI_CHECK(m_shaderStatsFile.writeText("ppline name,hash,"
 												   "stage 0 VGPR,stage 0 SGPR,"
@@ -1575,7 +1575,7 @@ Error GrManagerImpl::printPipelineShaderInfoInternal(VkPipeline ppline, CString
 
 		ANKI_CHECK(m_shaderStatsFile.writeTextf("%s,0x%" PRIx64 ",", name.cstr(), hash));
 
-		StringRaii str(&m_pool);
+		GrString str;
 
 		for(ShaderType type = ShaderType::kFirst; type < ShaderType::kCount; ++type)
 		{
@@ -1590,8 +1590,8 @@ Error GrManagerImpl::printPipelineShaderInfoInternal(VkPipeline ppline, CString
 			ANKI_VK_CHECK(m_pfnGetShaderInfoAMD(m_device, ppline, VkShaderStageFlagBits(convertShaderTypeBit(stage)),
 												VK_SHADER_INFO_TYPE_STATISTICS_AMD, &size, &stats));
 
-			str.append(StringRaii(&m_pool).sprintf("Stage %u: VGRPS %02u, SGRPS %02u ", U32(type),
-												   stats.resourceUsage.numUsedVgprs, stats.resourceUsage.numUsedSgprs));
+			str.append(GrString().sprintf("Stage %u: VGRPS %02u, SGRPS %02u ", U32(type),
+										  stats.resourceUsage.numUsedVgprs, stats.resourceUsage.numUsedSgprs));
 
 			ANKI_CHECK(m_shaderStatsFile.writeTextf((type != ShaderType::kLast) ? "%u,%u," : "%u,%u\n",
 													stats.resourceUsage.numUsedVgprs,
@@ -1606,14 +1606,14 @@ Error GrManagerImpl::printPipelineShaderInfoInternal(VkPipeline ppline, CString
 
 	if(!!(m_extensions & VulkanExtensions::kKHR_pipeline_executable_properties))
 	{
-		StringListRaii log(&m_pool);
+		GrStringList log;
 
 		VkPipelineInfoKHR pplineInf = {};
 		pplineInf.sType = VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR;
 		pplineInf.pipeline = ppline;
 		U32 executableCount = 0;
 		ANKI_VK_CHECK(vkGetPipelineExecutablePropertiesKHR(m_device, &pplineInf, &executableCount, nullptr));
-		DynamicArrayRaii<VkPipelineExecutablePropertiesKHR> executableProps(executableCount, &m_pool);
+		GrDynamicArray<VkPipelineExecutablePropertiesKHR> executableProps(executableCount);
 		for(VkPipelineExecutablePropertiesKHR& prop : executableProps)
 		{
 			prop = {};
@@ -1635,7 +1635,7 @@ Error GrManagerImpl::printPipelineShaderInfoInternal(VkPipeline ppline, CString
 			exeInf.pipeline = ppline;
 			U32 statCount = 0;
 			vkGetPipelineExecutableStatisticsKHR(m_device, &exeInf, &statCount, nullptr);
-			DynamicArrayRaii<VkPipelineExecutableStatisticKHR> stats(statCount, &m_pool);
+			GrDynamicArray<VkPipelineExecutableStatisticKHR> stats(statCount);
 			for(VkPipelineExecutableStatisticKHR& s : stats)
 			{
 				s = {};
@@ -1674,7 +1674,7 @@ Error GrManagerImpl::printPipelineShaderInfoInternal(VkPipeline ppline, CString
 			}
 		}
 
-		StringRaii finalLog(&m_pool);
+		GrString finalLog;
 		log.join("", finalLog);
 		ANKI_VK_LOGV("%s", finalLog.cstr());
 	}

+ 3 - 3
AnKi/Gr/Vulkan/GrUpscaler.cpp

@@ -9,13 +9,13 @@
 
 namespace anki {
 
-GrUpscaler* GrUpscaler::newInstance(GrManager* manager, const GrUpscalerInitInfo& initInfo)
+GrUpscaler* GrUpscaler::newInstance(const GrUpscalerInitInfo& initInfo)
 {
-	GrUpscalerImpl* impl = anki::newInstance<GrUpscalerImpl>(manager->getMemoryPool(), manager, initInfo.getName());
+	GrUpscalerImpl* impl = anki::newInstance<GrUpscalerImpl>(GrMemoryPool::getSingleton(), initInfo.getName());
 	const Error err = impl->initInternal(initInfo);
 	if(err)
 	{
-		deleteInstance(manager->getMemoryPool(), impl);
+		deleteInstance(GrMemoryPool::getSingleton(), impl);
 		impl = nullptr;
 	}
 	return impl;

+ 1 - 1
AnKi/Gr/Vulkan/GrUpscalerImpl.cpp

@@ -138,7 +138,7 @@ Error GrUpscalerImpl::createDlssFeature(const UVec2& srcRes, const UVec2& dstRes
 	// Create the feature with a tmp CmdBuffer
 	CommandBufferInitInfo cmdbinit;
 	cmdbinit.m_flags = CommandBufferFlag::kGeneralWork | CommandBufferFlag::kSmallBatch;
-	CommandBufferPtr cmdb = getManager().newCommandBuffer(cmdbinit);
+	CommandBufferPtr cmdb = getGrManagerImpl().newCommandBuffer(cmdbinit);
 	CommandBufferImpl& cmdbImpl = static_cast<CommandBufferImpl&>(*cmdb);
 
 	cmdbImpl.beginRecordingExt();

+ 3 - 4
AnKi/Gr/Vulkan/GrUpscalerImpl.h

@@ -6,7 +6,6 @@
 #pragma once
 
 #include <AnKi/Gr/GrUpscaler.h>
-#include <AnKi/Gr/Vulkan/VulkanObject.h>
 #include <AnKi/Gr/Vulkan/GpuMemoryManager.h>
 
 // Ngx Sdk forward declarations
@@ -26,11 +25,11 @@ public:
 	UVec2 m_dynamicMinimumRenderSize = UVec2(kMaxU32);
 };
 
-class GrUpscalerImpl final : public GrUpscaler, public VulkanObject<GrUpscaler, GrUpscalerImpl>
+class GrUpscalerImpl final : public GrUpscaler
 {
 public:
-	GrUpscalerImpl(GrManager* manager, CString name)
-		: GrUpscaler(manager, name)
+	GrUpscalerImpl(CString name)
+		: GrUpscaler(name)
 	{
 	}
 

+ 1 - 12
AnKi/Gr/Vulkan/MicroObjectRecycler.h

@@ -22,21 +22,11 @@ public:
 	{
 	}
 
-	MicroObjectRecycler(HeapMemoryPool* pool)
-	{
-		init(pool);
-	}
-
 	~MicroObjectRecycler()
 	{
 		destroy();
 	}
 
-	void init(HeapMemoryPool* pool)
-	{
-		m_pool = pool;
-	}
-
 	/// It's thread-safe.
 	void destroy();
 
@@ -67,8 +57,7 @@ private:
 		Bool m_fenceDone;
 	};
 
-	HeapMemoryPool* m_pool = nullptr;
-	DynamicArray<Object> m_objects;
+	GrDynamicArray<Object> m_objects;
 	Mutex m_mtx;
 
 	// Begin trim cache adjustment vars

+ 10 - 12
AnKi/Gr/Vulkan/MicroObjectRecycler.inl.h

@@ -20,14 +20,13 @@ inline void MicroObjectRecycler<T>::destroy()
 		ANKI_ASSERT(mobj);
 		ANKI_ASSERT(!mobj->getFence());
 
-		auto& pool = mobj->getMemoryPool();
-		deleteInstance(pool, mobj);
+		deleteInstance(GrMemoryPool::getSingleton(), mobj);
 #if ANKI_EXTRA_CHECKS
 		--m_createdAndNotRecycled;
 #endif
 	}
 
-	m_objects.destroy(*m_pool);
+	m_objects.destroy();
 	ANKI_ASSERT(m_createdAndNotRecycled == 0 && "Destroying the recycler while objects have not recycled yet");
 }
 
@@ -49,7 +48,7 @@ inline T* MicroObjectRecycler<T>::findToReuse()
 		{
 			out = m_objects[i].m_microObject;
 			m_objects[i] = m_objects[m_objects.getSize() - 1];
-			m_objects.popBack(*m_pool);
+			m_objects.popBack();
 
 			break;
 		}
@@ -86,7 +85,7 @@ void MicroObjectRecycler<T>::recycle(T* mobj)
 		mobj->onFenceDone();
 	}
 
-	m_objects.emplaceBack(*m_pool, obj);
+	m_objects.emplaceBack(obj);
 	checkDoneFences();
 	trimCacheInternal(m_readyObjectsAfterTrim);
 }
@@ -115,7 +114,7 @@ void MicroObjectRecycler<T>::checkDoneFences()
 template<typename T>
 void MicroObjectRecycler<T>::trimCacheInternal(U32 aliveObjectCountAfterTrim)
 {
-	DynamicArray<Object> aliveObjects;
+	GrDynamicArray<Object> aliveObjects;
 
 	for(Object& obj : m_objects)
 	{
@@ -125,18 +124,17 @@ void MicroObjectRecycler<T>::trimCacheInternal(U32 aliveObjectCountAfterTrim)
 		if(inUseByTheGpu)
 		{
 			// Can't delete it for sure
-			aliveObjects.emplaceBack(*m_pool, obj);
+			aliveObjects.emplaceBack(obj);
 		}
 		else if(aliveObjectCountAfterTrim > 0)
 		{
 			// Need to keep a few alive for recycling
-			aliveObjects.emplaceBack(*m_pool, obj);
+			aliveObjects.emplaceBack(obj);
 			--aliveObjectCountAfterTrim;
 		}
 		else
 		{
-			auto& pool = mobj.getMemoryPool();
-			deleteInstance(pool, &mobj);
+			deleteInstance(GrMemoryPool::getSingleton(), &mobj);
 #if ANKI_EXTRA_CHECKS
 			--m_createdAndNotRecycled;
 #endif
@@ -146,13 +144,13 @@ void MicroObjectRecycler<T>::trimCacheInternal(U32 aliveObjectCountAfterTrim)
 	if(aliveObjects.getSize() > 0)
 	{
 		// Some alive, store the alive
-		m_objects.destroy(*m_pool);
+		m_objects.destroy();
 		m_objects = std::move(aliveObjects);
 	}
 	else if(aliveObjects.getSize() == 0 && m_objects.getSize() > 0)
 	{
 		// All dead, destroy the array
-		m_objects.destroy(*m_pool);
+		m_objects.destroy();
 	}
 }
 

+ 3 - 3
AnKi/Gr/Vulkan/OcclusionQuery.cpp

@@ -9,13 +9,13 @@
 
 namespace anki {
 
-OcclusionQuery* OcclusionQuery::newInstance(GrManager* manager)
+OcclusionQuery* OcclusionQuery::newInstance()
 {
-	OcclusionQueryImpl* impl = anki::newInstance<OcclusionQueryImpl>(manager->getMemoryPool(), manager, "N/A");
+	OcclusionQueryImpl* impl = anki::newInstance<OcclusionQueryImpl>(GrMemoryPool::getSingleton(), "N/A");
 	const Error err = impl->init();
 	if(err)
 	{
-		deleteInstance(manager->getMemoryPool(), impl);
+		deleteInstance(GrMemoryPool::getSingleton(), impl);
 		impl = nullptr;
 	}
 	return impl;

+ 1 - 1
AnKi/Gr/Vulkan/OcclusionQueryImpl.cpp

@@ -28,7 +28,7 @@ OcclusionQueryResult OcclusionQueryImpl::getResultInternal() const
 	U64 out = 0;
 
 	VkResult res;
-	ANKI_VK_CHECKF(res = vkGetQueryPoolResults(getDevice(), m_handle.getQueryPool(), m_handle.getQueryIndex(), 1,
+	ANKI_VK_CHECKF(res = vkGetQueryPoolResults(getVkDevice(), m_handle.getQueryPool(), m_handle.getQueryIndex(), 1,
 											   sizeof(out), &out, sizeof(out),
 											   VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT
 												   | VK_QUERY_RESULT_PARTIAL_BIT));

+ 3 - 4
AnKi/Gr/Vulkan/OcclusionQueryImpl.h

@@ -6,7 +6,6 @@
 #pragma once
 
 #include <AnKi/Gr/OcclusionQuery.h>
-#include <AnKi/Gr/Vulkan/VulkanObject.h>
 #include <AnKi/Gr/Vulkan/QueryFactory.h>
 
 namespace anki {
@@ -15,13 +14,13 @@ namespace anki {
 /// @{
 
 /// Occlusion query.
-class OcclusionQueryImpl final : public OcclusionQuery, public VulkanObject<OcclusionQuery, OcclusionQueryImpl>
+class OcclusionQueryImpl final : public OcclusionQuery
 {
 public:
 	MicroQuery m_handle = {};
 
-	OcclusionQueryImpl(GrManager* manager, CString name)
-		: OcclusionQuery(manager, name)
+	OcclusionQueryImpl(CString name)
+		: OcclusionQuery(name)
 	{
 	}
 

+ 14 - 6
AnKi/Gr/Vulkan/Pipeline.cpp

@@ -410,17 +410,25 @@ public:
 	}
 };
 
+PipelineFactory::PipelineFactory()
+{
+}
+
+PipelineFactory::~PipelineFactory()
+{
+}
+
 void PipelineFactory::destroy()
 {
 	for(auto it : m_pplines)
 	{
 		if(it.m_handle)
 		{
-			vkDestroyPipeline(m_dev, it.m_handle, nullptr);
+			vkDestroyPipeline(getVkDevice(), it.m_handle, nullptr);
 		}
 	}
 
-	m_pplines.destroy(*m_pool);
+	m_pplines.destroy();
 }
 
 void PipelineFactory::getOrCreatePipeline(PipelineStateTracker& state, Pipeline& ppline, Bool& stateDirty)
@@ -474,7 +482,7 @@ void PipelineFactory::getOrCreatePipeline(PipelineStateTracker& state, Pipeline&
 		}
 #endif
 
-		ANKI_VK_CHECKF(vkCreateGraphicsPipelines(m_dev, m_pplineCache, 1, &ci, nullptr, &pp.m_handle));
+		ANKI_VK_CHECKF(vkCreateGraphicsPipelines(getVkDevice(), m_pplineCache, 1, &ci, nullptr, &pp.m_handle));
 
 #if ANKI_PLATFORM_MOBILE
 		if(m_globalCreatePipelineMtx)
@@ -486,12 +494,12 @@ void PipelineFactory::getOrCreatePipeline(PipelineStateTracker& state, Pipeline&
 
 	ANKI_TRACE_INC_COUNTER(VkPipelineCacheMiss, 1);
 
-	m_pplines.emplace(*m_pool, hash, pp);
+	m_pplines.emplace(hash, pp);
 	ppline.m_handle = pp.m_handle;
 
 	// Print shader info
-	state.m_state.m_prog->getGrManagerImpl().printPipelineShaderInfo(pp.m_handle, state.m_state.m_prog->getName(),
-																	 state.m_state.m_prog->getStages(), hash);
+	getGrManagerImpl().printPipelineShaderInfo(pp.m_handle, state.m_state.m_prog->getName(),
+											   state.m_state.m_prog->getStages(), hash);
 }
 
 } // end namespace anki

+ 4 - 13
AnKi/Gr/Vulkan/Pipeline.h

@@ -533,24 +533,17 @@ private:
 class PipelineFactory
 {
 public:
-	PipelineFactory()
-	{
-	}
+	PipelineFactory();
 
-	~PipelineFactory()
-	{
-	}
+	~PipelineFactory();
 
-	void init(HeapMemoryPool* pool, VkDevice dev, VkPipelineCache pplineCache
+	void init(VkPipelineCache pplineCache
 #if ANKI_PLATFORM_MOBILE
 			  ,
 			  Mutex* globalCreatePipelineMtx
 #endif
 	)
 	{
-		ANKI_ASSERT(pool);
-		m_pool = pool;
-		m_dev = dev;
 		m_pplineCache = pplineCache;
 #if ANKI_PLATFORM_MOBILE
 		m_globalCreatePipelineMtx = globalCreatePipelineMtx;
@@ -566,11 +559,9 @@ private:
 	class PipelineInternal;
 	class Hasher;
 
-	HeapMemoryPool* m_pool = nullptr;
-	VkDevice m_dev = VK_NULL_HANDLE;
 	VkPipelineCache m_pplineCache = VK_NULL_HANDLE;
 
-	HashMap<U64, PipelineInternal, Hasher> m_pplines;
+	GrHashMap<U64, PipelineInternal, Hasher> m_pplines;
 	RWMutex m_pplinesMtx;
 #if ANKI_PLATFORM_MOBILE
 	Mutex* m_globalCreatePipelineMtx = nullptr;

+ 16 - 17
AnKi/Gr/Vulkan/PipelineCache.cpp

@@ -4,20 +4,21 @@
 // http://www.anki3d.org/LICENSE
 
 #include <AnKi/Gr/Vulkan/PipelineCache.h>
+#include <AnKi/Gr/Vulkan/GrManagerImpl.h>
 #include <AnKi/Core/ConfigSet.h>
 #include <AnKi/Util/Filesystem.h>
 #include <AnKi/Util/File.h>
 
 namespace anki {
 
-Error PipelineCache::init(VkDevice dev, VkPhysicalDevice pdev, CString cacheDir, HeapMemoryPool& pool)
+Error PipelineCache::init(CString cacheDir)
 {
-	ANKI_ASSERT(cacheDir && dev && pdev);
+	ANKI_ASSERT(cacheDir);
 	m_dumpSize = ConfigSet::getSingleton().getGrDiskShaderCacheMaxSize();
-	m_dumpFilename.sprintf(pool, "%s/VkPipelineCache", &cacheDir[0]);
+	m_dumpFilename.sprintf("%s/VkPipelineCache", cacheDir.cstr());
 
 	// Try read the pipeline cache file.
-	DynamicArrayRaii<U8, PtrSize> diskDump(&pool);
+	GrDynamicArray<U8, PtrSize> diskDump;
 	if(fileExists(m_dumpFilename.toCString()))
 	{
 		File file;
@@ -32,7 +33,7 @@ Error PipelineCache::init(VkDevice dev, VkPhysicalDevice pdev, CString cacheDir,
 		{
 			// Get current pipeline UUID and compare it with the cache's
 			VkPhysicalDeviceProperties props;
-			vkGetPhysicalDeviceProperties(pdev, &props);
+			vkGetPhysicalDeviceProperties(getGrManagerImpl().getPhysicalDevice(), &props);
 
 			Array<U8, VK_UUID_SIZE> cacheUuid;
 			ANKI_CHECK(file.read(&cacheUuid[0], VK_UUID_SIZE));
@@ -63,46 +64,44 @@ Error PipelineCache::init(VkDevice dev, VkPhysicalDevice pdev, CString cacheDir,
 		ci.pInitialData = &diskDump[0];
 	}
 
-	ANKI_VK_CHECK(vkCreatePipelineCache(dev, &ci, nullptr, &m_cacheHandle));
+	ANKI_VK_CHECK(vkCreatePipelineCache(getVkDevice(), &ci, nullptr, &m_cacheHandle));
 
 	return Error::kNone;
 }
 
-void PipelineCache::destroy(VkDevice dev, VkPhysicalDevice pdev, HeapMemoryPool& pool)
+void PipelineCache::destroy()
 {
-	const Error err = destroyInternal(dev, pdev, pool);
+	const Error err = destroyInternal();
 	if(err)
 	{
 		ANKI_VK_LOGE("An error occurred while storing the pipeline cache to disk. Will ignore");
 	}
 
-	m_dumpFilename.destroy(pool);
+	m_dumpFilename.destroy();
 }
 
-Error PipelineCache::destroyInternal(VkDevice dev, VkPhysicalDevice pdev, HeapMemoryPool& pool)
+Error PipelineCache::destroyInternal()
 {
 	if(m_cacheHandle)
 	{
-		ANKI_ASSERT(dev && pdev);
-
 		// Get size of cache
 		size_t size = 0;
-		ANKI_VK_CHECK(vkGetPipelineCacheData(dev, m_cacheHandle, &size, nullptr));
+		ANKI_VK_CHECK(vkGetPipelineCacheData(getVkDevice(), m_cacheHandle, &size, nullptr));
 		size = min(size, m_dumpSize);
 
 		if(size > 0)
 		{
 			// Read cache
-			DynamicArrayRaii<U8, PtrSize> cacheData(&pool);
+			GrDynamicArray<U8, PtrSize> cacheData;
 			cacheData.create(size);
-			ANKI_VK_CHECK(vkGetPipelineCacheData(dev, m_cacheHandle, &size, &cacheData[0]));
+			ANKI_VK_CHECK(vkGetPipelineCacheData(getVkDevice(), m_cacheHandle, &size, &cacheData[0]));
 
 			// Write file
 			File file;
 			ANKI_CHECK(file.open(&m_dumpFilename[0], FileOpenFlag::kBinary | FileOpenFlag::kWrite));
 
 			VkPhysicalDeviceProperties props;
-			vkGetPhysicalDeviceProperties(pdev, &props);
+			vkGetPhysicalDeviceProperties(getGrManagerImpl().getPhysicalDevice(), &props);
 
 			ANKI_CHECK(file.write(&props.pipelineCacheUUID[0], VK_UUID_SIZE));
 			ANKI_CHECK(file.write(&cacheData[0], size));
@@ -111,7 +110,7 @@ Error PipelineCache::destroyInternal(VkDevice dev, VkPhysicalDevice pdev, HeapMe
 		}
 
 		// Destroy cache
-		vkDestroyPipelineCache(dev, m_cacheHandle, nullptr);
+		vkDestroyPipelineCache(getVkDevice(), m_cacheHandle, nullptr);
 		m_cacheHandle = VK_NULL_HANDLE;
 	}
 

+ 4 - 4
AnKi/Gr/Vulkan/PipelineCache.h

@@ -18,15 +18,15 @@ class PipelineCache
 public:
 	VkPipelineCache m_cacheHandle = VK_NULL_HANDLE;
 
-	Error init(VkDevice dev, VkPhysicalDevice pdev, CString cacheDir, HeapMemoryPool& pool);
+	Error init(CString cacheDir);
 
-	void destroy(VkDevice dev, VkPhysicalDevice pdev, HeapMemoryPool& pool);
+	void destroy();
 
 private:
-	String m_dumpFilename;
+	GrString m_dumpFilename;
 	PtrSize m_dumpSize = 0;
 
-	Error destroyInternal(VkDevice dev, VkPhysicalDevice pdev, HeapMemoryPool& pool);
+	Error destroyInternal();
 };
 /// @}
 

+ 4 - 4
AnKi/Gr/Vulkan/PipelineLayout.cpp

@@ -13,9 +13,9 @@ void PipelineLayoutFactory::destroy()
 	{
 		auto it = m_layouts.getBegin();
 		VkPipelineLayout handle = *it;
-		m_layouts.erase(*m_pool, it);
+		m_layouts.erase(it);
 
-		vkDestroyPipelineLayout(m_dev, handle, nullptr);
+		vkDestroyPipelineLayout(getVkDevice(), handle, nullptr);
 	}
 }
 
@@ -64,9 +64,9 @@ Error PipelineLayoutFactory::newPipelineLayout(const WeakArray<DescriptorSetLayo
 		}
 
 		VkPipelineLayout pplineLayHandle;
-		ANKI_VK_CHECK(vkCreatePipelineLayout(m_dev, &ci, nullptr, &pplineLayHandle));
+		ANKI_VK_CHECK(vkCreatePipelineLayout(getVkDevice(), &ci, nullptr, &pplineLayHandle));
 
-		m_layouts.emplace(*m_pool, hash, pplineLayHandle);
+		m_layouts.emplace(hash, pplineLayHandle);
 
 		layout.m_handle = pplineLayHandle;
 	}

+ 1 - 11
AnKi/Gr/Vulkan/PipelineLayout.h

@@ -35,13 +35,6 @@ public:
 	PipelineLayoutFactory() = default;
 	~PipelineLayoutFactory() = default;
 
-	void init(HeapMemoryPool* pool, VkDevice dev)
-	{
-		ANKI_ASSERT(pool);
-		m_pool = pool;
-		m_dev = dev;
-	}
-
 	void destroy();
 
 	/// @note It's thread-safe.
@@ -49,10 +42,7 @@ public:
 							PipelineLayout& layout);
 
 private:
-	HeapMemoryPool* m_pool = nullptr;
-	VkDevice m_dev = VK_NULL_HANDLE;
-
-	HashMap<U64, VkPipelineLayout> m_layouts;
+	GrHashMap<U64, VkPipelineLayout> m_layouts;
 	Mutex m_layoutsMtx;
 };
 /// @}

+ 4 - 4
AnKi/Gr/Vulkan/QueryFactory.cpp

@@ -44,14 +44,14 @@ Error QueryFactory::newQuery(MicroQuery& handle)
 	if(chunk == nullptr)
 	{
 		// Create new chunk
-		chunk = newInstance<Chunk>(*m_pool);
+		chunk = newInstance<Chunk>(GrMemoryPool::getSingleton());
 
 		VkQueryPoolCreateInfo ci = {};
 		ci.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
 		ci.queryType = m_poolType;
 		ci.queryCount = kMaxSuballocationsPerQueryChunk;
 
-		ANKI_VK_CHECK(vkCreateQueryPool(m_dev, &ci, nullptr, &chunk->m_pool));
+		ANKI_VK_CHECK(vkCreateQueryPool(getVkDevice(), &ci, nullptr, &chunk->m_pool));
 		m_chunks.pushBack(chunk);
 	}
 
@@ -91,10 +91,10 @@ void QueryFactory::deleteQuery(MicroQuery& handle)
 		// Delete the chunk
 
 		ANKI_ASSERT(chunk->m_allocatedMask.getAny());
-		vkDestroyQueryPool(m_dev, chunk->m_pool, nullptr);
+		vkDestroyQueryPool(getVkDevice(), chunk->m_pool, nullptr);
 
 		m_chunks.erase(chunk);
-		deleteInstance(*m_pool, chunk);
+		deleteInstance(GrMemoryPool::getSingleton(), chunk);
 	}
 	else
 	{

+ 1 - 6
AnKi/Gr/Vulkan/QueryFactory.h

@@ -74,11 +74,8 @@ public:
 
 	QueryFactory& operator=(const QueryFactory&) = delete; // Non-copyable
 
-	void init(HeapMemoryPool* pool, VkDevice dev, VkQueryType poolType)
+	void init(VkQueryType poolType)
 	{
-		ANKI_ASSERT(pool);
-		m_pool = pool;
-		m_dev = dev;
 		m_poolType = poolType;
 	}
 
@@ -91,8 +88,6 @@ public:
 private:
 	using Chunk = QueryFactoryChunk;
 
-	HeapMemoryPool* m_pool = nullptr;
-	VkDevice m_dev;
 	IntrusiveList<Chunk> m_chunks;
 	Mutex m_mtx;
 	VkQueryType m_poolType = VK_QUERY_TYPE_MAX_ENUM;

+ 3 - 3
AnKi/Gr/Vulkan/Sampler.cpp

@@ -9,13 +9,13 @@
 
 namespace anki {
 
-Sampler* Sampler::newInstance(GrManager* manager, const SamplerInitInfo& init)
+Sampler* Sampler::newInstance(const SamplerInitInfo& init)
 {
-	SamplerImpl* impl = anki::newInstance<SamplerImpl>(manager->getMemoryPool(), manager, init.getName());
+	SamplerImpl* impl = anki::newInstance<SamplerImpl>(GrMemoryPool::getSingleton(), init.getName());
 	const Error err = impl->init(init);
 	if(err)
 	{
-		deleteInstance(manager->getMemoryPool(), impl);
+		deleteInstance(GrMemoryPool::getSingleton(), impl);
 		impl = nullptr;
 	}
 	return impl;

+ 9 - 28
AnKi/Gr/Vulkan/SamplerFactory.cpp

@@ -12,7 +12,7 @@ MicroSampler::~MicroSampler()
 {
 	if(m_handle)
 	{
-		vkDestroySampler(m_factory->m_gr->getDevice(), m_handle, nullptr);
+		vkDestroySampler(getVkDevice(), m_handle, nullptr);
 	}
 }
 
@@ -33,7 +33,7 @@ Error MicroSampler::init(const SamplerInitInfo& inf)
 	else
 	{
 		ANKI_ASSERT(inf.m_minMagFilter == SamplingFilter::kMax || inf.m_minMagFilter == SamplingFilter::kMin);
-		ANKI_ASSERT(m_factory->m_gr->getDeviceCapabilities().m_samplingFilterMinMax);
+		ANKI_ASSERT(getGrManagerImpl().getDeviceCapabilities().m_samplingFilterMinMax);
 		ci.minFilter = VK_FILTER_LINEAR;
 	}
 
@@ -106,43 +106,26 @@ Error MicroSampler::init(const SamplerInitInfo& inf)
 	}
 
 	// Create
-	ANKI_VK_CHECK(vkCreateSampler(m_factory->m_gr->getDevice(), &ci, nullptr, &m_handle));
-	m_factory->m_gr->trySetVulkanHandleName(inf.getName(), VK_OBJECT_TYPE_SAMPLER, m_handle);
+	ANKI_VK_CHECK(vkCreateSampler(getVkDevice(), &ci, nullptr, &m_handle));
+	getGrManagerImpl().trySetVulkanHandleName(inf.getName(), VK_OBJECT_TYPE_SAMPLER, m_handle);
 
 	return Error::kNone;
 }
 
-void SamplerFactory::init(GrManagerImpl* gr)
-{
-	ANKI_ASSERT(gr);
-	ANKI_ASSERT(!m_gr);
-	m_gr = gr;
-}
-
 void SamplerFactory::destroy()
 {
-	if(!m_gr)
-	{
-		return;
-	}
-
-	HeapMemoryPool& pool = m_gr->getMemoryPool();
 	for(auto it : m_map)
 	{
 		MicroSampler* const sampler = it;
 		ANKI_ASSERT(sampler->getRefcount() == 0 && "Someone still holds a reference to a sampler");
-		deleteInstance(pool, sampler);
+		deleteInstance(GrMemoryPool::getSingleton(), sampler);
 	}
 
-	m_map.destroy(pool);
-
-	m_gr = nullptr;
+	m_map.destroy();
 }
 
 Error SamplerFactory::newInstance(const SamplerInitInfo& inf, MicroSamplerPtr& psampler)
 {
-	ANKI_ASSERT(m_gr);
-
 	Error err = Error::kNone;
 	MicroSampler* out = nullptr;
 	const U64 hash = inf.computeHash();
@@ -159,19 +142,17 @@ Error SamplerFactory::newInstance(const SamplerInitInfo& inf, MicroSamplerPtr& p
 	{
 		// Create a new one
 
-		HeapMemoryPool& pool = m_gr->getMemoryPool();
-
-		out = anki::newInstance<MicroSampler>(pool, this);
+		out = anki::newInstance<MicroSampler>(GrMemoryPool::getSingleton(), this);
 		err = out->init(inf);
 
 		if(err)
 		{
-			deleteInstance(pool, out);
+			deleteInstance(GrMemoryPool::getSingleton(), out);
 			out = nullptr;
 		}
 		else
 		{
-			m_map.emplace(pool, hash, out);
+			m_map.emplace(hash, out);
 		}
 	}
 

+ 1 - 13
AnKi/Gr/Vulkan/SamplerFactory.h

@@ -81,25 +81,13 @@ class SamplerFactory
 	friend class MicroSampler;
 
 public:
-	SamplerFactory()
-	{
-	}
-
-	~SamplerFactory()
-	{
-		ANKI_ASSERT(m_gr == nullptr && "Forgot to call destroy()");
-	}
-
-	void init(GrManagerImpl* gr);
-
 	void destroy();
 
 	/// Create a new sampler. It's thread-safe.
 	Error newInstance(const SamplerInitInfo& inf, MicroSamplerPtr& psampler);
 
 private:
-	GrManagerImpl* m_gr = nullptr;
-	HashMap<U64, MicroSampler*> m_map;
+	GrHashMap<U64, MicroSampler*> m_map;
 	Mutex m_mtx;
 };
 /// @}

+ 3 - 4
AnKi/Gr/Vulkan/SamplerImpl.h

@@ -6,7 +6,6 @@
 #pragma once
 
 #include <AnKi/Gr/Sampler.h>
-#include <AnKi/Gr/Vulkan/VulkanObject.h>
 #include <AnKi/Gr/Vulkan/SamplerFactory.h>
 
 namespace anki {
@@ -15,13 +14,13 @@ namespace anki {
 /// @{
 
 /// Vulkan implementation of Sampler.
-class SamplerImpl final : public Sampler, public VulkanObject<Sampler, SamplerImpl>
+class SamplerImpl final : public Sampler
 {
 public:
 	MicroSamplerPtr m_sampler;
 
-	SamplerImpl(GrManager* manager, CString name)
-		: Sampler(manager, name)
+	SamplerImpl(CString name)
+		: Sampler(name)
 	{
 	}
 

+ 0 - 13
AnKi/Gr/Vulkan/SemaphoreFactory.h

@@ -34,8 +34,6 @@ public:
 		return m_handle;
 	}
 
-	HeapMemoryPool& getMemoryPool();
-
 	void retain() const
 	{
 		m_refcount.fetchAdd(1);
@@ -123,15 +121,6 @@ class SemaphoreFactory
 	friend class MicroSemaphorePtrDeleter;
 
 public:
-	void init(HeapMemoryPool* pool, VkDevice dev)
-	{
-		ANKI_ASSERT(dev);
-		m_pool = pool;
-		m_dev = dev;
-		m_binaryRecycler.init(m_pool);
-		m_timelineRecycler.init(m_pool);
-	}
-
 	void destroy()
 	{
 		m_binaryRecycler.destroy();
@@ -141,8 +130,6 @@ public:
 	MicroSemaphorePtr newInstance(MicroFencePtr fence, Bool isTimeline);
 
 private:
-	HeapMemoryPool* m_pool = nullptr;
-	VkDevice m_dev = VK_NULL_HANDLE;
 	MicroObjectRecycler<MicroSemaphore> m_binaryRecycler;
 	MicroObjectRecycler<MicroSemaphore> m_timelineRecycler;
 };

+ 4 - 9
AnKi/Gr/Vulkan/SemaphoreFactory.inl.h

@@ -26,22 +26,17 @@ inline MicroSemaphore::MicroSemaphore(SemaphoreFactory* f, MicroFencePtr fence,
 	ci.pNext = &typeCreateInfo;
 
 	ANKI_TRACE_INC_COUNTER(VkSemaphoreCreate, 1);
-	ANKI_VK_CHECKF(vkCreateSemaphore(m_factory->m_dev, &ci, nullptr, &m_handle));
+	ANKI_VK_CHECKF(vkCreateSemaphore(getVkDevice(), &ci, nullptr, &m_handle));
 }
 
 inline MicroSemaphore::~MicroSemaphore()
 {
 	if(m_handle)
 	{
-		vkDestroySemaphore(m_factory->m_dev, m_handle, nullptr);
+		vkDestroySemaphore(getVkDevice(), m_handle, nullptr);
 	}
 }
 
-inline HeapMemoryPool& MicroSemaphore::getMemoryPool()
-{
-	return *m_factory->m_pool;
-}
-
 inline Bool MicroSemaphore::clientWait(Second seconds)
 {
 	ANKI_ASSERT(m_isTimeline);
@@ -59,7 +54,7 @@ inline Bool MicroSemaphore::clientWait(Second seconds)
 	const U64 ns = U64(nsf);
 
 	VkResult res;
-	ANKI_VK_CHECKF(res = vkWaitSemaphoresKHR(m_factory->m_dev, &waitInfo, ns));
+	ANKI_VK_CHECKF(res = vkWaitSemaphoresKHR(getVkDevice(), &waitInfo, ns));
 
 	return res != VK_TIMEOUT;
 }
@@ -86,7 +81,7 @@ inline MicroSemaphorePtr SemaphoreFactory::newInstance(MicroFencePtr fence, Bool
 	if(out == nullptr)
 	{
 		// Create a new one
-		out = anki::newInstance<MicroSemaphore>(*m_pool, this, fence, isTimeline);
+		out = anki::newInstance<MicroSemaphore>(GrMemoryPool::getSingleton(), this, fence, isTimeline);
 	}
 	else
 	{

+ 3 - 3
AnKi/Gr/Vulkan/Shader.cpp

@@ -9,13 +9,13 @@
 
 namespace anki {
 
-Shader* Shader::newInstance(GrManager* manager, const ShaderInitInfo& init)
+Shader* Shader::newInstance(const ShaderInitInfo& init)
 {
-	ShaderImpl* impl = anki::newInstance<ShaderImpl>(manager->getMemoryPool(), manager, init.getName());
+	ShaderImpl* impl = anki::newInstance<ShaderImpl>(GrMemoryPool::getSingleton(), init.getName());
 	const Error err = impl->init(init);
 	if(err)
 	{
-		deleteInstance(manager->getMemoryPool(), impl);
+		deleteInstance(GrMemoryPool::getSingleton(), impl);
 		impl = nullptr;
 	}
 	return impl;

+ 7 - 12
AnKi/Gr/Vulkan/ShaderImpl.cpp

@@ -25,25 +25,20 @@ public:
 
 ShaderImpl::~ShaderImpl()
 {
-	for(auto& x : m_bindings)
-	{
-		x.destroy(getMemoryPool());
-	}
-
 	if(m_handle)
 	{
-		vkDestroyShaderModule(getDevice(), m_handle, nullptr);
+		vkDestroyShaderModule(getVkDevice(), m_handle, nullptr);
 	}
 
 	if(m_specConstInfo.pMapEntries)
 	{
-		deleteArray(getMemoryPool(), const_cast<VkSpecializationMapEntry*>(m_specConstInfo.pMapEntries),
+		deleteArray(GrMemoryPool::getSingleton(), const_cast<VkSpecializationMapEntry*>(m_specConstInfo.pMapEntries),
 					m_specConstInfo.mapEntryCount);
 	}
 
 	if(m_specConstInfo.pData)
 	{
-		deleteArray(getMemoryPool(), static_cast<I32*>(const_cast<void*>(m_specConstInfo.pData)),
+		deleteArray(GrMemoryPool::getSingleton(), static_cast<I32*>(const_cast<void*>(m_specConstInfo.pData)),
 					m_specConstInfo.dataSize / sizeof(I32));
 	}
 }
@@ -70,7 +65,7 @@ Error ShaderImpl::init(const ShaderInitInfo& inf)
 	VkShaderModuleCreateInfo ci = {VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, nullptr, 0, inf.m_binary.getSize(),
 								   reinterpret_cast<const uint32_t*>(&inf.m_binary[0])};
 
-	ANKI_VK_CHECK(vkCreateShaderModule(getDevice(), &ci, nullptr, &m_handle));
+	ANKI_VK_CHECK(vkCreateShaderModule(getVkDevice(), &ci, nullptr, &m_handle));
 
 	// Get reflection info
 	SpecConstsVector specConstIds;
@@ -82,9 +77,9 @@ Error ShaderImpl::init(const ShaderInitInfo& inf)
 		const U32 constCount = U32(specConstIds.m_vec.size());
 
 		m_specConstInfo.mapEntryCount = constCount;
-		m_specConstInfo.pMapEntries = newArray<VkSpecializationMapEntry>(getMemoryPool(), constCount);
+		m_specConstInfo.pMapEntries = newArray<VkSpecializationMapEntry>(GrMemoryPool::getSingleton(), constCount);
 		m_specConstInfo.dataSize = constCount * sizeof(U32);
-		m_specConstInfo.pData = newArray<U32>(getMemoryPool(), constCount);
+		m_specConstInfo.pData = newArray<U32>(GrMemoryPool::getSingleton(), constCount);
 
 		U32 count = 0;
 		for(const spirv_cross::SpecializationConstant& sconst : specConstIds.m_vec)
@@ -203,7 +198,7 @@ void ShaderImpl::doReflection(ConstWeakArray<U8> spirv, SpecConstsVector& specCo
 	{
 		if(counts[set])
 		{
-			m_bindings[set].create(getMemoryPool(), counts[set]);
+			m_bindings[set].create(counts[set]);
 			memcpy(&m_bindings[set][0], &descriptors[set][0], counts[set] * sizeof(DescriptorBinding));
 		}
 	}

+ 4 - 5
AnKi/Gr/Vulkan/ShaderImpl.h

@@ -6,7 +6,6 @@
 #pragma once
 
 #include <AnKi/Gr/Shader.h>
-#include <AnKi/Gr/Vulkan/VulkanObject.h>
 #include <AnKi/Gr/Vulkan/DescriptorSet.h>
 #include <AnKi/Util/BitSet.h>
 
@@ -16,12 +15,12 @@ namespace anki {
 /// @{
 
 /// Shader vulkan implementation.
-class ShaderImpl final : public Shader, public VulkanObject<Shader, ShaderImpl>
+class ShaderImpl final : public Shader
 {
 public:
 	VkShaderModule m_handle = VK_NULL_HANDLE;
 
-	Array<DynamicArray<DescriptorBinding>, kMaxDescriptorSets> m_bindings;
+	Array<GrDynamicArray<DescriptorBinding>, kMaxDescriptorSets> m_bindings;
 	BitSet<kMaxColorRenderTargets, U8> m_colorAttachmentWritemask = {false};
 	BitSet<kMaxVertexAttributes, U8> m_attributeMask = {false};
 	BitSet<kMaxDescriptorSets, U8> m_descriptorSetMask = {false};
@@ -29,8 +28,8 @@ public:
 		{{false}, {false}, {false}}};
 	U32 m_pushConstantsSize = 0;
 
-	ShaderImpl(GrManager* manager, CString name)
-		: Shader(manager, name)
+	ShaderImpl(CString name)
+		: Shader(name)
 	{
 	}
 

+ 3 - 3
AnKi/Gr/Vulkan/ShaderProgram.cpp

@@ -10,13 +10,13 @@
 
 namespace anki {
 
-ShaderProgram* ShaderProgram::newInstance(GrManager* manager, const ShaderProgramInitInfo& init)
+ShaderProgram* ShaderProgram::newInstance(const ShaderProgramInitInfo& init)
 {
-	ShaderProgramImpl* impl = anki::newInstance<ShaderProgramImpl>(manager->getMemoryPool(), manager, init.getName());
+	ShaderProgramImpl* impl = anki::newInstance<ShaderProgramImpl>(GrMemoryPool::getSingleton(), init.getName());
 	const Error err = impl->init(init);
 	if(err)
 	{
-		deleteInstance(manager->getMemoryPool(), impl);
+		deleteInstance(GrMemoryPool::getSingleton(), impl);
 		impl = nullptr;
 	}
 	return impl;

+ 20 - 25
AnKi/Gr/Vulkan/ShaderProgramImpl.cpp

@@ -16,21 +16,18 @@ ShaderProgramImpl::~ShaderProgramImpl()
 	if(m_graphics.m_pplineFactory)
 	{
 		m_graphics.m_pplineFactory->destroy();
-		deleteInstance(getMemoryPool(), m_graphics.m_pplineFactory);
+		deleteInstance(GrMemoryPool::getSingleton(), m_graphics.m_pplineFactory);
 	}
 
 	if(m_compute.m_ppline)
 	{
-		vkDestroyPipeline(getDevice(), m_compute.m_ppline, nullptr);
+		vkDestroyPipeline(getVkDevice(), m_compute.m_ppline, nullptr);
 	}
 
 	if(m_rt.m_ppline)
 	{
-		vkDestroyPipeline(getDevice(), m_rt.m_ppline, nullptr);
+		vkDestroyPipeline(getVkDevice(), m_rt.m_ppline, nullptr);
 	}
-
-	m_shaders.destroy(getMemoryPool());
-	m_rt.m_allHandles.destroy(getMemoryPool());
 }
 
 Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
@@ -39,10 +36,10 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 
 	// Create the shader references
 	//
-	HashMapRaii<U64, U32> shaderUuidToMShadersIdx(&getMemoryPool()); // Shader UUID to m_shaders idx
+	GrHashMap<U64, U32> shaderUuidToMShadersIdx; // Shader UUID to m_shaders idx
 	if(inf.m_computeShader)
 	{
-		m_shaders.emplaceBack(getMemoryPool(), inf.m_computeShader);
+		m_shaders.emplaceBack(inf.m_computeShader);
 	}
 	else if(inf.m_graphicsShaders[ShaderType::kVertex])
 	{
@@ -50,7 +47,7 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 		{
 			if(s)
 			{
-				m_shaders.emplaceBack(getMemoryPool(), s);
+				m_shaders.emplaceBack(s);
 			}
 		}
 	}
@@ -58,18 +55,17 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 	{
 		// Ray tracing
 
-		m_shaders.resizeStorage(getMemoryPool(), inf.m_rayTracingShaders.m_rayGenShaders.getSize()
-													 + inf.m_rayTracingShaders.m_missShaders.getSize()
-													 + 1); // Plus at least one hit shader
+		m_shaders.resizeStorage(inf.m_rayTracingShaders.m_rayGenShaders.getSize()
+								+ inf.m_rayTracingShaders.m_missShaders.getSize() + 1); // Plus at least one hit shader
 
 		for(const ShaderPtr& s : inf.m_rayTracingShaders.m_rayGenShaders)
 		{
-			m_shaders.emplaceBack(getMemoryPool(), s);
+			m_shaders.emplaceBack(s);
 		}
 
 		for(const ShaderPtr& s : inf.m_rayTracingShaders.m_missShaders)
 		{
-			m_shaders.emplaceBack(getMemoryPool(), s);
+			m_shaders.emplaceBack(s);
 		}
 
 		m_rt.m_missShaderCount = inf.m_rayTracingShaders.m_missShaders.getSize();
@@ -82,7 +78,7 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 				if(it == shaderUuidToMShadersIdx.getEnd())
 				{
 					shaderUuidToMShadersIdx.emplace(group.m_anyHitShader->getUuid(), m_shaders.getSize());
-					m_shaders.emplaceBack(getMemoryPool(), group.m_anyHitShader);
+					m_shaders.emplaceBack(group.m_anyHitShader);
 				}
 			}
 
@@ -92,7 +88,7 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 				if(it == shaderUuidToMShadersIdx.getEnd())
 				{
 					shaderUuidToMShadersIdx.emplace(group.m_closestHitShader->getUuid(), m_shaders.getSize());
-					m_shaders.emplaceBack(getMemoryPool(), group.m_closestHitShader);
+					m_shaders.emplaceBack(group.m_closestHitShader);
 				}
 			}
 		}
@@ -221,9 +217,8 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 	//
 	if(graphicsProg)
 	{
-		m_graphics.m_pplineFactory = anki::newInstance<PipelineFactory>(getMemoryPool());
-		m_graphics.m_pplineFactory->init(&getMemoryPool(), getGrManagerImpl().getDevice(),
-										 getGrManagerImpl().getPipelineCache()
+		m_graphics.m_pplineFactory = anki::newInstance<PipelineFactory>(GrMemoryPool::getSingleton());
+		m_graphics.m_pplineFactory->init(getGrManagerImpl().getPipelineCache()
 #if ANKI_PLATFORM_MOBILE
 											 ,
 										 getGrManagerImpl().getGlobalCreatePipelineMutex()
@@ -254,7 +249,7 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 		ci.stage.pSpecializationInfo = shaderImpl.getSpecConstInfo();
 
 		ANKI_TRACE_SCOPED_EVENT(VkPipelineCreate);
-		ANKI_VK_CHECK(vkCreateComputePipelines(getDevice(), getGrManagerImpl().getPipelineCache(), 1, &ci, nullptr,
+		ANKI_VK_CHECK(vkCreateComputePipelines(getVkDevice(), getGrManagerImpl().getPipelineCache(), 1, &ci, nullptr,
 											   &m_compute.m_ppline));
 		getGrManagerImpl().printPipelineShaderInfo(m_compute.m_ppline, getName(), ShaderTypeBit::kCompute);
 	}
@@ -264,7 +259,7 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 	if(!!(m_stages & ShaderTypeBit::kAllRayTracing))
 	{
 		// Create shaders
-		DynamicArrayRaii<VkPipelineShaderStageCreateInfo> stages(m_shaders.getSize(), &getMemoryPool());
+		GrDynamicArray<VkPipelineShaderStageCreateInfo> stages(m_shaders.getSize());
 		for(U32 i = 0; i < stages.getSize(); ++i)
 		{
 			const ShaderImpl& impl = static_cast<const ShaderImpl&>(*m_shaders[i]);
@@ -289,7 +284,7 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 		U32 groupCount = inf.m_rayTracingShaders.m_rayGenShaders.getSize()
 						 + inf.m_rayTracingShaders.m_missShaders.getSize()
 						 + inf.m_rayTracingShaders.m_hitGroups.getSize();
-		DynamicArrayRaii<VkRayTracingShaderGroupCreateInfoKHR> groups(groupCount, defaultGroup, &getMemoryPool());
+		GrDynamicArray<VkRayTracingShaderGroupCreateInfoKHR> groups(groupCount, defaultGroup);
 
 		// 1st group is the ray gen
 		groupCount = 0;
@@ -341,14 +336,14 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 		{
 			ANKI_TRACE_SCOPED_EVENT(VkPipelineCreate);
 			ANKI_VK_CHECK(vkCreateRayTracingPipelinesKHR(
-				getDevice(), VK_NULL_HANDLE, getGrManagerImpl().getPipelineCache(), 1, &ci, nullptr, &m_rt.m_ppline));
+				getVkDevice(), VK_NULL_HANDLE, getGrManagerImpl().getPipelineCache(), 1, &ci, nullptr, &m_rt.m_ppline));
 		}
 
 		// Get RT handles
 		const U32 handleArraySize =
 			getGrManagerImpl().getPhysicalDeviceRayTracingProperties().shaderGroupHandleSize * groupCount;
-		m_rt.m_allHandles.create(getMemoryPool(), handleArraySize, 0);
-		ANKI_VK_CHECK(vkGetRayTracingShaderGroupHandlesKHR(getDevice(), m_rt.m_ppline, 0, groupCount, handleArraySize,
+		m_rt.m_allHandles.create(handleArraySize, 0);
+		ANKI_VK_CHECK(vkGetRayTracingShaderGroupHandlesKHR(getVkDevice(), m_rt.m_ppline, 0, groupCount, handleArraySize,
 														   &m_rt.m_allHandles[0]));
 	}
 

+ 5 - 6
AnKi/Gr/Vulkan/ShaderProgramImpl.h

@@ -6,7 +6,6 @@
 #pragma once
 
 #include <AnKi/Gr/ShaderProgram.h>
-#include <AnKi/Gr/Vulkan/VulkanObject.h>
 #include <AnKi/Gr/Vulkan/PipelineLayout.h>
 
 namespace anki {
@@ -29,11 +28,11 @@ public:
 };
 
 /// Shader program implementation.
-class ShaderProgramImpl final : public ShaderProgram, public VulkanObject<ShaderProgram, ShaderProgramImpl>
+class ShaderProgramImpl final : public ShaderProgram
 {
 public:
-	ShaderProgramImpl(GrManager* manager, CString name)
-		: ShaderProgram(manager, name)
+	ShaderProgramImpl(CString name)
+		: ShaderProgram(name)
 	{
 	}
 
@@ -107,7 +106,7 @@ public:
 	}
 
 private:
-	DynamicArray<ShaderPtr> m_shaders;
+	GrDynamicArray<ShaderPtr> m_shaders;
 	ShaderTypeBit m_stages = ShaderTypeBit::kNone;
 
 	PipelineLayout m_pplineLayout = {};
@@ -134,7 +133,7 @@ private:
 	{
 	public:
 		VkPipeline m_ppline = VK_NULL_HANDLE;
-		DynamicArray<U8> m_allHandles;
+		GrDynamicArray<U8> m_allHandles;
 		U32 m_missShaderCount = 0;
 	} m_rt;
 };

+ 20 - 36
AnKi/Gr/Vulkan/SwapchainFactory.cpp

@@ -21,27 +21,26 @@ MicroSwapchain::MicroSwapchain(SwapchainFactory* factory)
 
 MicroSwapchain::~MicroSwapchain()
 {
-	const VkDevice dev = m_factory->m_gr->getDevice();
-
-	m_textures.destroy(getMemoryPool());
+	m_textures.destroy();
 
 	if(m_swapchain)
 	{
-		vkDestroySwapchainKHR(dev, m_swapchain, nullptr);
+		vkDestroySwapchainKHR(getVkDevice(), m_swapchain, nullptr);
 		m_swapchain = {};
 	}
 }
 
 Error MicroSwapchain::initInternal()
 {
-	const VkDevice dev = m_factory->m_gr->getDevice();
+	const VkDevice dev = getVkDevice();
+	const VkPhysicalDevice pdev = getGrManagerImpl().getPhysicalDevice();
 
 	// Get the surface size
 	VkSurfaceCapabilitiesKHR surfaceProperties;
 	U32 surfaceWidth = 0, surfaceHeight = 0;
 	{
-		ANKI_VK_CHECK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_factory->m_gr->getPhysicalDevice(),
-																m_factory->m_gr->getSurface(), &surfaceProperties));
+		ANKI_VK_CHECK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(getGrManagerImpl().getPhysicalDevice(),
+																getGrManagerImpl().getSurface(), &surfaceProperties));
 
 #if ANKI_WINDOWING_SYSTEM_HEADLESS
 		if(surfaceProperties.currentExtent.width != kMaxU32 || surfaceProperties.currentExtent.height != kMaxU32)
@@ -67,13 +66,13 @@ Error MicroSwapchain::initInternal()
 	VkColorSpaceKHR colorspace = VK_COLOR_SPACE_MAX_ENUM_KHR;
 	{
 		uint32_t formatCount;
-		ANKI_VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(m_factory->m_gr->getPhysicalDevice(),
-														   m_factory->m_gr->getSurface(), &formatCount, nullptr));
+		ANKI_VK_CHECK(
+			vkGetPhysicalDeviceSurfaceFormatsKHR(pdev, getGrManagerImpl().getSurface(), &formatCount, nullptr));
 
-		DynamicArrayRaii<VkSurfaceFormatKHR> formats(&getMemoryPool());
+		GrDynamicArray<VkSurfaceFormatKHR> formats;
 		formats.create(formatCount);
-		ANKI_VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(m_factory->m_gr->getPhysicalDevice(),
-														   m_factory->m_gr->getSurface(), &formatCount, &formats[0]));
+		ANKI_VK_CHECK(
+			vkGetPhysicalDeviceSurfaceFormatsKHR(pdev, getGrManagerImpl().getSurface(), &formatCount, &formats[0]));
 
 		ANKI_VK_LOGV("Supported surface formats:");
 		Format akSurfaceFormat = Format::kNone;
@@ -122,12 +121,11 @@ Error MicroSwapchain::initInternal()
 	VkPresentModeKHR presentModeSecondChoice = VK_PRESENT_MODE_MAX_ENUM_KHR;
 	{
 		uint32_t presentModeCount;
-		vkGetPhysicalDeviceSurfacePresentModesKHR(m_factory->m_gr->getPhysicalDevice(), m_factory->m_gr->getSurface(),
-												  &presentModeCount, nullptr);
+		vkGetPhysicalDeviceSurfacePresentModesKHR(pdev, getGrManagerImpl().getSurface(), &presentModeCount, nullptr);
 		presentModeCount = min(presentModeCount, 4u);
 		Array<VkPresentModeKHR, 4> presentModes;
-		vkGetPhysicalDeviceSurfacePresentModesKHR(m_factory->m_gr->getPhysicalDevice(), m_factory->m_gr->getSurface(),
-												  &presentModeCount, &presentModes[0]);
+		vkGetPhysicalDeviceSurfacePresentModesKHR(pdev, getGrManagerImpl().getSurface(), &presentModeCount,
+												  &presentModes[0]);
 
 		if(m_factory->m_vsync)
 		{
@@ -193,7 +191,7 @@ Error MicroSwapchain::initInternal()
 
 		VkSwapchainCreateInfoKHR ci = {};
 		ci.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
-		ci.surface = m_factory->m_gr->getSurface();
+		ci.surface = getGrManagerImpl().getSurface();
 		ci.minImageCount = kMaxFramesInFlight;
 		ci.imageFormat = surfaceFormat;
 		ci.imageColorSpace = colorspace;
@@ -201,8 +199,8 @@ Error MicroSwapchain::initInternal()
 		ci.imageExtent.height = surfaceHeight;
 		ci.imageArrayLayers = 1;
 		ci.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
-		ci.queueFamilyIndexCount = m_factory->m_gr->getQueueFamilies().getSize();
-		ci.pQueueFamilyIndices = &m_factory->m_gr->getQueueFamilies()[0];
+		ci.queueFamilyIndexCount = getGrManagerImpl().getQueueFamilies().getSize();
+		ci.pQueueFamilyIndices = &getGrManagerImpl().getQueueFamilies()[0];
 		ci.imageSharingMode = (ci.queueFamilyIndexCount > 1) ? VK_SHARING_MODE_CONCURRENT : VK_SHARING_MODE_EXCLUSIVE;
 		ci.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
 		ci.compositeAlpha = compositeAlpha;
@@ -222,7 +220,7 @@ Error MicroSwapchain::initInternal()
 			ANKI_VK_LOGI("Requested a swapchain with %u images but got one with %u", kMaxFramesInFlight, count);
 		}
 
-		m_textures.create(getMemoryPool(), count);
+		m_textures.create(count);
 
 		ANKI_VK_LOGI("Created a swapchain. Image count: %u, present mode: %u, size: %ux%u, vsync: %u", count,
 					 presentMode, surfaceWidth, surfaceHeight, U32(m_factory->m_vsync));
@@ -241,8 +239,7 @@ Error MicroSwapchain::initInternal()
 						   | TextureUsageBit::kPresent;
 			init.m_type = TextureType::k2D;
 
-			TextureImpl* tex =
-				newInstance<TextureImpl>(m_factory->m_gr->getMemoryPool(), m_factory->m_gr, init.getName());
+			TextureImpl* tex = newInstance<TextureImpl>(GrMemoryPool::getSingleton(), init.getName());
 			m_textures[i].reset(tex);
 			ANKI_CHECK(tex->initExternal(images[i], init));
 		}
@@ -251,11 +248,6 @@ Error MicroSwapchain::initInternal()
 	return Error::kNone;
 }
 
-HeapMemoryPool& MicroSwapchain::getMemoryPool()
-{
-	return m_factory->m_gr->getMemoryPool();
-}
-
 MicroSwapchainPtr SwapchainFactory::newInstance()
 {
 	// Delete stale swapchains (they are stale because they are probably out of data) and always create a new one
@@ -265,15 +257,7 @@ MicroSwapchainPtr SwapchainFactory::newInstance()
 	[[maybe_unused]] MicroSwapchain* dummy = m_recycler.findToReuse();
 	ANKI_ASSERT(dummy == nullptr);
 
-	return MicroSwapchainPtr(anki::newInstance<MicroSwapchain>(m_gr->getMemoryPool(), this));
-}
-
-void SwapchainFactory::init(GrManagerImpl* manager, Bool vsync)
-{
-	ANKI_ASSERT(manager);
-	m_gr = manager;
-	m_vsync = vsync;
-	m_recycler.init(&m_gr->getMemoryPool());
+	return MicroSwapchainPtr(anki::newInstance<MicroSwapchain>(GrMemoryPool::getSingleton(), this));
 }
 
 } // end namespace anki

+ 5 - 5
AnKi/Gr/Vulkan/SwapchainFactory.h

@@ -26,7 +26,7 @@ class MicroSwapchain
 public:
 	VkSwapchainKHR m_swapchain = {};
 
-	DynamicArray<TexturePtr> m_textures;
+	GrDynamicArray<TexturePtr> m_textures;
 
 	MicroSwapchain(SwapchainFactory* factory);
 
@@ -47,8 +47,6 @@ public:
 		return m_refcount.load();
 	}
 
-	HeapMemoryPool& getMemoryPool();
-
 	void setFence(MicroFencePtr fence)
 	{
 		m_fence = fence;
@@ -106,7 +104,10 @@ class SwapchainFactory
 	friend class MicroSwapchain;
 
 public:
-	void init(GrManagerImpl* manager, Bool vsync);
+	void init(Bool vsync)
+	{
+		m_vsync = vsync;
+	}
 
 	void destroy()
 	{
@@ -116,7 +117,6 @@ public:
 	MicroSwapchainPtr newInstance();
 
 private:
-	GrManagerImpl* m_gr = nullptr;
 	Bool m_vsync = false;
 	MicroObjectRecycler<MicroSwapchain> m_recycler;
 };

+ 3 - 3
AnKi/Gr/Vulkan/Texture.cpp

@@ -9,13 +9,13 @@
 
 namespace anki {
 
-Texture* Texture::newInstance(GrManager* manager, const TextureInitInfo& init)
+Texture* Texture::newInstance(const TextureInitInfo& init)
 {
-	TextureImpl* impl = anki::newInstance<TextureImpl>(manager->getMemoryPool(), manager, init.getName());
+	TextureImpl* impl = anki::newInstance<TextureImpl>(GrMemoryPool::getSingleton(), init.getName());
 	const Error err = impl->init(init);
 	if(err)
 	{
-		deleteInstance(manager->getMemoryPool(), impl);
+		deleteInstance(GrMemoryPool::getSingleton(), impl);
 		impl = nullptr;
 	}
 	return impl;

+ 12 - 12
AnKi/Gr/Vulkan/TextureImpl.cpp

@@ -71,30 +71,30 @@ TextureImpl::~TextureImpl()
 	}
 #endif
 
-	TextureGarbage* garbage = anki::newInstance<TextureGarbage>(getMemoryPool());
+	TextureGarbage* garbage = anki::newInstance<TextureGarbage>(GrMemoryPool::getSingleton());
 
 	for(MicroImageView& it : m_viewsMap)
 	{
-		garbage->m_viewHandles.emplaceBack(getMemoryPool(), it.m_handle);
+		garbage->m_viewHandles.emplaceBack(it.m_handle);
 		it.m_handle = VK_NULL_HANDLE;
 
 		if(it.m_bindlessIndex != kMaxU32)
 		{
-			garbage->m_bindlessIndices.emplaceBack(getMemoryPool(), it.m_bindlessIndex);
+			garbage->m_bindlessIndices.emplaceBack(it.m_bindlessIndex);
 			it.m_bindlessIndex = kMaxU32;
 		}
 	}
 
-	m_viewsMap.destroy(getMemoryPool());
+	m_viewsMap.destroy();
 
 	if(m_singleSurfaceImageView.m_handle != VK_NULL_HANDLE)
 	{
-		garbage->m_viewHandles.emplaceBack(getMemoryPool(), m_singleSurfaceImageView.m_handle);
+		garbage->m_viewHandles.emplaceBack(m_singleSurfaceImageView.m_handle);
 		m_singleSurfaceImageView.m_handle = VK_NULL_HANDLE;
 
 		if(m_singleSurfaceImageView.m_bindlessIndex != kMaxU32)
 		{
-			garbage->m_bindlessIndices.emplaceBack(getMemoryPool(), m_singleSurfaceImageView.m_bindlessIndex);
+			garbage->m_bindlessIndices.emplaceBack(m_singleSurfaceImageView.m_bindlessIndex);
 			m_singleSurfaceImageView.m_bindlessIndex = kMaxU32;
 		}
 	}
@@ -187,7 +187,7 @@ Error TextureImpl::initInternal(VkImage externalImage, const TextureInitInfo& in
 		computeVkImageViewCreateInfo(subresource, viewCi, m_singleSurfaceImageView.m_derivedTextureType);
 		ANKI_ASSERT(m_singleSurfaceImageView.m_derivedTextureType == m_texType);
 
-		ANKI_VK_CHECKF(vkCreateImageView(getDevice(), &viewCi, nullptr, &m_singleSurfaceImageView.m_handle));
+		ANKI_VK_CHECKF(vkCreateImageView(getVkDevice(), &viewCi, nullptr, &m_singleSurfaceImageView.m_handle));
 		getGrManagerImpl().trySetVulkanHandleName(getName(), VK_OBJECT_TYPE_IMAGE_VIEW,
 												  ptrToNumber(m_singleSurfaceImageView.m_handle));
 	}
@@ -283,7 +283,7 @@ Error TextureImpl::initImage(const TextureInitInfo& init)
 	ci.sharingMode = (ci.queueFamilyIndexCount > 1) ? VK_SHARING_MODE_CONCURRENT : VK_SHARING_MODE_EXCLUSIVE;
 	ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
 
-	ANKI_VK_CHECK(vkCreateImage(getDevice(), &ci, nullptr, &m_imageHandle));
+	ANKI_VK_CHECK(vkCreateImage(getVkDevice(), &ci, nullptr, &m_imageHandle));
 	getGrManagerImpl().trySetVulkanHandleName(init.getName(), VK_OBJECT_TYPE_IMAGE, m_imageHandle);
 #if 0
 	printf("Creating texture %p %s\n", static_cast<void*>(m_imageHandle),
@@ -303,7 +303,7 @@ Error TextureImpl::initImage(const TextureInitInfo& init)
 	imageRequirementsInfo.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2;
 	imageRequirementsInfo.image = m_imageHandle;
 
-	vkGetImageMemoryRequirements2(getDevice(), &imageRequirementsInfo, &requirements);
+	vkGetImageMemoryRequirements2(getVkDevice(), &imageRequirementsInfo, &requirements);
 
 	U32 memIdx = getGrManagerImpl().getGpuMemoryManager().findMemoryType(requirements.memoryRequirements.memoryTypeBits,
 																		 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
@@ -331,7 +331,7 @@ Error TextureImpl::initImage(const TextureInitInfo& init)
 	}
 
 	// Bind
-	ANKI_VK_CHECK(vkBindImageMemory(getDevice(), m_imageHandle, m_memHandle.m_memory, m_memHandle.m_offset));
+	ANKI_VK_CHECK(vkBindImageMemory(getVkDevice(), m_imageHandle, m_memHandle.m_memory, m_memHandle.m_offset));
 
 	return Error::kNone;
 }
@@ -593,10 +593,10 @@ const MicroImageView& TextureImpl::getOrCreateView(const TextureSubresourceInfo&
 	computeVkImageViewCreateInfo(subresource, viewCi, viewTexType);
 	ANKI_ASSERT(viewTexType != TextureType::kCount);
 
-	ANKI_VK_CHECKF(vkCreateImageView(getDevice(), &viewCi, nullptr, &handle));
+	ANKI_VK_CHECKF(vkCreateImageView(getVkDevice(), &viewCi, nullptr, &handle));
 	getGrManagerImpl().trySetVulkanHandleName(getName(), VK_OBJECT_TYPE_IMAGE_VIEW, ptrToNumber(handle));
 
-	it = m_viewsMap.emplace(getMemoryPool(), subresource);
+	it = m_viewsMap.emplace(subresource);
 	it->m_handle = handle;
 	it->m_derivedTextureType = viewTexType;
 

+ 4 - 5
AnKi/Gr/Vulkan/TextureImpl.h

@@ -6,7 +6,6 @@
 #pragma once
 
 #include <AnKi/Gr/Texture.h>
-#include <AnKi/Gr/Vulkan/VulkanObject.h>
 #include <AnKi/Gr/Vulkan/GpuMemoryManager.h>
 #include <AnKi/Gr/Utils/Functions.h>
 #include <AnKi/Gr/Vulkan/SamplerFactory.h>
@@ -76,7 +75,7 @@ private:
 };
 
 /// Texture container.
-class TextureImpl final : public Texture, public VulkanObject<Texture, TextureImpl>
+class TextureImpl final : public Texture
 {
 public:
 	VkImage m_imageHandle = VK_NULL_HANDLE;
@@ -88,8 +87,8 @@ public:
 	VkImageViewCreateInfo m_viewCreateInfoTemplate;
 	VkImageViewASTCDecodeModeEXT m_astcDecodeMode;
 
-	TextureImpl(GrManager* manager, CString name)
-		: Texture(manager, name)
+	TextureImpl(CString name)
+		: Texture(name)
 	{
 	}
 
@@ -187,7 +186,7 @@ public:
 	const MicroImageView& getOrCreateView(const TextureSubresourceInfo& subresource) const;
 
 private:
-	mutable HashMap<TextureSubresourceInfo, MicroImageView> m_viewsMap;
+	mutable GrHashMap<TextureSubresourceInfo, MicroImageView> m_viewsMap;
 	mutable RWMutex m_viewsMapMtx;
 
 	/// This is a special optimization for textures that have only one surface. In this case we don't need to go through

+ 3 - 3
AnKi/Gr/Vulkan/TextureView.cpp

@@ -9,13 +9,13 @@
 
 namespace anki {
 
-TextureView* TextureView::newInstance(GrManager* manager, const TextureViewInitInfo& init)
+TextureView* TextureView::newInstance(const TextureViewInitInfo& init)
 {
-	TextureViewImpl* impl = anki::newInstance<TextureViewImpl>(manager->getMemoryPool(), manager, init.getName());
+	TextureViewImpl* impl = anki::newInstance<TextureViewImpl>(GrMemoryPool::getSingleton(), init.getName());
 	const Error err = impl->init(init);
 	if(err)
 	{
-		deleteInstance(manager->getMemoryPool(), impl);
+		deleteInstance(GrMemoryPool::getSingleton(), impl);
 		impl = nullptr;
 	}
 	return impl;

+ 3 - 4
AnKi/Gr/Vulkan/TextureViewImpl.h

@@ -6,7 +6,6 @@
 #pragma once
 
 #include <AnKi/Gr/TextureView.h>
-#include <AnKi/Gr/Vulkan/VulkanObject.h>
 #include <AnKi/Gr/Vulkan/TextureImpl.h>
 
 namespace anki {
@@ -15,11 +14,11 @@ namespace anki {
 /// @{
 
 /// Texture view implementation.
-class TextureViewImpl final : public TextureView, public VulkanObject<TextureView, TextureViewImpl>
+class TextureViewImpl final : public TextureView
 {
 public:
-	TextureViewImpl(GrManager* manager, CString name)
-		: TextureView(manager, name)
+	TextureViewImpl(CString name)
+		: TextureView(name)
 	{
 	}
 

+ 3 - 3
AnKi/Gr/Vulkan/TimestampQuery.cpp

@@ -9,13 +9,13 @@
 
 namespace anki {
 
-TimestampQuery* TimestampQuery::newInstance(GrManager* manager)
+TimestampQuery* TimestampQuery::newInstance()
 {
-	TimestampQueryImpl* impl = anki::newInstance<TimestampQueryImpl>(manager->getMemoryPool(), manager, "N/A");
+	TimestampQueryImpl* impl = anki::newInstance<TimestampQueryImpl>(GrMemoryPool::getSingleton(), "N/A");
 	const Error err = impl->init();
 	if(err)
 	{
-		deleteInstance(manager->getMemoryPool(), impl);
+		deleteInstance(GrMemoryPool::getSingleton(), impl);
 		impl = nullptr;
 	}
 	return impl;

+ 1 - 1
AnKi/Gr/Vulkan/TimestampQueryImpl.cpp

@@ -32,7 +32,7 @@ TimestampQueryResult TimestampQueryImpl::getResultInternal(Second& timestamp) co
 
 	VkResult res;
 	U64 value;
-	ANKI_VK_CHECKF(res = vkGetQueryPoolResults(getDevice(), m_handle.getQueryPool(), m_handle.getQueryIndex(), 1,
+	ANKI_VK_CHECKF(res = vkGetQueryPoolResults(getVkDevice(), m_handle.getQueryPool(), m_handle.getQueryIndex(), 1,
 											   sizeof(value), &value, sizeof(value), VK_QUERY_RESULT_64_BIT));
 
 	TimestampQueryResult qout = TimestampQueryResult::kNotAvailable;

+ 3 - 4
AnKi/Gr/Vulkan/TimestampQueryImpl.h

@@ -6,7 +6,6 @@
 #pragma once
 
 #include <AnKi/Gr/TimestampQuery.h>
-#include <AnKi/Gr/Vulkan/VulkanObject.h>
 #include <AnKi/Gr/Vulkan/QueryFactory.h>
 
 namespace anki {
@@ -15,13 +14,13 @@ namespace anki {
 /// @{
 
 /// Occlusion query.
-class TimestampQueryImpl final : public TimestampQuery, public VulkanObject<TimestampQuery, TimestampQueryImpl>
+class TimestampQueryImpl final : public TimestampQuery
 {
 public:
 	MicroQuery m_handle = {};
 
-	TimestampQueryImpl(GrManager* manager, CString name)
-		: TimestampQuery(manager, name)
+	TimestampQueryImpl(CString name)
+		: TimestampQuery(name)
 	{
 	}
 

+ 0 - 47
AnKi/Gr/Vulkan/VulkanObject.cpp

@@ -1,47 +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/Gr/Vulkan/VulkanObject.h>
-#include <AnKi/Gr/GrManager.h>
-#include <AnKi/Gr/Vulkan/GrManagerImpl.h>
-
-#include <AnKi/Gr/Vulkan/BufferImpl.h>
-#include <AnKi/Gr/Vulkan/TextureImpl.h>
-#include <AnKi/Gr/Vulkan/SamplerImpl.h>
-#include <AnKi/Gr/Vulkan/ShaderImpl.h>
-#include <AnKi/Gr/Vulkan/ShaderProgramImpl.h>
-#include <AnKi/Gr/Vulkan/CommandBufferImpl.h>
-#include <AnKi/Gr/Vulkan/FramebufferImpl.h>
-#include <AnKi/Gr/Vulkan/OcclusionQueryImpl.h>
-#include <AnKi/Gr/Vulkan/TimestampQueryImpl.h>
-#include <AnKi/Gr/Vulkan/FenceImpl.h>
-#include <AnKi/Gr/Vulkan/AccelerationStructureImpl.h>
-#include <AnKi/Gr/Vulkan/GrUpscalerImpl.h>
-
-namespace anki {
-
-#define ANKI_INSTANTIATE_GR_OBJECT(type_) \
-	template<> \
-	VkDevice VulkanObject<type_, type_##Impl>::getDevice() const \
-	{ \
-		return getGrManagerImpl().getDevice(); \
-	} \
-	template<> \
-	GrManagerImpl& VulkanObject<type_, type_##Impl>::getGrManagerImpl() \
-	{ \
-		return static_cast<GrManagerImpl&>(static_cast<type_##Impl*>(this)->getManager()); \
-	} \
-	template<> \
-	const GrManagerImpl& VulkanObject<type_, type_##Impl>::getGrManagerImpl() const \
-	{ \
-		return static_cast<const GrManagerImpl&>(static_cast<const type_##Impl*>(this)->getManager()); \
-	}
-
-#define ANKI_INSTANTIATE_GR_OBJECT_DELIMITER()
-#include <AnKi/Gr/Utils/InstantiationMacros.h>
-#undef ANKI_INSTANTIATE_GR_OBJECT_DELIMITER
-#undef ANKI_INSTANTIATE_GR_OBJECT
-
-} // end namespace anki

Some files were not shown because too many files changed in this diff