Browse Source

Vulkan: Improve the fence creation

Panagiotis Christopoulos Charitos 1 week ago
parent
commit
8207e9fffd

+ 1 - 6
AnKi/Gr/BackendCommon/MicroFenceFactory.inl.h

@@ -45,7 +45,7 @@ MicroFenceFactory<TImplementation>::MyMicroFence* MicroFenceFactory<TImplementat
 {
 	MyMicroFence* out = nullptr;
 
-	LockGuard<Mutex> lock(m_mtx);
+	LockGuard lock(m_mtx);
 
 	// Trim fences if needed
 	if(m_aliveFenceCount > kMaxAliveFences * 80 / 100)
@@ -156,11 +156,6 @@ void MicroFenceFactory<TImplementation>::releaseFence(MyMicroFence* fence)
 
 	ANKI_ASSERT(!m_markedForDeletionMask.get(fence->m_arrayIdx));
 	m_markedForDeletionMask.set(fence->m_arrayIdx);
-
-	if(!fence->signaled())
-	{
-		ANKI_GR_LOGW("Fence marked for deletion but it's not signaled: %s", fence->m_name.cstr());
-	}
 }
 
 } // end namespace anki

+ 133 - 88
AnKi/Gr/Vulkan/VkGrManager.cpp

@@ -168,11 +168,24 @@ GrManagerImpl::~GrManagerImpl()
 	m_crntSwapchain.reset(nullptr);
 	SwapchainFactory::freeSingleton();
 
-	for(U32 frame = 0; frame < m_perFrame.getSize(); ++frame)
+	for(auto it = m_cleanupGroups.getBegin(); it != m_cleanupGroups.getEnd(); ++it)
 	{
-		m_frame = frame;
-		deleteObjectsMarkedForDeletion();
+		it->m_finalized = false;
+		m_activeCleanupGroup = it.getArrayIndex();
+
+		while(it->m_objectsMarkedForDeletion.getSize())
+		{
+			GrDynamicArray<GrObject*> arr = std::move(it->m_objectsMarkedForDeletion);
+
+			for(GrObject* obj : arr)
+			{
+				deleteInstance(GrMemoryPool::getSingleton(), obj);
+			}
+		}
 	}
+	m_cleanupGroups.destroy();
+
+	m_acquireData.destroy();
 
 	// 3rd THING: Continue with the rest
 	CommandBufferFactory::freeSingleton();
@@ -1233,35 +1246,8 @@ void GrManagerImpl::freeCallback(void* userData, void* ptr)
 void GrManagerImpl::beginFrameInternal()
 {
 	ANKI_TRACE_FUNCTION();
-
 	LockGuard<Mutex> lock(m_globalMtx);
-
-	// Do that at begin frame, ALWAYS
 	++m_frame;
-	PerFrame& frame = m_perFrame[m_frame % m_perFrame.getSize()];
-	ANKI_ASSERT(m_frameState == kFrameEnded);
-	m_frameState = kFrameStarted;
-
-	// Wait for the oldest frame because we don't want to start the new one too early
-	{
-		ANKI_TRACE_SCOPED_EVENT(WaitFences);
-		for(MicroFencePtr& fence : frame.m_fences)
-		{
-			if(fence)
-			{
-				const Bool signaled = fence->clientWait(kMaxSecond);
-				if(!signaled)
-				{
-					ANKI_VK_LOGF("Timeout detected");
-				}
-			}
-		}
-	}
-
-	frame.m_fences.destroy();
-	frame.m_queueWroteToSwapchainImage = GpuQueueType::kCount;
-
-	// Clear garbage
 	deleteObjectsMarkedForDeletion();
 }
 
@@ -1274,18 +1260,21 @@ TexturePtr GrManagerImpl::acquireNextPresentableTexture()
 	snprintf(name.getBegin(), name.getSize(), "Acquire %" PRIu64, m_frame);
 	MicroFencePtr fence = FenceFactory::getSingleton().newInstance(name.getBegin());
 
-	LockGuard<Mutex> lock(m_globalMtx);
+	MicroSemaphorePtr acquireSemaphore = SemaphoreFactory::getSingleton().newInstance(false, name.getBegin());
 
