Selaa lähdekoodia

Vulkan: Add VkEvent support

Panagiotis Christopoulos Charitos 8 vuotta sitten
vanhempi
sitoutus
40fa82ee17

+ 94 - 0
src/anki/gr/vulkan/DeferredBarrierFactory.cpp

@@ -0,0 +1,94 @@
+// 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/vulkan/DeferredBarrierFactory.h>
+
+namespace anki
+{
+
+void DeferredBarrierFactory::destroy()
+{
+	U count = m_barrierCount;
+	while(count--)
+	{
+		m_alloc.deleteInstance(m_barriers[count]);
+	}
+
+	m_barriers.destroy(m_alloc);
+}
+
+void DeferredBarrierFactory::releaseFences()
+{
+	U count = m_barrierCount;
+	while(count--)
+	{
+		MicroDeferredBarrier& b = *m_barriers[count];
+		if(b.m_fence && b.m_fence->done())
+		{
+			b.m_fence.reset(nullptr);
+		}
+	}
+}
+
+MicroDeferredBarrierPtr DeferredBarrierFactory::newInstance()
+{
+	LockGuard<Mutex> lock(m_mtx);
+
+	MicroDeferredBarrier* out = nullptr;
+
+	if(m_barrierCount > 0)
+	{
+		releaseFences();
+
+		U count = m_barrierCount;
+		while(count--)
+		{
+			if(!m_barriers[count]->m_fence)
+			{
+				out = m_barriers[count];
+
+				// Pop it
+				for(U i = count; i < m_barrierCount - 1; ++i)
+				{
+					m_barriers[i] = m_barriers[i + 1];
+				}
+
+				--m_barrierCount;
+
+				break;
+			}
+		}
+	}
+
+	if(out == nullptr)
+	{
+		// Create a new one
+		out = m_alloc.newInstance<MicroDeferredBarrier>(this);
+	}
+
+	ANKI_ASSERT(out->m_refcount.get() == 0);
+	return MicroDeferredBarrierPtr(out);
+}
+
+void DeferredBarrierFactory::destroyBarrier(MicroDeferredBarrier* s)
+{
+	ANKI_ASSERT(s);
+	ANKI_ASSERT(s->m_refcount.get() == 0);
+
+	LockGuard<Mutex> lock(m_mtx);
+
+	if(m_barriers.getSize() <= m_barrierCount)
+	{
+		// Grow storage
+		m_barriers.resize(m_alloc, max<U>(1, m_barriers.getSize() * 2));
+	}
+
+	m_barriers[m_barrierCount] = s;
+	++m_barrierCount;
+
+	releaseFences();
+}
+
+} // end namespace anki

+ 100 - 0
src/anki/gr/vulkan/DeferredBarrierFactory.h

