소스 검색

Global frame alloc

Marko Pintera 10 년 전
부모
커밋
d0c5ecfb11

+ 2 - 2
BansheeEditor/Source/BsGUISceneTreeView.cpp

@@ -102,7 +102,7 @@ namespace BansheeEngine
 		{
 			Vector<TreeElement*> newChildren;
 
-			bool* tempToDelete = (bool*)stackAlloc(sizeof(bool) * (UINT32)element->mChildren.size());
+			bool* tempToDelete = (bool*)bs_stack_alloc(sizeof(bool) * (UINT32)element->mChildren.size());
 			for(UINT32 i = 0; i < (UINT32)element->mChildren.size(); i++)
 				tempToDelete[i] = true;
 
@@ -157,7 +157,7 @@ namespace BansheeEngine
 				deleteTreeElementInternal(element->mChildren[i]);
 			}
 
-			stackDeallocLast(tempToDelete);
+			bs_stack_free(tempToDelete);
 
 			element->mChildren = newChildren;
 			needsUpdate = true;

+ 2 - 2
BansheeEngine/Include/BsSpriteTexture.h

@@ -67,12 +67,12 @@ namespace BansheeEngine
 		/**
 		 * @copydoc	Resource::getResourceDependencies
 		 */
-		void getResourceDependencies(Vector<HResource>& dependencies) const;
+		void getResourceDependencies(Vector<HResource>& dependencies) const override;
 
 		/**
 		 * @copydoc	CoreObject::getCoreDependencies
 		 */
-		void getCoreDependencies(Vector<SPtr<CoreObject>>& dependencies);
+		void getCoreDependencies(Vector<SPtr<CoreObject>>& dependencies) override;
 
 		HTexture mAtlasTexture;
 		Vector2 mUVOffset;

+ 2 - 2
BansheeEngine/Source/BsGUILayoutUtility.cpp

@@ -28,7 +28,7 @@ namespace BansheeEngine
 		Rect2I* elementAreas = nullptr;
 
 		if (numElements > 0)
-			elementAreas = stackConstructN<Rect2I>(numElements);
+			elementAreas = bs_stack_new<Rect2I>(numElements);
 
 		Rect2I parentArea;
 		parentArea.width = width;
@@ -65,7 +65,7 @@ namespace BansheeEngine
 		Vector2I actualSize = layout->_calcActualSize(0, 0, actualAreas, numElements);
 
 		if (elementAreas != nullptr)
-			stackDeallocLast(elementAreas);
+			bs_stack_free(elementAreas);
 
 		return actualSize;
 	}

+ 6 - 6
BansheeEngine/Source/BsGUILayoutX.cpp

@@ -107,10 +107,10 @@ namespace BansheeEngine
 
 		if (mChildren.size() > 0)
 		{
-			processedElements = stackAllocN<bool>((UINT32)mChildren.size());
+			processedElements = bs_stack_alloc<bool>((UINT32)mChildren.size());
 			memset(processedElements, 0, mChildren.size() * sizeof(bool));
 
-			elementScaleWeights = stackAllocN<float>((UINT32)mChildren.size());
+			elementScaleWeights = bs_stack_alloc<float>((UINT32)mChildren.size());
 			memset(elementScaleWeights, 0, mChildren.size() * sizeof(float));
 		}
 
@@ -380,10 +380,10 @@ namespace BansheeEngine
 		}
 
 		if (elementScaleWeights != nullptr)
-			stackDeallocLast(elementScaleWeights);
+			bs_stack_free(elementScaleWeights);
 
 		if (processedElements != nullptr)
-			stackDeallocLast(processedElements);
+			bs_stack_free(processedElements);
 	}
 
 	void GUILayoutX::_updateLayoutInternal(const GUILayoutData& data)
@@ -392,7 +392,7 @@ namespace BansheeEngine
 		Rect2I* elementAreas = nullptr;
 
 		if (numElements > 0)
-			elementAreas = stackConstructN<Rect2I>(numElements);
+			elementAreas = bs_stack_new<Rect2I>(numElements);
 
 		_getElementAreas(data.area, elementAreas, numElements, mChildSizeRanges, mSizeRange);
 