-	ANKI_ASSERT(m_frameState == kFrameStarted);
-	m_frameState = kPresentableAcquired;
+	LockGuard<Mutex> lock(m_globalMtx);
 
-	PerFrame& frame = m_perFrame[m_frame % m_perFrame.getSize()];
-	frame.m_fences.emplaceBack(fence);
+	// Bookkeeping
+	m_crntFences[GpuQueueType::kCount] = fence;
+	auto it = m_acquireData.emplace();
+	AcquireData& data = *it;
+	data.m_fence = fence;
+	data.m_semaphore = acquireSemaphore;
+	m_activeAcquireDataIdx = it.getArrayIndex();
 
 	// Get new image
-	const MicroSemaphore& acquireSemaphore = *m_crntSwapchain->m_acquireSemaphores[m_frame % m_crntSwapchain->m_acquireSemaphores.getSize()];
 	uint32_t imageIdx;
-	const VkResult res = vkAcquireNextImageKHR(m_device, m_crntSwapchain->m_swapchain, UINT64_MAX, acquireSemaphore.getHandle(),
+	const VkResult res = vkAcquireNextImageKHR(m_device, m_crntSwapchain->m_swapchain, UINT64_MAX, acquireSemaphore->getHandle(),
 											   fence->getImplementation().m_handle, &imageIdx);
 
 	if(res == VK_ERROR_OUT_OF_DATE_KHR)
@@ -1300,10 +1289,9 @@ TexturePtr GrManagerImpl::acquireNextPresentableTexture()
 		}
 		m_crntSwapchain.reset(nullptr);
 		m_crntSwapchain = SwapchainFactory::getSingleton().newInstance();
-		const MicroSemaphore& acquireSemaphore = *m_crntSwapchain->m_acquireSemaphores[m_frame % m_crntSwapchain->m_acquireSemaphores.getSize()];
 
 		// Can't fail a second time
