Browse Source

Allocator stuff

Panagiotis Christopoulos Charitos 13 years ago
parent
commit
a08b8216fa

+ 10 - 0
include/anki/scene/Camera.h

@@ -81,6 +81,16 @@ public:
 	}
 	/// @}
 
+	/// @name Frustumable virtuals
+	/// @{
+
+	/// Override Frustumable::getFrustumableOrigin()
+	const Vec3& getFrustumableOrigin() const
+	{
+		return getWorldTransform().getOrigin();
+	}
+	/// @}
+
 	void lookAtPoint(const Vec3& point);
 
 protected:

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

@@ -2,6 +2,7 @@
 #define ANKI_SCENE_COMMON_H
 
 #include "anki/util/Allocator.h"
+#include "anki/util/Vector.h"
 
 namespace anki {
 
@@ -13,6 +14,10 @@ using SceneAllocator = StackAllocator<T, false>;
 typedef std::basic_string<char, std::char_traits<char>,
 	SceneAllocator<char>> SceneString;
 
+/// Scene vector
+template<typename T>
+using SceneVector = Vector<T, SceneAllocator<T>>;
+
 } // end namespace anki
 
 #endif

+ 6 - 13
include/anki/scene/Frustumable.h

@@ -18,8 +18,8 @@ public:
 	/// @{
 
 	/// Pass the frustum here so we can avoid the virtuals
-	Frustumable(Frustum* fr, SceneNode* sn)
-		: frustum(fr), node(sn)
+	Frustumable(Frustum* fr)
+		: frustum(fr)
 	{}
 	/// @}
 
@@ -59,14 +59,8 @@ public:
 		return viewProjectionMat;
 	}
 
-	const SceneNode& getSceneNode() const
-	{
-		return *node;
-	}
-	SceneNode& getSceneNode()
-	{
-		return *node;
-	}
+	/// Get the origin for sorting and visibility tests
+	virtual const Vec3& getFrustumableOrigin() const = 0;
 	/// @}
 
 	void frustumableMarkUpdated()
@@ -75,13 +69,13 @@ public:
 	}
 
 	/// Is a spatial inside the frustum?
-	bool insideFrustum(const Spatial& sp) const
+	Bool insideFrustum(const Spatial& sp) const
 	{
 		return frustum->insideFrustum(sp.getSpatialCollisionShape());
 	}
 
 	/// Is a collision shape inside the frustum?
-	bool insideFrustum(const CollisionShape& cs) const
+	Bool insideFrustum(const CollisionShape& cs) const
 	{
 		return frustum->insideFrustum(cs);
 	}
@@ -92,7 +86,6 @@ protected:
 	Mat4 projectionMat = Mat4::getIdentity();
 	Mat4 viewMat = Mat4::getIdentity();
 	Mat4 viewProjectionMat = Mat4::getIdentity();
-	SceneNode* node;
 
 private:
 	U32 timestamp = Timestamp::getTimestamp();

+ 10 - 0
include/anki/scene/Light.h

@@ -260,6 +260,16 @@ public:
 	}
 	/// @}
 
