Browse Source

Removing exceptions

Panagiotis Christopoulos Charitos 11 years ago
parent
commit
02fda0a6c3

+ 15 - 5
include/anki/scene/FrustumComponent.h

@@ -24,6 +24,13 @@ class VisibilityTestResults;
 class FrustumComponent: public SceneComponent
 {
 public:
+	class VisibilityStats
+	{
+	public:
+		U32 m_renderablesCount = 0;
+		U32 m_lightsCount = 0;
+	};
+
 	/// Pass the frustum here so we can avoid the virtuals
 	FrustumComponent(SceneNode* node, Frustum* frustum)
 	:	SceneComponent(Type::FRUSTUM, node), 
@@ -83,11 +90,8 @@ public:
 		return getFrustum().getTransform().getOrigin();
 	}
 
-	void setVisibilityTestResults(VisibilityTestResults* visible)
-	{
-		ANKI_ASSERT(m_visible == nullptr);
-		m_visible = visible;
-	}
+	void setVisibilityTestResults(VisibilityTestResults* visible);
+
 	/// Call this after the tests. Before it will point to junk
 	VisibilityTestResults& getVisibilityTestResults()
 	{
@@ -95,6 +99,11 @@ public:
 		return *m_visible;
 	}
 
+	VisibilityStats getLastVisibilityStats() const
+	{
+		return m_stats;
+	}
+
 	void markForUpdate()
 	{
 		m_markedForUpdate = true;
@@ -151,6 +160,7 @@ private:
 	Mat4 m_pm = Mat4::getIdentity(); ///< Projection matrix
 	Mat4 m_vm = Mat4::getIdentity(); ///< View matrix
 	Mat4 m_vpm = Mat4::getIdentity(); ///< View projection matrix
+	VisibilityStats m_stats;
 
 	/// Visibility stuff. It's per frame so the pointer is invalid on the next 
 	/// frame and before any visibility tests are run

+ 17 - 4
include/anki/scene/SceneGraph.h

@@ -132,25 +132,38 @@ public:
 
 	/// Iterate the scene nodes using a lambda
 	template<typename Func>
-	void iterateSceneNodes(Func func)
+	ANKI_USE_RESULT Error iterateSceneNodes(Func func)
 	{
 		for(SceneNode* psn : m_nodes)
 		{
-			func(*psn);
+			Error err = func(*psn);
+			if(err)
+			{
+				return err;
+			}
 		}
+
+		return ErrorCode::NONE;
 	}
 
 	/// Iterate a range of scene nodes using a lambda
 	template<typename Func>
-	void iterateSceneNodes(PtrSize begin, PtrSize count, Func func)
+	ANKI_USE_RESULT Error iterateSceneNodes(
+		PtrSize begin, PtrSize count, Func func)
 	{
 		ANKI_ASSERT(begin < m_nodes.size() && count <= m_nodes.size());
 		for(auto it = m_nodes.begin() + begin; 
 			it != m_nodes.begin() + count; 
 			it++)
 		{
-			func(*(*it));
+			Error err = func(*(*it));
+			if(err)
+			{
+				return err;
+			}
 		}
+
+		return ErrorCode::NONE;
 	}
 
 	/// Create a new SceneNode

+ 22 - 8
include/anki/scene/Visibility.h

@@ -47,7 +47,8 @@ public:
 	U8* m_spatialIndices = nullptr;
 	U8 m_spatialsCount = 0;
 
-	VisibleNode() = default;
+	VisibleNode()
+	{}
 
 	VisibleNode(VisibleNode&& other)
 	{
@@ -86,7 +87,7 @@ public:
 	}
 
 	ANKI_USE_RESULT Error create(
-		SceneAllocator<U8> alloc,
+		SceneFrameAllocator<U8> alloc,
 		U32 renderablesReservedSize,
 		U32 lightsReservedSize)
 	{
@@ -100,22 +101,33 @@ public:
 
 	VisibleNode* getRenderablesBegin()
 	{
-		return &m_renderables[0];
+		return (m_renderablesCount) ? &m_renderables[0] : nullptr;
 	}
 
 	VisibleNode* getRenderablesEnd()
 	{
-		return &m_renderables[0] + m_renderablesCount;
+		return (m_renderablesCount) 
+			? (&m_renderables[0] + m_renderablesCount) : nullptr;
 	}
 
 	VisibleNode* getLightsBegin()
 	{
-		return &m_lights[0];
+		return (m_lightsCount) ? &m_lights[0] : nullptr;
 	}
 
 	VisibleNode* getLightsEnd()
 	{
-		return &m_lights[0] + m_lightsCount;
+		return (m_lightsCount) ? (&m_lights[0] + m_lightsCount) : nullptr;
+	}
+
+	U32 getRenderablesCount() const
+	{
+		return m_renderablesCount;
+	}
+
+	U32 getLightsCount() const
+	{
+		return m_lightsCount;
 	}
 
 	ANKI_USE_RESULT Error moveBackRenderable(
@@ -180,11 +192,12 @@ public:
 	VisibilityTestResults::Container::iterator m_nodes;
 	Vec4 m_origin;
 
-	void operator()(U32 /*threadId*/, PtrSize /*threadsCount*/)
+	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;
 	}
 };
 
@@ -195,9 +208,10 @@ public:
 	U32 m_nodesCount;
 	VisibilityTestResults::Container::iterator m_nodes;
 
-	void operator()(U32 /*threadId*/, PtrSize /*threadsCount*/)
+	Error operator()(U32 /*threadId*/, PtrSize /*threadsCount*/)
 	{
 		std::sort(m_nodes, m_nodes + m_nodesCount, MaterialSortFunctor());
+		return ErrorCode::NONE;
 	}
 };
 