-		ANKI_VK_CHECKF(vkAcquireNextImageKHR(m_device, m_crntSwapchain->m_swapchain, UINT64_MAX, acquireSemaphore.getHandle(),
+		ANKI_VK_CHECKF(vkAcquireNextImageKHR(m_device, m_crntSwapchain->m_swapchain, UINT64_MAX, acquireSemaphore->getHandle(),
 											 fence->getImplementation().m_handle, &imageIdx));
 	}
 	else
@@ -1322,13 +1310,11 @@ void GrManagerImpl::endFrameInternal()
 
 	LockGuard<Mutex> lock(m_globalMtx);
 
-	PerFrame& frame = m_perFrame[m_frame % m_perFrame.getSize()];
 	const Bool imageAcquired = m_acquiredImageIdx < kMaxU8;
 
 	// Present
 	if(imageAcquired)
 	{
-		ANKI_ASSERT(m_frameState == kPresentableDrawn && "Acquired an image but didn't draw to it?");
 		ANKI_ASSERT(m_acquiredImageIdx < kMaxU8);
 
 		VkResult res;
@@ -1342,7 +1328,7 @@ void GrManagerImpl::endFrameInternal()
 		present.pImageIndices = &idx;
 		present.pResults = &res;
 
-		const VkResult res1 = vkQueuePresentKHR(m_queues[frame.m_queueWroteToSwapchainImage], &present);
+		const VkResult res1 = vkQueuePresentKHR(m_queues[m_queueWroteToSwapchainImage], &present);
 		if(res1 == VK_ERROR_OUT_OF_DATE_KHR)
 		{
 			ANKI_VK_LOGW("Swapchain is out of date. Will wait for the queues and create a new one");
@@ -1365,12 +1351,9 @@ void GrManagerImpl::endFrameInternal()
 
 		m_acquiredImageIdx = kMaxU8;
 	}
-	else
-	{
-		ANKI_ASSERT(m_frameState == kFrameStarted);
-	}
 
-	m_frameState = kFrameEnded;
+	deleteObjectsMarkedForDeletion();
+
 	GpuMemoryManager::getSingleton().updateStats();
 }
 
@@ -1441,17 +1424,30 @@ void GrManagerImpl::submitInternal(WeakArray<CommandBuffer*> cmdbs, WeakArray<Fe
 
 	// Submit
 	{
-		// Protect the class, the queue and other stuff
 		LockGuard<Mutex> lock(m_globalMtx);
 
-		// Do some special stuff for the last command buffer
-		GrManagerImpl::PerFrame& frame = m_perFrame[m_frame % m_perFrame.getSize()];
+		// New submit so we need to finalize all groups. Following deletes will create a new group with the newely created fence
+		for(CleanupGroup& group : m_cleanupGroups)
+		{
+			group.m_finalized = true;
+		}
+		m_activeCleanupGroup = kMaxU32;
+
+		// Do cleanup as well
+		deleteObjectsMarkedForDeletion();
+
+		// Store the last fence
+		m_crntFences[queueType] = fence;
+
 		if(renderedToDefaultFb)
 		{
-			ANKI_ASSERT(m_frameState == kPresentableAcquired);
-			m_frameState = kPresentableDrawn;
+			const MicroSemaphore& acquireSemaphore = *m_acquireData[m_activeAcquireDataIdx].m_semaphore;
+
+			// Can't release the acquireSemaphore until rendering is done
+			m_acquireData[m_activeAcquireDataIdx].m_fence = fence;
 
-			const MicroSemaphore& acquireSemaphore = *m_crntSwapchain->m_acquireSemaphores[m_frame % m_crntSwapchain->m_acquireSemaphores.getSize()];
+			// Won't need it until the next acquire sets it
+			m_activeAcquireDataIdx = kMaxU32;
 
 			// Wait semaphore
 			waitSemaphores.emplaceBack(acquireSemaphore.getHandle());
@@ -1469,11 +1465,9 @@ void GrManagerImpl::submitInternal(WeakArray<CommandBuffer*> cmdbs, WeakArray<Fe
 			// Increment the timeline values as well because the spec wants a dummy value even for non-timeline semaphores
 			signalTimelineValues.emplaceBack(0);
 
-			frame.m_queueWroteToSwapchainImage = queueType;
+			m_queueWroteToSwapchainImage = queueType;
 		}
 
-		frame.m_fences.emplaceBack(fence);
-
 		// Submit
 		VkSubmitInfo submit = {};
 		submit.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
@@ -1495,27 +1489,6 @@ void GrManagerImpl::submitInternal(WeakArray<CommandBuffer*> cmdbs, WeakArray<Fe
 
 		ANKI_TRACE_SCOPED_EVENT(VkQueueSubmit);
 		ANKI_VK_CHECKF(vkQueueSubmit(m_queues[queueType], 1, &submit, fence->getImplementation().m_handle));
-
-		// Throttle the number of fences
-		Bool fencesThrottled = false;
-		while(frame.m_fences.getSize() > 64)
-		{
-			fencesThrottled = true;
-			auto it = frame.m_fences.getBegin();
-			for(; it != frame.m_fences.getEnd(); ++it)
-			{
-				if((*it)->signaled())
-				{
-					frame.m_fences.erase(it);
-					break;
-				}
-			}
-		}
-
-		if(fencesThrottled)
-		{
-			ANKI_VK_LOGV("Had to throttle the number of fences");
-		}
 	}
 }
 
@@ -1530,28 +1503,21 @@ void GrManagerImpl::finishInternal()
 		}
 	}
 
-	for(PerFrame& frame : m_perFrame)
+	for(MicroFencePtr& fence : m_crntFences)
 	{
-		for(MicroFencePtr& fence : frame.m_fences)
+		if(fence)
 		{
 			const Bool signaled = fence->clientWait(kMaxSecond);
 			if(!signaled)
 			{
 				ANKI_VK_LOGF("Timeout detected");
 			}
+			fence.reset(nullptr);
 		}
-
-		frame.m_fences.destroy();
 	}
 
 	// Since we waited for the GPU do a cleanup as well
-	const U64 oldFrame = m_frame;
-	for(U32 frame = 0; frame < m_perFrame.getSize(); ++frame)
-	{
-		m_frame = frame;
-		deleteObjectsMarkedForDeletion();
-	}
-	m_frame = oldFrame;
+	deleteObjectsMarkedForDeletion();
 }
 
 void GrManagerImpl::trySetVulkanHandleName(CString name, VkObjectType type, U64 handle) const
