ソースを参照

[REFACTOR] Remove GrObjectCache

Panagiotis Christopoulos Charitos 8 年 前
コミット
8c6063e7df
48 ファイル変更195 行追加312 行削除
  1. 0 1
      src/anki/Gr.h
  2. 1 1
      src/anki/gr/Buffer.h
  3. 1 1
      src/anki/gr/CommandBuffer.h
  4. 6 8
      src/anki/gr/Common.h
  5. 1 1
      src/anki/gr/Fence.h
  6. 1 1
      src/anki/gr/Framebuffer.h
  7. 2 10
      src/anki/gr/GrManager.h
  8. 1 8
      src/anki/gr/GrObject.cpp
  9. 1 11
      src/anki/gr/GrObject.h
  10. 0 34
      src/anki/gr/GrObjectCache.cpp
  11. 0 87
      src/anki/gr/GrObjectCache.h
  12. 1 1
      src/anki/gr/OcclusionQuery.h
  13. 2 2
      src/anki/gr/RenderGraph.cpp
  14. 1 1
      src/anki/gr/RenderGraph.h
  15. 1 1
      src/anki/gr/Sampler.h
  16. 1 1
      src/anki/gr/Shader.h
  17. 1 1
      src/anki/gr/ShaderProgram.h
  18. 1 1
      src/anki/gr/Texture.h
  19. 2 2
      src/anki/gr/gl/Buffer.cpp
  20. 2 2
      src/anki/gr/gl/CommandBuffer.cpp
  21. 2 2
      src/anki/gr/gl/Fence.cpp
  22. 2 2
      src/anki/gr/gl/Framebuffer.cpp
  23. 2 2
      src/anki/gr/gl/OcclusionQuery.cpp
  24. 1 1
      src/anki/gr/gl/RenderingThread.cpp
  25. 2 2
      src/anki/gr/gl/Sampler.cpp
  26. 2 2
      src/anki/gr/gl/Shader.cpp
  27. 2 2
      src/anki/gr/gl/ShaderProgram.cpp
  28. 2 2
      src/anki/gr/gl/Texture.cpp
  29. 2 2
      src/anki/gr/vulkan/Buffer.cpp
  30. 2 2
      src/anki/gr/vulkan/CommandBuffer.cpp
  31. 11 1
      src/anki/gr/vulkan/CommandBufferFactory.cpp
  32. 4 0
      src/anki/gr/vulkan/CommandBufferFactory.h
  33. 1 1
      src/anki/gr/vulkan/DescriptorSet.cpp
  34. 3 3
      src/anki/gr/vulkan/DescriptorSet.h
  35. 3 3
      src/anki/gr/vulkan/Fence.cpp
  36. 2 2
      src/anki/gr/vulkan/Framebuffer.cpp
  37. 5 11
      src/anki/gr/vulkan/GrManagerImpl.cpp
  38. 7 8
      src/anki/gr/vulkan/GrManagerImpl.h
  39. 2 2
      src/anki/gr/vulkan/OcclusionQuery.cpp
  40. 2 2
      src/anki/gr/vulkan/Sampler.cpp
  41. 93 6
      src/anki/gr/vulkan/SamplerFactory.cpp
  42. 2 68
      src/anki/gr/vulkan/SamplerImpl.cpp
  43. 5 2
      src/anki/gr/vulkan/SamplerImpl.h
  44. 2 2
      src/anki/gr/vulkan/Shader.cpp
  45. 2 2
      src/anki/gr/vulkan/ShaderProgram.cpp
  46. 2 2
      src/anki/gr/vulkan/Texture.cpp
  47. 2 2
      src/anki/gr/vulkan/TextureImpl.cpp
  48. 2 1
      src/anki/gr/vulkan/TextureImpl.h

+ 0 - 1
src/anki/Gr.h

@@ -15,7 +15,6 @@
 #include <anki/gr/OcclusionQuery.h>
 #include <anki/gr/Fence.h>
 #include <anki/gr/GrManager.h>
-#include <anki/gr/GrObjectCache.h>
 #include <anki/gr/RenderGraph.h>
 
 /// @defgroup graphics Graphics API abstraction

+ 1 - 1
src/anki/gr/Buffer.h

@@ -55,7 +55,7 @@ anki_internal:
 	UniquePtr<BufferImpl> m_impl;
 
 	/// Construct.
-	Buffer(GrManager* manager, U64 hash, GrObjectCache* cache);
+	Buffer(GrManager* manager);
 
 	/// Destroy.
 	~Buffer();

+ 1 - 1
src/anki/gr/CommandBuffer.h

@@ -410,7 +410,7 @@ anki_internal:
 	static const GrObjectType CLASS_TYPE = GrObjectType::COMMAND_BUFFER;
 
 	/// Construct.
-	CommandBuffer(GrManager* manager, U64 hash, GrObjectCache* cache);
+	CommandBuffer(GrManager* manager);
 
 	/// Destroy.
 	~CommandBuffer();

+ 6 - 8
src/anki/gr/Common.h

@@ -15,7 +15,6 @@ namespace anki
 
 // Forward
 class GrObject;
-class GrObjectCache;
 
 class GrManager;
 class GrManagerImpl;
@@ -73,13 +72,12 @@ ANKI_GR_CLASS(RenderGraph)
 
 #undef ANKI_GR_CLASS
 
