Explorar o código

PhysX start up and shutdown

BearishSun %!s(int64=10) %!d(string=hai) anos
pai
achega
3f51844036

+ 1 - 1
BansheeCore/Include/BsCorePrerequisites.h

@@ -98,7 +98,7 @@
 #endif
 
 // Linux/Apple Settings
-#if BS_PLATFORM == BS_PLATFORM_LINUX || BS_PLATFORM == BS_PLATFORM_APPLE
+#if BS_PLATFORM == BS_PLATFORM_LINUX || BS_PLATFORM == BS_PLATFORM_OSX
 
 // Enable GCC symbol visibility
 #   if defined( BS_GCC_VISIBILITY )

+ 11 - 0
BansheeCore/Include/BsPhysics.h

@@ -8,6 +8,17 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT Physics : public Module<Physics>
 	{
 	public:
+		Physics();
 		virtual ~Physics() { }
+
+		virtual void update() = 0;
+
+		void toggleCollision(UINT64 groupA, UINT64 groupB, bool enabled);
+		bool isCollisionEnabled(UINT64 groupA, UINT64 groupB) const;
+
+		static const UINT64 CollisionMapSize = 64;
+	protected:
+		mutable Mutex mMutex;
+		bool mCollisionMap[CollisionMapSize][CollisionMapSize];
 	};
 }

+ 20 - 1
BansheeCore/Source/BsPhysics.cpp

@@ -2,5 +2,24 @@
 
 namespace BansheeEngine
 {
-	
+	Physics::Physics()
+	{
+		memset(mCollisionMap, 1, CollisionMapSize * CollisionMapSize * sizeof(bool));
+	}
+
+	void Physics::toggleCollision(UINT64 groupA, UINT64 groupB, bool enabled)
+	{
+		assert(groupA < CollisionMapSize && groupB < CollisionMapSize);
+
+		mMutex.lock();
+		mCollisionMap[groupA][groupB] = enabled;
+	}
+
+	bool Physics::isCollisionEnabled(UINT64 groupA, UINT64 groupB) const
+	{
+		assert(groupA < CollisionMapSize && groupB < CollisionMapSize);
+
+		mMutex.lock();
+		return mCollisionMap[groupA][groupB];
+	}
 }

+ 4 - 0
BansheeEngine.sln

@@ -62,6 +62,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BansheeEditorExec", "Banshe
 		{CC7F9445-71C9-4559-9976-FF0A64DCB582} = {CC7F9445-71C9-4559-9976-FF0A64DCB582}
 		{2DA6824A-4D3A-4B59-8AE9-85D3C14074A3} = {2DA6824A-4D3A-4B59-8AE9-85D3C14074A3}
 		{1437BB4E-DDB3-4307-AA41-8C035DA3014B} = {1437BB4E-DDB3-4307-AA41-8C035DA3014B}
+		{69517850-7050-4A1A-B03F-6DC4498B0340} = {69517850-7050-4A1A-B03F-6DC4498B0340}
 		{B280B769-1BA4-42AF-8263-D644A67B4473} = {B280B769-1BA4-42AF-8263-D644A67B4473}
 		{F58FF869-2EA6-4FFF-AB84-328C531BA9D9} = {F58FF869-2EA6-4FFF-AB84-328C531BA9D9}
 		{08975177-4A13-4EE7-BB21-3BB92FB3F3CC} = {08975177-4A13-4EE7-BB21-3BB92FB3F3CC}
@@ -88,11 +89,13 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExampleProject", "ExamplePr
 		{122B7A22-0C62-4B35-B661-EBF3F394EA79} = {122B7A22-0C62-4B35-B661-EBF3F394EA79}
 		{CC7F9445-71C9-4559-9976-FF0A64DCB582} = {CC7F9445-71C9-4559-9976-FF0A64DCB582}
 		{1437BB4E-DDB3-4307-AA41-8C035DA3014B} = {1437BB4E-DDB3-4307-AA41-8C035DA3014B}