@@ -1685,6 +1651,85 @@ Error GrManagerImpl::initSurface()
 	return Error::kNone;
 }
 
+void GrManagerImpl::releaseObjectDeleteLoop(GrObject* object)
+{
+	ANKI_ASSERT(object);
+	CleanupGroup* group;
+	if(m_activeCleanupGroup == kMaxU32)
+	{
+		auto it = m_cleanupGroups.emplace();
+		group = &*it;
+		group->m_fences[GpuQueueType::kGeneral] = m_crntFences[GpuQueueType::kGeneral];
+		group->m_fences[GpuQueueType::kCompute] = m_crntFences[GpuQueueType::kCompute];
+		m_activeCleanupGroup = it.getArrayIndex();
+	}
+	else
+	{
+		group = &m_cleanupGroups[m_activeCleanupGroup];
+	}
+
+	ANKI_ASSERT(!group->m_finalized);
+	group->m_objectsMarkedForDeletion.emplaceBack(object);
+}
+
+void GrManagerImpl::deleteObjectsMarkedForDeletion()
+{
+	ANKI_TRACE_FUNCTION();
+
+	// Object cleanup
+	Array<U32, 8> cleanupGroups;
+	U32 cleanupGroupCount = 0;
+
+	for(auto it = m_cleanupGroups.getBegin(); it != m_cleanupGroups.getEnd(); ++it)
+	{
+		if(it.getArrayIndex() != m_activeCleanupGroup && cleanupGroupCount < cleanupGroups.getSize() && it->canDelete())
+		{
+			cleanupGroups[cleanupGroupCount++] = it.getArrayIndex();
+		}
+	}
+
+	for(U32 i = 0; i < cleanupGroupCount; ++i)
+	{
+		const U32 idx = cleanupGroups[i];
+
+		const U32 crntActiveGroup = m_activeCleanupGroup;
+		m_activeCleanupGroup = idx;
+
+		m_cleanupGroups[idx].m_finalized = false;
+
+		while(m_cleanupGroups[idx].m_objectsMarkedForDeletion.getSize())
+		{
+			GrDynamicArray<GrObject*> arr = std::move(m_cleanupGroups[idx].m_objectsMarkedForDeletion);
+
+			for(GrObject* obj : arr)
+			{
+				deleteInstance(GrMemoryPool::getSingleton(), obj);
+			}
+		}
+
+		m_cleanupGroups.erase(idx);
+		m_activeCleanupGroup = crntActiveGroup; // Restore
+	}
+
+	// Acquire cleanup
+	Array<U32, 8> acquireDatas;
+	U32 acquireDataCount = 0;
+
+	for(auto it = m_acquireData.getBegin(); it != m_acquireData.getEnd(); ++it)
+	{
+		if(it.getArrayIndex() != m_activeAcquireDataIdx && acquireDataCount < acquireDatas.getSize() && it->m_fence->signaled())
+		{
+			acquireDatas[acquireDataCount++] = it.getArrayIndex();
+		}
+	}
+
+	for(U32 i = 0; i < acquireDataCount; ++i)
+	{
+		const U32 idx = acquireDatas[i];
+		m_acquireData.erase(idx);
+	}
+}
+
 VkBool32 GrManagerImpl::debugReportCallbackEXT(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
 											   [[maybe_unused]] VkDebugUtilsMessageTypeFlagsEXT messageTypes,
 											   const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, [[maybe_unused]] void* pUserData)

+ 58 - 51
AnKi/Gr/Vulkan/VkGrManager.h