@@ -0,0 +1,100 @@
+// 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/vulkan/FenceFactory.h>
+
+namespace anki
+{
+
+// Forward
+class DeferredBarrierFactory;
+
+/// @addtogroup vulkan
+/// @{
+
+/// Wrapper on top of VkEvent.
+class MicroDeferredBarrier
+{
+	friend class DeferredBarrierFactory;
+	friend class MicroDeferredBarrierPtrDeleter;
+
+public:
+	MicroDeferredBarrier(DeferredBarrierFactory* factory);
+
+	~MicroDeferredBarrier();
+
+	const VkEvent& getHandle() const
+	{
+		ANKI_ASSERT(m_handle);
+		return m_handle;
+	}
+
+	Atomic<U32>& getRefcount()
+	{
+		return m_refcount;
+	}
+
+	GrAllocator<U8> getAllocator() const;
+
+	void setFence(MicroFencePtr& f)
+	{
+		m_fence = f;
+	}
+
+private:
+	VkEvent m_handle = VK_NULL_HANDLE;
+	Atomic<U32> m_refcount = {0};
+	DeferredBarrierFactory* m_factory = nullptr;
+
+	/// Fence to find out when it's safe to reuse this barrier.
+	MicroFencePtr m_fence;
+};
+
+/// Deleter for MicroDeferredBarrierPtr smart pointer.
+class MicroDeferredBarrierPtrDeleter
+{
+public:
+	void operator()(MicroDeferredBarrier* x);
+};
+
+/// MicroDeferredBarrier smart pointer.
+using MicroDeferredBarrierPtr = IntrusivePtr<MicroDeferredBarrier, MicroDeferredBarrierPtrDeleter>;
+
+/// MicroDeferredBarrier factory.
+class DeferredBarrierFactory : public NonCopyable
+{
+	friend class MicroDeferredBarrierPtrDeleter;
+	friend class MicroDeferredBarrier;
+
+public:
+	void init(GrAllocator<U8> alloc, VkDevice dev)
+	{
+		ANKI_ASSERT(dev);
+		m_alloc = alloc;
+		m_dev = dev;
+	}
+
+	void destroy();
+
+	MicroDeferredBarrierPtr newInstance();
+
+private:
+	GrAllocator<U8> m_alloc;
+	VkDevice m_dev = VK_NULL_HANDLE;
+	DynamicArray<MicroDeferredBarrier*> m_barriers;
+	U32 m_barrierCount = 0;
+	Mutex m_mtx;
+
+	void destroyBarrier(MicroDeferredBarrier* barrier);
+
+	void releaseFences();
+};
+/// @}
+
+} // end namespace anki
+
+#include <anki/gr/vulkan/DeferredBarrierFactory.inl.h>

+ 35 - 0
src/anki/gr/vulkan/DeferredBarrierFactory.inl.h

@@ -0,0 +1,35 @@
+// 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/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 void MicroDeferredBarrierPtrDeleter::operator()(MicroDeferredBarrier* s)
+{
+	ANKI_ASSERT(s);
+	s->m_factory->destroyBarrier(s);
+}
+
+} // end namespace anki

+ 2 - 0
src/anki/gr/vulkan/GrManagerImpl.cpp

@@ -79,6 +79,7 @@ GrManagerImpl::~GrManagerImpl()
 	// THIRD THING: Continue with the rest
 	m_gpuMemManager.destroy();
 
+	m_barrierFactory.destroy(); // Destroy before fences
 	m_semaphores.destroy(); // Destroy before fences
 	m_fences.destroy();
 
@@ -163,6 +164,7 @@ Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
 	glslang::InitializeProcess();
 	m_fences.init(getAllocator(), m_device);
 	m_semaphores.init(getAllocator(), m_device);
+	m_barrierFactory.init(getAllocator(), m_device);
 
 	m_queryAlloc.init(getAllocator(), m_device);
 

+ 6 - 4
src/anki/gr/vulkan/GrManagerImpl.h

@@ -7,7 +7,8 @@
 
 #include <anki/gr/vulkan/Common.h>
 #include <anki/gr/vulkan/GpuMemoryManager.h>
-#include <anki/gr/vulkan/GrSemaphore.h>
+#include <anki/gr/vulkan/SemaphoreFactory.h>
+#include <anki/gr/vulkan/DeferredBarrierFactory.h>
 #include <anki/gr/vulkan/FenceFactory.h>
 #include <anki/gr/vulkan/QueryExtra.h>
 #include <anki/gr/vulkan/DescriptorSet.h>
@@ -237,10 +238,10 @@ private:
 	{
 	public:
 		MicroFencePtr m_presentFence;
-		GrSemaphorePtr m_acquireSemaphore;
+		MicroSemaphorePtr m_acquireSemaphore;
 
 		/// The semaphore that the submit that renders to the default FB.
-		GrSemaphorePtr m_renderSemaphore;
+		MicroSemaphorePtr m_renderSemaphore;
 	};
 
 	VkSurfaceKHR m_surface = VK_NULL_HANDLE;
@@ -263,7 +264,8 @@ private:
 	CommandBufferFactory m_cmdbFactory;
 
 	FenceFactory m_fences;