+		{69517850-7050-4A1A-B03F-6DC4498B0340} = {69517850-7050-4A1A-B03F-6DC4498B0340}
 		{F58FF869-2EA6-4FFF-AB84-328C531BA9D9} = {F58FF869-2EA6-4FFF-AB84-328C531BA9D9}
 		{08975177-4A13-4EE7-BB21-3BB92FB3F3CC} = {08975177-4A13-4EE7-BB21-3BB92FB3F3CC}
 		{AB6C9284-D1CB-4AAD-BA4B-8A9E81AD1A73} = {AB6C9284-D1CB-4AAD-BA4B-8A9E81AD1A73}
 		{07B0C186-5173-46F2-BE26-7E4148BD0CCA} = {07B0C186-5173-46F2-BE26-7E4148BD0CCA}
 		{7F449698-73DF-4203-9F31-0877DBF01695} = {7F449698-73DF-4203-9F31-0877DBF01695}
+		{2BA791F1-87F6-4863-A784-D07FF605AC5E} = {2BA791F1-87F6-4863-A784-D07FF605AC5E}
 		{BFEBBAF8-8A84-4899-8899-D0D7196AF9A1} = {BFEBBAF8-8A84-4899-8899-D0D7196AF9A1}
 		{796B6DFF-BA04-42B7-A43A-2B14D707A33A} = {796B6DFF-BA04-42B7-A43A-2B14D707A33A}
 	EndProjectSection
@@ -166,6 +169,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Game", "Game\Game.vcxproj",
 		{876EB338-489E-4727-84DA-8CBBF0DA5B5E} = {876EB338-489E-4727-84DA-8CBBF0DA5B5E}
 		{CC7F9445-71C9-4559-9976-FF0A64DCB582} = {CC7F9445-71C9-4559-9976-FF0A64DCB582}
 		{1437BB4E-DDB3-4307-AA41-8C035DA3014B} = {1437BB4E-DDB3-4307-AA41-8C035DA3014B}
+		{69517850-7050-4A1A-B03F-6DC4498B0340} = {69517850-7050-4A1A-B03F-6DC4498B0340}
 		{F58FF869-2EA6-4FFF-AB84-328C531BA9D9} = {F58FF869-2EA6-4FFF-AB84-328C531BA9D9}
 		{08975177-4A13-4EE7-BB21-3BB92FB3F3CC} = {08975177-4A13-4EE7-BB21-3BB92FB3F3CC}
 		{AB6C9284-D1CB-4AAD-BA4B-8A9E81AD1A73} = {AB6C9284-D1CB-4AAD-BA4B-8A9E81AD1A73}

+ 1 - 0
BansheePhysX/BansheePhysX.vcxproj

@@ -245,6 +245,7 @@
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>
+    <ClCompile Include="Source\BsPhysX.cpp" />
     <ClCompile Include="Source\BsPhysXPlugin.cpp" />
   </ItemGroup>
   <ItemGroup>

+ 3 - 0
BansheePhysX/BansheePhysX.vcxproj.filters

@@ -14,6 +14,9 @@
     <ClCompile Include="Source\BsPhysXPlugin.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsPhysX.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="Include\BsPhysXPrerequisites.h">

+ 17 - 1
BansheePhysX/Include/BsPhysX.h

@@ -2,11 +2,27 @@
 
 #include "BsPhysXPrerequisites.h"
 #include "BsPhysics.h"
+#include "PxPhysics.h"
+#include "foundation/Px.h"
+#include "cooking/PxCooking.h"
 
 namespace BansheeEngine
 {
 	class PhysX : public Physics
 	{
-		
+	public:
+		PhysX();
+		~PhysX();
+
+		void update() override;
+
+	private:
+		float mSimulationStep = 1.0f/60.0f;
+		float mLastSimulationTime = 0.0f;
+
+		physx::PxFoundation* mFoundation = nullptr;
+		physx::PxPhysics* mPhysics = nullptr;
+		physx::PxCooking* mCooking = nullptr;
+		physx::PxScene* mScene = nullptr;
 	};
 }

+ 234 - 0
BansheePhysX/Source/BsPhysX.cpp