+	/// @name Frustumable virtuals
+	/// @{
+
+	/// Override Frustumable::getFrustumableOrigin()
+	const Vec3& getFrustumableOrigin() const
+	{
+		return getWorldTransform().getOrigin();
+	}
+	/// @}
+
 	void loadTexture(const char* filename)
 	{
 		tex.load(filename);

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

@@ -153,6 +153,7 @@ protected:
 
 	/// The frame where it was last moved
 	U32 timestamp = Timestamp::getTimestamp();
+	
 
 	/// Called for every frame. It updates the @a wTrf if @a shouldUpdateWTrf
 	/// is true. Then it moves to the children.

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

@@ -243,7 +243,7 @@ public:
 
 private:
 	ParticleEmitterResourcePointer particleEmitterResource;
-	std::unique_ptr<btCollisionShape> collShape;
+	std::unique_ptr<btCollisionShape> collShape = nullptr;
 	Vector<ParticleBase*> particles;
 	F32 timeLeftForNextEmission;
 	/// The resource

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

@@ -2,6 +2,7 @@
 #define ANKI_SCENE_RENDERABLE_H
 
 #include "anki/scene/Property.h"
+#include "anki/scene/Common.h"
 #include "anki/util/Vector.h"
 #include "anki/gl/Ubo.h"
 #include "anki/resource/Material.h"
@@ -146,10 +147,9 @@ private:
 class Renderable
 {
 public:
-	typedef Vector<RenderableVariable*> RenderableVariables;
+	typedef SceneVector<RenderableVariable*> RenderableVariables;
 
-	Renderable()
-	{}
+	Renderable(const SceneAllocator<U8>& alloc);
 
 	virtual ~Renderable();
 

+ 19 - 19
include/anki/scene/SkinNode.h

@@ -7,7 +7,6 @@
 #include "anki/scene/Spatial.h"
 #include "anki/resource/Model.h"
 #include "anki/math/Math.h"
-#include "anki/util/Vector.h"
 
 namespace anki {
 
@@ -84,7 +83,8 @@ public:
 
 	/// @name Constructors/Destructor
 	/// @{
-	SkinModelPatch(const ModelPatch* mpatch_);
+	SkinModelPatch(const ModelPatch* mpatch_, 
+		const SceneAllocator<U8>& alloc);
 	~SkinModelPatch();
 	/// @}
 
@@ -124,9 +124,9 @@ public:
 	/// @}
 
 private:
-	Vector<SkinMesh*> skinMeshes;
 	const ModelPatch* mpatch;
-	Vector<Vao> xfbVaos; ///< Used as a source VAO in XFB
+	SceneVector<SkinMesh*> skinMeshes;
+	SceneVector<Vao> xfbVaos; ///< Used as a source VAO in XFB
 };
 
 /// A fragment of the SkinNode
@@ -244,27 +244,27 @@ public:
 
 	/// @name Accessors
 	/// @{
-	const Vector<Vec3>& getHeads() const
+	const SceneVector<Vec3>& getHeads() const
 	{
 		return heads;
 	}
 
-	const Vector<Vec3>& getTails() const
+	const SceneVector<Vec3>& getTails() const
 	{
 		return tails;
 	}
 
-	const Vector<Mat3>& getBoneRotations() const
+	const SceneVector<Mat3>& getBoneRotations() const
 	{
 		return boneRotations;
 	}
 
-	const Vector<Vec3>& getBoneTranslations() const
+	const SceneVector<Vec3>& getBoneTranslations() const
 	{
 		return boneTranslations;
 	}
 
-	const Vector<SkinPatchNode*>& getPatchNodes() const
+	const SceneVector<SkinPatchNode*>& getPatchNodes() const
 	{
 		return patches;
 	}
@@ -312,7 +312,7 @@ public:
 
 private:
 	SkinResourcePointer skin; ///< The resource
-	Vector<SkinPatchNode*> patches;
+	SceneVector<SkinPatchNode*> patches;
 	Obb visibilityShapeWSpace;
 
 	/// @name Animation stuff
@@ -324,10 +324,10 @@ private:
 
 	/// @name Bone data
 	/// @{
-	Vector<Vec3> heads;
-	Vector<Vec3> tails;
-	Vector<Mat3> boneRotations;
-	Vector<Vec3> boneTranslations;
+	SceneVector<Vec3> heads;
+	SceneVector<Vec3> tails;
+	SceneVector<Mat3> boneRotations;
+	SceneVector<Vec3> boneTranslations;
 	/// @}
 
 	/// Interpolate
@@ -336,17 +336,17 @@ private:
 	/// @param[out] translations Translations vector
 	/// @param[out] rotations Rotations vector
 	static void interpolate(const SkelAnim& animation, F32 frame,
-		Vector<Vec3>& translations, Vector<Mat3>& rotations);
+		SceneVector<Vec3>& translations, SceneVector<Mat3>& rotations);
 
 	/// Calculate the global pose
 	static void updateBoneTransforms(const Skeleton& skel,
-		Vector<Vec3>& translations, Vector<Mat3>& rotations);
+		SceneVector<Vec3>& translations, SceneVector<Mat3>& rotations);
 
 	/// Deform the heads and tails
 	static void deformHeadsTails(const Skeleton& skeleton,
-		const Vector<Vec3>& boneTranslations,
-		const Vector<Mat3>& boneRotations,
-		Vector<Vec3>& heads, Vector<Vec3>& tails);
+		const SceneVector<Vec3>& boneTranslations,
+		const SceneVector<Mat3>& boneRotations,
+		SceneVector<Vec3>& heads, SceneVector<Vec3>& tails);
 };
 
 } // end namespace

+ 126 - 0
include/anki/util/Memory.h