-	GrSemaphoreFactory m_semaphores;
+	SemaphoreFactory m_semaphores;
+	DeferredBarrierFactory m_barrierFactory;
 	/// @}
 
 	PipelineLayoutFactory m_pplineLayoutFactory;

+ 9 - 9
src/anki/gr/vulkan/GrSemaphore.cpp → src/anki/gr/vulkan/SemaphoreFactory.cpp

@@ -3,12 +3,12 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
-#include <anki/gr/vulkan/GrSemaphore.h>
+#include <anki/gr/vulkan/SemaphoreFactory.h>
 
 namespace anki
 {
 
-void GrSemaphoreFactory::destroy()
+void SemaphoreFactory::destroy()
 {
 	for(U i = 0; i < m_semCount; ++i)
 	{
@@ -18,12 +18,12 @@ void GrSemaphoreFactory::destroy()
 	m_sems.destroy(m_alloc);
 }
 
-void GrSemaphoreFactory::releaseFences()
+void SemaphoreFactory::releaseFences()
 {
 	U count = m_semCount;
 	while(count--)
 	{
-		GrSemaphore& sem = *m_sems[count];
+		MicroSemaphore& sem = *m_sems[count];
 		if(sem.m_fence && sem.m_fence->done())
 		{
 			sem.m_fence.reset(nullptr);
@@ -31,13 +31,13 @@ void GrSemaphoreFactory::releaseFences()
 	}
 }
 
-GrSemaphorePtr GrSemaphoreFactory::newInstance(MicroFencePtr fence)
+MicroSemaphorePtr SemaphoreFactory::newInstance(MicroFencePtr fence)
 {
 	ANKI_ASSERT(fence);
 
 	LockGuard<Mutex> lock(m_mtx);
 
-	GrSemaphore* out = nullptr;
+	MicroSemaphore* out = nullptr;
 
 	if(m_semCount > 0)
 	{
@@ -66,7 +66,7 @@ GrSemaphorePtr GrSemaphoreFactory::newInstance(MicroFencePtr fence)
 	if(out == nullptr)
 	{
 		// Create a new one
-		out = m_alloc.newInstance<GrSemaphore>(this, fence);
+		out = m_alloc.newInstance<MicroSemaphore>(this, fence);
 	}
 	else
 	{
@@ -74,10 +74,10 @@ GrSemaphorePtr GrSemaphoreFactory::newInstance(MicroFencePtr fence)
 	}
 
 	ANKI_ASSERT(out->m_refcount.get() == 0);
-	return GrSemaphorePtr(out);
+	return MicroSemaphorePtr(out);
 }
 
-void GrSemaphoreFactory::destroySemaphore(GrSemaphore* s)
+void SemaphoreFactory::destroySemaphore(MicroSemaphore* s)
 {
 	ANKI_ASSERT(s);
 	ANKI_ASSERT(s->m_refcount.get() == 0);

+ 19 - 19
src/anki/gr/vulkan/GrSemaphore.h → src/anki/gr/vulkan/SemaphoreFactory.h

@@ -11,16 +11,16 @@ namespace anki
 {
 
 // Forward
-class GrSemaphoreFactory;
+class SemaphoreFactory;
 
 /// @addtogroup vulkan
 /// @{
 
 /// Simple semaphore wrapper.
-class GrSemaphore : public NonCopyable
+class MicroSemaphore : public NonCopyable
 {
-	friend class GrSemaphoreFactory;
-	friend class GrSemaphorePtrDeleter;
+	friend class SemaphoreFactory;
+	friend class MicroSemaphorePtrDeleter;
 	template<typename, typename>
 	friend class GenericPoolAllocator;
 
@@ -41,31 +41,31 @@ public:
 private:
 	VkSemaphore m_handle = VK_NULL_HANDLE;
 	Atomic<U32> m_refcount = {0};
-	GrSemaphoreFactory* m_factory = nullptr;
+	SemaphoreFactory* m_factory = nullptr;
 
 	/// Fence to find out when it's safe to reuse this semaphore.
 	MicroFencePtr m_fence;
 
-	GrSemaphore(GrSemaphoreFactory* f, MicroFencePtr fence);
+	MicroSemaphore(SemaphoreFactory* f, MicroFencePtr fence);
 
-	~GrSemaphore();
+	~MicroSemaphore();
 };
 
-/// GrSemaphorePtr deleter.
-class GrSemaphorePtrDeleter
+/// MicroSemaphorePtr deleter.
+class MicroSemaphorePtrDeleter
 {
 public:
-	void operator()(GrSemaphore* s);
+	void operator()(MicroSemaphore* s);
 };
 
-/// GrSemaphore smart pointer.
-using GrSemaphorePtr = IntrusivePtr<GrSemaphore, GrSemaphorePtrDeleter>;
+/// MicroSemaphore smart pointer.
+using MicroSemaphorePtr = IntrusivePtr<MicroSemaphore, MicroSemaphorePtrDeleter>;
 
 /// Factory of semaphores.
-class GrSemaphoreFactory
+class SemaphoreFactory
 {
-	friend class GrSemaphore;
-	friend class GrSemaphorePtrDeleter;
+	friend class MicroSemaphore;
+	friend class MicroSemaphorePtrDeleter;
 
 public:
 	void init(GrAllocator<U8> alloc, VkDevice dev)
@@ -77,16 +77,16 @@ public:
 
 	void destroy();
 
-	GrSemaphorePtr newInstance(MicroFencePtr fence);
+	MicroSemaphorePtr newInstance(MicroFencePtr fence);
 
 private:
 	GrAllocator<U8> m_alloc;
-	DynamicArray<GrSemaphore*> m_sems;
+	DynamicArray<MicroSemaphore*> m_sems;
 	U32 m_semCount = 0;
 	VkDevice m_dev = VK_NULL_HANDLE;
 	Mutex m_mtx;
 
-	void destroySemaphore(GrSemaphore* s);
+	void destroySemaphore(MicroSemaphore* s);
 
 	/// Iterate the semaphores and release the fences.
 	void releaseFences();
@@ -95,4 +95,4 @@ private:
 
 } // end namespace anki
 
-#include <anki/gr/vulkan/GrSemaphore.inl.h>
+#include <anki/gr/vulkan/SemaphoreFactory.inl.h>

+ 4 - 4
src/anki/gr/vulkan/GrSemaphore.inl.h → src/anki/gr/vulkan/SemaphoreFactory.inl.h

@@ -3,13 +3,13 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
-#include <anki/gr/vulkan/GrSemaphore.h>
+#include <anki/gr/vulkan/SemaphoreFactory.h>
 #include <anki/core/Trace.h>
 
 namespace anki
 {
 
-inline GrSemaphore::GrSemaphore(GrSemaphoreFactory* f, MicroFencePtr fence)
+inline MicroSemaphore::MicroSemaphore(SemaphoreFactory* f, MicroFencePtr fence)
 	: m_factory(f)
 	, m_fence(fence)
 {
@@ -22,7 +22,7 @@ inline GrSemaphore::GrSemaphore(GrSemaphoreFactory* f, MicroFencePtr fence)
 	ANKI_VK_CHECKF(vkCreateSemaphore(m_factory->m_dev, &ci, nullptr, &m_handle));
 }
 
-inline GrSemaphore::~GrSemaphore()
+inline MicroSemaphore::~MicroSemaphore()
 {
 	if(m_handle)
 	{
@@ -30,7 +30,7 @@ inline GrSemaphore::~GrSemaphore()
 	}
 }
 
-inline void GrSemaphorePtrDeleter::operator()(GrSemaphore* s)
+inline void MicroSemaphorePtrDeleter::operator()(MicroSemaphore* s)
 {
 	ANKI_ASSERT(s);
 	s->m_factory->destroySemaphore(s);