@@ -0,0 +1,234 @@
+#include "BsPhysX.h"
+#include "PxPhysicsAPI.h"
+#include "BsTaskScheduler.h"
+#include "BsTime.h"
+#include "Bsvector3.h"
+
+using namespace physx;
+
+namespace BansheeEngine
+{
+	struct PHYSICS_INIT_DESC
+	{
+		float typicalLength = 1.0f;
+		float typicalSpeed = 9.81f;
+		Vector3 gravity = Vector3(0.0f, -9.81f, 0.0f);
+		bool initCooking = false;
+		float timeStep = 1.0f / 60.0f;
+	};
+
+	class PhysXAllocator : public PxAllocatorCallback
+	{
+	public:
+		void* allocate(size_t size, const char*, const char*, int) override
+		{
+			void* ptr = bs_alloc_aligned16(size);
+			PX_ASSERT((reinterpret_cast<size_t>(ptr) & 15) == 0);
+			return ptr;
+		}
+
+		void deallocate(void* ptr) override
+		{
+			bs_free_aligned16(ptr);
+		}
+	};
+
+	class PhysXErrorCallback : public PxErrorCallback
+	{
+	public:
+		void reportError(PxErrorCode::Enum code, const char* message, const char* file, int line) override
+		{
+			{
+				const char* errorCode = nullptr;
+
+				UINT32 severity = 0;
+				switch (code)
+				{
+				case PxErrorCode::eNO_ERROR:
+					errorCode = "No error";
+					break;
+				case PxErrorCode::eINVALID_PARAMETER:
+					errorCode = "Invalid parameter";
+					severity = 2;
+					break;
+				case PxErrorCode::eINVALID_OPERATION:
+					errorCode = "Invalid operation";
+					severity = 2;
+					break;
+				case PxErrorCode::eOUT_OF_MEMORY:
+					errorCode = "Out of memory";
+					severity = 2;
+					break;
+				case PxErrorCode::eDEBUG_INFO:
+					errorCode = "Info";
+					break;
+				case PxErrorCode::eDEBUG_WARNING:
+					errorCode = "Warning";
+					severity = 1;
+					break;
+				case PxErrorCode::ePERF_WARNING:
+					errorCode = "Performance warning";
+					severity = 1;
+					break;
+				case PxErrorCode::eABORT:
+					errorCode = "Abort";
+					severity = 2;
+					break;
+				case PxErrorCode::eINTERNAL_ERROR:
+					errorCode = "Internal error";
+					severity = 2;
+					break;
+				case PxErrorCode::eMASK_ALL:
+				default:
+					errorCode = "Unknown error";
+					severity = 2;
+					break;
+				}
+
+				StringStream ss;
+
+				switch(severity)
+				{
+				case 0:
+					ss << "PhysX info (" << errorCode << "): " << message << " at " << file << ":" << line;
+					LOGDBG(ss.str());
+					break;
+				case 1:
+					ss << "PhysX warning (" << errorCode << "): " << message << " at " << file << ":" << line;
+					LOGWRN(ss.str());
+					break;
+				case 2:
+					ss << "PhysX error (" << errorCode << "): " << message << " at " << file << ":" << line;
+					LOGERR(ss.str());
+					BS_ASSERT(false); // Halt execution on debug builds when error occurrs
+					break;
+				}
+			}
+		}
+	};
+
+	class PhysXCPUDispatcher : public PxCpuDispatcher
+	{
+	public:
+		void submitTask(PxBaseTask& physxTask) override
+		{
+			// TODO - Banshee's task scheduler is pretty low granularity. Consider a better task manager in case PhysX ends
+			// up submitting many tasks.
+			// - PhysX's task manager doesn't seem much lighter either. But perhaps I can at least create a task pool to 
+			//   avoid allocating them constantly.
+
+			auto runTask = [&]() { physxTask.run(); physxTask.release(); };
+			TaskPtr task = Task::create("PhysX", runTask);
+
+			TaskScheduler::instance().addTask(task);
+		}
+
+		PxU32 getWorkerCount() const override
+		{
+			return (PxU32)TaskScheduler::instance().getNumWorkers();
+		}
+	};
+
+	PxFilterFlags PhysXFilterShader(PxFilterObjectAttributes attr0, PxFilterData data0, PxFilterObjectAttributes attr1, 
+		PxFilterData data1, PxPairFlags& pairFlags, const void* constantBlock, PxU32 constantBlockSize)
+	{
+		if (PxFilterObjectIsTrigger(attr0) || PxFilterObjectIsTrigger(attr1))
+		{
+			pairFlags = PxPairFlag::eTRIGGER_DEFAULT;
+			return PxFilterFlags();
+		}
+
+		UINT64 groupA = *(UINT64*)&data0.word0;
+		UINT64 groupB = *(UINT64*)&data1.word0;
+
+		bool canCollide = Physics::instance().isCollisionEnabled(groupA, groupB);
+		if (!canCollide)
+			return PxFilterFlag::eSUPPRESS;
+
+		pairFlags = PxPairFlag::eCONTACT_DEFAULT;
+		return PxFilterFlags();
+	}
+
+	PxVec3 toPxVector(Vector3 input)
+	{
+		return PxVec3(input.x, input.y, input.z);
+	}
+
+	static PhysXAllocator gPhysXAllocator;
+	static PhysXErrorCallback gPhysXErrorHandler;
+	static PhysXCPUDispatcher gPhysXCPUDispatcher;
+	
+	PhysX::PhysX()
+	{
+		PHYSICS_INIT_DESC input; // TODO - Make this an input parameter.
+
+		PxTolerancesScale scale; // TODO - Use these same values for cooking, physx init and scene desc
+		scale.length = input.typicalLength;
+		scale.speed = input.typicalSpeed;
+
+		mFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gPhysXAllocator, gPhysXErrorHandler);
+		mPhysics = PxCreateBasePhysics(PX_PHYSICS_VERSION, *mFoundation, scale);
+
+		PxRegisterArticulations(*mPhysics);
+
+		if (input.initCooking)
+		{
+			PxCookingParams cookingParams(scale); // TODO - Potentially allow more customization to set up cooking params
+			mCooking = PxCreateCooking(PX_PHYSICS_VERSION, *mFoundation, cookingParams);
+		}
+
+		PxSceneDesc sceneDesc(scale); // TODO - Test out various other parameters provided by scene desc
+		sceneDesc.gravity = toPxVector(input.gravity);
+		sceneDesc.cpuDispatcher = &gPhysXCPUDispatcher;
+		sceneDesc.filterShader = PhysXFilterShader;
+
+		// TODO - Hook up triggers
+		// TODO - Allow for continuous collision detection, and regions of interest stuff
+		// TODO - Set up various performance limits, call flushCache when needed
+		// TODO - Probably many more startup settings I'm missing
+
+		mScene = mPhysics->createScene(sceneDesc);
+		mSimulationStep = input.timeStep;
+	}
+
+	PhysX::~PhysX()
+	{
+		mScene->release();
+
+		if (mCooking != nullptr)
+			mCooking->release();
+
+		mPhysics->release();
+		mFoundation->release();
+	}
+
+	void PhysX::update()
+	{
+		float nextFrameTime = mLastSimulationTime + mSimulationStep;
+		float curFrameTime = gTime().getTime();
+		if(curFrameTime < nextFrameTime)
+		{
+			// TODO - Interpolate rigidbodies but perform no actual simulation
+
+			return;
+		}
+
+		float simulationAmount = curFrameTime - mLastSimulationTime;
+		while (simulationAmount >= mSimulationStep) // In case we're running really slow multiple updates might be needed
+		{
+			// TODO - Consider delaying fetchResults one frame. This could improve performance but at a cost to input latency.
+			// TODO - Provide a scratch buffer for the simulation (use the frame allocator, but I must extend it so it allocates
+			//	      on a 16 byte boundary).
+			mScene->simulate(mSimulationStep);
+			mScene->fetchResults(true);
+
+			// TODO - Update all rigidbody transfroms from their PhsyX state
+
+			simulationAmount -= mSimulationStep;
+		}
+
+		// TODO - Consider extrapolating for the remaining "simulationAmount" value
+
+		mLastSimulationTime = curFrameTime; 
+	}
+}

