Преглед на файлове

Multidraw is working. MS seems faster, visibility tests much slower. Need to balance

Panagiotis Christopoulos Charitos преди 13 години
родител
ревизия
a831cdda6f

+ 1 - 1
include/anki/collision/CollisionShape.h

@@ -90,7 +90,7 @@ public:
 	virtual void transform(const Transform& trf) = 0;
 
 	/// Get the AABB
-	virtual void toAabb(Aabb&) const = 0;
+	void toAabb(Aabb&) const;
 
 	/// Visitor accept
 	virtual void accept(MutableVisitor&) = 0;

+ 4 - 1
include/anki/collision/Frustum.h

@@ -93,7 +93,7 @@ public:
 	}
 
 	/// Check if a collision shape @a b is inside the frustum
-	bool insideFrustum(const CollisionShape& b) const;
+	Bool insideFrustum(const CollisionShape& b) const;
 
 	/// Calculate the projection matrix
 	virtual Mat4 calculateProjectionMatrix() const = 0;
@@ -102,6 +102,9 @@ public:
 	/// the @a trf, it just replaces it
 	virtual void setTransform(const Transform& trf) = 0;
 
+	/// Implements CollisionShape::toAbb
+	void toAabb(Aabb& aabb) const;
+
 protected:
 	/// @name Viewing variables
 	/// @{

+ 14 - 0
include/anki/renderer/Common.h

@@ -0,0 +1,14 @@
+#ifndef ANKI_RENDERER_COMMON_H
+#define ANKI_RENDERER_COMMON_H
+
+/// @addtogroup config
+/// @{
+/// @addtogroup renderer_config
+/// @{
+
+#define ANKI_CFG_RENDERER_PROFILE 1
+
+/// @}
+/// @}
+
+#endif

+ 8 - 0
include/anki/renderer/Renderer.h

@@ -6,7 +6,9 @@
 #include "anki/resource/ShaderProgramResource.h"
 #include "anki/resource/Resource.h"
 #include "anki/gl/Gl.h"
+#include "anki/util/HighRezTimer.h"
 
+#include "anki/renderer/Common.h"
 #include "anki/renderer/Ms.h"
 #include "anki/renderer/Is.h"
 #include "anki/renderer/Pps.h"
@@ -284,6 +286,8 @@ public:
 	/// skipped
 	void clearAfterBindingFbo(const GLenum cap);
 
+	void printProfileInfo() const;
+
 protected:
 	/// @name Rendering stages
 	/// @{
@@ -329,6 +333,10 @@ private:
 	Vbo quadVertIndecesVbo; ///< The VBO for quad array buffer elements
 	Vao quadVao; ///< This VAO is used everywhere except material stage
 	/// @}
+
+#if ANKI_CFG_RENDERER_PROFILE
+	HighRezTimer::Scalar tilerTime = 0, msTime = 0, isTime = 0, ppsTime = 0;
+#endif
 };
 
 

+ 2 - 0
include/anki/scene/Common.h

@@ -29,6 +29,8 @@ namespace anki {
 /// If true then we can place spatials in a thread-safe way
 #define ANKI_CFG_OCTREE_THREAD_SAFE 1
 
+#define ANKI_CFG_SCENE_PROFILE 1
+
 /// @}
 /// @}
 

+ 7 - 0
include/anki/scene/Frustumable.h

@@ -70,10 +70,12 @@ public:
 
 	void setVisibilityTestResults(VisibilityTestResults* visible_)
 	{
+		ANKI_ASSERT(visible == nullptr);
 		visible = visible_;
 	}
 	VisibilityTestResults* getVisibilityTestResults()
 	{
+		ANKI_ASSERT(visible);
 		return visible;
 	}
 	/// @}
@@ -95,6 +97,11 @@ public:
 		return frustum->insideFrustum(cs);
 	}
 
+	void resetFrame()
+	{
+		visible = nullptr;
+	}
+
 protected:
 	Frustum* frustum = nullptr;
 	Mat4 projectionMat = Mat4::getIdentity();

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

@@ -199,7 +199,7 @@ public:
 	void setVisibleSubMeshesMask(const SceneNode* frustumable, U64 mask);
 
 	/// Get the mask to render only the needed submeshess. Called on rendering