@@ -2,6 +2,7 @@
 #define ANKI_UTIL_MEMORY_H
 
 #include "anki/util/StdTypes.h"
+#include "anki/util/Assert.h"
 #include "anki/util/NonCopyable.h"
 #include <atomic>
 #include <algorithm>
@@ -68,6 +69,131 @@ private:
 	PtrSize calcAlignSize(PtrSize size) const;
 };
 
+template<typename T>
+class Allocator;
+
+/// Function that imitates the new operator. The function allocates memory for
+/// a number of elements and calls their constructor. The interesting thing is
+/// that if the elements size is >1 then it allocates size bigger than the
+/// required. The extra chunk is a number that will be used in
+/// deleteObjectArray to identify the number of elements that were allocated
+template<typename T, typename Alloc = Allocator<T>>
+struct New
+{
+	PtrSize n; ///< Number of elements
+	Alloc alloc; ///< The allocator
+
+	New(PtrSize n_, const Alloc& alloc_ = Alloc())
+		: n(n_), alloc(alloc_)
+	{}
+
+	template<typename... Args>
+	T* operator()(Args&&... args)
+	{
+		ANKI_ASSERT(n != 0);
+		T* out;
+
+		// If the number of elements is then do a simple allocaton
+		if(n == 1)
+		{
+			out = alloc.allocate(n);
+		}
+		else
+		{
+			// Allocate a memory block that includes the array size
+			typedef typename Alloc::template rebind<U8>::other CharAlloc;
+			CharAlloc charAlloc(alloc);
+			U8* mem = charAlloc.allocate(sizeof(PtrSize) + n * sizeof(T));
+
+			// Set the size of the block
+			*(PtrSize*)mem = n;
+
+			// Set the output address
+			out = (T*)(mem + sizeof(PtrSize));
+		}
+
+		// Call the constuctors
+		for(PtrSize i = 0; i < n; i++)
+		{
+			alloc.construct(&out[i], std::forward<Args>(args)...);
+		}
+
+		// Return result
+		return out;
+	}
+};
+
+/// Function that imitates the delete operator
+template<typename T, typename Alloc = Allocator<T>>
+struct Delete
+{
+	Alloc alloc;
+
+	Delete(const Alloc& alloc_ = Alloc())
+		: alloc(alloc_)
+	{}
+
+	void operator()(void* ptr)
+	{
+		T* p = (T*)ptr;
+
+		// Make sure the type is defined
+		typedef U8 TypeMustBeComplete[sizeof(T) ? 1 : -1];
+		(void) sizeof(TypeMustBeComplete);
+
+		if(p)
+		{
+			// Rebind allocator because the Alloc may be of another type
+			typename Alloc::template rebind<T>::other alloc(alloc);
+
+			// Call the destructor
+			alloc.destroy(p);
+
+			// Deallocate
+			alloc.deallocate(p, 1);
+		}
+	}
+};
+
+/// Function that imitates the delete[] operator
+template<typename T, typename Alloc = Allocator<T>>
+struct DeleteArray
+{
+	Alloc alloc;
+
+	DeleteArray(const Alloc& alloc_ = Alloc())
+		: alloc(alloc_)
+	{}
+
+	void operator()(void* ptr)
+	{
+		// Make sure the type is defined
+		typedef U8 TypeMustBeComplete[sizeof(T) ? 1 : -1];
+		(void) sizeof(TypeMustBeComplete);
+
+		T* p = (T*)ptr;
+
+		if(p)
+		{
+			// Get the allocated block
+			U8* block = (U8*)(p) - sizeof(PtrSize);
+
+			// Get number of elements
+			const PtrSize n = *(PtrSize*)block;
+
+			// Call the destructors
+			for(PtrSize i = 0; i < n; i++)
+			{
+				alloc.destroy(&p[i]);
+			}
+
+			// Deallocate the block
+			typename Alloc::template rebind<U8>::other allocc(alloc);
+			allocc.deallocate(block, n * sizeof(T) + sizeof(PtrSize));
+		}
+	}
+};
+
 /// @}
 /// @}
 

+ 1 - 2
src/renderer/Drawer.cpp