+ 2 - 10
BansheeUtility/Include/BsGlobalFrameAlloc.h

@@ -158,25 +158,17 @@ namespace BansheeEngine
 	class MemoryAllocator<FrameAlloc> : public MemoryAllocatorBase
 	{
 	public:
+		/** Allocates @p bytes bytes. */
 		static void* allocate(size_t bytes)
 		{
 			return bs_frame_alloc((UINT32)bytes);
 		}
 
-		static void* allocateArray(size_t bytes, UINT32 count)
-		{
-			return bs_frame_alloc((UINT32)(bytes * count));
-		}
-
+		/** Frees the memory at the specified location. */
 		static void free(void* ptr)
 		{
 			bs_frame_free(ptr);
 		}
-
-		static void freeArray(void* ptr, UINT32 count)
-		{
-			bs_frame_free(ptr);
-		}
 	};
 
 	/** @endcond */

+ 0 - 14
BansheeUtility/Include/BsMemAllocProfiler.h

@@ -27,25 +27,11 @@ namespace BansheeEngine
 			return malloc(bytes);
 		}
 
-		/** Allocates the given a number of objects, each of the given number of bytes. */
-		static void* allocateArray(size_t bytes, UINT32 count)
-		{
-			return malloc(bytes * count);
-		}
-
 		/** Frees memory previously allocated with allocate(). */
 		static void free(void* ptr)
 		{
 			::free(ptr);
 		}