-	U64 getVisibleSubMeshsMask(const SceneNode& frustumable) const;
+	U64 getVisibleSubMeshesMask(const SceneNode& frustumable) const;
 
 	/// Reset on frame start
 	void resetFrame()

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

@@ -7,6 +7,7 @@
 #include "anki/core/Timestamp.h"
 #include "anki/math/Math.h"
 #include "anki/util/Singleton.h"
+#include "anki/util/HighRezTimer.h"
 
 #include "anki/scene/Sector.h"
 #include "anki/physics/PhysWorld.h"
@@ -136,6 +137,8 @@ public:
 	SceneNode& findSceneNode(const char* name);
 	SceneNode* tryFindSceneNode(const char* name);
 
+	void printProfileInfo() const;
+
 private:
 	SceneAllocator<U8> alloc;
 	SceneAllocator<U8> frameAlloc;
@@ -154,6 +157,10 @@ private:
 
 	EventManager events;
 
+#if ANKI_CFG_SCENE_PROFILE
+	HighRezTimer::Scalar timeForUpdates = 0.0;
+#endif
+
 	/// Put a node in the appropriate containers
 	void registerNode(SceneNode* node);
 	void unregisterNode(SceneNode* node);

+ 24 - 0
include/anki/scene/Spatial.h

@@ -126,8 +126,32 @@ public:
 	void spatialMarkForUpdate()
 	{
 		timestamp = Timestamp::getTimestamp();
+
+		for(Spatial* subsp : spatialProtected.subSpatials)
+		{
+			subsp->spatialMarkForUpdate();
+		}
+	}
+
+	void update()
+	{
 		spatialProtected.spatialCs->toAabb(aabb);
 		origin = (aabb.getMax() + aabb.getMin()) * 0.5;
+
+		for(Spatial* subsp : spatialProtected.subSpatials)
+		{
+			subsp->update();
+		}
+	}
+
+	void resetFrame()
+	{
+		disableFlags(SF_VISIBLE_ANY);
+
+		for(Spatial* subsp : spatialProtected.subSpatials)
+		{
+			subsp->disableFlags(SF_VISIBLE_ANY);
+		}
 	}
 
 protected:

+ 1 - 1
shaders/IsLpGeneric.glsl

@@ -291,7 +291,7 @@ void main()
 #endif
 
 #if 0
-	fColor = fColor * 0.005 + vec3(vLimitsOfNearPlaneOpt, 1.0);
+	fColor = fColor * 0.005 + normal;
 #endif
 
 #if 0

+ 37 - 0
src/collision/CollisionShape.cpp

@@ -0,0 +1,37 @@
+#include "anki/collision/CollisionShape.h"
+#include "anki/collision/Collision.h"
+
+namespace anki {
+
+//==============================================================================
+void CollisionShape::toAabb(Aabb& out) const
+{
+	switch(cid)
+	{
+	case CST_LINE_SEG:
+		static_cast<const LineSegment*>(this)->toAabb(out);
+		break;
+	case CST_RAY:
+		static_cast<const Ray*>(this)->toAabb(out);
+		break;
+	case CST_PLANE:
+		static_cast<const Plane*>(this)->toAabb(out);
+		break;
+	case CST_SPHERE:
+		static_cast<const Sphere*>(this)->toAabb(out);
+		break;
+	case CST_AABB:
+		static_cast<const Aabb*>(this)->toAabb(out);
+		break;
+	case CST_OBB:
+		static_cast<const Obb*>(this)->toAabb(out);
+		break;
+	case CST_FRUSTUM:
+		static_cast<const Frustum*>(this)->toAabb(out);
+		break;
+	default:
+		ANKI_ASSERT(0);
+	};
+}
+
+} // end namespace anki

+ 17 - 1
src/collision/Frustum.cpp

@@ -21,7 +21,7 @@ Frustum& Frustum::operator=(const Frustum& b)
 }
 
 //==============================================================================