-#define ANKI_GR_OBJECT                 \
-	friend class GrManager;            \
-	template<typename, typename>       \
-	friend class IntrusivePtr;         \
-	template<typename, typename>       \
-	friend class GenericPoolAllocator; \
-	friend class GrObjectCache;
+#define ANKI_GR_OBJECT           \
+	friend class GrManager;      \
+	template<typename, typename> \
+	friend class IntrusivePtr;   \
+	template<typename, typename> \
+	friend class GenericPoolAllocator;
 
 /// Knowing the ventor allows some optimizations
 enum class GpuVendor : U8

+ 1 - 1
src/anki/gr/Fence.h

@@ -30,7 +30,7 @@ anki_internal:
 	UniquePtr<FenceImpl> m_impl;
 
 	/// Construct.
-	Fence(GrManager* manager, U64 hash, GrObjectCache* cache);
+	Fence(GrManager* manager);
 
 	/// Destroy.
 	~Fence();

+ 1 - 1
src/anki/gr/Framebuffer.h

@@ -89,7 +89,7 @@ anki_internal:
 	static const GrObjectType CLASS_TYPE = GrObjectType::FRAMEBUFFER;
 
 	/// Construct.
-	Framebuffer(GrManager* manager, U64 hash, GrObjectCache* cache);
+	Framebuffer(GrManager* manager);
 
 	/// Destroy.
 	~Framebuffer();

+ 2 - 10
src/anki/gr/GrManager.h

@@ -36,7 +36,6 @@ public:
 class GrManager
 {
 	friend class GrManagerImpl;
-	friend class GrObjectCache;
 
 	template<typename>
 	friend class GrObjectPtrDeleter;
@@ -61,20 +60,13 @@ public:
 
 	/// Create a new graphics object.
 	template<typename T, typename... Args>
-	ANKI_USE_RESULT GrObjectPtr<T> newInstanceCached(U64 hash, GrObjectCache* cache, Args&&... args)
+	ANKI_USE_RESULT GrObjectPtr<T> newInstance(Args&&... args)
 	{
-		GrObjectPtr<T> ptr(m_alloc.newInstance<T>(this, hash, cache));
+		GrObjectPtr<T> ptr(m_alloc.newInstance<T>(this));
 		ptr->init(args...);
 		return ptr;
 	}
 
-	/// Create a new graphics object.
-	template<typename T, typename... Args>
-	ANKI_USE_RESULT GrObjectPtr<T> newInstance(Args&&... args)
-	{
-		return newInstanceCached<T>(0, nullptr, args...);
-	}
-
 	/// Call this before calling allocateFrameTransientMemory or tryAllocateFrameTransientMemory to get the exact memory
 	/// that will be required for the CommandBuffer::uploadTextureSurface.
 	///

+ 1 - 8
src/anki/gr/GrObject.cpp

@@ -5,27 +5,20 @@
 
 #include <anki/gr/GrObject.h>
 #include <anki/gr/GrManager.h>
-#include <anki/gr/GrObjectCache.h>
 
 namespace anki
 {
 
-GrObject::GrObject(GrManager* manager, GrObjectType type, U64 hash, GrObjectCache* cache)
+GrObject::GrObject(GrManager* manager, GrObjectType type)
 	: m_refcount(0)
 	, m_manager(manager)
 	, m_uuid(m_manager->getUuidIndex()++)
-	, m_hash(hash)
 	, m_type(type)
-	, m_cache(cache)
 {
 }
 
 GrObject::~GrObject()
 {
-	if(m_cache)
-	{
-		m_cache->unregisterObject(this);
-	}
 }
 
 GrAllocator<U8> GrObject::getAllocator() const

+ 1 - 11
src/anki/gr/GrObject.h

@@ -34,10 +34,8 @@ enum GrObjectType : U16
 /// Base of all graphics objects.
 class GrObject : public NonCopyable
 {
-	friend class GrObjectCache;
-
 public:
-	GrObject(GrManager* manager, GrObjectType type, U64 hash, GrObjectCache* cache);
+	GrObject(GrManager* manager, GrObjectType type);
 
 	virtual ~GrObject();
 
@@ -69,19 +67,11 @@ public:
 		return m_uuid;
 	}
 
-	/// Get a hash if it's part of a cache. If zero then it's not cached.
-	U64 getHash() const
-	{
-		return m_hash;
-	}
-
 private:
 	Atomic<I32> m_refcount;
 	GrManager* m_manager;
 	U64 m_uuid;
-	U64 m_hash;
 	GrObjectType m_type;
-	GrObjectCache* m_cache;
 };
 /// @}
 

+ 0 - 34
src/anki/gr/GrObjectCache.cpp

@@ -1,34 +0,0 @@
-// Copyright (C) 2009-2017, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <anki/gr/GrObjectCache.h>
-
-namespace anki
-{
-
-GrObjectCache::~GrObjectCache()
-{
-	// Some GrObjects may be in flight but someone destroys the cache. Do a manual destruction of the map
-	while(!m_map.isEmpty())
-	{
-		auto it = m_map.getBegin();
-		unregisterObject(*it);
-	}
-}
-
-void GrObjectCache::unregisterObject(GrObject* obj)
-{
-	ANKI_ASSERT(obj);
-	ANKI_ASSERT(obj->getHash() != 0);
-	ANKI_ASSERT(obj->m_cache == this);
-
-	LockGuard<Mutex> lock(m_mtx);
-	ANKI_ASSERT(tryFind(obj->getHash()) != nullptr);
-	auto it = m_map.find(obj->getHash());
-	m_map.erase(m_gr->getAllocator(), it);
-	obj->m_cache = nullptr;
-}
-
-} // end namespace anki

+ 0 - 87
src/anki/gr/GrObjectCache.h

@@ -1,87 +0,0 @@
-// Copyright (C) 2009-2017, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#pragma once
-
-#include <anki/gr/Common.h>
-#include <anki/gr/GrObject.h>
-#include <anki/gr/GrManager.h>
-#include <anki/util/HashMap.h>
-#include <anki/util/NonCopyable.h>
-
-namespace anki
-{
-
-/// @addtogroup graphics
-/// @{
-
-/// A cache that can be used for specific GrObject types.
-class GrObjectCache : public NonCopyable
-{
-	friend class GrObject;
-
-public:
-	GrObjectCache(GrManager* gr)
-		: m_gr(gr)
-	{
-	}
-
-	~GrObjectCache();
-
-	/// Create a new graphics object and use the cache to avoid duplication. It's thread safe.
-	template<typename T, typename TArg>
-	GrObjectPtr<T> newInstance(const TArg& arg, U64 overrideHash = 0);
-
-private:
-	using Key = U64;
-
-	/// Hash the hash.
-	class Hasher
-	{
-	public:
-		U64 operator()(const Key& b) const
-		{
-			return b;
-		}
-	};
-
-	GrManager* m_gr;
-	HashMap<U64, GrObject*, Hasher> m_map;
-	Mutex m_mtx;
-
-	/// Try to find an object in the cache.
-	GrObject* tryFind(U64 hash)
-	{
-		auto it = m_map.find(hash);
-		return (it != m_map.getEnd()) ? (*it) : nullptr;
-	}
-
-	/// Unregister an object from the cache.
-	void unregisterObject(GrObject* obj);
-};
-
-template<typename T, typename TArg>
-inline GrObjectPtr<T> GrObjectCache::newInstance(const TArg& arg, U64 overrideHash)
-{
-	U64 hash = (overrideHash != 0) ? overrideHash : arg.computeHash();
-	ANKI_ASSERT(hash != 0);
-
-	LockGuard<Mutex> lock(m_mtx);
-	GrObject* ptr = tryFind(hash);
-	if(ptr == nullptr)
-	{
-		auto tptr = m_gr->template newInstanceCached<T>(hash, this, arg);
-		m_map.emplace(m_gr->getAllocator(), hash, tptr.get());
-		return tptr;
-	}
-	else
-	{
-		ANKI_ASSERT(ptr->getType() == T::CLASS_TYPE);
-		return GrObjectPtr<T>(static_cast<T*>(ptr));
-	}
-}
-/// @}
-
-} // end namespace anki

+ 1 - 1
src/anki/gr/OcclusionQuery.h

@@ -24,7 +24,7 @@ anki_internal:
 	static const GrObjectType CLASS_TYPE = GrObjectType::OCCLUSION_QUERY;
 
 	/// Construct.
-	OcclusionQuery(GrManager* manager, U64 hash, GrObjectCache* cache);
+	OcclusionQuery(GrManager* manager);
 
 	/// Destroy.
 	~OcclusionQuery();

+ 2 - 2
src/anki/gr/RenderGraph.cpp

@@ -242,8 +242,8 @@ void FramebufferDescription::bake()
 	ANKI_ASSERT(m_hash != 0 && m_hash != 1);
 }
 