-
-		/**
-		 * Frees memory previously allocated with freeArray(). @p count must match the original value when array was allocated.
-		 */
-		static void freeArray(void* ptr, UINT32 count)
-		{
-			::free(ptr);
-		}
 	};
 
 	/** @} */

+ 0 - 10
BansheeUtility/Include/BsMemStack.h

@@ -365,20 +365,10 @@ namespace BansheeEngine
 			return bs_stack_alloc((UINT32)bytes);
 		}
 
-		static void* allocateArray(size_t bytes, UINT32 count)
-		{
-			return bs_stack_alloc((UINT32)(bytes * count));
-		}
-
 		static void free(void* ptr)
 		{
 			bs_stack_free(ptr);
 		}
-
-		static void freeArray(void* ptr, UINT32 count)
-		{
-			bs_stack_free(ptr);
-		}
 	};
 
 	/** @endcond */

+ 133 - 8
BansheeUtility/Include/BsMemoryAllocator.h

@@ -17,6 +17,76 @@ namespace BansheeEngine
 
 	/** @cond INTERNAL */
 
+#if BS_PLATFORM == BS_PLATFORM_WIN32
+	inline void* platformAlignedAlloc16(size_t size)
+	{
+		return _aligned_malloc(size, 16);
+	}
+
+	inline void platformAlignedFree16(void* ptr)
+	{
+		_aligned_free(ptr);
+	}
+
+	inline void* platformAlignedAlloc(size_t size, size_t alignment)
+	{
+		return _aligned_malloc(size, alignment);
+	}
+
+	inline void platformAlignedFree(void* ptr)
+	{
+		_aligned_free(ptr);
+	}
+#elif BS_PLATFORM == BS_PLATFORM_LINUX || BS_PLATFORM == BS_PLATFORM_ANDROID
+	inline void* platformAlignedAlloc16(size_t size)
+	{
+		return ::memalign(16, size);
+	}
+
+	inline void platformAlignedFree16(void* ptr)
+	{
+		::free(ptr);
+	}
+
+	inline void* platformAlignedAlloc(size_t size, size_t alignment)
+	{
+		return ::memalign(alignment, size);
+	}
+
+	inline void platformAlignedFree(void* ptr)
+	{
+		::free(ptr);
+	}
+#else // 16 byte aligment by default
+	inline void* platformAlignedAlloc16(size_t size)
+	{
+		return ::malloc(size);
+	}
+
+	inline void platformAlignedFree16(void* ptr)
+	{
+		::free(ptr);
+	}
+
+	inline void* platformAlignedAlloc(size_t size, size_t alignment)
+	{
+		void* data = ::malloc(size + (alignment - 1) + sizeof(void*));
+		if (data == nullptr)
+			return nullptr;
+
+		UINT8* alignedData = ((UINT8*)data) + sizeof(void*);
+		alignedData += alignment - ((uintptr_t)alignedData) & (alignment - 1);
+
+		((void**)alignedData)[-1] = data;
+		return alignedData;
+	}
+
+	inline void platformAlignedFree(void* ptr)
+	{
+		::free(((void**)ptr)[-1]);
+	}
+#endif
+
 	/**
 	 * Thread safe class used for storing total number of memory allocations and deallocations, primarily for statistic 
 	 * purposes.
@@ -63,6 +133,7 @@ namespace BansheeEngine
 	class MemoryAllocator : public MemoryAllocatorBase
 	{
 	public:
+		/** Allocates @p bytes bytes. */
 		static void* allocate(size_t bytes)
 		{
 #if BS_PROFILING_ENABLED
@@ -72,25 +143,51 @@ namespace BansheeEngine
 			return malloc(bytes);
 		}
 