-bool Frustum::insideFrustum(const CollisionShape& b) const
+Bool Frustum::insideFrustum(const CollisionShape& b) const
 {
 	for(const Plane& plane : planes)
 	{
@@ -34,6 +34,22 @@ bool Frustum::insideFrustum(const CollisionShape& b) const
 	return true;
 }
 
+//==============================================================================
+void Frustum::toAabb(Aabb& aabb) const
+{
+	switch(type)
+	{
+	case FT_PERSPECTIVE:
+		static_cast<const PerspectiveFrustum*>(this)->toAabb(aabb);
+		break;
+	case FT_ORTHOGRAPHIC:
+		static_cast<const OrthographicFrustum*>(this)->toAabb(aabb);
+		break;
+	default:
+		ANKI_ASSERT(0);
+	}
+}
+
 //==============================================================================
 // PerspectiveFrustum                                                          =
 //==============================================================================

+ 2 - 2
src/renderer/Bs.cpp

@@ -27,8 +27,8 @@ void Bs::run()
 	VisibilityTestResults& vi =
 		*scene.getActiveCamera().getFrustumable()->getVisibilityTestResults();
 
-	for(auto it = vi.getRenderablesEnd() - 1; it >= vi.getRenderablesBegin();
-		--it)
+	for(auto it = vi.getRenderablesBegin(); it != vi.getRenderablesEnd();
+		++it)
 	{
 		drawer.render(scene.getActiveCamera(), RenderableDrawer::RS_BLEND,
 			0, *(*it));

+ 11 - 2
src/renderer/DebugDrawer.cpp

@@ -313,7 +313,6 @@ void CollisionDebugDrawer::visit(const Obb& obb)
 	tsl = Mat4::combineTransformations(trs, tsl);
 
 	dbg->setModelMatrix(tsl);
-	dbg->setColor(Vec3(1.0, 1.0, 0.0));
 	dbg->drawCube(2.0);
 }
 
@@ -362,7 +361,6 @@ void CollisionDebugDrawer::visit(const Frustum& f)
 		break;
 	case Frustum::FT_PERSPECTIVE:
 		{
-			dbg->setColor(Vec4(0.5, 0.0, 0.5, 1.0));
 			const PerspectiveFrustum& pf =
 				static_cast<const PerspectiveFrustum&>(f);
 
@@ -504,6 +502,7 @@ void SceneDebugDrawer::draw(Frustumable& fr) const
 {
 	const Frustum& fs = fr.getFrustum();
 
+	dbg->setColor(Vec3(1.0, 1.0, 0.0));
 	CollisionDebugDrawer coldraw(dbg);
 	fs.accept(coldraw);
 }
@@ -511,8 +510,18 @@ void SceneDebugDrawer::draw(Frustumable& fr) const
 //==============================================================================
 void SceneDebugDrawer::draw(Spatial& x) const
 {
+	dbg->setColor(Vec3(1.0, 0.0, 1.0));
 	CollisionDebugDrawer coldraw(dbg);
 	x.getAabb().accept(coldraw);
+
+	dbg->setColor(Vec3(0.25, 0.0, 0.25));
+	for(auto it = x.getSubSpatialsBegin(); it != x.getSubSpatialsEnd(); ++it)
+	{
+		if((*it)->flagsEnabled(Spatial::SF_VISIBLE_CAMERA))
+		{
+			(*it)->getAabb().accept(coldraw);
+		}
+	}
 }
 
 //==============================================================================

+ 14 - 4
src/renderer/Drawer.cpp

@@ -51,8 +51,8 @@ struct SetupRenderableVariableVisitor
 				*uni, x.get(), x.getArraySize());
 			break;
 		case BMV_MVP_MATRIX:
+			if(trfs)
 			{
-				ANKI_ASSERT(trfs != nullptr);
 				Array<Mat4, maxInstances> mvp;
 
 				for(U i = 0; i < size; i++)
@@ -62,6 +62,11 @@ struct SetupRenderableVariableVisitor
 
 				uniSet(*uni, &mvp[0], size);
 			}
+			else
+			{
+				ANKI_ASSERT(size == 1 && "Shouldn't instance that one");
+				uniSet(*uni, &vp, 1);
+			}
 			break;
 		case BMV_MV_MATRIX:
 			{
@@ -271,7 +276,12 @@ void RenderableDrawer::render(SceneNode& frsn, RenderingStage stage,
 	const ShaderProgram* prog;
 	const Vao* vao;
 	U32 indicesCountArray[64];
-	void* indicesOffsetArray[64];
+	void* indicesOffsetArray[64] = {nullptr};
+#if ANKI_DEBUG
+	memset(indicesCountArray, 0, sizeof(indicesCountArray));
+	memset(indicesOffsetArray, 0, sizeof(indicesOffsetArray));
+#endif
+
 	U32 primCount = 1;
 
 	if(renderable->getSubMeshesCount() == 0)
@@ -281,7 +291,7 @@ void RenderableDrawer::render(SceneNode& frsn, RenderingStage stage,
 	}
 	else
 	{
-		U64 mask = renderable->getVisibleSubMeshsMask(frsn);
+		U64 mask = renderable->getVisibleSubMeshesMask(frsn);
 
 		renderable->getRenderableModelPatchBase().getRenderingDataSub(
 			key, mask, vao, prog, indicesCountArray, indicesOffsetArray,
@@ -303,7 +313,7 @@ void RenderableDrawer::render(SceneNode& frsn, RenderingStage stage,
 				GL_TRIANGLES, 
 				indicesCountArray[0], 
 				GL_UNSIGNED_SHORT, 
-				0);
+				indicesOffsetArray[0]);
 		}
 		else
 		{

+ 37 - 0
src/renderer/Renderer.cpp

@@ -82,12 +82,40 @@ void Renderer::render(SceneGraph& scene_)
 
 	viewProjectionMat = cam.getViewProjectionMatrix();
 
+#if ANKI_CFG_RENDERER_PROFILE
+	HighRezTimer::Scalar timea, timeb;
+
+	timea = HighRezTimer::getCurrentTime();
 	tiler.updateTiles(scene->getActiveCamera());
+	timeb = HighRezTimer::getCurrentTime();
+	tilerTime += timeb - timea;
+
 	ms.run();
+	timea = HighRezTimer::getCurrentTime();
+	msTime += timea - timeb;
+
 	tiler.runMinMax(ms.getDepthFai());
+	timeb = HighRezTimer::getCurrentTime();
+	tilerTime += timeb - timea;
+
 	is.run();
+	timea = HighRezTimer::getCurrentTime();
+	isTime += timea - timeb;
+
 	bs.run();
+	timeb = HighRezTimer::getCurrentTime();
+
 	pps.run();
+	timea = HighRezTimer::getCurrentTime();
+	ppsTime += timea - timeb;
+#else
+	tiler.updateTiles(scene->getActiveCamera());
+	ms.run();
+	tiler.runMinMax(ms.getDepthFai());
+	is.run();
+	bs.run();
+	pps.run();
+#endif
 
 	ANKI_CHECK_GL_ERROR();
 	++framesNum;
@@ -207,4 +235,13 @@ void Renderer::clearAfterBindingFbo(const GLenum cap)
 	}
 }
 
+//==============================================================================
+void Renderer::printProfileInfo() const
+{
+#if ANKI_CFG_RENDERER_PROFILE
+	ANKI_LOGI("Renderer times: MS " << msTime << " IS " << isTime
+		<< " PPS " << ppsTime << " Tiler " << tilerTime);
+#endif
+}
+
 } // end namespace anki

+ 2 - 1
src/scene/Renderable.cpp

@@ -136,6 +136,7 @@ void Renderable::init(PropertyMap& pmap)
 //==============================================================================
 void Renderable::setVisibleSubMeshesMask(const SceneNode* frustumable, U64 mask)
 {
+	ANKI_ASSERT(frustumable && mask != 0);
 	mtx.lock();
 
 	if(ANKI_UNLIKELY(perframe == nullptr))
@@ -150,7 +151,7 @@ void Renderable::setVisibleSubMeshesMask(const SceneNode* frustumable, U64 mask)
 }
 
 //==============================================================================
-U64 Renderable::getVisibleSubMeshsMask(const SceneNode& frustumable) const
+U64 Renderable::getVisibleSubMeshesMask(const SceneNode& frustumable) const
 {
 	ANKI_ASSERT(perframe);
 

+ 21 - 4
src/scene/SceneGraph.cpp

@@ -42,18 +42,19 @@ static void updateSceneNode(SceneNode& sn, F32 prevUpdateTime,
 	Spatial* sp = sn.getSpatial();
 	if(sp)
 	{
-		if(sp->getSpatialTimestamp() == Timestamp::getTimestamp())
+		if(sp->getSpatialTimestamp() >= Timestamp::getTimestamp())
 		{
+			sp->update();
 			sectorGroup.placeSceneNode(&sn);
 		}
-		sp->disableFlags(Spatial::SF_VISIBLE_ANY);
+		sp->resetFrame();
 	}
 
 	// Do some frustumable stuff
 	Frustumable* fr = sn.getFrustumable();
 	if(fr)
 	{
-		fr->setVisibilityTestResults(nullptr);
+		fr->resetFrame();
 	}
 
 	// Do some renderable stuff
@@ -124,6 +125,10 @@ void SceneGraph::unregisterNode(SceneNode* node)
 //==============================================================================
 void SceneGraph::update(F32 prevUpdateTime, F32 crntTime, Renderer& renderer)
 {
+#if ANKI_CFG_SCENE_PROFILE
+	HighRezTimer::Scalar startTime = HighRezTimer::getCurrentTime();
+#endif
+
 	frameAlloc.reset();
 
 	physics.update(prevUpdateTime, crntTime);
@@ -158,7 +163,7 @@ void SceneGraph::update(F32 prevUpdateTime, F32 crntTime, Renderer& renderer)
 #if 0
 	for(SceneNode* n : nodes)
 	{
-		updateSceneNode(*n, prevUpdateTime, crntTime, *sectorGroup);
+		updateSceneNode(*n, prevUpdateTime, crntTime, sectorGroup);
 	}
 #else
 	Array<UpdateSceneNodesJob, ThreadPool::MAX_THREADS> jobs2;
@@ -209,6 +214,10 @@ void SceneGraph::update(F32 prevUpdateTime, F32 crntTime, Renderer& renderer)
 		}
 	}
 #endif
+
+#if ANKI_CFG_SCENE_PROFILE
+	timeForUpdates += HighRezTimer::getCurrentTime() - startTime;
+#endif
 }
 
 //==============================================================================
@@ -225,4 +234,12 @@ SceneNode* SceneGraph::tryFindSceneNode(const char* name)
 	return (it == nameToNode.end()) ? nullptr : it->second;
 }
 