-RenderGraph::RenderGraph(GrManager* manager, U64 hash, GrObjectCache* cache)
-	: GrObject(manager, CLASS_TYPE, hash, cache)
+RenderGraph::RenderGraph(GrManager* manager)
+	: GrObject(manager, CLASS_TYPE)
 {
 	ANKI_ASSERT(manager);
 }

+ 1 - 1
src/anki/gr/RenderGraph.h

@@ -600,7 +600,7 @@ class RenderGraph final : public GrObject
 public:
 	static const GrObjectType CLASS_TYPE = GrObjectType::RENDER_GRAPH;
 
-	RenderGraph(GrManager* manager, U64 hash, GrObjectCache* cache);
+	RenderGraph(GrManager* manager);
 
 	// Non-copyable
 	RenderGraph(const RenderGraph&) = delete;

+ 1 - 1
src/anki/gr/Sampler.h

@@ -25,7 +25,7 @@ anki_internal:
 	static const GrObjectType CLASS_TYPE = GrObjectType::SAMPLER;
 
 	/// Construct.
-	Sampler(GrManager* manager, U64 hash, GrObjectCache* cache);
+	Sampler(GrManager* manager);
 
 	/// Destroy.
 	~Sampler();

+ 1 - 1
src/anki/gr/Shader.h

@@ -76,7 +76,7 @@ anki_internal:
 	static const GrObjectType CLASS_TYPE = GrObjectType::SHADER;
 
 	/// Construct.
-	Shader(GrManager* manager, U64 hash, GrObjectCache* cache);
+	Shader(GrManager* manager);
 
 	/// Destroy.
 	~Shader();

+ 1 - 1
src/anki/gr/ShaderProgram.h

@@ -24,7 +24,7 @@ anki_internal:
 	static const GrObjectType CLASS_TYPE = GrObjectType::SHADER_PROGRAM;
 
 	/// Construct.
-	ShaderProgram(GrManager* manager, U64 hash, GrObjectCache* cache);
+	ShaderProgram(GrManager* manager);
 
 	/// Destroy.
 	~ShaderProgram();

+ 1 - 1
src/anki/gr/Texture.h

@@ -94,7 +94,7 @@ anki_internal:
 	static const GrObjectType CLASS_TYPE = GrObjectType::TEXTURE;
 
 	/// Construct.