-		static void* allocateArray(size_t bytes, UINT32 count)
+		/** 
+		 * Allocates @p bytes and aligns them to the specified boundary (in bytes). If the aligment is less or equal to
+		 * 16 it is more efficient to use the allocateAligned16() alternative of this method. Alignment must be power of two.
+		 */
+		static void* allocateAligned(size_t bytes, size_t alignment)
 		{
 #if BS_PROFILING_ENABLED
 			incAllocCount();
 #endif
 
-			return malloc(bytes * count);
+			return platformAlignedAlloc(bytes, alignment);
 		}
 
-		static void free(void* ptr)
+		/** Allocates @p bytes and aligns them to a 16 byte boundary. */
+		static void* allocateAligned16(size_t bytes)
+		{
+#if BS_PROFILING_ENABLED
+			incAllocCount();
+#endif
+
+			return platformAlignedAlloc16(bytes);
+		}
+
+		/** Frees memory allocated with allocateAligned() */
+		static void freeAligned(void* ptr)
 		{
 #if BS_PROFILING_ENABLED
 			incFreeCount();
 #endif
 
-			::free(ptr);
+			platformAlignedFree(ptr);
+		}
+
+		/** Frees memory allocated with allocateAligned16() */
+		static void freeAligned16(void* ptr)
+		{
+#if BS_PROFILING_ENABLED
+			incFreeCount();
+#endif
+
+			platformAlignedFree16(ptr);
 		}
 
-		static void freeArray(void* ptr, UINT32 count)
+		/** Frees the memory at the specified location. */
+		static void free(void* ptr)
 		{
 #if BS_PROFILING_ENABLED
 			incFreeCount();
@@ -127,7 +224,7 @@ namespace BansheeEngine
 	template<class T, class Alloc> 
 	inline T* bs_newN(UINT32 count)
 	{
-		T* ptr = (T*)MemoryAllocator<Alloc>::allocateArray(sizeof(T), count);
+		T* ptr = (T*)MemoryAllocator<Alloc>::allocate(sizeof(T) * count);
 
 		for(unsigned int i = 0; i < count; i++)
 			new ((void*)&ptr[i]) T;
@@ -165,7 +262,7 @@ namespace BansheeEngine
 		for(unsigned int i = 0; i < count; i++)
 			ptr[i].~T();
 
-		MemoryAllocator<Alloc>::freeArray(ptr, count);
+		MemoryAllocator<Alloc>::free(ptr);
 	}
 
 	/*****************************************************************************/
@@ -185,6 +282,22 @@ namespace BansheeEngine
 		return (T*)MemoryAllocator<GenAlloc>::allocate(sizeof(T));
 	}
 
+	/** 
+	 * Allocates the specified number of bytes aligned to the provided boundary. Boundary is in bytes and must be a power 
+	 * of two.
+	 */
+	inline void* bs_alloc_aligned(UINT32 count, UINT32 align)
+	{
+		return MemoryAllocator<GenAlloc>::allocateAligned(count, align);
+	}
+
+
+	/** Allocates the specified number of bytes aligned to a 16 bytes boundary. */
+	inline void* bs_alloc_aligned16(UINT32 count)
+	{
+		return MemoryAllocator<GenAlloc>::allocateAligned16(count);
+	}
+
 	/** Allocates enough bytes to hold an array of @p count elements the specified type, but doesn't construct them. */
 	template<class T> 
 	inline T* bs_allocN(UINT32 count)
@@ -196,7 +309,7 @@ namespace BansheeEngine
 	template<class T> 
 	inline T* bs_newN(UINT32 count)
 	{
-		T* ptr = (T*)MemoryAllocator<GenAlloc>::allocateArray(sizeof(T), count);
+		T* ptr = (T*)MemoryAllocator<GenAlloc>::allocate(count * sizeof(T));
 
 		for(unsigned int i = 0; i < count; i++)
 			new ((void*)&ptr[i]) T;
@@ -217,6 +330,18 @@ namespace BansheeEngine
 		MemoryAllocator<GenAlloc>::free(ptr);
 	}
 
+	/** Frees memory previously allocated with bs_alloc_aligned(). */
+	inline void bs_free_aligned(void* ptr)
+	{
+		MemoryAllocator<GenAlloc>::freeAligned(ptr);
+	}
+
+	/** Frees memory previously allocated with bs_alloc_aligned16(). */
+	inline void bs_free_aligned16(void* ptr)
+	{
+		MemoryAllocator<GenAlloc>::freeAligned16(ptr);
+	}
+
 /************************************************************************/
 /* 							MACRO VERSIONS                      		*/
 /* You will almost always want to use the template versions but in some */

