Browse Source

Visibility work. COMPILES

Panagiotis Christopoulos Charitos 10 years ago
parent
commit
9d2fddabd5

+ 0 - 1
include/anki/scene/InstanceNode.h

@@ -55,7 +55,6 @@ public:
 		return err;
 	}
 };
-
 /// @}
 
 } // end namespace anki

+ 8 - 0
include/anki/scene/SceneGraph.h

@@ -24,6 +24,7 @@ class Renderer;
 class ResourceManager;
 class Camera;
 class Input;
+class SectorGroup;
 
 /// @addtogroup scene
 /// @{
@@ -181,6 +182,12 @@ public:
 		ANKI_ASSERT(m_input);
 		return *m_input;
 	}
+
+	SectorGroup& getSectorGroup()
+	{
+		ANKI_ASSERT(m_sectors);
+		return *m_sectors;
+	}
 	/// @}
 
 private:
@@ -207,6 +214,7 @@ private:
 	Timestamp m_activeCameraChangeTimestamp = getGlobalTimestamp();
 
 	EventManager m_events;
+	SectorGroup* m_sectors;
 
 	Atomic<U32> m_objectsMarkedForDeletionCount;
 

+ 1 - 1
include/anki/scene/Sector.h

@@ -18,7 +18,7 @@ class Sector;
 class SectorGroup;
 class FrustumComponent;
 
-/// @addtogroup Scene
+/// @addtogroup scene
 /// @{
 
 /// 2 way Portal

+ 1 - 65
include/anki/scene/Visibility.h

@@ -18,7 +18,7 @@ namespace anki {
 // Forward
 class Renderer;
 
-/// @addtogroup Scene
+/// @addtogroup scene
 /// @{
 
 /// Visibility test type
@@ -173,75 +173,11 @@ private:
 		Container& c, U32& count, VisibleNode& x);
 };
 
-/// Sort spatial scene nodes on distance
-class DistanceSortFunctor
-{
-public:
-	Vec4 m_origin;
-
-	Bool operator()(const VisibleNode& a, const VisibleNode& b)
-	{
-		ANKI_ASSERT(a.m_node && b.m_node);
-
-		F32 dist0 = m_origin.getDistanceSquared(
-			a.m_node->getComponent<SpatialComponent>().getSpatialOrigin());
-		F32 dist1 = m_origin.getDistanceSquared(
-			b.m_node->getComponent<SpatialComponent>().getSpatialOrigin());
-
-		return dist0 < dist1;
-	}
-};
-
-/// Sort renderable scene nodes on material
-class MaterialSortFunctor
-{
-public:
-	Bool operator()(const VisibleNode& a, const VisibleNode& b)
-	{
-		ANKI_ASSERT(a.m_node && b.m_node);
-
-		return a.m_node->getComponent<RenderComponent>().getMaterial()
-			< b.m_node->getComponent<RenderComponent>().getMaterial();
-	}
-};
-
-/// Thread job to short scene nodes by distance
-class DistanceSortJob: public Threadpool::Task					
-{
-public:
-	U32 m_nodesCount;
-	VisibilityTestResults::Container::Iterator m_nodes;
-	Vec4 m_origin;
-
-	Error operator()(U32 /*threadId*/, PtrSize /*threadsCount*/)
-	{
-		DistanceSortFunctor comp;
-		comp.m_origin = m_origin;
-		std::sort(m_nodes, m_nodes + m_nodesCount, comp);
-		return ErrorCode::NONE;
-	}
-};
-
-/// Thread job to short renderable scene nodes by material
-class MaterialSortJob: public Threadpool::Task
-{
-public:
-	U32 m_nodesCount;
-	VisibilityTestResults::Container::Iterator m_nodes;
-
-	Error operator()(U32 /*threadId*/, PtrSize /*threadsCount*/)
-	{
-		std::sort(m_nodes, m_nodes + m_nodesCount, MaterialSortFunctor());
-		return ErrorCode::NONE;
-	}
-};
-
 /// Do visibility tests bypassing portals 
 ANKI_USE_RESULT Error doVisibilityTests(
 	SceneNode& frustumable, 
 	SceneGraph& scene, 
 	Renderer& renderer);
