Quellcode durchsuchen

Fixed out of file descriptor bug due to many VkFences created. Also fixed a VRS validation error

Panagiotis Christopoulos Charitos vor 3 Jahren
Ursprung
Commit
840a1b9fdc

+ 35 - 28
AnKi/Gr/Vulkan/FenceFactory.cpp

@@ -9,9 +9,9 @@ namespace anki {
 
 void FenceFactory::destroy()
 {
-	for(U32 i = 0; i < m_fenceCount; ++i)
+	for(MicroFence* fence : m_fences)
 	{
-		m_alloc.deleteInstance(m_fences[i]);
+		m_alloc.deleteInstance(fence);
 	}
 
 	m_fences.destroy(m_alloc);
@@ -21,31 +21,41 @@ MicroFence* FenceFactory::newFence()
 {
 	MicroFence* out = nullptr;
 
-	LockGuard<Mutex> lock(m_mtx);
-
-	U32 count = m_fenceCount;
-	while(count--)
 	{
-		VkResult status;
-		ANKI_VK_CHECKF(status = vkGetFenceStatus(m_dev, m_fences[count]->getHandle()));
-		if(status == VK_SUCCESS)
+		LockGuard<Mutex> lock(m_mtx);
+
+		for(U32 i = 0; i < m_fences.getSize(); ++i)
 		{
-			out = m_fences[count];
-			ANKI_VK_CHECKF(vkResetFences(m_dev, 1, &m_fences[count]->getHandle()));
+			VkResult status;
+			ANKI_VK_CHECKF(status = vkGetFenceStatus(m_dev, m_fences[i]->getHandle()));
+			if(status == VK_SUCCESS)
+			{
+				out = m_fences[i];
 
-			// Pop it
-			for(U32 i = count; i < m_fenceCount - 1; ++i)
+				// Pop it
+				m_fences.erase(m_alloc, m_fences.getBegin() + i);
+				break;
+			}
+			else if(status != VK_NOT_READY)
 			{
-				m_fences[i] = m_fences[i + 1];
+				ANKI_ASSERT(0);
 			}
+		}
 
-			--m_fenceCount;
-
-			break;
+		if(out)
+		{
+			// Recycle
 		}
-		else if(status != VK_NOT_READY)
+		else
 		{
-			ANKI_ASSERT(0);
+			// Create new
+
+			++m_aliveFenceCount;
+
+			if(m_aliveFenceCount > MAX_ALIVE_FENCES)
+			{
+				ANKI_VK_LOGW("Too many alive fences (%u). You may run out of file descriptors", m_aliveFenceCount);
+			}
 		}
 	}
 
@@ -54,6 +64,11 @@ MicroFence* FenceFactory::newFence()
 		// Create a new one
 		out = m_alloc.newInstance<MicroFence>(this);
 	}
+	else
+	{
+		// Recycle
+		ANKI_VK_CHECKF(vkResetFences(m_dev, 1, &out->getHandle()));
+	}
 
 	ANKI_ASSERT(out->m_refcount.getNonAtomically() == 0);
 	return out;
@@ -64,15 +79,7 @@ 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<U32>(1, m_fences.getSize() * 2));
-	}
-
-	m_fences[m_fenceCount] = fence;
-	++m_fenceCount;
+	m_fences.emplaceBack(m_alloc, fence);
 }
 
 } // end namespace anki

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

@@ -79,6 +79,9 @@ class FenceFactory
 	friend class MicroFencePtrDeleter;
 
 public:
+	/// Limit the alive fences to avoid having too many file descriptors used in Linux.
+	static constexpr U32 MAX_ALIVE_FENCES = 32;
+
 	FenceFactory()
 	{
 	}
@@ -106,7 +109,7 @@ private:
 	GrAllocator<U8> m_alloc;
 	VkDevice m_dev = VK_NULL_HANDLE;
 	DynamicArray<MicroFence*> m_fences;
-	U32 m_fenceCount = 0;
+	U32 m_aliveFenceCount = 0;
 	Mutex m_mtx;
 
 	MicroFence* newFence();

+ 1 - 1
AnKi/Gr/Vulkan/SemaphoreFactory.inl.h

@@ -59,7 +59,7 @@ inline Bool MicroSemaphore::clientWait(Second seconds)
 	const U64 ns = U64(nsf);
 
 	VkResult res;
-	ANKI_VK_CHECKF(res = vkWaitSemaphores(m_factory->m_dev, &waitInfo, ns));
+	ANKI_VK_CHECKF(res = vkWaitSemaphoresKHR(m_factory->m_dev, &waitInfo, ns));
 
 	return res != VK_TIMEOUT;
 }

+ 3 - 0
AnKi/Gr/Vulkan/TextureImpl.cpp

@@ -120,6 +120,9 @@ Error TextureImpl::initInternal(VkImage externalImage, const TextureInitInfo& in
 		ANKI_ASSERT(!!(init.m_usage & TextureUsageBit::PRESENT));
 	}
 
+	ANKI_ASSERT(getGrManagerImpl().getDeviceCapabilities().m_vrs
+				|| !(init.m_usage & TextureUsageBit::FRAMEBUFFER_SHADING_RATE));
+
 	// Set some stuff
 	m_width = init.m_width;
 	m_height = init.m_height;

+ 5 - 0
AnKi/Renderer/VrsSriGeneration.cpp

@@ -32,6 +32,11 @@ Error VrsSriGeneration::init()
 
 Error VrsSriGeneration::initInternal()
 {
+	if(!getGrManager().getDeviceCapabilities().m_vrs)
+	{
+		return Error::NONE;
+	}
+
 	const UVec2 rez = (m_r->getInternalResolution() + m_sriTexelDimension - 1) / m_sriTexelDimension;
 
 	ANKI_R_LOGV("Intializing VRS SRI generation. SRI resolution %ux%u", rez.x(), rez.y());

+ 21 - 0
AnKi/Resource/TransferGpuAllocator.cpp

@@ -124,6 +124,27 @@ Error TransferGpuAllocator::allocate(PtrSize size, TransferGpuAllocatorHandle& h
 	m_crntPoolAllocatedSize += size;
 	++pool->m_pendingReleases;
 
+	// Do a cleanup of done fences. Do that to avoid having too many fences alive. Fences are implemented with file
+	// decriptors in Linux and we don't want to exceed the process' limit of max open file descriptors
+	for(Pool& p : m_pools)
+	{
+		List<FencePtr>::Iterator it = p.m_fences.getBegin();
+		while(it != p.m_fences.getEnd())
+		{
+			const Bool fenceDone = (*it)->clientWait(0.0);
+			if(fenceDone)
+			{
+				auto nextIt = it + 1;
+				p.m_fences.erase(m_alloc, it);
+				it = nextIt;
+			}
+			else
+			{
+				++it;
+			}
+		}
+	}
+
 	return Error::NONE;
 }