@@ -413,7 +413,7 @@ namespace BansheeEngine
 		}
 
 		if(elementAreas != nullptr)
-			stackDeallocLast(elementAreas);
+			bs_stack_free(elementAreas);
 	}
 
 	Vector2I GUILayoutX::_calcActualSize(INT32 x, INT32 y, Rect2I* elementAreas, UINT32 numElements) const

+ 6 - 6
BansheeEngine/Source/BsGUILayoutY.cpp

@@ -107,10 +107,10 @@ namespace BansheeEngine
 
 		if (mChildren.size() > 0)
 		{
-			processedElements = stackAllocN<bool>((UINT32)mChildren.size());
+			processedElements = bs_stack_alloc<bool>((UINT32)mChildren.size());
 			memset(processedElements, 0, mChildren.size() * sizeof(bool));
 
-			elementScaleWeights = stackAllocN<float>((UINT32)mChildren.size());
+			elementScaleWeights = bs_stack_alloc<float>((UINT32)mChildren.size());
 			memset(elementScaleWeights, 0, mChildren.size() * sizeof(float));
 		}
 
@@ -334,10 +334,10 @@ namespace BansheeEngine
 		}
 
 		if (elementScaleWeights != nullptr)
-			stackDeallocLast(elementScaleWeights);
+			bs_stack_free(elementScaleWeights);
 
 		if (processedElements != nullptr)
-			stackDeallocLast(processedElements);
+			bs_stack_free(processedElements);
 
 		// Compute offsets and width
 		UINT32 yOffset = 0;
@@ -390,7 +390,7 @@ namespace BansheeEngine
 		Rect2I* elementAreas = nullptr;
 		
 		if (numElements > 0)
-			elementAreas = stackConstructN<Rect2I>(numElements);
+			elementAreas = bs_stack_new<Rect2I>(numElements);
 
 		_getElementAreas(data.area, elementAreas, numElements, mChildSizeRanges, mSizeRange);
 
@@ -411,7 +411,7 @@ namespace BansheeEngine
 		}
 
 		if (elementAreas != nullptr)
-			stackDeallocLast(elementAreas);
+			bs_stack_free(elementAreas);
 	}
 
 	Vector2I GUILayoutY::_calcActualSize(INT32 x, INT32 y, Rect2I* elementAreas, UINT32 numElements) const

+ 2 - 2
BansheeEngine/Source/BsGUIPanel.cpp

@@ -199,7 +199,7 @@ namespace BansheeEngine
 		Rect2I* elementAreas = nullptr;
 
 		if (numElements > 0)
-			elementAreas = stackConstructN<Rect2I>(numElements);
+			elementAreas = bs_stack_new<Rect2I>(numElements);
 
 		_getElementAreas(data.area, elementAreas, numElements, mChildSizeRanges, mSizeRange);
 
@@ -215,7 +215,7 @@ namespace BansheeEngine
 		}
 
 		if (elementAreas != nullptr)
-			stackDeallocLast(elementAreas);
+			bs_stack_free(elementAreas);
 	}
 
 	void GUIPanel::_updateChildLayout(GUIElementBase* element, const GUILayoutData& data)

+ 2 - 2
BansheeEngine/Source/BsGUIScrollArea.cpp

@@ -219,7 +219,7 @@ namespace BansheeEngine
 		Rect2I* elementAreas = nullptr;
 
 		if (numElements > 0)
-			elementAreas = stackConstructN<Rect2I>(numElements);
+			elementAreas = bs_stack_new<Rect2I>(numElements);
 
 		Vector<LayoutSizeRange> sizeRanges;
 		UINT32 layoutIdx = 0;
@@ -310,7 +310,7 @@ namespace BansheeEngine
 		}
 
 		if (elementAreas != nullptr)
-			stackDeallocLast(elementAreas);
+			bs_stack_free(elementAreas);
 	}
 
 	void GUIScrollArea::vertScrollUpdate(float scrollPos)

+ 8 - 8
BansheeFBXImporter/Source/BsFBXImporter.cpp

@@ -424,25 +424,25 @@ namespace BansheeEngine
 
 				// Copy & transform positions
 				UINT32 positionsSize = sizeof(Vector3) * (UINT32)numVertices;