@@ -248,8 +248,7 @@ void RenderableDrawer::render(Frustumable& fr, RenderingStage stage,
 	GlStateSingleton::get().enable(GL_BLEND, blending);
 
 	// Calculate the LOD
-	Vec3 camPos =
-		fr.getSceneNode().getMovable()->getWorldTransform().getOrigin();
+	Vec3 camPos = fr.getFrustumableOrigin();
 
 	F32 dist = (renderable.getRenderableOrigin() - camPos).getLength();
 	U8 lod = r->calculateLod(dist);

+ 2 - 1
src/scene/Camera.cpp

@@ -14,7 +14,8 @@ Camera::Camera(CameraType type_,
 	:	SceneNode(name, scene),
 		Movable(movableFlags, movParent, *this, getSceneAllocator()),
 		Spatial(this, frustum),
-		Frustumable(frustum, this), type(type_)
+		Frustumable(frustum), 
+		type(type_)
 {}
 
 //==============================================================================

+ 2 - 2
src/scene/Light.cpp

@@ -47,8 +47,8 @@ PointLight::PointLight(const char* name, Scene* scene,
 //==============================================================================
 SpotLight::SpotLight(const char* name, Scene* scene,
 	U32 movableFlags, Movable* movParent)
-	: Light(LT_SPOT, name, scene, movableFlags, movParent, &frustum),
-		Frustumable(&frustum, this)
+	: 	Light(LT_SPOT, name, scene, movableFlags, movParent, &frustum),
+		Frustumable(&frustum)
 {
 	const F32 ang = toRad(45.0);
 	setOuterAngle(ang / 2.0);

+ 4 - 3
src/scene/ModelNode.cpp

@@ -11,9 +11,10 @@ namespace anki {
 //==============================================================================
 ModelPatchNode::ModelPatchNode(const ModelPatch* modelPatch_,
 	const char* name, Scene* scene,
-	uint movableFlags, Movable* movParent)
-	: SceneNode(name, scene),
+	U32 movableFlags, Movable* movParent)
+	: 	SceneNode(name, scene),
 		Movable(movableFlags, movParent, *this, getSceneAllocator()),
+		Renderable(getSceneAllocator()),
 		Spatial(this, &obb), modelPatch(modelPatch_)
 {
 	Renderable::init(*this);
@@ -27,7 +28,7 @@ ModelPatchNode::ModelPatchNode(const ModelPatch* modelPatch_,
 ModelNode::ModelNode(const char* modelFname,
 	const char* name, Scene* scene,
 	uint movableFlags, Movable* movParent)
-	: SceneNode(name, scene),
+	: 	SceneNode(name, scene),
 		Movable(movableFlags, movParent, *this, getSceneAllocator())
 {
 	model.load(modelFname);

+ 2 - 2
src/scene/ParticleEmitter.cpp

@@ -225,7 +225,8 @@ ParticleEmitter::ParticleEmitter(
 	U32 movableFlags, Movable* movParent)
 	:	SceneNode(name, scene),
 		Spatial(this, &aabb),
-		Movable(movableFlags, movParent, *this, getSceneAllocator())
+		Movable(movableFlags, movParent, *this, getSceneAllocator()),
+		Renderable(getSceneAllocator())
 {
 	// Load resource
 	particleEmitterResource.load(filename);
@@ -292,7 +293,6 @@ void ParticleEmitter::movableUpdate()
 //==============================================================================
 void ParticleEmitter::createParticlesSimulation(Scene* scene)
 {
-	// create the particles
 	collShape.reset(new btSphereShape(particle.size));
 
 	RigidBody::Initializer binit;

+ 8 - 1
src/scene/Renderable.cpp

@@ -7,7 +7,7 @@
 namespace anki {
 
 //==============================================================================
-// CreateNewRenderableVariableVisitor                                                    =
+// CreateNewRenderableVariableVisitor                                          =
 //==============================================================================
 
 /// Create a new RenderableVariable given a MaterialVariable
@@ -76,6 +76,11 @@ RenderableVariable::~RenderableVariable()
 // Renderable                                                                  =
 //==============================================================================
 
+//==============================================================================
+Renderable::Renderable(const SceneAllocator<U8>& alloc)
+	:	vars(alloc)
+{}
+
 //==============================================================================
 Renderable::~Renderable()
 {
@@ -95,6 +100,8 @@ void Renderable::init(PropertyMap& pmap)
 	vis.pmap = &pmap;
 	vis.vars = &vars;
 
+	vars.reserve(mtl.getVariables().size());
+
 	for(const MaterialVariable* mv : mtl.getVariables())
 	{
 		vis.mvar = mv;

+ 20 - 11
src/scene/SkinNode.cpp

@@ -57,8 +57,11 @@ SkinModelPatch::~SkinModelPatch()
 }
 
 //==============================================================================
-SkinModelPatch::SkinModelPatch(const ModelPatch* mpatch_)
-	: mpatch(mpatch_)
+SkinModelPatch::SkinModelPatch(const ModelPatch* mpatch_, 
+	const SceneAllocator<U8>& alloc)
+	:	mpatch(mpatch_),
+		skinMeshes(alloc),
+		xfbVaos(alloc)
 {
 #if 0
 	// Create the model patch
@@ -125,11 +128,12 @@ SkinPatchNode::SkinPatchNode(const ModelPatch* modelPatch_,
 	const char* name, Scene* scene,
 	uint movableFlags, Movable* movParent,
 	CollisionShape* spatialCs)
-	: SceneNode(name, scene),
+	: 	SceneNode(name, scene),
 		Movable(movableFlags, movParent, *this, getSceneAllocator()),
+		Renderable(getSceneAllocator()),
 		Spatial(this, spatialCs)
 {
-	skinModelPatch.reset(new SkinModelPatch(modelPatch_));
+	skinModelPatch.reset(new SkinModelPatch(modelPatch_, getSceneAllocator()));
 	Renderable::init(*this);
 }
 
@@ -141,8 +145,13 @@ SkinPatchNode::SkinPatchNode(const ModelPatch* modelPatch_,
 SkinNode::SkinNode(const char* skinFname,
 	const char* name, Scene* scene, // SceneNode
 	uint movableFlags, Movable* movParent) // Movable
-	: SceneNode(name, scene),
-		Movable(movableFlags, movParent, *this, getSceneAllocator())
+	:	SceneNode(name, scene),
+		Movable(movableFlags, movParent, *this, getSceneAllocator()),
+		patches(getSceneAllocator()),
+		heads(getSceneAllocator()),
+		tails(getSceneAllocator()),
+		boneRotations(getSceneAllocator()),
+		boneTranslations(getSceneAllocator())
 {
 	skin.load(skinFname);
 
@@ -211,7 +220,7 @@ void SkinNode::frameUpdate(float prevUpdateTime, float crntTime, int f)
 
 //==============================================================================
 void SkinNode::interpolate(const SkelAnim& animation, float frame,
-	Vector<Vec3>& boneTranslations, Vector<Mat3>& boneRotations)
+	SceneVector<Vec3>& boneTranslations, SceneVector<Mat3>& boneRotations)
 {
 	ANKI_ASSERT(frame < animation.getFramesNum());
 
@@ -276,7 +285,7 @@ void SkinNode::interpolate(const SkelAnim& animation, float frame,
 
 //==============================================================================
 void SkinNode::updateBoneTransforms(const Skeleton& skeleton,
-	Vector<Vec3>& boneTranslations, Vector<Mat3>& boneRotations)
+	SceneVector<Vec3>& boneTranslations, SceneVector<Mat3>& boneRotations)
 {
 	std::array<uint, 128> queue;
 	uint head = 0, tail = 0;
@@ -334,9 +343,9 @@ void SkinNode::updateBoneTransforms(const Skeleton& skeleton,
 
 //==============================================================================
 void SkinNode::deformHeadsTails(const Skeleton& skeleton,
-    const Vector<Vec3>& boneTranslations,
-    const Vector<Mat3>& boneRotations,
-	Vector<Vec3>& heads, Vector<Vec3>& tails)
+    const SceneVector<Vec3>& boneTranslations,
+    const SceneVector<Mat3>& boneRotations,
+	SceneVector<Vec3>& heads, SceneVector<Vec3>& tails)
 {
 	for(uint i = 0; i < skeleton.getBones().size(); i++)
 	{

+ 1 - 2
src/scene/VisibilityTester.cpp

@@ -252,8 +252,7 @@ void VisibilityTester::test(Frustumable& ref, Scene& scene, Renderer& r)
 	DistanceSortJob dsjob;
 	dsjob.nodes = vinfo.lights.begin();
 	dsjob.nodesCount = vinfo.lights.size();
-	dsjob.origin =
-		ref.getSceneNode().getMovable()->getWorldTransform().getOrigin();
+	dsjob.origin = ref.getFrustumableOrigin();
 	threadPool.assignNewJob(0, &dsjob);
 
 	// The rest of the jobs are dummy