@@ -14,16 +14,13 @@
 
 namespace anki {
 
-/// @note Disable that because it crashes Intel drivers
+// Note: Disable that because it crashes Intel drivers
 #define ANKI_GR_MANAGER_DEBUG_MEMMORY ANKI_EXTRA_CHECKS && 0
 
 // Forward
 class TextureFallbackUploader;
 class MicroCommandBuffer;
 
-/// @addtogroup vulkan
-/// @{
-
 enum class AsyncComputeType
 {
 	kProper,
@@ -31,7 +28,7 @@ enum class AsyncComputeType
 	kDisabled
 };
 
-/// A small struct with all the caps we need.
+// A small struct with all the caps we need.
 class VulkanCapabilities
 {
 public:
@@ -42,7 +39,7 @@ public:
 	U32 m_asBufferAlignment = 256; // Spec says 256
 };
 
-/// Vulkan implementation of GrManager.
+// Vulkan implementation of GrManager.
 class GrManagerImpl : public GrManager
 {
 	friend class GrManager;
@@ -139,54 +136,87 @@ public:
 		ANKI_ASSERT(width && height);
 	}
 
-	/// @name Debug report
-	/// @{
+	// Debug report //
 	void trySetVulkanHandleName(CString name, VkObjectType type, U64 handle) const;
 
 	void trySetVulkanHandleName(CString name, VkObjectType type, void* handle) const
 	{
 		trySetVulkanHandleName(name, type, U64(ptrToNumber(handle)));
 	}
-	/// @}
+	// End debug report //
 
-	/// @note It's thread-safe.
+	// Node: It's thread-safe.
 	void printPipelineShaderInfo(VkPipeline ppline, CString name, U64 hash = 0) const;
 
-	/// @note It's thread-safe.
+	// Node: It's thread-safe.
 	void releaseObject(GrObject* object)
 	{
 		ANKI_ASSERT(object);
 		LockGuard lock(m_globalMtx);
-		m_perFrame[m_frame % m_perFrame.getSize()].m_objectsMarkedForDeletion.emplaceBack(object);
+		releaseObjectDeleteLoop(object);
 	}
 
-	void releaseObjectDeleteLoop(GrObject* object)
-	{
-		ANKI_ASSERT(object);
-		m_perFrame[m_frame % m_perFrame.getSize()].m_objectsMarkedForDeletion.emplaceBack(object);
-	}
+	void releaseObjectDeleteLoop(GrObject* object);
 
 private:
-	enum FrameState : U8
+	// Contains objects that are marked for deletion
+	class CleanupGroup
 	{
-		kFrameStarted,
-		kPresentableAcquired,
-		kPresentableDrawn,
-		kFrameEnded,
+	public:
+		Array<MicroFencePtr, U32(GpuQueueType::kCount)> m_fences;
+		GrDynamicArray<GrObject*> m_objectsMarkedForDeletion;
+		Bool m_finalized = false;
+
+		~CleanupGroup()
+		{
+			ANKI_ASSERT(m_objectsMarkedForDeletion.getSize() == 0);
+		}
+
+		Bool canDelete() const
+		{
+			if(m_fences[GpuQueueType::kGeneral] && !m_fences[GpuQueueType::kGeneral]->signaled())
+			{
+				return false;
+			}
+
+			if(m_fences[GpuQueueType::kCompute] && !m_fences[GpuQueueType::kCompute]->signaled())
+			{
+				return false;
+			}
+
+			return true;
+		}
 	};
 
-	class PerFrame
+	class AcquireData
 	{
 	public:
-		GrDynamicArray<MicroFencePtr> m_fences;
+		MicroSemaphorePtr m_semaphore;
+		MicroFencePtr m_fence; // It's used to check if we can delete the semaphore
 
-		GpuQueueType m_queueWroteToSwapchainImage = GpuQueueType::kCount;
-
-		GrDynamicArray<GrObject*> m_objectsMarkedForDeletion;
+		~AcquireData()
+		{
+			ANKI_ASSERT(!m_fence || m_fence->signaled());
+		}
 	};
 
 	U64 m_frame = 0;
 
+	GrBlockArray<CleanupGroup> m_cleanupGroups;
+	U32 m_activeCleanupGroup = kMaxU32;
+
+	Array<MicroFencePtr, U32(GpuQueueType::kCount) + 1> m_crntFences;
+
+	VkSurfaceKHR m_surface = VK_NULL_HANDLE;
+	U32 m_nativeWindowWidth = 0;
+	U32 m_nativeWindowHeight = 0;
+	MicroSwapchainPtr m_crntSwapchain;
+
+	GrBlockArray<AcquireData> m_acquireData;
+	U32 m_activeAcquireDataIdx = kMaxU32;
+	GpuQueueType m_queueWroteToSwapchainImage = GpuQueueType::kCount;
+	U8 m_acquiredImageIdx = kMaxU8;
+
 #if ANKI_GR_MANAGER_DEBUG_MEMMORY
 	VkAllocationCallbacks m_debugAllocCbs;
 	static constexpr U32 MAX_ALLOC_ALIGNMENT = 64;
@@ -211,17 +241,8 @@ private:
 
 	mutable SpinLock m_shaderStatsMtx;
 
-	VkSurfaceKHR m_surface = VK_NULL_HANDLE;
-	U32 m_nativeWindowWidth = 0;
-	U32 m_nativeWindowHeight = 0;
-	MicroSwapchainPtr m_crntSwapchain;
-	U8 m_acquiredImageIdx = kMaxU8;
-	FrameState m_frameState = kFrameEnded;
-
 	VulkanCapabilities m_caps;
 
-	Array<PerFrame, kMaxFramesInFlight> m_perFrame;
-
 	VkPhysicalDeviceMemoryProperties m_memoryProperties;
 
 	Error initInternal(const GrManagerInitInfo& init);
@@ -261,21 +282,7 @@ private:
 		vkGetPhysicalDeviceFeatures2(m_physicalDevice, &features2);
 	}
 