+ 4 - 2
BansheeUtility/Include/BsPlatformDefines.h

@@ -5,7 +5,9 @@
 // Initial platform/compiler-related stuff to set.
 #define BS_PLATFORM_WIN32 1
 #define BS_PLATFORM_LINUX 2
-#define BS_PLATFORM_APPLE 3
+#define BS_PLATFORM_OSX 3
+#define BS_PLATFORM_IOS 4
+#define BS_PLATFORM_ANDROID 5
 
 #define BS_COMPILER_MSVC 1
 #define BS_COMPILER_GNUC 2
@@ -108,7 +110,7 @@
 #endif // BS_PLATFORM == BS_PLATFORM_WIN32
 
 // Linux/Apple Settings
-#if BS_PLATFORM == BS_PLATFORM_LINUX || BS_PLATFORM == BS_PLATFORM_APPLE
+#if BS_PLATFORM == BS_PLATFORM_LINUX || BS_PLATFORM == BS_PLATFORM_OSX
 
 // Enable GCC symbol visibility
 #   if defined( BS_GCC_VISIBILITY )

+ 1 - 1
BansheeUtility/Include/BsPrerequisitesUtil.h

@@ -137,7 +137,7 @@
 #endif
 
 // Linux/Apple Settings
-#if BS_PLATFORM == BS_PLATFORM_LINUX || BS_PLATFORM == BS_PLATFORM_APPLE
+#if BS_PLATFORM == BS_PLATFORM_LINUX || BS_PLATFORM == BS_PLATFORM_OSX
 // A quick define to overcome different names for the same function
 #   define stricmp strcasecmp
 

+ 1 - 1
BansheeUtility/Include/BsStdHeaders.h

@@ -93,7 +93,7 @@ extern "C" {
 }
 #endif
 
-#if BS_PLATFORM == BS_PLATFORM_APPLE
+#if BS_PLATFORM == BS_PLATFORM_OSX
 extern "C" {
 #   include <unistd.h>
 #   include <sys/param.h>

+ 2 - 0
BansheeUtility/Include/BsTaskScheduler.h

@@ -105,6 +105,8 @@ namespace BansheeEngine
 		/**	Removes a worker thread (as soon as its current task is finished). */
 		void removeWorker();
 
+		/** Returns the maximum available worker threads (maximum number of tasks that can be executed simultaneously). */
+		UINT32 getNumWorkers() const { return mMaxActiveTasks; }
 	protected:
 		friend class Task;
 

+ 4 - 2
BansheeUtility/Source/BsDynLib.cpp

@@ -11,7 +11,7 @@
 #  include <windows.h>
 #endif
 
-#if BS_PLATFORM == BS_PLATFORM_APPLE
+#if BS_PLATFORM == BS_PLATFORM_OSX
 #   include "macUtils.h"
 #   include <dlfcn.h>
 #endif
@@ -40,7 +40,7 @@ namespace BansheeEngine
         // dlopen() does not add .so to the filename, like windows does for .dll
         if (name.substr(name.length() - 3, 3) != ".so")
            name += ".so";
-#elif BS_PLATFORM == BS_PLATFORM_APPLE
+#elif BS_PLATFORM == BS_PLATFORM_OSX
         // dlopen() does not add .dylib to the filename, like windows does for .dll
         if (name.substr(name.length() - 6, 6) != ".dylib")
 			name += ".dylib";
@@ -52,6 +52,8 @@ namespace BansheeEngine
 #endif
         m_hInst = (DYNLIB_HANDLE)DYNLIB_LOAD(name.c_str());
 
+		DWORD lastError = GetLastError();
+
         if(!m_hInst)
 		{
             BS_EXCEPT(InternalErrorException,  

+ 1 - 1
BansheeUtility/Source/BsDynLibManager.cpp

@@ -15,7 +15,7 @@ namespace BansheeEngine
 #if BS_PLATFORM == BS_PLATFORM_LINUX
 		if (name.substr(name.length() - 3, 3) != ".so")
 			name += ".so";
-#elif BS_PLATFORM == BS_PLATFORM_APPLE
+#elif BS_PLATFORM == BS_PLATFORM_OSX
 		if (name.substr(name.length() - 6, 6) != ".dylib")
 			name += ".dylib";
 #elif BS_PLATFORM == BS_PLATFORM_WIN32