+//==============================================================================
+void SceneGraph::printProfileInfo() const
+{
+#if ANKI_CFG_SCENE_PROFILE
+	ANKI_LOGI("Scene times: " << timeForUpdates);
+#endif
+}
+
 } // end namespace anki

+ 21 - 5
src/scene/Visibility.cpp

@@ -3,6 +3,7 @@
 #include "anki/scene/Frustumable.h"
 #include "anki/scene/Light.h"
 #include "anki/renderer/Renderer.h"
+#include "anki/core/Logger.h"
 
 namespace anki {
 
@@ -58,13 +59,21 @@ struct VisibilityTestJob: ThreadJob
 			{
 				Spatial* subsp = *it;
 	
-				if(frustumable->insideFrustum(*subsp))
+				if(frustumable->insideFrustum(*subsp)
+					&& renderer->doVisibilityTests(
+					subsp->getOptimalCollisionShape()))
 				{
 					subSpatialsMask |= 1 << i;
+					subsp->enableFlags(Spatial::SF_VISIBLE_CAMERA);
 				}
 				++i;
 			}
 
+			if(ANKI_UNLIKELY(i > 0 && subSpatialsMask == 0))
+			{
+				continue;
+			}
+
 			// renderable
 			Renderable* r = node->getRenderable();
 			if(r)
@@ -146,10 +155,16 @@ struct VisibilityTestJob: ThreadJob
 				if(frustumableSn->getFrustumable()->insideFrustum(*subsp))
 				{
 					subSpatialsMask |= 1 << i;
+					subsp->enableFlags(Spatial::SF_VISIBLE_LIGHT);
 				}
 				++i;
 			}
 