-				Vector3* transformedPositions = (Vector3*)stackAlloc(positionsSize);
+				Vector3* transformedPositions = (Vector3*)bs_stack_alloc(positionsSize);
 
 				for (UINT32 i = 0; i < (UINT32)numVertices; i++)
 					transformedPositions[i] = worldTransform.multiplyAffine((Vector3)mesh->positions[i]);
 
 				meshData->setPositions(transformedPositions, positionsSize);
-				stackDeallocLast(transformedPositions);
+				bs_stack_free(transformedPositions);
 
 				// Copy & transform normals
 				if (hasNormals)
 				{
 					UINT32 normalsSize = sizeof(Vector3) * (UINT32)numVertices;
-					Vector3* transformedNormals = (Vector3*)stackAlloc(normalsSize);
+					Vector3* transformedNormals = (Vector3*)bs_stack_alloc(normalsSize);
 
 					// Copy, convert & transform tangents & bitangents
 					if (hasTangents)
 					{
 						UINT32 tangentsSize = sizeof(Vector4) * (UINT32)numVertices;
-						Vector4* transformedTangents = (Vector4*)stackAlloc(tangentsSize);
+						Vector4* transformedTangents = (Vector4*)bs_stack_alloc(tangentsSize);
 
 						for (UINT32 i = 0; i < (UINT32)numVertices; i++)
 						{
@@ -462,7 +462,7 @@ namespace BansheeEngine
 						}
 
 						meshData->setTangents(transformedTangents, tangentsSize);
-						stackDeallocLast(transformedTangents);
+						bs_stack_free(transformedTangents);
 					}
 					else // Just normals
 					{
@@ -471,7 +471,7 @@ namespace BansheeEngine
 					}
 
 					meshData->setNormals(transformedNormals, normalsSize);
-					stackDeallocLast(transformedNormals);
+					bs_stack_free(transformedNormals);
 				}
 
 				// Copy colors
@@ -487,7 +487,7 @@ namespace BansheeEngine
 					if (uvLayer.size() == numVertices)
 					{
 						UINT32 size = sizeof(Vector2) * (UINT32)numVertices;
-						Vector2* transformedUV = (Vector2*)stackAlloc(size);
+						Vector2* transformedUV = (Vector2*)bs_stack_alloc(size);
 
 						UINT32 i = 0;
 						for (auto& uv : uvLayer)
@@ -503,7 +503,7 @@ namespace BansheeEngine
 						else if (writeUVIDx == 1)
 							meshData->setUV1(transformedUV, size);
 
-						stackDeallocLast(transformedUV);
+						bs_stack_free(transformedUV);
 
 						writeUVIDx++;
 					}

+ 6 - 6
BansheeGLRenderSystem/Source/BsGLVertexArrayObjectManager.cpp

@@ -83,8 +83,8 @@ namespace BansheeEngine
 
 		UINT32 numStreams = maxStreamIdx + 1;
 		UINT32 numUsedBuffers = 0;
-		INT32* streamToSeqIdx = stackAllocN<INT32>(numStreams);
-		GLVertexBufferCore** usedBuffers = stackAllocN<GLVertexBufferCore*>((UINT32)boundBuffers.size());
+		INT32* streamToSeqIdx = bs_stack_alloc<INT32>(numStreams);
+		GLVertexBufferCore** usedBuffers = bs_stack_alloc<GLVertexBufferCore*>((UINT32)boundBuffers.size());
 		
 		memset(usedBuffers, 0, (UINT32)boundBuffers.size() * sizeof(GLVertexBuffer*));
 
@@ -116,8 +116,8 @@ namespace BansheeEngine
 		auto findIter = mVAObjects.find(wantedVAO);
 		if (findIter != mVAObjects.end())
 		{
-			stackDeallocLast(usedBuffers);
-			stackDeallocLast(streamToSeqIdx);
+			bs_stack_free(usedBuffers);
+			bs_stack_free(streamToSeqIdx);
 
 			return *findIter; // Found existing, return that
 		}