-
 /// @}
 
 } // end namespace anki

+ 88 - 70
src/scene/Visibility.cpp

@@ -14,30 +14,65 @@
 namespace anki {
 
 //==============================================================================
-// VisibilityTestTask                                                          =
+// Misc                                                                        =
 //==============================================================================
 
-struct ThreadLocal
+/// Sort spatial scene nodes on distance
+class DistanceSortFunctor
 {
-	VisibilityTestResults* m_testResults = nullptr;
+public:
+	Vec4 m_origin;
+
+	Bool operator()(const VisibleNode& a, const VisibleNode& b)
+	{
+		ANKI_ASSERT(a.m_node && b.m_node);
+
+		F32 dist0 = m_origin.getDistanceSquared(
+			a.m_node->getComponent<SpatialComponent>().getSpatialOrigin());
+		F32 dist1 = m_origin.getDistanceSquared(
+			b.m_node->getComponent<SpatialComponent>().getSpatialOrigin());
+
+		return dist0 < dist1;
+	}
 };
 
-struct ThreadCommon
+/// Sort renderable scene nodes on material
+class MaterialSortFunctor
 {
-	Array<ThreadLocal, Threadpool::MAX_THREADS> m_threadLocal;
+public:
+	Bool operator()(const VisibleNode& a, const VisibleNode& b)
+	{
+		ANKI_ASSERT(a.m_node && b.m_node);
+
+		return a.m_node->getComponent<RenderComponent>().getMaterial()
+			< b.m_node->getComponent<RenderComponent>().getMaterial();
+	}
+};
+
+/// Data common for all tasks.
+class VisibilityShared
+{
+public:
+	SceneGraph* m_scene = nullptr;
 	Barrier m_barrier;
-	List<SceneNode*> m_frustumsList;
+	List<SceneNode*> m_frustumsList; ///< Nodes to test
 	SpinLock m_lock;
-}
 
+	// Data per thread but that can be accessed by all threads
+	Array<VisibilityTestResults*, Threadpool::MAX_THREADS> m_testResults;
+
+	VisibilityShared(U threadCount)
+	:	m_barrier(threadCount)
+	{
+		memset(&m_testResults[0], 0, sizeof(m_testResults));
+	}
+};
+
+/// Task.
 class VisibilityTestTask: public Threadpool::Task
 {
 public:
-	SceneGraph* m_scene = nullptr;
-	SceneNode* m_frustumableSn = nullptr;
-	SceneFrameAllocator<U8> m_alloc;
-
-	ThreadsLocal* m_threadLocal;
+	VisibilityShared* m_shared;
 
 	/// Test a frustum component
 	ANKI_USE_RESULT Error test(SceneNode& testedNode,
@@ -50,32 +85,24 @@ public:
 	/// Do the tests
 	Error operator()(U32 threadId, PtrSize threadsCount)
 	{
-		// Run once
-		ANKI_CHECK(test(*m_frustumableSn, threadId, threadsCount));
+		auto& list = m_shared->m_frustumsList;
+		auto alloc = m_shared->m_scene->getFrameAllocator();
 
-		// Rucurse the extra frustumables
-		while(!m_frustumsList.isEmpty())
+		// Iterate the nodes to check against
+		while(!list.isEmpty())
 		{
-			printf("%d: going deeper\n", threadId);
-
-			// Get front
-			SceneNode* node = m_frustumsList.getFront();
+			// Get front and pop it
+			SceneNode* node = list.getFront();
 			ANKI_ASSERT(node);
 
-			m_barrier->wait();
-
-			ANKI_CHECK(test(*node, threadId, threadsCount));
-
-			// Pop
+			m_shared->m_barrier.wait();
 			if(threadId == 0)
 			{
-				m_frustumsList.popFront(m_alloc);
+				list.popFront(alloc);
 			}
-		}
 
-		if(threadId == 0)
-		{
-			m_frustumsList.destroy(m_alloc);
+			m_shared->m_barrier.wait();
+			ANKI_CHECK(test(*node, threadId, threadsCount));
 		}
 
 		return ErrorCode::NONE;
@@ -91,23 +118,28 @@ Error VisibilityTestTask::test(SceneNode& testedNode,
 	FrustumComponent& testedFr = 
 		testedNode.getComponent<FrustumComponent>();
 	Bool testedNodeShadowCaster = testedFr.getShadowCaster();
+	auto alloc = m_shared->m_scene->getFrameAllocator();
 
 	// Init test results
-	VisibilityTestResults* visible = 
-		m_alloc.newInstance<VisibilityTestResults>();
+	VisibilityTestResults* visible = alloc.newInstance<VisibilityTestResults>();
 
 	FrustumComponent::VisibilityStats stats = testedFr.getLastVisibilityStats();
 
 	ANKI_CHECK(visible->create(
-		m_alloc, stats.m_renderablesCount, stats.m_lightsCount, 4));
+		alloc, stats.m_renderablesCount, stats.m_lightsCount, 4));
+
+	m_shared->m_testResults[threadId] = visible;
+
+	List<SceneNode*> frustumsList;
 
 	// Chose the test range and a few other things
 	PtrSize start, end;
-	U nodesCount = m_scene->getSceneNodesCount();
+	U nodesCount = m_shared->m_scene->getSceneNodesCount();
 	choseStartEnd(threadId, threadsCount, nodesCount, start, end);
 
 	// Iterate range of nodes
-	err = m_scene->iterateSceneNodes(start, end, [&](SceneNode& node) -> Error
+	err = m_shared->m_scene->iterateSceneNodes(
+		start, end, [&](SceneNode& node) -> Error
 	{
 		Error err = ErrorCode::NONE;
 
@@ -173,7 +205,7 @@ Error VisibilityTestTask::test(SceneNode& testedNode,
 		// Update the visibleNode
 		ANKI_ASSERT(count < MAX_U8);
 		visibleNode.m_spatialsCount = count;
-		visibleNode.m_spatialIndices = m_alloc.newArray<U8>(count);
+		visibleNode.m_spatialIndices = alloc.newArray<U8>(count);
 		if(ANKI_UNLIKELY(visibleNode.m_spatialIndices == nullptr))
 		{
 			return ErrorCode::OUT_OF_MEMORY;
@@ -190,32 +222,32 @@ Error VisibilityTestTask::test(SceneNode& testedNode,
 		{
 			if(r && r->getCastsShadow())
 			{
-				err = visible->moveBackRenderable(m_alloc, visibleNode);
+				err = visible->moveBackRenderable(alloc, visibleNode);
 			}
 		}
 		else
 		{
 			if(r)
 			{
-				err = visible->moveBackRenderable(m_alloc, visibleNode);
+				err = visible->moveBackRenderable(alloc, visibleNode);
 			}
 
 			LightComponent* l = node.tryGetComponent<LightComponent>();
 			if(!err && l)
 			{
-				err = visible->moveBackLight(m_alloc, visibleNode);
+				err = visible->moveBackLight(alloc, visibleNode);
 
 				if(!err && l->getShadowEnabled() && fr)
 				{
-					LockGuard<SpinLock> l(m_lock);
-					err = m_frustumsList.pushBack(m_alloc, &node);
+					LockGuard<SpinLock> l(m_shared->m_lock);
+					err = m_shared->m_frustumsList.pushBack(alloc, &node);
 				}
 			}
 
 			LensFlareComponent* lf = node.tryGetComponent<LensFlareComponent>();
 			if(!err && lf)
 			{
-				err = visible->moveBackLensFlare(m_alloc, visibleNode);
+				err = visible->moveBackLensFlare(alloc, visibleNode);
 				ANKI_ASSERT(visibleNode.m_node);
 			}
 		}
@@ -225,24 +257,13 @@ Error VisibilityTestTask::test(SceneNode& testedNode,
 
 	ANKI_CHECK(err);
 
-	m_threadLocal[threadId].m_testResults = visible;
-	printf("%d: assigning %p\n", threadId, (void*)visible);
-
 	// Gather the results from all threads
-	m_barrier->wait();
-
-	//printf("%d: checking what is assigned %p\n", threadId, 
-	//		(void*)m_threadLocal[threadId].m_testResults);
-
-	printf("%d: checking what is assigned to 0 %p\n", threadId, 
-			(void*)m_threadLocal[0].m_testResults);
+	m_shared->m_barrier.wait();
 	
 	if(threadId == 0)
 	{
-		printf("%d: combine\n", threadId);
 		ANKI_CHECK(combineTestResults(testedFr, threadsCount));
 	}
-	m_barrier->wait();
 
 	return err;
 }
@@ -252,6 +273,8 @@ ANKI_USE_RESULT Error VisibilityTestTask::combineTestResults(
 	FrustumComponent& frc,
 	PtrSize threadsCount)
 {
+	auto alloc = m_shared->m_scene->getFrameAllocator();
+
 	// Count the visible scene nodes to optimize the allocation of the 
 	// final result
 	U32 renderablesSize = 0;
@@ -259,8 +282,7 @@ ANKI_USE_RESULT Error VisibilityTestTask::combineTestResults(
 	U32 lensFlaresSize = 0;
 	for(U i = 0; i < threadsCount; i++)
 	{
-		ANKI_ASSERT(m_threadLocal[i].m_testResults);
-		VisibilityTestResults& rez = *m_threadLocal[i].m_testResults;
+		VisibilityTestResults& rez = *m_shared->m_testResults[i];
 
 		renderablesSize += rez.getRenderablesCount();
 		lightsSize += rez.getLightsCount();
@@ -268,8 +290,7 @@ ANKI_USE_RESULT Error VisibilityTestTask::combineTestResults(
 	}
 
 	// Allocate
-	VisibilityTestResults* visible = 
-		m_alloc.newInstance<VisibilityTestResults>();
+	VisibilityTestResults* visible = alloc.newInstance<VisibilityTestResults>();
 	if(visible == nullptr)
 	{
 		return ErrorCode::OUT_OF_MEMORY;
@@ -277,7 +298,7 @@ ANKI_USE_RESULT Error VisibilityTestTask::combineTestResults(
 
 	ANKI_CHECK(
 		visible->create(
-		m_alloc, 
+		alloc, 
 		renderablesSize, 
 		lightsSize,
 		lensFlaresSize));
@@ -295,7 +316,7 @@ ANKI_USE_RESULT Error VisibilityTestTask::combineTestResults(
 	VisibleNode* lensFlares = visible->getLensFlaresBegin();
 	for(U i = 0; i < threadsCount; i++)
 	{
-		VisibilityTestResults& from = *m_threadLocal[i].m_testResults;
+		VisibilityTestResults& from = *m_shared->m_testResults[i];
 
 		U rCount = from.getRenderablesCount();
 		U lCount = from.getLightsCount();
@@ -400,19 +421,16 @@ Error doVisibilityTests(SceneNode& fsn, SceneGraph& scene, Renderer& r)
 {
 	// Do the tests in parallel
 	Threadpool& threadPool = scene._getThreadpool();
-	Barrier barrier(threadPool.getThreadsCount());
-	ThreadsLocal tlocal;
+	
+	VisibilityShared shared(threadPool.getThreadsCount());
+	shared.m_scene = &scene;
+	ANKI_CHECK(shared.m_frustumsList.pushBack(scene.getFrameAllocator(), &fsn));
 
-	Array<VisibilityTestTask, Threadpool::MAX_THREADS> jobs;
+	Array<VisibilityTestTask, Threadpool::MAX_THREADS> tasks;
 	for(U i = 0; i < threadPool.getThreadsCount(); i++)
 	{
-		jobs[i].m_scene = &scene;
-		jobs[i].m_frustumableSn = &fsn;
-		jobs[i].m_alloc = scene.getFrameAllocator();
-		jobs[i].m_barrier = &barrier;
-		jobs[i].m_threadLocal = &tlocal;
-
-		threadPool.assignNewTask(i, &jobs[i]);
+		tasks[i].m_shared = &shared;
+		threadPool.assignNewTask(i, &tasks[i]);
 	}
 	
 	return threadPool.waitForAllThreadsToFinish();