-	Texture(GrManager* manager, U64 hash, GrObjectCache* cache);
+	Texture(GrManager* manager);
 
 	/// Destroy.
 	~Texture();

+ 2 - 2
src/anki/gr/gl/Buffer.cpp

@@ -11,8 +11,8 @@
 namespace anki
 {
 
-Buffer::Buffer(GrManager* manager, U64 hash, GrObjectCache* cache)
-	: GrObject(manager, CLASS_TYPE, hash, cache)
+Buffer::Buffer(GrManager* manager)
+	: GrObject(manager, CLASS_TYPE)
 {
 }
 

+ 2 - 2
src/anki/gr/gl/CommandBuffer.cpp

@@ -28,8 +28,8 @@
 namespace anki
 {
 
-CommandBuffer::CommandBuffer(GrManager* manager, U64 hash, GrObjectCache* cache)
-	: GrObject(manager, CLASS_TYPE, hash, cache)
+CommandBuffer::CommandBuffer(GrManager* manager)
+	: GrObject(manager, CLASS_TYPE)
 {
 }
 

+ 2 - 2
src/anki/gr/gl/Fence.cpp

@@ -13,8 +13,8 @@
 namespace anki
 {
 
-Fence::Fence(GrManager* manager, U64 hash, GrObjectCache* cache)
-	: GrObject(manager, CLASS_TYPE, hash, cache)
+Fence::Fence(GrManager* manager)
+	: GrObject(manager, CLASS_TYPE)
 {
 }
 

+ 2 - 2
src/anki/gr/gl/Framebuffer.cpp

@@ -11,8 +11,8 @@
 namespace anki
 {
 
-Framebuffer::Framebuffer(GrManager* manager, U64 hash, GrObjectCache* cache)
-	: GrObject(manager, CLASS_TYPE, hash, cache)
+Framebuffer::Framebuffer(GrManager* manager)
+	: GrObject(manager, CLASS_TYPE)
 {
 }
 

+ 2 - 2
src/anki/gr/gl/OcclusionQuery.cpp

@@ -11,8 +11,8 @@
 namespace anki
 {
 
-OcclusionQuery::OcclusionQuery(GrManager* manager, U64 hash, GrObjectCache* cache)
-	: GrObject(manager, CLASS_TYPE, hash, cache)
+OcclusionQuery::OcclusionQuery(GrManager* manager)
+	: GrObject(manager, CLASS_TYPE)
 {
 }
 

+ 1 - 1
src/anki/gr/gl/RenderingThread.cpp

@@ -85,7 +85,7 @@ void RenderingThread::flushCommandBuffer(CommandBufferPtr cmdb, FencePtr* fence)
 	{
 		FencePtr& f = *fence;
 
-		f.reset(m_manager->getImplementation().getAllocator().newInstance<Fence>(m_manager.get(), 0, nullptr));
+		f.reset(m_manager->getImplementation().getAllocator().newInstance<Fence>(m_manager.get()));
 		f->m_impl.reset(m_manager->getAllocator().newInstance<FenceImpl>(m_manager.get()));
 
 		class CreateFenceCmd final : public GlCommand

+ 2 - 2
src/anki/gr/gl/Sampler.cpp

@@ -11,8 +11,8 @@
 namespace anki
 {
 
-Sampler::Sampler(GrManager* manager, U64 hash, GrObjectCache* cache)
-	: GrObject(manager, CLASS_TYPE, hash, cache)
+Sampler::Sampler(GrManager* manager)
+	: GrObject(manager, CLASS_TYPE)
 {
 }
 

+ 2 - 2
src/anki/gr/gl/Shader.cpp

@@ -11,8 +11,8 @@
 namespace anki
 {
 
-Shader::Shader(GrManager* manager, U64 hash, GrObjectCache* cache)
-	: GrObject(manager, CLASS_TYPE, hash, cache)
+Shader::Shader(GrManager* manager)
+	: GrObject(manager, CLASS_TYPE)
 {
 }
 

+ 2 - 2
src/anki/gr/gl/ShaderProgram.cpp

@@ -12,8 +12,8 @@
 namespace anki
 {
 
-ShaderProgram::ShaderProgram(GrManager* manager, U64 hash, GrObjectCache* cache)
-	: GrObject(manager, CLASS_TYPE, hash, cache)
+ShaderProgram::ShaderProgram(GrManager* manager)
+	: GrObject(manager, CLASS_TYPE)
 {
 }
 

+ 2 - 2
src/anki/gr/gl/Texture.cpp

@@ -11,8 +11,8 @@
 namespace anki
 {
 
-Texture::Texture(GrManager* manager, U64 hash, GrObjectCache* cache)
-	: GrObject(manager, CLASS_TYPE, hash, cache)
+Texture::Texture(GrManager* manager)
+	: GrObject(manager, CLASS_TYPE)
 {
 }
 

+ 2 - 2
src/anki/gr/vulkan/Buffer.cpp

@@ -9,8 +9,8 @@
 namespace anki
 {
 
-Buffer::Buffer(GrManager* manager, U64 hash, GrObjectCache* cache)
-	: GrObject(manager, CLASS_TYPE, hash, cache)
+Buffer::Buffer(GrManager* manager)
+	: GrObject(manager, CLASS_TYPE)
 {
 }
 

+ 2 - 2
src/anki/gr/vulkan/CommandBuffer.cpp

@@ -10,8 +10,8 @@
 namespace anki
 {
 
-CommandBuffer::CommandBuffer(GrManager* manager, U64 hash, GrObjectCache* cache)
-	: GrObject(manager, CLASS_TYPE, hash, cache)
+CommandBuffer::CommandBuffer(GrManager* manager)
+	: GrObject(manager, CLASS_TYPE)
 {
 }
 

+ 11 - 1
src/anki/gr/vulkan/CommandBufferFactory.cpp

@@ -53,6 +53,9 @@ void CommandBufferThreadAllocator::destroyList(IntrusiveList<MicroCommandBuffer>
 		list.popFront();
 		ptr->destroy();
 		getAllocator().deleteInstance(ptr);
+#if ANKI_EXTRA_CHECKS
+		m_createdCmdbs.fetchSub(1);
+#endif
 	}
 }
 
@@ -78,6 +81,8 @@ void CommandBufferThreadAllocator::destroy()
 		vkDestroyCommandPool(m_factory->m_dev, m_pool, nullptr);
 		m_pool = {};
 	}
+
+	ANKI_ASSERT(m_createdCmdbs.load() == 0 && "Someone still holds references to command buffers");
 }
 
 Error CommandBufferThreadAllocator::newCommandBuffer(CommandBufferFlag cmdbFlags, MicroCommandBufferPtr& outPtr)
@@ -170,9 +175,14 @@ Error CommandBufferThreadAllocator::newCommandBuffer(CommandBufferFlag cmdbFlags
 		ANKI_VK_CHECK(vkAllocateCommandBuffers(m_factory->m_dev, &ci, &cmdb));
 
 		MicroCommandBuffer* newCmdb = getAllocator().newInstance<MicroCommandBuffer>(this);
+
+#if ANKI_EXTRA_CHECKS
+		m_createdCmdbs.fetchAdd(1);
+#endif
+
 		newCmdb->m_fastAlloc = StackAllocator<U8>(m_factory->m_alloc.getMemoryPool().getAllocationCallback(),
 			m_factory->m_alloc.getMemoryPool().getAllocationCallbackUserData(),
-			(smallBatch) ? (1024 * 1024) : (1024 * 1024),
+			(smallBatch) ? 1_MB : 1_MB,
 			2.0f);
 
 		newCmdb->m_handle = cmdb;

+ 4 - 0
src/anki/gr/vulkan/CommandBufferFactory.h

@@ -139,6 +139,10 @@ private:
 		Mutex m_deletedMtx; ///< Lock because the dallocations may happen anywhere.
 	};
 
+#if ANKI_EXTRA_CHECKS
+	Atomic<U32> m_createdCmdbs = {0};
+#endif
+
 	Array2d<CmdbType, 2, 2> m_types;
 
 	void destroyList(IntrusiveList<MicroCommandBuffer>& list);

+ 1 - 1
src/anki/gr/vulkan/DescriptorSet.cpp

@@ -285,7 +285,7 @@ void DSThreadAllocator::writeSet(const Array<AnyBinding, MAX_BINDINGS_PER_DESCRI
 			switch(b.m_type)
 			{
 			case DescriptorType::TEXTURE:
-				tex[texCount].sampler = b.m_tex.m_sampler->m_handle;
+				tex[texCount].sampler = b.m_tex.m_sampler->getHandle();
 				tex[texCount].imageView = b.m_tex.m_tex->getOrCreateResourceGroupView(b.m_tex.m_aspect);
 				tex[texCount].imageLayout = b.m_tex.m_layout;
 

+ 3 - 3
src/anki/gr/vulkan/DescriptorSet.h

@@ -66,7 +66,7 @@ class TextureBinding
 {
 public:
 	TextureImpl* m_tex = nullptr;
-	SamplerImpl* m_sampler = nullptr;
+	MicroSampler* m_sampler = nullptr;
 	DepthStencilAspectBit m_aspect = DepthStencilAspectBit::NONE;
 	VkImageLayout m_layout = VK_IMAGE_LAYOUT_MAX_ENUM;
 };
@@ -117,7 +117,7 @@ public:
 		b.m_uuids[0] = b.m_uuids[1] = tex->getUuid();
 
 		b.m_tex.m_tex = tex->m_impl.get();
-		b.m_tex.m_sampler = tex->m_impl->m_sampler->m_impl.get();
+		b.m_tex.m_sampler = tex->m_impl->m_sampler.get();
 		b.m_tex.m_aspect = aspect;
 		b.m_tex.m_layout = layout;
 
@@ -134,7 +134,7 @@ public:
 		b.m_uuids[1] = sampler->getUuid();
 
 		b.m_tex.m_tex = tex->m_impl.get();
-		b.m_tex.m_sampler = sampler->m_impl.get();
+		b.m_tex.m_sampler = sampler->m_impl->m_sampler.get();
 		b.m_tex.m_aspect = aspect;
 		b.m_tex.m_layout = layout;
 

+ 3 - 3
src/anki/gr/vulkan/Fence.cpp

@@ -9,8 +9,8 @@
 namespace anki
 {
 
-Fence::Fence(GrManager* manager, U64 hash, GrObjectCache* cache)
-	: GrObject(manager, CLASS_TYPE, hash, cache)
+Fence::Fence(GrManager* manager)
+	: GrObject(manager, CLASS_TYPE)
 {
 }
 
@@ -23,4 +23,4 @@ Bool Fence::clientWait(F64 seconds)
 	return m_impl->m_fence->clientWait(seconds);
 }
 
-} // end namespace anki
+} // end namespace anki

+ 2 - 2
src/anki/gr/vulkan/Framebuffer.cpp

@@ -9,8 +9,8 @@
 namespace anki
 {
 
-Framebuffer::Framebuffer(GrManager* manager, U64 hash, GrObjectCache* cache)
-	: GrObject(manager, CLASS_TYPE, hash, cache)
+Framebuffer::Framebuffer(GrManager* manager)
+	: GrObject(manager, CLASS_TYPE)
 {
 }
 

+ 5 - 11
src/anki/gr/vulkan/GrManagerImpl.cpp

@@ -7,7 +7,6 @@
 #include <anki/gr/GrManager.h>
 #include <anki/gr/vulkan/CommandBufferImpl.h>
 #include <anki/gr/CommandBuffer.h>
-#include <anki/gr/GrObjectCache.h>
 #include <anki/gr/Fence.h>
 #include <anki/gr/vulkan/FenceImpl.h>
 
@@ -37,11 +36,6 @@ GrManagerImpl::~GrManagerImpl()
 		x.m_renderSemaphore.reset(nullptr);
 	}
 
-	if(m_samplerCache)
-	{
-		getAllocator().deleteInstance(m_samplerCache);
-	}
-
 	m_crntSwapchain.reset(nullptr);
 
 	// THIRD THING: Continue with the rest
@@ -50,13 +44,15 @@ GrManagerImpl::~GrManagerImpl()
 	m_barrierFactory.destroy(); // Destroy before fences
 	m_semaphores.destroy(); // Destroy before fences
 	m_swapchainFactory.destroy(); // Destroy before fences
-	m_fences.destroy();
+	m_samplerFactory.destroy(); // Destroy before fences
 
 	m_pplineLayoutFactory.destroy();
 	m_descrFactory.destroy();
 
 	m_pplineCache.destroy(m_device, m_physicalDevice, getAllocator());
 
+	m_fences.destroy();
+
 	if(m_device)
 	{
 		vkDestroyDevice(m_device, nullptr);
@@ -133,12 +129,10 @@ Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
 	glslang::InitializeProcess();
 	m_fences.init(getAllocator(), m_device);
 	m_semaphores.init(getAllocator(), m_device);
+	m_samplerFactory.init(this);
 	m_barrierFactory.init(getAllocator(), m_device);
-
 	m_queryAlloc.init(getAllocator(), m_device);
 
-	m_samplerCache = getAllocator().newInstance<GrObjectCache>(m_manager);
-
 	// Set m_r8g8b8ImagesSupported
 	{
 		VkImageFormatProperties props = {};
@@ -723,7 +717,7 @@ void GrManagerImpl::flushCommandBuffer(CommandBufferPtr cmdb, FencePtr* outFence
 	// Create fence
 	if(outFence)
 	{
-		outFence->reset(getAllocator().newInstance<Fence>(m_manager, 0, nullptr));
+		outFence->reset(getAllocator().newInstance<Fence>(m_manager));
 		(*outFence)->m_impl.reset(getAllocator().newInstance<FenceImpl>(m_manager));
 		(*outFence)->m_impl->m_fence = fence;
 	}

+ 7 - 8
src/anki/gr/vulkan/GrManagerImpl.h

@@ -10,6 +10,7 @@
 #include <anki/gr/vulkan/SemaphoreFactory.h>
 #include <anki/gr/vulkan/DeferredBarrierFactory.h>
 #include <anki/gr/vulkan/FenceFactory.h>
+#include <anki/gr/vulkan/SamplerFactory.h>
 #include <anki/gr/vulkan/QueryExtra.h>
 #include <anki/gr/vulkan/DescriptorSet.h>
 #include <anki/gr/vulkan/CommandBufferFactory.h>
@@ -84,6 +85,11 @@ public:
 	{
 		return m_fences.newInstance();
 	}
+
+	SamplerFactory& getSamplerFactory()
+	{
+		return m_samplerFactory;
+	}
 	/// @}
 
 	void flushCommandBuffer(CommandBufferPtr ptr, FencePtr* fence, Bool wait = false);
@@ -131,12 +137,6 @@ public:
 		return m_d24S8ImagesSupported;
 	}
 
-	GrObjectCache& getSamplerCache()
-	{
-		ANKI_ASSERT(m_samplerCache);
-		return *m_samplerCache;
-	}
-
 	DescriptorSetFactory& getDescriptorSetFactory()
 	{
 		return m_descrFactory;
@@ -244,6 +244,7 @@ private:
 	FenceFactory m_fences;
 	SemaphoreFactory m_semaphores;
 	DeferredBarrierFactory m_barrierFactory;
+	SamplerFactory m_samplerFactory;
 	/// @}
 
 	SwapchainFactory m_swapchainFactory;
@@ -260,8 +261,6 @@ private:
 	Bool8 m_s8ImagesSupported = false;
 	Bool8 m_d24S8ImagesSupported = false;
 
-	GrObjectCache* m_samplerCache = nullptr;
-
 	mutable HashMap<U64, StringAuto> m_vkHandleToName;
 	mutable SpinLock m_vkHandleToNameLock;
 

+ 2 - 2
src/anki/gr/vulkan/OcclusionQuery.cpp

@@ -9,8 +9,8 @@
 namespace anki
 {
 
-OcclusionQuery::OcclusionQuery(GrManager* manager, U64 hash, GrObjectCache* cache)
-	: GrObject(manager, CLASS_TYPE, hash, cache)
+OcclusionQuery::OcclusionQuery(GrManager* manager)
+	: GrObject(manager, CLASS_TYPE)
 {
 }
 

+ 2 - 2
src/anki/gr/vulkan/Sampler.cpp

@@ -9,8 +9,8 @@
 namespace anki
 {
 
-Sampler::Sampler(GrManager* manager, U64 hash, GrObjectCache* cache)
-	: GrObject(manager, CLASS_TYPE, hash, cache)
+Sampler::Sampler(GrManager* manager)
+	: GrObject(manager, CLASS_TYPE)
 {
 }
 

+ 93 - 6
src/anki/gr/vulkan/SamplerFactory.cpp

@@ -11,7 +11,10 @@ namespace anki
 
 MicroSampler::~MicroSampler()
 {
-	// TODO
+	if(m_handle)
+	{
+		vkDestroySampler(m_factory->m_gr->getDevice(), m_handle, nullptr);
+	}
 }
 
 GrAllocator<U8> MicroSampler::getAllocator() const
@@ -21,26 +24,110 @@ GrAllocator<U8> MicroSampler::getAllocator() const
 
 Error MicroSampler::init(const SamplerInitInfo& inf)
 {
-	// TODO
+	// Fill the create cio
+	VkSamplerCreateInfo ci = {};
+	ci.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
+
+	if(inf.m_minMagFilter == SamplingFilter::NEAREST)
+	{
+		ci.magFilter = ci.minFilter = VK_FILTER_NEAREST;
+	}
+	else
+	{
+		ANKI_ASSERT(inf.m_minMagFilter == SamplingFilter::LINEAR);
+		ci.magFilter = ci.minFilter = VK_FILTER_LINEAR;
+	}
+
+	if(inf.m_mipmapFilter == SamplingFilter::BASE || inf.m_mipmapFilter == SamplingFilter::NEAREST)
+	{
+		ci.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
+	}
+	else
+	{
+		ci.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
+	}
+
+	if(inf.m_repeat)
+	{
+		ci.addressModeU = ci.addressModeV = ci.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
+	}
+	else
+	{
+		ci.addressModeU = ci.addressModeV = ci.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+	}
+
+	ci.mipLodBias = 0.0;
+
+	if(inf.m_anisotropyLevel > 0)
+	{
+		ci.anisotropyEnable = VK_TRUE;
+		ci.maxAnisotropy = inf.m_anisotropyLevel;
+	}
+
+	ci.compareOp = convertCompareOp(inf.m_compareOperation);
+	if(ci.compareOp != VK_COMPARE_OP_ALWAYS)
+	{
+		ci.compareEnable = VK_TRUE;
+	}
+
+	ci.minLod = inf.m_minLod;
+	ci.maxLod = inf.m_maxLod;
+
+	ci.unnormalizedCoordinates = VK_FALSE;
+
+	// Create
+	ANKI_VK_CHECK(vkCreateSampler(m_factory->m_gr->getDevice(), &ci, nullptr, &m_handle));
+	m_factory->m_gr->trySetVulkanHandleName(inf.getName(), VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT, m_handle);
+
 	return Error::NONE;
 }
 
 Error SamplerFactory::init(GrManagerImpl* gr)
 {
 	ANKI_ASSERT(gr);
-	// TODO
+	ANKI_ASSERT(!m_gr);
+	m_gr = gr;
+	m_recycler.init(gr->getAllocator());
+
 	return Error::NONE;
 }
 
 void SamplerFactory::destroy()
 {
-	// TODO
+	m_recycler.destroy();
+	m_gr = nullptr;
 }
 
 Error SamplerFactory::newInstance(const SamplerInitInfo& inf, MicroSamplerPtr& psampler)
 {
-	// TODO
-	return Error::NONE;
+	ANKI_ASSERT(m_gr);
+
+	Error err = Error::NONE;
+	MicroSampler* out = m_recycler.findToReuse();
+
+	if(out == nullptr)
+	{
+		// Create a new one
+
+		GrAllocator<U8> alloc = m_gr->getAllocator();
+
+		out = alloc.newInstance<MicroSampler>(this);
+		err = out->init(inf);
+
+		if(err)
+		{
+			alloc.deleteInstance(out);
+			out = nullptr;
+		}
+	}
+
+	if(!err)
+	{
+		ANKI_ASSERT(out->m_refcount.get() == 0);
+		psampler.reset(out);
+	}
+
+	return err;
 }
 
 } // end namespace anki

+ 2 - 68
src/anki/gr/vulkan/SamplerImpl.cpp

@@ -6,79 +6,13 @@
 #include <anki/gr/vulkan/SamplerImpl.h>
 #include <anki/gr/Texture.h>
 #include <anki/gr/vulkan/GrManagerImpl.h>
-#include <cstring>
 
 namespace anki
 {
 
-SamplerImpl::~SamplerImpl()
+Error SamplerImpl::init(const SamplerInitInfo& inf)
 {
-	if(m_handle)
-	{
-		vkDestroySampler(getDevice(), m_handle, nullptr);
-	}
-}
-
-Error SamplerImpl::init(const SamplerInitInfo& ii)
-{
-	// Fill the create cio
-	VkSamplerCreateInfo ci;
-	memset(&ci, 0, sizeof(ci));
-
-	ci.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
-
-	if(ii.m_minMagFilter == SamplingFilter::NEAREST)
-	{
-		ci.magFilter = ci.minFilter = VK_FILTER_NEAREST;
-	}
-	else
-	{
-		ANKI_ASSERT(ii.m_minMagFilter == SamplingFilter::LINEAR);
-		ci.magFilter = ci.minFilter = VK_FILTER_LINEAR;
-	}
-
-	if(ii.m_mipmapFilter == SamplingFilter::BASE || ii.m_mipmapFilter == SamplingFilter::NEAREST)
-	{
-		ci.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
-	}
-	else
-	{
-		ci.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
-	}
-
-	if(ii.m_repeat)
-	{
-		ci.addressModeU = ci.addressModeV = ci.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
-	}
-	else
-	{
-		ci.addressModeU = ci.addressModeV = ci.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
-	}
-
-	ci.mipLodBias = 0.0;
-
-	if(ii.m_anisotropyLevel > 0)
-	{
-		ci.anisotropyEnable = VK_TRUE;
-		ci.maxAnisotropy = ii.m_anisotropyLevel;
-	}
-
-	ci.compareOp = convertCompareOp(ii.m_compareOperation);
-	if(ci.compareOp != VK_COMPARE_OP_ALWAYS)
-	{
-		ci.compareEnable = VK_TRUE;
-	}
-
-	ci.minLod = ii.m_minLod;
-	ci.maxLod = ii.m_maxLod;
-
-	ci.unnormalizedCoordinates = VK_FALSE;
-
-	// Create
-	ANKI_VK_CHECK(vkCreateSampler(getDevice(), &ci, nullptr, &m_handle));
-	getGrManagerImpl().trySetVulkanHandleName(ii.getName(), VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT, m_handle);
-
-	return Error::NONE;
+	return getGrManagerImpl().getSamplerFactory().newInstance(inf, m_sampler);
 }
 
 } // end namespace anki

+ 5 - 2
src/anki/gr/vulkan/SamplerImpl.h

@@ -6,6 +6,7 @@
 #pragma once
 
 #include <anki/gr/vulkan/VulkanObject.h>
+#include <anki/gr/vulkan/SamplerFactory.h>
 
 namespace anki
 {
@@ -17,14 +18,16 @@ namespace anki
 class SamplerImpl : public VulkanObject
 {
 public:
-	VkSampler m_handle = VK_NULL_HANDLE;
+	MicroSamplerPtr m_sampler;
 
 	SamplerImpl(GrManager* manager)
 		: VulkanObject(manager)
 	{
 	}
 
-	~SamplerImpl();
+	~SamplerImpl()
+	{
+	}
 
 	ANKI_USE_RESULT Error init(const SamplerInitInfo& init);
 };

+ 2 - 2
src/anki/gr/vulkan/Shader.cpp

@@ -9,8 +9,8 @@
 namespace anki
 {
 
-Shader::Shader(GrManager* manager, U64 hash, GrObjectCache* cache)
-	: GrObject(manager, CLASS_TYPE, hash, cache)
+Shader::Shader(GrManager* manager)
+	: GrObject(manager, CLASS_TYPE)
 {
 }
 

+ 2 - 2
src/anki/gr/vulkan/ShaderProgram.cpp

@@ -10,8 +10,8 @@
 namespace anki
 {
 
-ShaderProgram::ShaderProgram(GrManager* manager, U64 hash, GrObjectCache* cache)
-	: GrObject(manager, CLASS_TYPE, hash, cache)
+ShaderProgram::ShaderProgram(GrManager* manager)
+	: GrObject(manager, CLASS_TYPE)
 {
 }
 

+ 2 - 2
src/anki/gr/vulkan/Texture.cpp

@@ -9,8 +9,8 @@
 namespace anki
 {
 
-Texture::Texture(GrManager* manager, U64 hash, GrObjectCache* cache)
-	: GrObject(manager, CLASS_TYPE, hash, cache)
+Texture::Texture(GrManager* manager)
+	: GrObject(manager, CLASS_TYPE)
 {
 }
 

+ 2 - 2
src/anki/gr/vulkan/TextureImpl.cpp

@@ -10,7 +10,6 @@
 #include <anki/gr/CommandBuffer.h>
 #include <anki/gr/vulkan/CommandBufferImpl.h>
 #include <anki/gr/common/Misc.h>
-#include <anki/gr/GrObjectCache.h>
 
 namespace anki
 {
@@ -54,7 +53,8 @@ Error TextureImpl::init(const TextureInitInfo& init_, Texture* tex)
 	TextureInitInfo init = init_;
 	init.m_sampling.setName(init.getName());
 	ANKI_ASSERT(textureInitInfoValid(init));
-	m_sampler = getGrManagerImpl().getSamplerCache().newInstance<Sampler>(init.m_sampling);
+
+	ANKI_CHECK(getGrManagerImpl().getSamplerFactory().newInstance(init.m_sampling, m_sampler));
 
 	// Set some stuff
 	m_width = init.m_width;

+ 2 - 1
src/anki/gr/vulkan/TextureImpl.h

@@ -8,6 +8,7 @@
 #include <anki/gr/vulkan/VulkanObject.h>
 #include <anki/gr/vulkan/GpuMemoryManager.h>
 #include <anki/gr/common/Misc.h>
+#include <anki/gr/vulkan/SamplerFactory.h>
 #include <anki/util/HashMap.h>
 
 namespace anki
@@ -32,7 +33,7 @@ ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(TextureImplWorkaround, inline)
 class TextureImpl : public VulkanObject
 {
 public:
-	SamplerPtr m_sampler;
+	MicroSamplerPtr m_sampler;
 
 	VkImage m_imageHandle = VK_NULL_HANDLE;