@@ -187,8 +187,8 @@ namespace BansheeEngine
 			usedBuffers[i]->registerVAO(wantedVAO);
 		}
 
-		stackDeallocLast(usedBuffers);
-		stackDeallocLast(streamToSeqIdx);
+		bs_stack_free(usedBuffers);
+		bs_stack_free(streamToSeqIdx);
 
 		auto iter = mVAObjects.insert(wantedVAO);
 

+ 4 - 4
BansheeGLRenderSystem/Source/GLSL/src/BsGLSLGpuProgram.cpp

@@ -129,7 +129,7 @@ namespace BansheeEngine
 		{
 			Vector<GLchar*> lines;
 
-			GLchar* firstLineData = (GLchar*)stackAlloc(sizeof(GLSL_VERSION_LINE));
+			GLchar* firstLineData = (GLchar*)bs_stack_alloc(sizeof(GLSL_VERSION_LINE));
 			memcpy(firstLineData, GLSL_VERSION_LINE, sizeof(GLSL_VERSION_LINE));
 
 			lines.push_back(firstLineData);
@@ -145,7 +145,7 @@ namespace BansheeEngine
 
 						bool isDefine = source[i - lineLength] == '#';
 
-						GLchar* lineData = (GLchar*)stackAlloc(sizeof(GLchar) * (lineLength + 1 + (isDefine ? 1 : 0)));
+						GLchar* lineData = (GLchar*)bs_stack_alloc(sizeof(GLchar) * (lineLength + 1 + (isDefine ? 1 : 0)));
 						memcpy(lineData, &source[i - lineLength], sizeof(GLchar) * lineLength);
 
 						if (isDefine) // Defines require a newline as well as a null terminator, otherwise it doesn't compile properly
@@ -171,7 +171,7 @@ namespace BansheeEngine
 				UINT32 end = (UINT32)source.size() - 1;
 				assert(sizeof(source[end]) == sizeof(GLchar));
 
-				GLchar* lineData = (GLchar*)stackAlloc(sizeof(GLchar) * (lineLength + 1));
+				GLchar* lineData = (GLchar*)bs_stack_alloc(sizeof(GLchar) * (lineLength + 1));
 				memcpy(lineData, &source[source.size() - lineLength], sizeof(GLchar) * lineLength);
 				lineData[lineLength] = '\0';
 
@@ -183,7 +183,7 @@ namespace BansheeEngine
 
 			for (auto iter = lines.rbegin(); iter != lines.rend(); ++iter)
 			{
-				stackDeallocLast(*iter);
+				bs_stack_free(*iter);
 			}
 
 			mCompileError = "";

+ 2 - 0
BansheeUtility/BansheeUtility.vcxproj

@@ -255,6 +255,7 @@
     <ClCompile Include="Source\BsBounds.cpp" />
     <ClCompile Include="Source\BsCapsule.cpp" />
     <ClCompile Include="Source\BsConvexVolume.cpp" />
+    <ClCompile Include="Source\BsGlobalFrameAlloc.cpp" />
     <ClCompile Include="Source\BsLineSegment3.cpp" />
     <ClCompile Include="Source\BsMessageHandler.cpp" />
     <ClCompile Include="Source\BsRect3.cpp" />
@@ -376,6 +377,7 @@
     <ClInclude Include="Include\BsTexAtlasGenerator.h" />
     <ClCompile Include="Source\BsHString.cpp" />
     <ClInclude Include="Include\BsVectorNI.h" />
+    <ClInclude Include="Include\BsGlobalFrameAlloc.h" />
     <ClInclude Include="Include\ThirdParty\md5.h" />
   </ItemGroup>
   <ItemGroup>

+ 6 - 0
BansheeUtility/BansheeUtility.vcxproj.filters

@@ -305,6 +305,9 @@
     <ClInclude Include="Include\BsBinaryCloner.h">
       <Filter>Header Files\Serialization</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsGlobalFrameAlloc.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsThreadPool.cpp">
@@ -487,5 +490,8 @@
     <ClCompile Include="Source\BsBinaryCloner.cpp">
       <Filter>Source Files\Serialization</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsGlobalFrameAlloc.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 1 - 0
BansheeUtility/Include/BsFwdDeclUtil.h

@@ -60,6 +60,7 @@ namespace BansheeEngine
 	struct RTTIReflectablePtrFieldBase;
 	struct SerializedObject;
 	struct SerializedInstance;
+	class FrameAlloc;
 	// Reflection
 	class IReflectable;
 	class RTTITypeBase;

+ 150 - 0
BansheeUtility/Include/BsGlobalFrameAlloc.h

@@ -0,0 +1,150 @@
+#pragma once
+
+#include "BsStdHeaders.h"
+#include "BsThreadDefines.h"
+
+namespace BansheeEngine
+{
+	class FrameAlloc;
+
+	extern BS_THREADLOCAL FrameAlloc* _GlobalFrameAlloc;
+
+	/**
+	 * @brief	Returns a global, application wide frame allocator. Each thread
+	 *			gets its own frame allocator.
+	 *
+	 * @note	Thread safe.
+	 */
+	inline BS_UTILITY_EXPORT FrameAlloc& gFrameAlloc();
+
+	/**
+	 * @brief	Allocates some memory using the global frame allocator.
+	 *
+	 * @param	numBytes	Number of bytes to allocate.
+	 */
+	inline BS_UTILITY_EXPORT UINT8* bs_frame_alloc(UINT32 numBytes);
+
+	/**
+	 * @brief	Deallocates memory allocated with the global frame allocator.
+	 *
+	 * @note	Must be called on the same thread the memory was allocated on.
+	 */
+	inline BS_UTILITY_EXPORT void bs_frame_free(void* data);
+
+	/**
+	 * @brief	Allocates enough memory to hold the object of specified type using
+	 *			the global frame allocator, but does not construct the object. 
+	 */
+	template<class T>
+	T* bs_frame_alloc()
+	{
+		return (T*)bs_frame_alloc(sizeof(T));
+	}
+
+	/**
+	 * @brief	Allocates enough memory to hold N objects of specified type using
+	 *			the global frame allocator, but does not construct the object. 
+	 */
+	template<class T>
+	T* bs_frame_alloc(UINT32 count)
+	{
+		return (T*)bs_frame_alloc(sizeof(T) * count);
+	}
+
+	/**
+	 * @brief	Allocates enough memory to hold the object(s) of specified type using
+	 *			the global frame allocator, and constructs them.
+	 */
+	template<class T>
+	T* bs_frame_new(UINT32 count = 0)
+	{
+		T* data = bs_frame_alloc<T>(count);
+
+		for(unsigned int i = 0; i < count; i++)
+			new ((void*)&data[i]) T;
+
+		return data;
+	}
+
+	/**
+	 * @brief	Allocates enough memory to hold the object(s) of specified type using
+	 *			the global frame allocator, and constructs them.
+	 */
+	template<class T, class... Args>
+	T* bs_frame_new(Args &&...args, UINT32 count = 0)
+	{
+		T* data = bs_frame_alloc<T>(count);
+
+		for(unsigned int i = 0; i < count; i++)
+			new ((void*)&data[i]) T(std::forward<Args>(args)...);
+
+		return data;
+	}
+
+	/**
+	 * @brief	Destructs and deallocates an object allocated with the global frame allocator.
+	 *
+	 * @note	Must be called on the same thread the memory was allocated on.
+	 */
+	template<class T>
+	void bs_frame_delete(T* data)
+	{
+		data->~T();
+
+		bs_frame_free((UINT8*)data);
+	}
+
+	/**
+	 * @brief	Destructs and deallocates an array of objects 
+	 *			allocated with the global frame allocator.
+	 *
+	 * @note	Must be called on the same thread the memory was allocated on.
+	 */
+	template<class T>
+	void bs_frame_delete(T* data, UINT32 count)
+	{
+		for(unsigned int i = 0; i < count; i++)
+			data[i].~T();
+
+		bs_frame_free((UINT8*)data);
+	}
+
+	/**
+	 * @copydoc	FrameAlloc::markFrame
+	 */
+	inline BS_UTILITY_EXPORT void bs_frame_mark();
+
+	/**
+	 * @copydoc	FrameAlloc::clear
+	 */
+	inline BS_UTILITY_EXPORT void bs_frame_clear();
+
+	/**
+	* @brief	Specialized memory allocator implementations that allows use of a 
+	* 			global frame allocator in normal new/delete/free/dealloc operators.
+	*/
+	template<>
+	class MemoryAllocator<FrameAlloc> : public MemoryAllocatorBase
+	{
+	public:
+		static inline void* allocate(size_t bytes)
+		{
+			return bs_frame_alloc((UINT32)bytes);
+		}
+
+		static inline void* allocateArray(size_t bytes, UINT32 count)
+		{
+			return bs_frame_alloc((UINT32)(bytes * count));
+		}
+
+		static inline void free(void* ptr)
+		{
+			bs_frame_free(ptr);
+		}
+
+		static inline void freeArray(void* ptr, UINT32 count)
+		{
+			bs_frame_free(ptr);
+		}
+	};
+}

+ 32 - 15
BansheeUtility/Include/BsMemStack.h

@@ -213,9 +213,9 @@ namespace BansheeEngine
 	};
 
 	/**
-	* @copydoc	MemoryStackInternal::alloc
-	*/
-	BS_UTILITY_EXPORT inline void* stackAlloc(UINT32 numBytes);
+	 * @copydoc	MemoryStackInternal::alloc
+	 */
+	BS_UTILITY_EXPORT inline void* bs_stack_alloc(UINT32 numBytes);
 
 	/**
 	 * @brief	Allocates enough memory to hold the specified type, on the stack, but
@@ -224,7 +224,7 @@ namespace BansheeEngine
 	 * @see		MemoryStackInternal::alloc()
 	 */
 	template<class T>
