2
0
Panagiotis Christopoulos Charitos 10 жил өмнө
parent
commit
566dbd8026

+ 83 - 2
include/anki/gr/PipelineCommon.h

@@ -14,11 +14,92 @@ namespace anki {
 /// @addtogroup graphics
 /// @{
 
+struct VertexBinding
+{
+	PtrSize m_stride; ///< Vertex stride.
+	VertexStepRate m_stepRate = VertexStepRate::VERTEX;
+};
+
+struct VertexAttributeBinding
+{
+	PixelFormat m_format;
+	PtrSize m_offset = 0;
+	U8 m_binding = 0;
+};
+
+struct VertexStateInfo
+{
+	U8 m_bindingCount = 0;
+	Array<VertexBinding, MAX_VERTEX_ATTRIBUTES> m_bindings;
+	U8 m_attributeCount = 0;
+	Array<VertexAttributeBinding, MAX_VERTEX_ATTRIBUTES> m_attributes;
+};
+
+struct InputAssemblerStateInfo
+{
+	PrimitiveTopology m_topology = PrimitiveTopology::TRIANGLES;
+	Bool8 m_primitiveRestartEnabled = false;
+};
+
+struct TessellationStateInfo
+{
+	U32 m_patchControlPointsCount = 3;
+};
+
+struct ViewportStateInfo
+{
+	Bool8 m_scissorEnabled = false;
+	Array<U32, 4> m_scissorRect = {{0, 0, 0, 0}};
+	Array<U32, 4> m_viewport = {{0, 0, 0, 0}};
+};
+
+struct RasterizerStateInfo
+{
+	FillMode m_fillCode = FillMode::SOLID;
+	CullMode m_cullMode = CullMode::BACK;
+};
+
+struct DepthStateInfo
+{
+	Bool8 m_writeEnabled = false;
+	DepthCompareFunction m_compareFunction;
+};
+
+struct ColorStateInfo
+{
+	Bool8 m_alphaToCoverageEnabled = false;
+	Bool8 m_blendEnabled = false;
+	BlendMethod m_srcBlendMethod = BlendMethod::ONE;
+	BlendMethod m_dstBlendMethod = BlendMethod::ONE;
+	BlendFunction m_blendFunction = BlendFunction::ADD;
+	U8 m_channelWriteMask = 15;
+};
+
+enum class SubStateBit: U16
+{
+	NONE = 0,
+	VERTEX = 1 << 0,
+	INPUT_ASSEMBLER = 1 << 1,
+	TESSELLATION = 1 << 2,
+	VIEWPORT = 1 << 3,
+	RASTERIZER = 1 << 4,
+	DEPTH = 1 << 5,
+	COLOR = 1 << 6
+};
+
 /// Pipeline initializer.
 struct PipelineInitializer
 {
-	Array<ShaderHandle, 5> m_graphicsShaders;
-	ShaderHandle m_computeShader;
+	VertexStateInfo m_vertex;
+	InputAssemblerStateInfo m_inputAssembler;
+	TessellationStateInfo m_tessellation;
+	ViewportStateInfo m_viewport;
+	RasterizerStateInfo m_rasterizer;
+	DepthStateInfo m_depthStencil;
+	ColorStateInfo m_color;
+
+	Array<ShaderHandle, 6> m_shaders;
+	SubStateBit m_definedState = SubStateBit::NONE;
 };
 /// @}
 

+ 1 - 0
include/anki/gr/PipelineHandle.h

@@ -7,6 +7,7 @@
 #define ANKI_GR_PIPELINE_HANDLE_H
 
 #include "anki/gr/GrHandle.h"
+#include "anki/gr/PipelineCommon.h"
 
 namespace anki {
 

+ 1 - 1
include/anki/gr/gl/PipelineImpl.h

@@ -7,7 +7,7 @@
 #define ANKI_GR_GL_PIPELINE_IMPL_H
 
 #include "anki/gr/gl/GlObject.h"
-#include "anki/gr/ShaderHandle.h"
+#include "anki/gr/PipelineCommon.h"
 
 namespace anki {
 

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

@@ -14,10 +14,8 @@ namespace anki {
 
 // Forward
 class SceneNode;
-class SceneGraph;
 class Sector;
 class SectorGroup;
-class Renderer;
 
 /// @addtogroup Scene
 /// @{
@@ -26,15 +24,26 @@ class Renderer;
 class Portal
 {
 public:
-	Portal();
+	Portal(SectorGroup* sectorGroup)
+	:	m_group(sectorGroup)
+	{}
 
 	~Portal();
 
 	ANKI_USE_RESULT Error create(const SArray<Vec4>& vertPositions);
 
+	const CollisionShape& getCollisionShape() const
+	{
+		return *m_shape;
+	}
+
+	ANKI_USE_RESULT Error addSector(Sector* sector);
+
 private:
-	Array<Sector*, 2> m_sectors = {{nullptr, nullptr}};
+	SectorGroup* m_group;
+	List<Sector*> m_sectors;
 	CollisionShape* m_shape = nullptr;
+	DArray<Vec4> m_shapeStorage;
 	Bool8 m_open = true;
 };
 
@@ -48,34 +57,33 @@ public:
 	static const U AVERAGE_PORTALS_PER_SECTOR = 4;
 
 	/// Default constructor
-	Sector(SectorGroup* group);
+	Sector(SectorGroup* group)
+	:	m_group(group)
+	{}
+
+	~Sector();
 
 	ANKI_USE_RESULT Error create(const SArray<Vec4>& vertPositions);
 
-	const CollisionShape& getShape() const
+	const CollisionShape& getCollisionShape() const
 	{
 		return *m_shape;
 	}
 
-	const SectorGroup& getSectorGroup() const
-	{
-		return *m_group;
-	}
-	SectorGroup& getSectorGroup()
-	{
-		return *m_group;
-	}
+	ANKI_USE_RESULT Error addPortal(Portal* portal);
 
-	/// Sector does not take ownership of the portal
-	void addNewPortal(Portal* portal);
-
-	/// Remove a Portal from the portals container
-	void removePortal(Portal* portal);
+	ANKI_USE_RESULT Error addSceneNode(SceneNode* node);
+	void removeSceneNode(SceneNode* node);
 
 private:
 	SectorGroup* m_group; ///< Know your father
-	DArray<Portal*> m_portals;
 	CollisionShape* m_shape;
+	DArray<Vec4> m_shapeStorage;
+
+	List<Portal*> m_portals;
+	List<SceneNode*> m_nodes;
+
+	List<SceneNode*>::Iterator findSceneNode(SceneNode* node);
 };
 
 /// Sector group. This is supposed to represent the whole scene
@@ -83,30 +91,14 @@ class SectorGroup
 {
 public:
 	/// Default constructor
-	SectorGroup(SceneGraph* scene);
+	SectorGroup(SceneGraph* scene)
+	:	m_scene(scene)
+	{}
 
 	/// Destructor
 	~SectorGroup();
 
-	const SceneGraph& getSceneGraph() const
-	{
-		return *scene;
-	}
-
-	SceneGraph& getSceneGraph()
-	{
-		return *scene;
-	}
-
-	const List<Portal*>& getPortals() const
-	{
-		return portals;
-	}
-
-	const List<Sector*>& getSectors() const
-	{
-		return sectors;
-	}
+	SceneAllocator<U8> getAllocator() const;
 
 	/// The owner of the pointer is the sector group
 	Sector* createNewSector(const SArray<Vec4>& vertexPositions);
@@ -114,6 +106,14 @@ public:
 	/// The owner of the pointer is the sector group
 	Portal* createNewPortal(const SArray<Vec4>& vertexPositions);
 
+	ANKI_USE_RESULT Error bake();
+
+	/// @privatesection
+	/// @{
+	ConvexHullShape* createConvexHull(const SArray<Vec4>& vertPositions,
+		DArray<Vec4>& shapeStorage);
+	/// @}
+
 private:
 	SceneGraph* m_scene; ///< Keep it here to access various allocators
 	List<Sector*> m_sectors;

+ 124 - 325
src/scene/Sector.cpp

@@ -3,7 +3,6 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
-#if 0
 #include "anki/scene/Sector.h"
 #include "anki/scene/SpatialComponent.h"
 #include "anki/scene/SceneNode.h"
@@ -22,410 +21,210 @@ namespace anki {
 //==============================================================================
 
 //==============================================================================
-Portal::Portal()
+Portal::~Portal()
 {
-	sectors[0] = sectors[1] = nullptr;
-	open = true;
+	auto alloc = m_group->getAllocator();
+	m_shapeStorage.destroy(alloc);
+
+	if(m_shape)
+	{
+		alloc.deleteInstance(m_shape);
+		m_shape = nullptr;
+	}
 }
 
 //==============================================================================
-// Sector                                                                      =
-//==============================================================================
+Error Portal::create(const SArray<Vec4>& vertPositions)
+{
+	m_shape = m_group->createConvexHull(vertPositions, m_shapeStorage);
+	return m_shape ? ErrorCode::NONE : ErrorCode::OUT_OF_MEMORY;
+}
 
 //==============================================================================
-Sector::Sector(SectorGroup* group_, const Aabb& box)
-	:	group(group_),
-		portals(group->getSceneGraph().getAllocator())
+Error Portal::addSector(Sector* sector)
 {
-	// Reserve some space for portals
-	portals.reserve(AVERAGE_PORTALS_PER_SECTOR);
+	ANKI_ASSERT(sector);
+	return m_sectors.pushBack(m_group->getAllocator(), sector);
 }
 
 //==============================================================================
-Bool Sector::placeSceneNode(SceneNode* sn)
+// Sector                                                                      =
+//==============================================================================
+
+//==============================================================================
+Sector::~Sector()
 {
-#if 0
-	// XXX Optimize
+	auto alloc = m_group->getAllocator();
 
-	SpatialComponent* sp = sn->getSpatialComponent();
-	ANKI_ASSERT(sp);
-	if(!sp->getAabb().collide(octree.getRoot().getAabb()))
+	if(m_shape)
 	{
-		return false;
+		alloc.deleteInstance(m_shape);
+		m_shape = nullptr;
 	}
 
-	octree.placeSceneNode(sn);
-#endif
-	return true;
+	m_portals.destroy(alloc);
+	m_nodes.destroy(alloc);
 }
 
 //==============================================================================
-void Sector::addNewPortal(Portal* portal)
+Error Sector::create(const SArray<Vec4>& vertPositions)
 {
-	ANKI_ASSERT(portal);
-	ANKI_ASSERT(
-		std::find(portals.begin(), portals.end(), portal) == portals.end()
-		&& "Portal found in the container");
-
-	portals.push_back(portal);
+	m_shape = m_group->createConvexHull(vertPositions, m_shapeStorage);
+	return m_shape ? ErrorCode::NONE : ErrorCode::OUT_OF_MEMORY;
 }
 
 //==============================================================================
-void Sector::removePortal(Portal* portal)
+Error Sector::addPortal(Portal* portal)
 {
 	ANKI_ASSERT(portal);
-	SceneVector<Portal*>::iterator it =
-		std::find(portals.begin(), portals.end(), portal);
-
-	ANKI_ASSERT(it != portals.end());
-	portals.erase(it);
+	return m_portals.pushBack(m_group->getAllocator(), portal);
 }
 
 //==============================================================================
-// SectorGroup                                                                 =
-//==============================================================================
+Error Sector::addSceneNode(SceneNode* node)
+{
+	ANKI_ASSERT(node);
+	ANKI_ASSERT(findSceneNode(node) == m_nodes.getEnd());
+	return m_nodes.pushBack(m_group->getAllocator(), node);
+}
 
 //==============================================================================
-SectorGroup::SectorGroup(SceneGraph* scene_)
-	:	scene(scene_),
-		sectors(scene->getAllocator()),
-		portals(scene->getAllocator())
+void Sector::removeSceneNode(SceneNode* node)
 {
-	ANKI_ASSERT(scene != nullptr);
+	ANKI_ASSERT(node);
+	auto it = findSceneNode(node);
+	ANKI_ASSERT(it != m_nodes.getEnd());
+	m_nodes.erase(m_group->getAllocator(), it);
 }
 
 //==============================================================================
-SectorGroup::~SectorGroup()
+List<SceneNode*>::Iterator Sector::findSceneNode(SceneNode* node)
 {
-#if 0
-	for(Sector* sector : sectors)
+	ANKI_ASSERT(node);
+	auto it = m_nodes.getBegin();
+	for(; it != m_nodes.getEnd(); ++it)
 	{
-		ANKI_DELETE(sector, scene->getAllocator());
+		if(*it == node)
+		{
+			break;
+		}
 	}
 
-	for(Portal* portal : portals)
-	{
-		ANKI_DELETE(portal, scene->getAllocator());
-	}
-#endif
+	return it;
 }
 
 //==============================================================================
-Sector* SectorGroup::createNewSector(const Aabb& aabb)
-{
-#if 0
-	Sector* out = ANKI_NEW(Sector, scene->getAllocator(), this, aabb);
-	sectors.push_back(out);
-	return out;
-#endif
-	return nullptr;
-}
-
+// SectorGroup                                                                 =
 //==============================================================================
-Portal* SectorGroup::createNewPortal(Sector* a, Sector* b, 
-	const Obb& collisionShape)
-{
-#if 0
-	ANKI_ASSERT(a && b);
-	Portal* out = ANKI_NEW_0(Portal, scene->getAllocator());
-
-	out->sectors[0] = a;
-	out->sectors[1] = b;
-	out->shape = collisionShape;
-
-	portals.push_back(out);
-
-	a->addNewPortal(out);
-	b->addNewPortal(out);
-
-	return out;
-#endif
-	return nullptr;
-}
 
 //==============================================================================
-void SectorGroup::placeSceneNode(SceneNode* sn)
+ConvexHullShape* SectorGroup::createConvexHull(
+	const SArray<Vec4>& vertPositions, DArray<Vec4>& shapeStorage)
 {
-#if 0
-	ANKI_ASSERT(sn != nullptr);
-	SpatialComponent* sp = sn->getSpatial();
-	ANKI_ASSERT(sp);
-	const Vec3& spPos = sp->getSpatialOrigin();
-
-	// Find the candidates first. Sectors overlap, chose the smaller(??!!??)
-	Sector* sector = nullptr;
-	for(Sector* s : sectors)
-	{
-		// Find if the spatia's position is inside the sector
-		Bool inside = true;
-		for(U i = 0; i < 3; i++)
-		{
-			if(spPos[i] > s->getAabb().getMax()[i]
-				|| spPos[i] < s->getAabb().getMin()[i])
-			{
-				inside = false;
-				continue;
-			}
-		}
+	Error err = ErrorCode::NONE;
 
-		if(!inside)
-		{
-			// continue
-		}
-		else
-		{
-			// No other candidate?
-			if(sector == nullptr)
-			{
-				sector = s;
-			}
-			else
-			{
-				// Other candidata so chose the smaller
-				F32 lengthSqA = (sector->getAabb().getMax()
-					- sector->getAabb().getMin()).getLengthSquared();
-
-				F32 lengthSqB = (s->getAabb().getMax()
-					- s->getAabb().getMin()).getLengthSquared();
+	auto alloc = getAllocator();
+	U vertCount = vertPositions.getSize();
+	ANKI_ASSERT(vertCount >= 4 && "Minimum shape should be tetrahedron");
 
-				if(lengthSqB < lengthSqA)
-				{
-					sector = s;
-				}
-			}
-		} // end if inside
+	// Create hull
+	ConvexHullShape* hull = alloc.newInstance<ConvexHullShape>();
+	if(!hull)
+	{
+		err = ErrorCode::OUT_OF_MEMORY;
 	}
 
-	// Ask the octree to place it
-	if(sector != nullptr)
+	// Alloc storage
+	if(!err)
 	{
-		sector->octree.placeSceneNode(sn);
+		err = shapeStorage.create(alloc, vertCount);
 	}
-	else
+
+	// Assign storage to hull
+	if(!err)
 	{
-		ANKI_LOGW("Spatial outside all sectors");
+		memcpy(&shapeStorage[0], &vertPositions[0], sizeof(Vec4) * vertCount);
+		hull->initStorage(&shapeStorage[0], vertCount);
 	}
-#endif
-}
 
-//==============================================================================
-void SectorGroup::doVisibilityTests(SceneNode& sn, VisibilityTest test,
-	Renderer* r)
-{
-#if 0
-	// Set all sectors to not visible
-	for(Sector* sector : sectors)
+	// Cleanup on error
+	if(err)
 	{
-		sector->visibleBy = VB_NONE;
+		shapeStorage.destroy(alloc);
+		
+		if(hull)
+		{
+			alloc.deleteInstance(hull);
+			hull = nullptr;
+		}
 	}
 
-	doVisibilityTestsInternal(sn, test, r, VB_CAMERA);
-#endif
+	return hull;
 }
 
 //==============================================================================
-void SectorGroup::doVisibilityTestsInternal(SceneNode& sn, VisibilityTest test,
-	Renderer* r, VisibleBy visibleBy)
+Sector* SectorGroup::createNewSector(const SArray<Vec4>& vertexPositions)
 {
-#if 0
-	Frustumable* fr = sn.getFrustumable();
-	ANKI_ASSERT(fr != nullptr && "sn should be frustumable");
-	fr->visible = nullptr;
-
-	SpatialComponent* sp = sn.getSpatial();
-	ANKI_ASSERT(sp != nullptr && "sn should be spatial as well");
-
-	// sn is not placed in any octree
-	if(sp->getOctreeNode() == nullptr)
+	Sector* sector = getAllocator().newInstance<Sector>(this);
+	if(sector)
 	{
-		return;
-	}
-
-	//
-	// Find the visible sectors
-	//
-
-	SceneFrameVector<Sector*> visibleSectors(scene->getFrameAllocator());
-
-	// Find the sector that contains the frustumable
-	Sector& containerSector = sp->getOctreeNode()->getOctree().getSector();
-	containerSector.visibleBy |= visibleBy;
-	visibleSectors.push_back(&containerSector);
-
-	// Loop all sector portals and add other sectors
-	for(Portal* portal : containerSector.portals)
-	{
-		if(ANKI_UNLIKELY(!portal->open))
-		{
-			continue;
-		}
-
-		// Get the "other" sector of that portal
-		Sector* testAgainstSector;
-
-		if(portal->sectors[0] == &containerSector)
-		{
-			testAgainstSector = portal->sectors[1];
-		}
-		else
+		Error err = sector->create(vertexPositions);
+		if(err)
 		{
-			ANKI_ASSERT(portal->sectors[1] == &containerSector);
-			testAgainstSector = portal->sectors[0];
+			getAllocator().deleteInstance(sector);
+			sector = nullptr;
 		}
-		ANKI_ASSERT(testAgainstSector != nullptr);
+	}
 
-		// Search if portal is in the container from another portal
-		SceneVector<Sector*>::iterator it = std::find(visibleSectors.begin(),
-			visibleSectors.end(), testAgainstSector);
+	return sector;
+}
 
-		if(it == visibleSectors.end())
+//==============================================================================
+Portal* SectorGroup::createNewPortal(const SArray<Vec4>& vertexPositions)
+{
+	Portal* portal = getAllocator().newInstance<Portal>(this);
+	if(portal)
+	{
+		Error err = portal->create(vertexPositions);
+		if(err)
 		{
-			// Not found so test the portal
-
-			// Portal is visible
-			if(fr->insideFrustum(portal->shape))
-			{
-				/*if(r == nullptr || r->doVisibilityTests(portal->shape))*/
-				{
-					testAgainstSector->visibleBy |= visibleBy;
-					visibleSectors.push_back(testAgainstSector);
-				}
-			}
+			getAllocator().deleteInstance(portal);
+			portal = nullptr;
 		}
 	}
 
-	//
-	// For all visible sectors do the tests
-	//
-
-	// Create a few VisibilityTestResults to pass to every octree
-	SceneVector<VisibilityTestResults> testResults(scene->getFrameAllocator());
-	testResults.resize(visibleSectors.size(), 
-		VisibilityTestResults(scene->getFrameAllocator()));
-	U renderablesCount = 0;
-	U lightsCount = 0;
+	return portal;
+}
 
-	// Run tests for every octree
-	for(U i = 0; i < visibleSectors.size(); i++)
+//==============================================================================
+Error SectorGroup::bake()
+{
+	// Connect portals with sectors
+	auto it = m_portals.getBegin();
+	auto end = m_portals.getEnd();
+	for(; it != end; ++it)
 	{
-		Sector* sector = visibleSectors[i];
-
-		sector->octree.doVisibilityTests(sn, test, testResults[i]);
-
-		renderablesCount += testResults[i].renderables.size();
-		lightsCount += testResults[i].lights.size();
-	}
-
-	// If you don't want lights then the octree should do tests with them
-	ANKI_ASSERT(!((test & VT_LIGHTS) == 0 && lightsCount != 0));
-	// Same as ^
-	ANKI_ASSERT(!((test & VT_RENDERABLES) == 0 && renderablesCount != 0));
+		Portal& portal = *(*it);
 
-	//
-	// Combine test results and try doing renderer tests
-	//
+		auto sit = m_sectors.getBegin();
+		auto send = m_sectors.getEnd();
 
-	// Create the visibility container
-	VisibilityTestResults* visible =
-		ANKI_NEW(VisibilityTestResults, scene->getFrameAllocator(),
-		scene->getFrameAllocator());
-
-	// Set the sizes to save some moves
-	visible->renderables.reserve(renderablesCount);
-	visible->lights.reserve(lightsCount);
-
-	// Iterate previous test results and append to the combined one
-	if(r == nullptr)
-	{
-		for(VisibilityTestResults& testResult : testResults)
-		{
-			visible->renderables.insert(
-				visible->renderables.end(), 
-				testResult.renderables.begin(), 
-				testResult.renderables.end());
-
-			visible->lights.insert(
-				visible->lights.end(), 
-				testResult.lights.begin(), 
-				testResult.lights.end());
-		}
-	}
-	else
-	{
-		for(VisibilityTestResults& testResult : testResults)
+		for(; sit != send; ++sit)
 		{
-			// First the renderables
-			for(VisibleNode& renderable : testResult.renderables)
-			{
-				/*XXX if(r->getTiler().test2(
-					renderable->getSpatial()->getOptimalCollisionShape()))*/
-				{
-					visible->renderables.push_back(renderable);
-				}
-			}
+			Sector& sector = *(*sit);
 
-			// Then the lights
-			for(VisibleNode& light : testResult.lights)
+			Bool collide = testCollisionShapes(
+				portal.getCollisionShape(), sector.getCollisionShape());
+
+			if(collide)
 			{
-				/*XXX if(r->doVisibilityTests(
-					light->getSpatial()->getOptimalCollisionShape()))*/
-				{
-					visible->lights.push_back(light);
-				}
+				ANKI_CHECK(portal.addSector(&sector));
+				ANKI_CHECK(sector.addPortal(&portal));
 			}
 		}
 	}
 
-	// The given frustumable is finished
-	fr->visible = visible;
-
-	//
-	// Sort
-	//
-
-	Threadpool.h& threadPool = Threadpool.hSingleton::get();
-
-	// Sort the renderables in a another thread
-	DistanceSortJob dsjob;
-	dsjob.nodes = visible->renderables.begin();
-	dsjob.nodesCount = visible->renderables.size();
-	dsjob.origin = sp->getSpatialOrigin();
-	threadPool.assignNewJob(0, &dsjob);
-
-	// The rest of the jobs are dummy
-	Array<ThreadJobDummy, Threadpool.h::MAX_THREADS>  dummyjobs;
-	for(U i = 1; i < threadPool.getThreadsCount(); i++)
-	{
-		threadPool.assignNewJob(i, &dummyjobs[i]);
-	}
-
-	// Sort the lights in the main thread
-	std::sort(visible->lights.begin(),
-		visible->lights.end(), DistanceSortFunctor{sp->getSpatialOrigin()});
-
-	threadPool.waitForAllJobsToFinish();
-
-	//
-	// Continue by testing the lights
-	//
-
-	for(VisibleNode& lsn : visible->lights)
-	{
-		Light* l = lsn.node->getLight();
-		ANKI_ASSERT(l != nullptr);
-
-		if(l->getShadowEnabled())
-		{
-			ANKI_ASSERT(lsn.node->getFrustumable() != nullptr);
-
-			doVisibilityTestsInternal(*lsn.node,
-				(VisibilityTest)(VT_RENDERABLES | VT_ONLY_SHADOW_CASTERS),
-				nullptr, VB_LIGHT);
-		}
-	}
-#endif
+	return ErrorCode::NONE;
 }
 
 } // end namespace anki
-
-#endif