-	void deleteObjectsMarkedForDeletion()
-	{
-		ANKI_TRACE_FUNCTION();
-		PerFrame& frame = m_perFrame[m_frame % m_perFrame.getSize()];
-		while(!frame.m_objectsMarkedForDeletion.isEmpty())
-		{
-			GrDynamicArray<GrObject*> objects = std::move(frame.m_objectsMarkedForDeletion);
-
-			for(GrObject* obj : objects)
-			{
-				deleteInstance(GrMemoryPool::getSingleton(), obj);
-			}
-		}
-	}
+	void deleteObjectsMarkedForDeletion();
 };
-/// @}
 
 } // end namespace anki

+ 6 - 1
AnKi/Gr/Vulkan/VkSemaphoreFactory.cpp

@@ -6,9 +6,12 @@
 #include <AnKi/Gr/Vulkan/VkSemaphoreFactory.h>
 #include <AnKi/Gr/Vulkan/VkGrManager.h>
 #include <AnKi/Util/Tracer.h>
+#include <AnKi/Core/StatsSet.h>
 
 namespace anki {
 
+ANKI_SVAR(SemaphoreCount, StatCategory::kGr, "Semaphore count", StatFlag::kNone)
+
 MicroSemaphore::MicroSemaphore(Bool isTimeline)
 	: m_isTimeline(isTimeline)
 {
@@ -21,8 +24,9 @@ MicroSemaphore::MicroSemaphore(Bool isTimeline)
 	ci.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
 	ci.pNext = &typeCreateInfo;
 
-	ANKI_TRACE_INC_COUNTER(VkSemaphoreCreate, 1);
 	ANKI_VK_CHECKF(vkCreateSemaphore(getVkDevice(), &ci, nullptr, &m_handle));
+	ANKI_TRACE_INC_COUNTER(VkSemaphoreCreate, 1);
+	g_svarSemaphoreCount.increment(1u);
 }
 
 MicroSemaphore::~MicroSemaphore()
@@ -30,6 +34,7 @@ MicroSemaphore::~MicroSemaphore()
 	if(m_handle)
 	{
 		vkDestroySemaphore(getVkDevice(), m_handle, nullptr);
+		g_svarSemaphoreCount.decrement(1u);
 	}
 }
 

+ 7 - 11
AnKi/Gr/Vulkan/VkSemaphoreFactory.h