-	T* stackAlloc()
+	T* bs_stack_alloc()
 	{
 		return (T*)MemStack::alloc(sizeof(T));
 	}
@@ -236,21 +236,21 @@ namespace BansheeEngine
 	 * @see		MemoryStackInternal::alloc()
 	 */
 	template<class T>
-	T* stackAllocN(UINT32 count)
+	T* bs_stack_alloc(UINT32 count)
 	{
 		return (T*)MemStack::alloc(sizeof(T) * count);
 	}
 
 	/**
 	 * @brief	Allocates enough memory to hold the specified type, on the stack, 
-	 * 			and initializes the object using the parameterless constructor.
+	 * 			and constructs the object.
 	 *
 	 * @see		MemoryStackInternal::alloc()
 	 */
 	template<class T>
-	T* stackConstructN(UINT32 count)
+	T* bs_stack_new(UINT32 count = 0)
 	{
-		T* data = stackAllocN<T>(count);
+		T* data = bs_stack_alloc<T>(count);
 
 		for(unsigned int i = 0; i < count; i++)
 			new ((void*)&data[i]) T;
@@ -258,13 +258,30 @@ namespace BansheeEngine
 		return data;
 	}
 
+	/**
+	 * @brief	Allocates enough memory to hold the specified type, on the stack, 
+	 * 			and constructs the object.
+	 *
+	 * @see		MemoryStackInternal::alloc()
+	 */
+	template<class T, class... Args>
+	T* bs_stack_new(Args &&...args, UINT32 count = 0)
+	{
+		T* data = bs_stack_alloc<T>(count);
+
+		for(unsigned int i = 0; i < count; i++)
+			new ((void*)&data[i]) T(std::forward<Args>(args)...);
+
+		return data;
+	}
+
 	/**
 	 * @brief	Destructs and deallocates last allocated entry currently located on stack.
 	 *
 	 * @see		MemoryStackInternal::dealloc()
 	 */
 	template<class T>