+			if(i > 0 && subSpatialsMask == 0)
+			{
+				continue;
+			}
+
 			sp->enableFlags(Spatial::SF_VISIBLE_LIGHT);
 
 			Renderable* r = node->getRenderable();
@@ -214,8 +229,8 @@ void doVisibilityTests(SceneNode& fsn, SceneGraph& scene,
 		renderablesSize, 
 		lightsSize);
 
-	visible->renderables.resize(renderablesSize);
-	visible->lights.resize(lightsSize);
+	visible->renderables.resize(renderablesSize, nullptr);
+	visible->lights.resize(lightsSize, nullptr);
 
 	// Append thread results
 	renderablesSize = 0;
@@ -259,8 +274,9 @@ void doVisibilityTests(SceneNode& fsn, SceneGraph& scene,
 	}
 
 	// Sort the renderables in the main thread
-	std::sort(visible->renderables.begin(), 
-		visible->renderables.end(), MaterialSortFunctor());
+	DistanceSortFunctor dsfunc;
+	dsfunc.origin = fr->getFrustumableOrigin();
+	std::sort(visible->renderables.begin(), visible->renderables.end(), dsfunc);
 
 	threadPool.waitForAllJobsToFinish();
 }

+ 11 - 9
testapp/Main.cpp

@@ -222,22 +222,22 @@ void init()
 	}
 #endif
 