@@ -10,10 +10,7 @@
 
 namespace anki {
 
-/// @addtogroup vulkan
-/// @{
-
-/// Simple semaphore wrapper.
+// Simple semaphore wrapper.
 class MicroSemaphore
 {
 	friend class SemaphoreFactory;
@@ -56,16 +53,16 @@ public:
 		return m_isTimeline;
 	}
 
-	/// Get the value of the semaphore after a signal.
-	/// @note It's thread safe.
+	// Get the value of the semaphore after a signal.
+	// Note: It's thread safe.
 	U64 getNextSemaphoreValue()
 	{
 		ANKI_ASSERT(m_isTimeline);
 		return m_timelineValue.fetchAdd(1) + 1;
 	}
 
-	/// Get the value of the semaphore to wait on.
-	/// @note It's thread safe.
+	// Get the value of the semaphore to wait on.
+	// Note: It's thread safe.
 	U64 getSemaphoreValue() const
 	{
 		ANKI_ASSERT(m_isTimeline);
@@ -86,10 +83,10 @@ private:
 	void releaseInternal();
 };
 
-/// MicroSemaphore smart pointer.
+// MicroSemaphore smart pointer.
 using MicroSemaphorePtr = IntrusiveNoDelPtr<MicroSemaphore>;
 
-/// Factory of semaphores.
+// Factory of semaphores.
 class SemaphoreFactory : public MakeSingleton<SemaphoreFactory>
 {
 	friend class MicroSemaphore;
@@ -108,6 +105,5 @@ private:
 	MicroObjectRecycler<MicroSemaphore> m_binaryRecycler;
 	MicroObjectRecycler<MicroSemaphore> m_timelineRecycler;
 };
-/// @}
 
 } // end namespace anki

+ 0 - 2
AnKi/Gr/Vulkan/VkSwapchainFactory.cpp

@@ -211,7 +211,6 @@ Error MicroSwapchain::initInternal()
 		}
 
 		m_textures.resize(count);
-		m_acquireSemaphores.resize(count);
 		m_renderSemaphores.resize(count);
 
 		ANKI_VK_LOGI("Created a swapchain. Image count: %u, present mode: %u, size: %ux%u, vsync: %u", count, presentMode, surfaceWidth,
@@ -234,7 +233,6 @@ Error MicroSwapchain::initInternal()
 			m_textures[i].reset(tex);
 			ANKI_CHECK(tex->initExternal(images[i], init));
 
-			m_acquireSemaphores[i] = SemaphoreFactory::getSingleton().newInstance(false, GrString().sprintf("Acquire #%u", i));
 			m_renderSemaphores[i] = SemaphoreFactory::getSingleton().newInstance(false, GrString().sprintf("Present #%u", i));
 		}
 	}

+ 4 - 9
AnKi/Gr/Vulkan/VkSwapchainFactory.h

@@ -12,10 +12,7 @@
 
 namespace anki {
 
-/// @addtogroup vulkan
-/// @{
-
-/// A wrapper for the swapchain.
+// A wrapper for the swapchain
 class MicroSwapchain
 {
 	friend class MicroSwapchainPtrDeleter;
@@ -25,8 +22,7 @@ public:
 	VkSwapchainKHR m_swapchain = {};
 
 	GrDynamicArray<TextureInternalPtr> m_textures;
-	GrDynamicArray<MicroSemaphorePtr> m_acquireSemaphores;
-	GrDynamicArray<MicroSemaphorePtr> m_renderSemaphores; ///< Signaled by the operation that renders to a presentable image.
+	GrDynamicArray<MicroSemaphorePtr> m_renderSemaphores; // Signaled by the operation that renders to a presentable image
 
 	MicroSwapchain();
 
@@ -58,10 +54,10 @@ private:
 	void releaseInternal();
 };
 
-/// MicroSwapchain smart pointer.
+// MicroSwapchain smart pointer
 using MicroSwapchainPtr = IntrusiveNoDelPtr<MicroSwapchain>;
 
-/// Swapchain factory.
+// Swapchain factory
 class SwapchainFactory : public MakeSingleton<SwapchainFactory>
 {
 	friend class MicroSwapchain;
@@ -83,6 +79,5 @@ private:
 	Bool m_vsync = false;
 	MicroObjectRecycler<MicroSwapchain> m_recycler;
 };
-/// @}
 
 } // end namespace anki

+ 1 - 1
AnKi/Math/Simd.h