-	void stackDestruct(T* data)
+	void bs_stack_delete(T* data)
 	{
 		data->~T();
 
@@ -278,7 +295,7 @@ namespace BansheeEngine
 	 * @see		MemoryStackInternal::dealloc()
 	 */
 	template<class T>
-	void stackDestructN(T* data, UINT32 count)
+	void bs_stack_delete(T* data, UINT32 count)
 	{
 		for(unsigned int i = 0; i < count; i++)
 			data[i].~T();
@@ -289,7 +306,7 @@ namespace BansheeEngine
 	/**
 	 * @copydoc	MemoryStackInternal::dealloc()
 	 */
-	BS_UTILITY_EXPORT inline void stackDeallocLast(void* data);
+	BS_UTILITY_EXPORT inline void bs_stack_free(void* data);
 
 	/**
 	* @brief	Allows use of a stack allocator by using normal new/delete/free/dealloc operators.
@@ -311,22 +328,22 @@ namespace BansheeEngine
 	public:
 		static inline void* allocate(size_t bytes)
 		{
-			return stackAlloc((UINT32)bytes);
+			return bs_stack_alloc((UINT32)bytes);
 		}
 
 		static inline void* allocateArray(size_t bytes, UINT32 count)
 		{
-			return stackAlloc((UINT32)(bytes * count));
+			return bs_stack_alloc((UINT32)(bytes * count));
 		}
 
 		static inline void free(void* ptr)
 		{
-			stackDeallocLast(ptr);
+			bs_stack_free(ptr);
 		}
 
 		static inline void freeArray(void* ptr, UINT32 count)
 		{
-			stackDeallocLast(ptr);
+			bs_stack_free(ptr);
 		}
 	};
 }

+ 1 - 0
BansheeUtility/Include/BsMemoryAllocator.h

@@ -404,4 +404,5 @@ namespace BansheeEngine
 }
 
 #include "BsMemStack.h"
+#include "BsGlobalFrameAlloc.h"
 #include "BsMemAllocProfiler.h"

+ 8 - 8
BansheeUtility/Include/BsRTTIType.h

@@ -184,12 +184,12 @@ namespace BansheeEngine
 			else
 				typeSize = sizeof(DataType);
 
-			UINT8* tempBuffer = (UINT8*)stackAlloc(typeSize);
+			UINT8* tempBuffer = (UINT8*)bs_stack_alloc(typeSize);
 			RTTIPlainType<DataType>::toMemory(value, (char*)tempBuffer);
 			
 			field->fromBuffer(object, tempBuffer);
 
-			stackDeallocLast(tempBuffer);
+			bs_stack_free(tempBuffer);
 		}
 
 		/**
@@ -212,12 +212,12 @@ namespace BansheeEngine
 			else
 				typeSize = sizeof(DataType);
 
-			UINT8* tempBuffer = (UINT8*)stackAlloc(typeSize);
+			UINT8* tempBuffer = (UINT8*)bs_stack_alloc(typeSize);
 			RTTIPlainType<DataType>::toMemory(value, (char*)tempBuffer);
 
 			field->arrayElemFromBuffer(object, index, tempBuffer);
 
-			stackDeallocLast(tempBuffer);
+			bs_stack_free(tempBuffer);
 		}
 
 		/**
@@ -331,12 +331,12 @@ namespace BansheeEngine
 			else
 				typeSize = field->getTypeSize();
 
-			UINT8* tempBuffer = (UINT8*)stackAlloc(typeSize);
+			UINT8* tempBuffer = (UINT8*)bs_stack_alloc(typeSize);
 
 			field->toBuffer(object, tempBuffer);
 			RTTIPlainType<DataType>::fromMemory(value, (char*)tempBuffer);
 
-			stackDeallocLast(tempBuffer);
+			bs_stack_free(tempBuffer);
 		}
 
 		/**
@@ -358,12 +358,12 @@ namespace BansheeEngine
 			else
 				typeSize = field->getTypeSize();
 
-			UINT8* tempBuffer = (UINT8*)stackAlloc(typeSize);
+			UINT8* tempBuffer = (UINT8*)bs_stack_alloc(typeSize);
 
 			field->arrayElemToBuffer(object, index, tempBuffer);
 			RTTIPlainType<DataType>::fromMemory(value, (char*)tempBuffer);
 
-			stackDeallocLast(tempBuffer);
+			bs_stack_free(tempBuffer);
 		}	
 
 		/**

+ 6 - 6
BansheeUtility/Source/BsBinarySerializer.cpp

@@ -242,18 +242,18 @@ namespace BansheeEngine
 
 								if ((*bytesWritten + typeSize) > bufferLength)
 								{
-									UINT8* tempBuffer = (UINT8*)stackAlloc(typeSize);
+									UINT8* tempBuffer = (UINT8*)bs_stack_alloc(typeSize);
 									curField->arrayElemToBuffer(object, arrIdx, tempBuffer);
 
 									buffer = dataBlockToBuffer(tempBuffer, typeSize, buffer, bufferLength, bytesWritten, flushBufferCallback);
 									if (buffer == nullptr || bufferLength == 0)
 									{
-										stackDeallocLast(tempBuffer);
+										bs_stack_free(tempBuffer);
 										si->onSerializationEnded(object);
 										return nullptr;
 									}
 
-									stackDeallocLast(tempBuffer);
+									bs_stack_free(tempBuffer);
 								}
 								else
 								{
@@ -315,18 +315,18 @@ namespace BansheeEngine
 
 							if ((*bytesWritten + typeSize) > bufferLength)
 							{
-								UINT8* tempBuffer = (UINT8*)stackAlloc(typeSize);
+								UINT8* tempBuffer = (UINT8*)bs_stack_alloc(typeSize);
 								curField->toBuffer(object, tempBuffer);
 								
 								buffer = dataBlockToBuffer(tempBuffer, typeSize, buffer, bufferLength, bytesWritten, flushBufferCallback);
 								if (buffer == nullptr || bufferLength == 0)
 								{
-									stackDeallocLast(tempBuffer);
+									bs_stack_free(tempBuffer);
 									si->onSerializationEnded(object);
 									return nullptr;
 								}
 
-								stackDeallocLast(tempBuffer);
+								bs_stack_free(tempBuffer);
 							}
 							else
 							{

+ 40 - 0
BansheeUtility/Source/BsGlobalFrameAlloc.cpp

@@ -0,0 +1,40 @@
+#include "BsPrerequisitesUtil.h"
+#include "BsGlobalFrameAlloc.h"
+#include "BsFrameAlloc.h"
+
+namespace BansheeEngine
+{
+	BS_THREADLOCAL FrameAlloc* _GlobalFrameAlloc = nullptr;
+
+	inline BS_UTILITY_EXPORT FrameAlloc& gFrameAlloc()
+	{
+		if (_GlobalFrameAlloc == nullptr)
+		{
+			// Note: This will leak memory but since it should exist throughout the entirety 
+			// of runtime it should only leak on shutdown when the OS will free it anyway.
+			_GlobalFrameAlloc = new FrameAlloc();
+		}
+
+		return *_GlobalFrameAlloc;
+	}
+
+	inline BS_UTILITY_EXPORT UINT8* bs_frame_alloc(UINT32 numBytes)
+	{
+		return gFrameAlloc().alloc(numBytes);
+	}
+
+	inline BS_UTILITY_EXPORT void bs_frame_free(void* data)
+	{
+		gFrameAlloc().dealloc(data);
+	}
+
+	inline BS_UTILITY_EXPORT void bs_frame_mark()
+	{
+		gFrameAlloc().markFrame();
+	}
+
+	inline BS_UTILITY_EXPORT void bs_frame_clear()
+	{
+		gFrameAlloc().clear();
+	}
+}

+ 2 - 2
BansheeUtility/Source/BsMemStack.cpp

@@ -36,12 +36,12 @@ namespace BansheeEngine
 		ThreadMemStack->dealloc(data);
 	}
 
-	void* stackAlloc(UINT32 numBytes)
+	void* bs_stack_alloc(UINT32 numBytes)
 	{
 		return (void*)MemStack::alloc(numBytes);
 	}
 
-	void stackDeallocLast(void* data)
+	void bs_stack_free(void* data)
 	{
 		return MemStack::deallocLast((UINT8*)data);
 	}

+ 1 - 0
TODO.txt

@@ -80,6 +80,7 @@ Optimization:
  - Remove profiling calls in GUIWidget and text sprite
  - Remove pause mechanic from profiler overlay
  - HResource.isLoaded checks are using up a lot of allocations in GUI updates
+  - getResourceDependencies AND getCoreDependencies need to use frame alloc
  - There are more issues with GUI allocations
 
 -----------