-	/*PointLight* point1 = new PointLight("point1", &scene, Movable::MF_NONE,
-		nullptr);
-	point1->setRadius(3.0);
-	point1->setDiffuseColor(Vec4(2.0, 2.0, 2.0, 0.0));
-	point1->setSpecularColor(Vec4(3.0, 3.0, 0.0, 0.0));
-	point1->setLocalTranslation(Vec3(-3.0, 2.0, 0.0));*/
-
 	// horse
 	horse = new ModelNode("data/models/horse/horse.mdl", "horse", &scene,
 		Movable::MF_NONE, nullptr);
 	horse->setLocalTransform(Transform(Vec3(-2, 0, 0), Mat3::getIdentity(),
 		0.7));
 
+	// barrel
+	ModelNode* redBarrel = new ModelNode("data/models/red_barrel/red_barrel.mdl",
+		"red_barrel", &scene, Movable::MF_NONE, nullptr);
+	redBarrel->setLocalTransform(Transform(Vec3(+2, 0, 0), Mat3::getIdentity(),
+		0.7));
+
 #if 1
 	StaticGeometryNode* sponzaModel = new StaticGeometryNode(
-		"data/maps/sponza/sponza_new.mdl",
+		//"data/maps/sponza/sponza_no_bmeshes.mdl",
+		"data/maps/sponza/sponza.mdl",
 		"sponza", &scene);
 
 	(void)sponzaModel;
@@ -447,7 +447,7 @@ void mainLoop()
 
 		// Sleep
 		//
-#if 0
+#if 1
 		timer.stop();
 		if(timer.getElapsedTime() < AppSingleton::get().getTimerTick())
 		{
@@ -469,6 +469,8 @@ void mainLoop()
 
 	ANKI_LOGI("Exiting main loop (" << mainLoopTimer.getElapsedTime()
 		<< " sec)");
+	MainRendererSingleton::get().printProfileInfo();
+	SceneGraphSingleton::get().printProfileInfo();
 }
 
 //==============================================================================

+ 1 - 1
tools/material/diff.template.mtl

@@ -9,7 +9,7 @@
 		<shader>
 			<type>vertex</type>
 			<includes>
-				<include>shaders/MaterialVertex.glsl</include>
+				<include>shaders/MaterialVertexCommon.glsl</include>
 			</includes>
 		
 			<inputs>

+ 1 - 1
tools/material/diff_norm.template.mtl

@@ -9,7 +9,7 @@
 		<shader>
 			<type>vertex</type>
 			<includes>
-				<include>shaders/MaterialVertex.glsl</include>
+				<include>shaders/MaterialVertexCommon.glsl</include>
 			</includes>
 		
 			<inputs>