@@ -46,7 +46,7 @@ public:
 };
 #endif
 
-// Suffle NEON vector. Code stolen by Jolt
+// Suffle NEON vector. Code stolen from Jolt
 #if ANKI_SIMD_NEON
 
 // Constructing NEON values

+ 3 - 5
Samples/SimpleScene/Main.cpp

@@ -13,12 +13,10 @@ class MyApp : public SampleApp
 public:
 	using SampleApp::SampleApp;
 
-	Error sampleExtraInit()
+	Error userPreInit() final
 	{
-		ScriptResourcePtr script;
-		ANKI_CHECK(ResourceManager::getSingleton().loadResource("Assets/Scene.lua", script));
-		ANKI_CHECK(ScriptManager::getSingleton().evalString(script->getSource()));
-
+		ANKI_CHECK(SampleApp::userPreInit());
+		g_cvarCoreStartupScene = "Assets/Scene.lua";
 		return Error::kNone;
 	}
 };

+ 0 - 47
Sandbox/Main.cpp

@@ -7,9 +7,6 @@
 
 using namespace anki;
 
-#define PLAYER 0
-#define MOUSE 1
-
 class MyApp : public App
 {
 public:
@@ -31,29 +28,12 @@ public:
 
 Error MyApp::userPreInit()
 {
-#if !ANKI_OS_ANDROID
-	if(m_argc < 2)
-	{
-		ANKI_LOGE("usage: %s relative/path/to/scene.lua [anki config options]", m_argv[0]);
-		return Error::kUserData;
-	}
-#endif
-
-	// Config
-#if ANKI_OS_ANDROID
 	ANKI_CHECK(CVarSet::getSingleton().setFromCommandLineArguments(m_argc - 1, m_argv + 1));
-#else
-	ANKI_CHECK(CVarSet::getSingleton().setFromCommandLineArguments(m_argc - 2, m_argv + 2));
-#endif
-
 	return Error::kNone;
 }
 
 Error MyApp::userPostInit()
 {
-	// Other init
-	ResourceManager& resources = ResourceManager::getSingleton();
-
 	if(getenv("PROFILE"))
 	{
 		m_profile = true;
@@ -63,31 +43,6 @@ Error MyApp::userPostInit()
 #endif
 	}
 
-	// Load scene
-	ScriptResourcePtr script;
-#if ANKI_OS_ANDROID
-	ANKI_CHECK(resources.loadResource("Assets/Scene.lua", script));
-#else
-	ANKI_CHECK(resources.loadResource(m_argv[1], script));
-#endif
-	ANKI_CHECK(ScriptManager::getSingleton().evalString(script->getSource()));
-
-	// ANKI_CHECK(renderer.getFinalComposite().loadColorGradingTexture(
-	//	"textures/color_gradient_luts/forge_lut.ankitex"));
-
-#if PLAYER
-	SceneGraph& scene = getSceneGraph();
-	SceneNode& cam = scene.getActiveCameraNode();
-
-	PlayerNode* pnode;
-	ANKI_CHECK(
-		scene.newSceneNode<PlayerNode>("player", pnode, cam.getFirstComponentOfType<MoveComponent>().getLocalOrigin() - Vec4(0.0, 1.0, 0.0, 0.0)));
-
-	cam.getFirstComponentOfType<MoveComponent>().setLocalTransform(Transform(Vec4(0.0, 0.0, 0.0, 0.0), Mat3x4::getIdentity(), 1.0));
-
-	pnode->addChild(&cam);
-#endif
-
 	return Error::kNone;
 }
 
@@ -130,7 +85,6 @@ Error MyApp::userMainLoop(Bool& quit, Second elapsedTime)
 	}
 #endif
 
-#if !PLAYER
 	static Vec2 mousePosOn1stClick = in.getMousePositionNdc();
 	if(in.getMouseButton(MouseButton::kRight) == 1)
 	{
@@ -285,7 +239,6 @@ Error MyApp::userMainLoop(Bool& quit, Second elapsedTime)
 	{
 		in.hideMouseCursor(false);
 	}
-#endif
 
 	if(in.getKey(KeyCode::kY) == 1)
 	{