浏览代码

Expose vulkan fence as well

Panagiotis Christopoulos Charitos 8 年之前
父节点
当前提交
970156681d

+ 2 - 1
src/anki/core/Trace.cpp

@@ -11,7 +11,8 @@
 namespace anki
 {
 
-static Array<const char*, U(TraceEventType::COUNT)> eventNames = {{"SCENE_UPDATE",
+static Array<const char*, U(TraceEventType::COUNT)> eventNames = {{"RESOURCE_ALLOCATE_TRANSFER",
+	"SCENE_UPDATE",
 	"SCENE_DELETE_STUFF",
 	"SCENE_PHYSICS_UPDATE",
 	"SCENE_NODES_UPDATE",

+ 25 - 0
src/anki/core/Trace.h

@@ -24,6 +24,7 @@ namespace anki
 /// Trace event type.
 enum class TraceEventType
 {
+	RESOURCE_ALLOCATE_TRANSFER,
 	SCENE_UPDATE,
 	SCENE_DELETE_STUFF,
 	SCENE_PHYSICS_UPDATE,
@@ -139,6 +140,26 @@ private:
 	ANKI_USE_RESULT Error flushEvents();
 };
 
+class ScopedTraceManagerEvent
+{
+public:
+	ScopedTraceManagerEvent(TraceManager* manager, TraceEventType type)
+		: m_manager(manager)
+		, m_type(type)
+	{
+		m_manager->startEvent();
+	}
+
+	~ScopedTraceManagerEvent()
+	{
+		m_manager->stopEvent(m_type);
+	}
+
+private:
+	TraceManager* m_manager;
+	TraceEventType m_type;
+};
+
 using TraceManagerSingleton = Singleton<TraceManager>;
 
 /// @name Trace macros.
@@ -150,6 +171,9 @@ using TraceManagerSingleton = Singleton<TraceManager>;
 
 #define ANKI_TRACE_STOP_EVENT(name_) TraceManagerSingleton::get().stopEvent(TraceEventType::name_)
 
+#define ANKI_TRACE_SCOPED_EVENT(name_)                                                                                 \
+	ScopedTraceManagerEvent _tse##name_(&TraceManagerSingleton::get(), TraceEventType::name_)
+
 #define ANKI_TRACE_INC_COUNTER(name_, val_) TraceManagerSingleton::get().incCounter(TraceCounterType::name_, val_)
 
 #define ANKI_TRACE_START_FRAME() TraceManagerSingleton::get().startFrame()
@@ -160,6 +184,7 @@ using TraceManagerSingleton = Singleton<TraceManager>;
 
 #define ANKI_TRACE_START_EVENT(name_) ((void)0)
 #define ANKI_TRACE_STOP_EVENT(name_) ((void)0)
+#define ANKI_TRACE_SCOPED_EVENT(name_) ((void)0)
 #define ANKI_TRACE_INC_COUNTER(name_, val_) ((void)0)
 #define ANKI_TRACE_START_FRAME() ((void)0)
 #define ANKI_TRACE_STOP_FRAME() ((void)0)

+ 2 - 0
src/anki/gr/Fence.h

@@ -20,6 +20,8 @@ class Fence final : public GrObject
 
 public:
 	/// Wait for the fence.
+	/// @param seconds The time to wait in seconds. If it's zero then just return the status.
+	/// @return True if is signaled (signaled == GPU work is done).
 	Bool clientWait(F64 seconds);
 
 anki_internal:

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

@@ -36,13 +36,17 @@ CommandBufferInitHints CommandBuffer::computeInitHints() const
 	return hints;
 }
 
-void CommandBuffer::flush()
+void CommandBuffer::flush(FencePtr* fence)
 {
 	m_impl->endRecording();
 
 	if(!m_impl->isSecondLevel())
 	{
-		m_impl->getGrManagerImpl().flushCommandBuffer(CommandBufferPtr(this));
+		m_impl->getGrManagerImpl().flushCommandBuffer(CommandBufferPtr(this), fence);
+	}
+	else
+	{
+		ANKI_ASSERT(fence == nullptr);
 	}
 }
 

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

@@ -5,7 +5,7 @@
 
 #pragma once
 
-#include <anki/gr/vulkan/Fence.h>
+#include <anki/gr/vulkan/FenceFactory.h>
 #include <anki/gr/CommandBuffer.h>
 #include <anki/util/List.h>
 
@@ -61,7 +61,7 @@ public:
 		m_objectRefs[m_objectRefCount++] = IntrusivePtr<GrObject>(grobj);
 	}
 
-	void setFence(FencePtr& fence)
+	void setFence(MicroFencePtr& fence)
 	{
 		ANKI_ASSERT(!(m_flags & CommandBufferFlag::SECOND_LEVEL));
 		ANKI_ASSERT(!m_fence.isCreated());
@@ -78,7 +78,7 @@ private:
 	U32 m_objectRefCount = 0;
 	CommandBufferFlag m_flags = CommandBufferFlag::NONE;
 
-	FencePtr m_fence;
+	MicroFencePtr m_fence;
 
 	void destroy();
 	void reset();

+ 1 - 1
src/anki/gr/vulkan/CommandBufferImpl.h

@@ -52,7 +52,7 @@ public:
 
 	ANKI_USE_RESULT Error init(const CommandBufferInitInfo& init);
 
-	void setFence(FencePtr& fence)
+	void setFence(MicroFencePtr& fence)
 	{
 		m_microCmdb->setFence(fence);
 	}

+ 8 - 61
src/anki/gr/vulkan/Fence.cpp

@@ -3,77 +3,24 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
-#include <anki/gr/vulkan/Fence.h>
+#include <anki/gr/Fence.h>
+#include <anki/gr/vulkan/FenceImpl.h>
 
 namespace anki
 {
 
-void FenceFactory::destroy()
+Fence::Fence(GrManager* manager, U64 hash, GrObjectCache* cache)
+	: GrObject(manager, CLASS_TYPE, hash, cache)
 {
-	for(U i = 0; i < m_fenceCount; ++i)
-	{
-		m_alloc.deleteInstance(m_fences[i]);
-	}
-
-	m_fences.destroy(m_alloc);
 }
 
-Fence* FenceFactory::newFence()
+Fence::~Fence()
 {
-	Fence* out = nullptr;
-
-	LockGuard<Mutex> lock(m_mtx);
-
-	U count = m_fenceCount;
-	while(count--)
-	{
-		VkResult status;
-		ANKI_VK_CHECKF(status = vkGetFenceStatus(m_dev, m_fences[count]->getHandle()));
-		if(status == VK_SUCCESS)
-		{
-			out = m_fences[count];
-			ANKI_VK_CHECKF(vkResetFences(m_dev, 1, &m_fences[count]->getHandle()));
-
-			// Pop it
-			for(U i = count; i < m_fenceCount - 1; ++i)
-			{
-				m_fences[i] = m_fences[i + 1];
-			}
-
-			--m_fenceCount;
-
-			break;
-		}
-		else if(status != VK_NOT_READY)
-		{
-			ANKI_ASSERT(0);
-		}
-	}
-
-	if(out == nullptr)
-	{
-		// Create a new one
-		out = m_alloc.newInstance<Fence>(this);
-	}
-
-	ANKI_ASSERT(out->m_refcount.get() == 0);
-	return out;
 }
 
-void FenceFactory::deleteFence(Fence* fence)
+Bool Fence::clientWait(F64 seconds)
 {
-	ANKI_ASSERT(fence);
-
-	LockGuard<Mutex> lock(m_mtx);
-
-	if(m_fences.getSize() <= m_fenceCount)
-	{
-		// Grow storage
-		m_fences.resize(m_alloc, max<U>(1, m_fences.getSize() * 2));
-	}
-
-	m_fences[m_fenceCount] = fence;
-	++m_fenceCount;
+	return m_impl->m_fence->clientWait(seconds);
 }
 
-} // end namespace anki
+} // end namespace anki

+ 79 - 0
src/anki/gr/vulkan/FenceFactory.cpp

@@ -0,0 +1,79 @@
+// 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/FenceFactory.h>
+
+namespace anki
+{
+
+void FenceFactory::destroy()
+{
+	for(U i = 0; i < m_fenceCount; ++i)
+	{
+		m_alloc.deleteInstance(m_fences[i]);
+	}
+
+	m_fences.destroy(m_alloc);
+}
+
+MicroFence* FenceFactory::newFence()
+{
+	MicroFence* out = nullptr;
+
+	LockGuard<Mutex> lock(m_mtx);
+
+	U count = m_fenceCount;
+	while(count--)
+	{
+		VkResult status;
+		ANKI_VK_CHECKF(status = vkGetFenceStatus(m_dev, m_fences[count]->getHandle()));
+		if(status == VK_SUCCESS)
+		{
+			out = m_fences[count];
+			ANKI_VK_CHECKF(vkResetFences(m_dev, 1, &m_fences[count]->getHandle()));
+
+			// Pop it
+			for(U i = count; i < m_fenceCount - 1; ++i)
+			{
+				m_fences[i] = m_fences[i + 1];
+			}
+
+			--m_fenceCount;
+
+			break;
+		}
+		else if(status != VK_NOT_READY)
+		{
+			ANKI_ASSERT(0);
+		}
+	}
+
+	if(out == nullptr)
+	{
+		// Create a new one
+		out = m_alloc.newInstance<MicroFence>(this);
+	}
+
+	ANKI_ASSERT(out->m_refcount.get() == 0);
+	return out;
+}
+
+void FenceFactory::deleteFence(MicroFence* fence)
+{
+	ANKI_ASSERT(fence);
+
+	LockGuard<Mutex> lock(m_mtx);
+
+	if(m_fences.getSize() <= m_fenceCount)
+	{
+		// Grow storage
+		m_fences.resize(m_alloc, max<U>(1, m_fences.getSize() * 2));
+	}
+
+	m_fences[m_fenceCount] = fence;
+	++m_fenceCount;
+}
+
+} // end namespace anki

+ 17 - 15
src/anki/gr/vulkan/Fence.h → src/anki/gr/vulkan/FenceFactory.h

@@ -17,15 +17,15 @@ class FenceFactory;
 /// @{
 
 /// Fence wrapper over VkFence.
-class Fence : public NonCopyable
+class MicroFence : public NonCopyable
 {
 	friend class FenceFactory;
-	friend class FencePtrDeleter;
+	friend class MicroFencePtrDeleter;
 
 public:
-	Fence(FenceFactory* f);
+	MicroFence(FenceFactory* f);
 
-	~Fence();
+	~MicroFence();
 
 	const VkFence& getHandle() const
 	{
@@ -44,6 +44,8 @@ public:
 
 	Bool done() const;
 
+	Bool clientWait(F64 seconds);
+
 private:
 	VkFence m_handle = VK_NULL_HANDLE;
 	Atomic<U32> m_refcount = {0};
@@ -51,20 +53,20 @@ private:
 };
 
 /// Deleter for FencePtr.
-class FencePtrDeleter
+class MicroFencePtrDeleter
 {
 public:
-	void operator()(Fence* f);
+	void operator()(MicroFence* f);
 };
 
 /// Fence smart pointer.
-using FencePtr = IntrusivePtr<Fence, FencePtrDeleter>;
+using MicroFencePtr = IntrusivePtr<MicroFence, MicroFencePtrDeleter>;
 
 /// A factory of fences.
 class FenceFactory
 {
-	friend class Fence;
-	friend class FencePtrDeleter;
+	friend class MicroFence;
+	friend class MicroFencePtrDeleter;
 
 public:
 	FenceFactory()
@@ -85,23 +87,23 @@ public:
 	void destroy();
 
 	/// Create a new fence pointer.
-	FencePtr newInstance()
+	MicroFencePtr newInstance()
 	{
-		return FencePtr(newFence());
+		return MicroFencePtr(newFence());
 	}
 
 private:
 	GrAllocator<U8> m_alloc;
 	VkDevice m_dev = VK_NULL_HANDLE;
-	DynamicArray<Fence*> m_fences;
+	DynamicArray<MicroFence*> m_fences;
 	U32 m_fenceCount = 0;
 	Mutex m_mtx;
 
-	Fence* newFence();
-	void deleteFence(Fence* fence);
+	MicroFence* newFence();
+	void deleteFence(MicroFence* fence);
 };
 /// @}
 
 } // end namespace anki
 
-#include <anki/gr/vulkan/Fence.inl.h>
+#include <anki/gr/vulkan/FenceFactory.inl.h>

+ 24 - 7
src/anki/gr/vulkan/Fence.inl.h → src/anki/gr/vulkan/FenceFactory.inl.h

@@ -3,13 +3,13 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
-#include <anki/gr/vulkan/Fence.h>
+#include <anki/gr/vulkan/FenceFactory.h>
 #include <anki/core/Trace.h>
 
 namespace anki
 {
 
-inline Fence::Fence(FenceFactory* f)
+inline MicroFence::MicroFence(FenceFactory* f)
 	: m_factory(f)
 {
 	ANKI_ASSERT(f);
@@ -20,7 +20,7 @@ inline Fence::Fence(FenceFactory* f)
 	ANKI_VK_CHECKF(vkCreateFence(m_factory->m_dev, &ci, nullptr, &m_handle));
 }
 
-inline Fence::~Fence()
+inline MicroFence::~MicroFence()
 {
 	if(m_handle)
 	{
@@ -28,18 +28,18 @@ inline Fence::~Fence()
 	}
 }
 
-inline GrAllocator<U8> Fence::getAllocator() const
+inline GrAllocator<U8> MicroFence::getAllocator() const
 {
 	return m_factory->m_alloc;
 }
 
-inline void Fence::wait()
+inline void MicroFence::wait()
 {
 	ANKI_ASSERT(m_handle);
 	ANKI_VK_CHECKF(vkWaitForFences(m_factory->m_dev, 1, &m_handle, true, ~0U));
 }
 
-inline Bool Fence::done() const
+inline Bool MicroFence::done() const
 {
 	ANKI_ASSERT(m_handle);
 	VkResult status = vkGetFenceStatus(m_factory->m_dev, m_handle);
@@ -55,7 +55,24 @@ inline Bool Fence::done() const
 	return false;
 }
 
-inline void FencePtrDeleter::operator()(Fence* f)
+inline Bool MicroFence::clientWait(F64 seconds)
+{
+	if(seconds == 0.0)
+	{
+		return done();
+	}
+	else
+	{
+		VkResult res;
+		F64 nsf = 1e+9 * seconds;
+		U64 ns = U64(nsf);
+		ANKI_VK_CHECKF(res = vkWaitForFences(m_factory->m_dev, 1, &m_handle, true, ns));
+
+		return res != VK_TIMEOUT;
+	}
+}
+
+inline void MicroFencePtrDeleter::operator()(MicroFence* f)
 {
 	ANKI_ASSERT(f);
 	f->m_factory->deleteFence(f);

+ 34 - 0
src/anki/gr/vulkan/FenceImpl.h

@@ -0,0 +1,34 @@
+// 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/VulkanObject.h>
+#include <anki/gr/vulkan/FenceFactory.h>
+
+namespace anki
+{
+
+/// @addtogroup vulkan
+/// @{
+
+/// Buffer implementation
+class FenceImpl : public VulkanObject
+{
+public:
+	MicroFencePtr m_fence;
+
+	FenceImpl(GrManager* manager)
+		: VulkanObject(manager)
+	{
+	}
+
+	~FenceImpl()
+	{
+	}
+};
+/// @}
+
+} // end namespace anki

+ 13 - 4
src/anki/gr/vulkan/GrManagerImpl.cpp

@@ -5,10 +5,11 @@
 
 #include <anki/gr/vulkan/GrManagerImpl.h>
 #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>
 
 #include <anki/core/Config.h>
 #include <glslang/Public/ShaderLang.h>
@@ -725,7 +726,7 @@ void GrManagerImpl::beginFrame()
 	PerFrame& frame = m_perFrame[m_frame % MAX_FRAMES_IN_FLIGHT];
 
 	// Create sync objects
-	FencePtr fence = newFence();
+	MicroFencePtr fence = newFence();
 	frame.m_acquireSemaphore = m_semaphores.newInstance(fence);
 
 	// Get new image
@@ -787,7 +788,7 @@ void GrManagerImpl::resetFrame(PerFrame& frame)
 	frame.m_renderSemaphore.reset(nullptr);
 }
 
-void GrManagerImpl::flushCommandBuffer(CommandBufferPtr cmdb, Bool wait)
+void GrManagerImpl::flushCommandBuffer(CommandBufferPtr cmdb, FencePtr* outFence, Bool wait)
 {
 	CommandBufferImpl& impl = *cmdb->m_impl;
 	VkCommandBuffer handle = impl.getHandle();
@@ -795,7 +796,15 @@ void GrManagerImpl::flushCommandBuffer(CommandBufferPtr cmdb, Bool wait)
 	VkSubmitInfo submit = {};
 	submit.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
 
-	FencePtr fence = newFence();
+	MicroFencePtr fence = newFence();
+
+	// Create fence
+	if(outFence)
+	{
+		outFence->reset(getAllocator().newInstance<Fence>(m_manager, 0, nullptr));
+		(*outFence)->m_impl.reset(getAllocator().newInstance<FenceImpl>(m_manager));
+		(*outFence)->m_impl->m_fence = fence;
+	}
 
 	LockGuard<Mutex> lock(m_globalMtx);
 

+ 5 - 5
src/anki/gr/vulkan/GrManagerImpl.h

@@ -8,7 +8,7 @@
 #include <anki/gr/vulkan/Common.h>
 #include <anki/gr/vulkan/GpuMemoryManager.h>
 #include <anki/gr/vulkan/GrSemaphore.h>
-#include <anki/gr/vulkan/Fence.h>
+#include <anki/gr/vulkan/FenceFactory.h>
 #include <anki/gr/vulkan/QueryExtra.h>
 #include <anki/gr/vulkan/DescriptorSet.h>
 #include <anki/gr/vulkan/CommandBufferFactory.h>
@@ -78,7 +78,7 @@ public:
 		return m_cmdbFactory;
 	}
 
-	FencePtr newFence()
+	MicroFencePtr newFence()
 	{
 		return m_fences.newInstance();
 	}
@@ -118,11 +118,11 @@ public:
 		return m_surfaceHeight;
 	}
 
-	void flushCommandBuffer(CommandBufferPtr ptr, Bool wait = false);
+	void flushCommandBuffer(CommandBufferPtr ptr, FencePtr* fence, Bool wait = false);
 
 	void finishCommandBuffer(CommandBufferPtr ptr)
 	{
-		flushCommandBuffer(ptr, true);
+		flushCommandBuffer(ptr, nullptr, true);
 	}
 
 	/// @name Memory
@@ -235,7 +235,7 @@ private:
 	class PerFrame
 	{
 	public:
-		FencePtr m_presentFence;
+		MicroFencePtr m_presentFence;
 		GrSemaphorePtr m_acquireSemaphore;
 
 		/// The semaphore that the submit that renders to the default FB.

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

@@ -31,7 +31,7 @@ void GrSemaphoreFactory::releaseFences()
 	}
 }
 
-GrSemaphorePtr GrSemaphoreFactory::newInstance(FencePtr fence)
+GrSemaphorePtr GrSemaphoreFactory::newInstance(MicroFencePtr fence)
 {
 	ANKI_ASSERT(fence);
 

+ 4 - 4
src/anki/gr/vulkan/GrSemaphore.h

@@ -5,7 +5,7 @@
 
 #pragma once
 
-#include <anki/gr/vulkan/Fence.h>
+#include <anki/gr/vulkan/FenceFactory.h>
 
 namespace anki
 {
@@ -44,9 +44,9 @@ private:
 	GrSemaphoreFactory* m_factory = nullptr;
 
 	/// Fence to find out when it's safe to reuse this semaphore.
-	FencePtr m_fence;
+	MicroFencePtr m_fence;
 
-	GrSemaphore(GrSemaphoreFactory* f, FencePtr fence);
+	GrSemaphore(GrSemaphoreFactory* f, MicroFencePtr fence);
 
 	~GrSemaphore();
 };
@@ -77,7 +77,7 @@ public:
 
 	void destroy();
 
-	GrSemaphorePtr newInstance(FencePtr fence);
+	GrSemaphorePtr newInstance(MicroFencePtr fence);
 
 private:
 	GrAllocator<U8> m_alloc;

+ 1 - 1
src/anki/gr/vulkan/GrSemaphore.inl.h

@@ -9,7 +9,7 @@
 namespace anki
 {
 
-inline GrSemaphore::GrSemaphore(GrSemaphoreFactory* f, FencePtr fence)
+inline GrSemaphore::GrSemaphore(GrSemaphoreFactory* f, MicroFencePtr fence)
 	: m_factory(f)
 	, m_fence(fence)
 {

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

@@ -128,7 +128,7 @@ Error TextureImpl::init(const TextureInitInfo& init_, Texture* tex)
 		cmdb->m_impl->setTextureBarrierRange(TexturePtr(tex), TextureUsageBit::NONE, init.m_initialUsage, range);
 
 		cmdb->m_impl->endRecording();
-		getGrManagerImpl().flushCommandBuffer(cmdb);
+		getGrManagerImpl().flushCommandBuffer(cmdb, nullptr);
 	}
 
 	return ErrorCode::NONE;

+ 7 - 0
src/anki/resource/TransferGpuAllocator.cpp

@@ -7,6 +7,7 @@
 #include <anki/gr/Fence.h>
 #include <anki/gr/Buffer.h>
 #include <anki/gr/GrManager.h>
+#include <anki/core/Trace.h>
 
 namespace anki
 {
@@ -45,6 +46,10 @@ public:
 		ANKI_ASSERT(mem);
 
 		TransferGpuAllocator::Memory* mm = static_cast<TransferGpuAllocator::Memory*>(mem);
+		if(mm->m_mappedMemory)
+		{
+			mm->m_buffer->unmap();
+		}
 		m_alloc.deleteInstance(mm);
 	}
 
@@ -118,6 +123,8 @@ void TransferGpuAllocator::destroy()
 
 Error TransferGpuAllocator::allocate(PtrSize size, TransferGpuAllocatorHandle& handle)
 {
+	ANKI_TRACE_SCOPED_EVENT(RESOURCE_ALLOCATE_TRANSFER);
+
 	const PtrSize frameSize = m_maxAllocSize / FRAME_COUNT;
 
 	LockGuard<Mutex> lock(m_mtx);