+ 21 - 1
include/anki/util/Allocator.h

@@ -239,7 +239,27 @@ public:
 	/// Allocate a new array of objects and call their constructor
 	/// @note This is AnKi specific
 	template<typename U>
-	U* newArray(size_type n, const U& v = U())
+	U* newArray(size_type n)
+	{
+		typename rebind<U>::other alloc(*this);
+
+		U* x = alloc.allocate(n);
+		if(x)
+		{
+			// Call the constuctors
+			for(size_type i = 0; i < n; i++)
+			{
+				alloc.construct(&x[i]);
+			}
+		}
+
+		return x;
+	}
+
+	/// Allocate a new array of objects and call their constructor
+	/// @note This is AnKi specific
+	template<typename U>
+	U* newArray(size_type n, const U& v)
 	{
 		typename rebind<U>::other alloc(*this);
 

+ 25 - 2
include/anki/util/DArray.h

@@ -155,8 +155,31 @@ public:
 	}
 
 	/// Create the array.
-	ANKI_USE_RESULT Error create(Allocator alloc, PtrSize size, 
-		const Value& v = Value())
+	ANKI_USE_RESULT Error create(Allocator alloc, PtrSize size)
+	{
+		ANKI_ASSERT(m_data == nullptr && m_size == 0);
+		Error err = ErrorCode::NONE;
+
+		destroy(alloc);
+
+		if(size > 0)
+		{
+			m_data = alloc.template newArray<Value>(size);
+			if(m_data)
+			{
+				m_size = size;
+			}
+			else
+			{
+				err = ErrorCode::OUT_OF_MEMORY;
+			}
+		}
+
+		return err;
+	}
+
+	/// Create the array.
+	ANKI_USE_RESULT Error create(Allocator alloc, PtrSize size, const Value& v)
 	{
 		ANKI_ASSERT(m_data == nullptr && m_size == 0);
 		Error err = ErrorCode::NONE;

+ 21 - 0
src/scene/FrustumComponent.cpp

@@ -0,0 +1,21 @@
+// Copyright (C) 2014, Panagiotis Christopoulos Charitos.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include "anki/scene/FrustumComponent.h"
+#include "anki/scene/Visibility.h"
+
+namespace anki {
+
+//==============================================================================
+void FrustumComponentsetVisibilityTestResults(VisibilityTestResults* visible)
+{
+	ANKI_ASSERT(m_visible == nullptr);
+	m_visible = visible;
+
+	m_stats.m_renderablesCount = visible->getRenderablesCount();
+	m_stats.m_lightsCount = visible->getLightsCount();
+}
+
+} // end namespace anki

+ 195 - 132
src/scene/Visibility.cpp

@@ -12,154 +12,200 @@
 
 namespace anki {
 
+//==============================================================================
+// VisibilityTestTask                                                          =
+//==============================================================================
+
 //==============================================================================
 class VisibilityTestTask: public Threadpool::Task
 {
 public:
 	U m_nodesCount = 0;
 	SceneGraph* m_scene = nullptr;
-	SceneNode* frustumableSn = nullptr;
+	SceneNode* m_frustumableSn = nullptr;
 	SceneFrameAllocator<U8> m_alloc;
 
 	VisibilityTestResults* m_cameraVisible; // out
 
 	/// Test a frustum component
 	ANKI_USE_RESULT Error test(SceneNode& testedNode, Bool isLight, 
-		U32 threadId, PtrSize threadsCount)
+		U32 threadId, PtrSize threadsCount);
+
+	/// Do the tests
+	Error operator()(U32 threadId, PtrSize threadsCount)
 	{
-		ANKI_ASSERT(isLight == 
-			(testedNode.tryGetComponent<LightComponent>() != nullptr));
+		return test(*m_frustumableSn, false, threadId, threadsCount);
+	}
+};
+
+//==============================================================================
+Error VisibilityTestTask::test(SceneNode& testedNode, Bool isLight, 
+	U32 threadId, PtrSize threadsCount)
+{
+	ANKI_ASSERT(isLight == 
+		(testedNode.tryGetComponent<LightComponent>() != nullptr));
 
-		VisibilityTestResults* visible = 
-			frameAlloc.newInstance<VisibilityTestResults>(frameAlloc);
+	Error err = ErrorCode::NONE;
 
-		FrustumComponent& testedFr = 
-			testedNode.getComponent<FrustumComponent>();
+	FrustumComponent& testedFr = 
+		testedNode.getComponent<FrustumComponent>();
 
-		// Chose the test range and a few other things
-		PtrSize start, end;
-		if(!isLight)
-		{
-			choseStartEnd(threadId, threadsCount, m_nodesCount, start, end);
-			cameraVisible = visible;
-		}
-		else
+	// Allocate visible
+	VisibilityTestResults* visible = 
+		m_alloc.newInstance<VisibilityTestResults>();
+
+	if(visible == nullptr)
+	{
+		return ErrorCode::OUT_OF_MEMORY;
+	}
+
+	// Init visible
+	FrustumComponent::VisibilityStats stats = testedFr.getLastVisibilityStats();
+	
+	if(!isLight)
+	{
+		// For camera be conservative
+		stats.m_renderablesCount /= threadsCount;
+		stats.m_lightsCount /= threadsCount;
+	}
+
+	err = visible->create(
+		m_alloc, stats.m_renderablesCount, stats.m_lightsCount);
+	if(err)
+	{
+		return err;
+	}
+
+	// Chose the test range and a few other things
+	PtrSize start, end;
+	if(!isLight)
+	{
+		choseStartEnd(threadId, threadsCount, m_nodesCount, start, end);
+		m_cameraVisible = visible;
+	}
+	else
+	{
+		// Is light
+		start = 0;
+		end = m_nodesCount;
+		testedFr.setVisibilityTestResults(visible);
+	}
+
+	// Iterate range of nodes
+	err = m_scene->iterateSceneNodes(start, end, [&](SceneNode& node) -> Error
+	{
+		Error err = ErrorCode::NONE;
+
+		FrustumComponent* fr = node.tryGetComponent<FrustumComponent>();
+
+		// Skip if it is the same
+		if(ANKI_UNLIKELY(&testedFr == fr))
 		{
-			// Is light
-			start = 0;
-			end = m_nodesCount;
-			testedFr.setVisibilityTestResults(visible);
+			return ErrorCode::NONE;
 		}
 
-		// Iterate range of nodes
-		m_scene->iterateSceneNodes(start, end, [&](SceneNode& node)
-		{
-			FrustumComponent* fr = node.tryGetComponent<FrustumComponent>();
+		VisibleNode visibleNode;
+		visibleNode.m_node = &node;
 
-			// Skip if it is the same
-			if(ANKI_UNLIKELY(&testedFr == fr))
+		// Test all spatial components of that node
+		struct SpatialTemp
+		{
+			SpatialComponent* m_sp;
+			U8 m_idx;
+		};
+		Array<SpatialTemp, ANKI_GL_MAX_SUB_DRAWCALLS> sps;
+
+		U spIdx = 0;
+		U count = 0;
+		err = node.iterateComponentsOfType<SpatialComponent>(
+			[&](SpatialComponent& sp)
+		{
+			if(testedFr.insideFrustum(sp))
 			{
-				return;
+				// Inside
+				ANKI_ASSERT(spIdx < MAX_U8);
+				sps[count++] = SpatialTemp{&sp, static_cast<U8>(spIdx)};
+
+				sp.enableBits(isLight 
+					? SpatialComponent::Flag::VISIBLE_LIGHT 
+					: SpatialComponent::Flag::VISIBLE_CAMERA);
 			}
 
-			VisibleNode visibleNode;
-			visibleNode.m_node = &node;
+			++spIdx;
 
-			// Test all spatial components of that node
-			struct SpatialTemp
-			{
-				SpatialComponent* m_sp;
-				U8 m_idx;
-			};
-			Array<SpatialTemp, ANKI_GL_MAX_SUB_DRAWCALLS> sps;
-
-			U spIdx = 0;
-			U count = 0;
-			node.iterateComponentsOfType<SpatialComponent>(
-				[&](SpatialComponent& sp)
-			{
-				if(testedFr.insideFrustum(sp))
-				{
-					// Inside
-					ANKI_ASSERT(spIdx < MAX_U8);
-					sps[count++] = SpatialTemp{&sp, static_cast<U8>(spIdx)};
+			return ErrorCode::NONE;
+		});
 
-					sp.enableBits(isLight 
-						? SpatialComponent::Flag::VISIBLE_LIGHT 
-						: SpatialComponent::Flag::VISIBLE_CAMERA);
-				}
+		if(count == 0)
+		{
+			return err;
+		}
 
-				++spIdx;
-			});
+		// Sort spatials
+		Vec4 origin = testedFr.getFrustumOrigin();
+		std::sort(sps.begin(), sps.begin() + count, 
+			[origin](const SpatialTemp& a, const SpatialTemp& b) -> Bool
+		{
+			Vec4 spa = a.m_sp->getSpatialOrigin();
+			Vec4 spb = b.m_sp->getSpatialOrigin();
 
-			if(count == 0)
-			{
-				return;
-			}
+			F32 dist0 = origin.getDistanceSquared(spa);
+			F32 dist1 = origin.getDistanceSquared(spb);
 
-			// Sort spatials
-			Vec4 origin = testedFr.getFrustumOrigin();
-			std::sort(sps.begin(), sps.begin() + count, 
-				[origin](const SpatialTemp& a, const SpatialTemp& b) -> Bool
-			{
-				Vec4 spa = a.m_sp->getSpatialOrigin();
-				Vec4 spb = b.m_sp->getSpatialOrigin();
+			return dist0 < dist1;
+		});
 
-				F32 dist0 = origin.getDistanceSquared(spa);
-				F32 dist1 = origin.getDistanceSquared(spb);
+		// Update the visibleNode
+		ANKI_ASSERT(count < MAX_U8);
+		visibleNode.m_spatialsCount = count;
+		visibleNode.m_spatialIndices = m_alloc.newArray<U8>(count);
+		if(visibleNode.m_spatialIndices == nullptr)
+		{
+			return ErrorCode::OUT_OF_MEMORY;
+		}
 
-				return dist0 < dist1;
-			});
+		for(U i = 0; i < count; i++)
+		{
+			visibleNode.m_spatialIndices[i] = sps[i].m_idx;
+		}
 
-			// Update the visibleNode
-			ANKI_ASSERT(count < MAX_U8);
-			visibleNode.m_spatialsCount = count;
-			visibleNode.m_spatialIndices = frameAlloc.newArray<U8>(count);
-			for(U i = 0; i < count; i++)
+		// Do something with the result
+		RenderComponent* r = node.tryGetComponent<RenderComponent>();
+		if(isLight)
+		{
+			if(r && r->getCastsShadow())
 			{
-				visibleNode.m_spatialIndices[i] = sps[i].m_idx;
+				err = visible->moveBackRenderable(m_alloc, visibleNode);
 			}
-
-			// Do something with the result
-			RenderComponent* r = node.tryGetComponent<RenderComponent>();
-			if(isLight)
+		}
+		else
+		{
+			if(r)
 			{
-				if(r && r->getCastsShadow())
-				{
-					visible->m_renderables.emplace_back(std::move(visibleNode));
-				}
+				err = visible->moveBackRenderable(m_alloc, visibleNode);
 			}
 			else
 			{
-				if(r)
+				LightComponent* l = node.tryGetComponent<LightComponent>();
+				if(l)
 				{
-					visible->m_renderables.emplace_back(std::move(visibleNode));
-				}
-				else
-				{
-					LightComponent* l = node.tryGetComponent<LightComponent>();
-					if(l)
-					{
-						Light* light = staticCastPtr<Light*>(&node);
+					Light* light = staticCastPtr<Light*>(&node);
 
-						visible->m_lights.emplace_back(std::move(visibleNode));
+					err = visible->moveBackLight(m_alloc, visibleNode);
 
-						if(light->getShadowEnabled() && fr)
-						{
-							test(node, true, 0, 0);
-						}
+					if(!err && light->getShadowEnabled() && fr)
+					{
+						err = test(node, true, 0, 0);
 					}
 				}
 			}
-		}); // end for
-	}
+		}
 
-	/// Do the tests
-	Error operator()(U32 threadId, PtrSize threadsCount)
-	{
-		return test(*frustumableSn, false, threadId, threadsCount);
-	}
-};
+		return err;
+	}); // end for
+
+	return err;
+}
 
 //==============================================================================
 Error VisibilityTestResults::moveBack(
@@ -182,8 +228,7 @@ Error VisibilityTestResults::moveBack(
 }
 
 //==============================================================================
-Error doVisibilityTests(SceneNode& fsn, SceneGraph& scene, 
-	Renderer& r)
+Error doVisibilityTests(SceneNode& fsn, SceneGraph& scene, Renderer& r)
 {
 	FrustumComponent& fr = fsn.getComponent<FrustumComponent>();
 
@@ -196,13 +241,17 @@ Error doVisibilityTests(SceneNode& fsn, SceneGraph& scene,
 	{
 		jobs[i].m_nodesCount = scene.getSceneNodesCount();
 		jobs[i].m_scene = &scene;
-		jobs[i].frustumableSn = &fsn;
-		jobs[i].frameAlloc = scene.getFrameAllocator();
+		jobs[i].m_frustumableSn = &fsn;
+		jobs[i].m_alloc = scene.getFrameAllocator();
 
 		threadPool.assignNewTask(i, &jobs[i]);
 	}
 
-	threadPool.waitForAllThreadsToFinish();
+	Error err = threadPool.waitForAllThreadsToFinish();
+	if(err)
+	{
+		return err;
+	}
 
 	//
 	// Combine results
@@ -214,48 +263,60 @@ Error doVisibilityTests(SceneNode& fsn, SceneGraph& scene,
 	U32 lightsSize = 0;
 	for(U i = 0; i < threadPool.getThreadsCount(); i++)
 	{
-		renderablesSize += jobs[i].cameraVisible->m_renderables.size();
-		lightsSize += jobs[i].cameraVisible->m_lights.size();
+		renderablesSize += jobs[i].m_cameraVisible->getRenderablesCount();
+		lightsSize += jobs[i].m_cameraVisible->getLightsCount();
 	}
 
 	// Allocate
 	VisibilityTestResults* visible = 
-		scene.getFrameAllocator().newInstance<VisibilityTestResults>(
+		scene.getFrameAllocator().newInstance<VisibilityTestResults>();
+
+	if(visible == nullptr)
+	{
+		return ErrorCode::OUT_OF_MEMORY;
+	}
+
+	err = visible->create(
 		scene.getFrameAllocator(), 
 		renderablesSize, 
 		lightsSize);
 
+	if(err)
+	{
+		return err;
+	}
+
 	if(renderablesSize == 0)
 	{
 		ANKI_LOGW("No visible renderables");
 	}
 
-	visible->m_renderables.resize(renderablesSize);
-	visible->m_lights.resize(lightsSize);
-
 	// Append thread results
-	renderablesSize = 0;
-	lightsSize = 0;
+	VisibleNode* renderables = visible->getRenderablesBegin();
+	VisibleNode* lights = visible->getLightsBegin();
 	for(U i = 0; i < threadPool.getThreadsCount(); i++)
 	{
-		const VisibilityTestResults& from = *jobs[i].cameraVisible;
+		VisibilityTestResults& from = *jobs[i].m_cameraVisible;
+
+		U rCount = from.getRenderablesCount();
+		U lCount = from.getLightsCount();
 
-		if(from.m_renderables.size() > 0)
+		if(rCount > 0)
 		{
-			memcpy(&visible->m_renderables[renderablesSize],
-				&from.m_renderables[0],
-				sizeof(VisibleNode) * from.m_renderables.size());
+			memcpy(renderables,
+				from.getRenderablesBegin(),
+				sizeof(VisibleNode) * rCount);
 
-			renderablesSize += from.m_renderables.size();
+			renderables += rCount;
 		}
 
-		if(from.m_lights.size() > 0)
+		if(lCount > 0)
 		{
-			memcpy(&visible->m_lights[lightsSize],
-				&from.m_lights[0],
-				sizeof(VisibleNode) * from.m_lights.size());
+			memcpy(lights,
+				from.getLightsBegin(),
+				sizeof(VisibleNode) * lCount);
 
-			lightsSize += from.m_lights.size();
+			lights += lCount;
 		}
 	}
 
@@ -268,8 +329,8 @@ Error doVisibilityTests(SceneNode& fsn, SceneGraph& scene,
 
 	// The lights
 	DistanceSortJob dsjob;
-	dsjob.m_nodes = visible->m_lights.begin();
-	dsjob.m_nodesCount = visible->m_lights.size();
+	dsjob.m_nodes = visible->getLightsBegin();
+	dsjob.m_nodesCount = visible->getLightsCount();
 	dsjob.m_origin = fr.getFrustumOrigin();
 	threadPool.assignNewTask(0, &dsjob);
 
@@ -283,9 +344,11 @@ Error doVisibilityTests(SceneNode& fsn, SceneGraph& scene,
 	DistanceSortFunctor dsfunc;
 	dsfunc.m_origin = fr.getFrustumOrigin();
 	std::sort(
-		visible->m_renderables.begin(), visible->m_renderables.end(), dsfunc);
+		visible->getRenderablesBegin(), visible->getRenderablesEnd(), dsfunc);
 
-	threadPool.waitForAllThreadsToFinish();
+	err = threadPool.waitForAllThreadsToFinish();
+
+	return err;
 }
 
 } // end namespace anki