Browse Source

Moved some of TextUtility allocations into vectors instead of doing each manually, hoping to reduce total alloc count

Marko Pintera 12 năm trước cách đây
mục cha
commit
63de13b0ab

+ 6 - 6
BansheeEngine/Source/BsTextSprite.cpp

@@ -20,13 +20,13 @@ namespace BansheeEngine
 		if(textData == nullptr)
 			return;
 
-		const std::vector<TextUtility::TextLine*>& lines = textData->getLines();
+		const std::vector<TextUtility::TextLine>& lines = textData->getLines();
 		const std::vector<UINT32>& quadsPerPage = textData->getNumQuadsPerPage();
 
 		UINT32 curHeight = 0;
 		for(auto& line : lines)
 		{
-			curHeight += line->getYOffset();
+			curHeight += line.getYOffset();
 		}
 
 		// Calc vertical alignment offset
@@ -92,22 +92,22 @@ namespace BansheeEngine
 				horzOffset = 0;
 				break;
 			case THA_Right:
-				horzOffset = std::max(0, (INT32)(desc.width - lines[i]->getWidth()));
+				horzOffset = std::max(0, (INT32)(desc.width - lines[i].getWidth()));
 				break;
 			case THA_Center:
-				horzOffset = std::max(0, (INT32)(desc.width - lines[i]->getWidth())) / 2;
+				horzOffset = std::max(0, (INT32)(desc.width - lines[i].getWidth())) / 2;
 				break;
 			}
 
 			Int2 position = offset + Int2(horzOffset, vertOffset + curY);
-			curY += lines[i]->getYOffset();
+			curY += lines[i].getYOffset();
 
 			for(size_t j = 0; j < numPages; j++)
 			{
 				SpriteRenderElement& renderElem = mCachedRenderElements[j];
 				UINT32 offset = faceOffsets[j];
 
-				UINT32 writtenQuads = lines[i]->fillBuffer((UINT32)j, renderElem.vertices, renderElem.uvs, renderElem.indexes, offset, renderElem.numQuads);
+				UINT32 writtenQuads = lines[i].fillBuffer((UINT32)j, renderElem.vertices, renderElem.uvs, renderElem.indexes, offset, renderElem.numQuads);
 				
 				UINT32 numVertices = writtenQuads * 4;
 				for(size_t i = 0; i < numVertices; i++)

+ 0 - 6
CamelotClient/CamelotClient.cpp

@@ -30,9 +30,6 @@
 #include "CmRTTIType.h"
 #include "CmCursor.h"
 
-#include "CmMemBlockPool.h"
-
-
 #define DX11
 //#define DX9
 //#define GL
@@ -66,9 +63,6 @@ int CALLBACK WinMain(
 	//CommandQueue::addBreakpoint(0, 22);
 	//CommandQueue::addBreakpoint(0, 12);
 
-	MemBlockPool<> blockPool;
-	void* someMemory = blockPool.alloc(32);
-
 	RenderSystem* renderSystem = RenderSystem::instancePtr();
 	RenderWindowPtr renderWindow = gApplication().getPrimaryWindow();
 

+ 5 - 5
CamelotCore/Include/CmTextUtility.h

@@ -83,14 +83,14 @@ namespace CamelotFramework
 			UINT32 mBaselineOffset;
 			UINT32 mLineHeight;
 			UINT32 mSpaceWidth;
-			vector<TextWord*>::type mWords;
+			vector<TextWord>::type mWords;
 			TextWord* mLastWord;
 
 			void add(const CHAR_DESC& charDesc);
 			void addSpace();
-			void addWord(TextWord* word);
+			void addWord(const TextWord& word);
 
-			TextWord* removeLastWord();
+			TextWord removeLastWord();
 
 			void calculateBounds();
 		};
@@ -100,7 +100,7 @@ namespace CamelotFramework
 		public:
 			~TextData();
 
-			const std::vector<TextLine*>& getLines() const { return mLines; }
+			const std::vector<TextLine>& getLines() const { return mLines; }
 			const std::vector<HTexture>& getTexturePages() const { return mTexturePages; }
 			const std::vector<UINT32>& getNumQuadsPerPage() const  { return mQuadsPerPage; }
 			UINT32 getWidth() const;
@@ -110,7 +110,7 @@ namespace CamelotFramework
 			friend class TextUtility;
 
 			std::vector<UINT32> mQuadsPerPage;
-			std::vector<TextLine*> mLines;
+			std::vector<TextLine> mLines;
 			std::vector<HTexture> mTexturePages;
 		};
 

+ 32 - 42
CamelotCore/Source/CmTextUtility.cpp

@@ -80,18 +80,14 @@ namespace CamelotFramework
 
 	TextUtility::TextLine::~TextLine()
 	{
-		for(auto iter = mWords.begin(); iter != mWords.end(); ++iter)
-			CM_DELETE(*iter, TextWord, ScratchAlloc);
 	}
 
 	void TextUtility::TextLine::add(const CHAR_DESC& charDesc)
 	{
 		if(mLastWord == nullptr)
 		{
-			TextWord* newWord = CM_NEW(TextWord, ScratchAlloc) TextWord(false);
-			mLastWord = newWord;
-
-			mWords.push_back(mLastWord);
+			mWords.push_back(TextWord(false));
+			mLastWord = &mWords.back();
 
 			mLastWord->addChar(charDesc);
 		}
@@ -99,10 +95,8 @@ namespace CamelotFramework
 		{
 			if(mLastWord->isSpacer())
 			{
-				TextWord* newWord = CM_NEW(TextWord, ScratchAlloc) TextWord(false);
-				mLastWord = newWord;
-
-				mWords.push_back(mLastWord);
+				mWords.push_back(TextWord(false));
+				mLastWord = &mWords.back();
 			}
 
 			mLastWord->addChar(charDesc);
@@ -115,19 +109,15 @@ namespace CamelotFramework
 	{
 		if(mLastWord == nullptr)
 		{
-			TextWord* newWord = CM_NEW(TextWord, ScratchAlloc) TextWord(true);
-			mLastWord = newWord;
-
-			mWords.push_back(mLastWord);
+			mWords.push_back(TextWord(true));
+			mLastWord = &mWords.back();
 
 			mLastWord->addSpace(mSpaceWidth);
 		}
 		else
 		{
-			TextWord* newWord = CM_NEW(TextWord, ScratchAlloc) TextWord(true); // Each space is counted as its own word, to make certain operations easier
-			mLastWord = newWord;
-
-			mWords.push_back(mLastWord);
+			mWords.push_back(TextWord(true)); // Each space is counted as its own word, to make certain operations easier
+			mLastWord = &mWords.back();
 
 			mLastWord->addSpace(mSpaceWidth);
 		}
@@ -135,24 +125,24 @@ namespace CamelotFramework
 		calculateBounds();
 	}
 
-	void TextUtility::TextLine::addWord(TextWord* word)
+	void TextUtility::TextLine::addWord(const TextWord& word)
 	{
 		mWords.push_back(word);
-		mLastWord = word;
+		mLastWord = &mWords.back();
 
 		calculateBounds();
 	}
 
-	TextUtility::TextWord* TextUtility::TextLine::removeLastWord()
+	TextUtility::TextWord TextUtility::TextLine::removeLastWord()
 	{
 		if(mWords.size() == 0)
 			return nullptr;
 
-		TextWord* word = mWords[mWords.size() - 1];
+		TextWord word = mWords[mWords.size() - 1];
 		mWords.erase(mWords.end() - 1);
 
 		if(mWords.size() > 0)
-			mLastWord = mWords[mWords.size() - 1];
+			mLastWord = &mWords[mWords.size() - 1];
 		else
 			mLastWord = nullptr;
 
@@ -166,9 +156,9 @@ namespace CamelotFramework
 		std::vector<UINT32> quadsPerPage;
 		for(auto wordIter = mWords.begin(); wordIter != mWords.end(); ++wordIter)
 		{
-			if(!(*wordIter)->isSpacer())
+			if(!wordIter->isSpacer())
 			{
-				const vector<CHAR_DESC>::type& chars = (*wordIter)->getChars();
+				const vector<CHAR_DESC>::type& chars = wordIter->getChars();
 				UINT32 kerning = 0;
 				for(auto charIter = chars.begin(); charIter != chars.end(); ++charIter)
 				{
@@ -190,13 +180,13 @@ namespace CamelotFramework
 		UINT32 penX = 0;
 		for(auto wordIter = mWords.begin(); wordIter != mWords.end(); ++wordIter)
 		{
-			if((*wordIter)->isSpacer())
+			if(wordIter->isSpacer())
 			{
 				penX += mSpaceWidth;
 			}
 			else
 			{
-				const vector<CHAR_DESC>::type& chars = (*wordIter)->getChars();
+				const vector<CHAR_DESC>::type& chars = wordIter->getChars();
 				UINT32 kerning = 0;
 				for(auto charIter = chars.begin(); charIter != chars.end(); ++charIter)
 				{
@@ -259,15 +249,13 @@ namespace CamelotFramework
 		mHeight = 0;
 		for(auto iter = mWords.begin(); iter != mWords.end(); ++iter)
 		{
-			mWidth += (*iter)->getWidth();
-			mHeight = std::max(mHeight, (*iter)->getHeight());
+			mWidth += iter->getWidth();
+			mHeight = std::max(mHeight, iter->getHeight());
 		}
 	}
 
 	TextUtility::TextData::~TextData()
 	{
-		for(size_t i = 0; i < mLines.size(); i++)
-			CM_DELETE(mLines[i], TextLine, ScratchAlloc);
 	}
 
 	std::shared_ptr<TextUtility::TextData> TextUtility::getTextData(const String& text, const HFont& font, UINT32 fontSize, UINT32 width, UINT32 height, bool wordWrap)
@@ -291,8 +279,8 @@ namespace CamelotFramework
 		bool widthIsLimited = width > 0;
 
 		std::shared_ptr<TextUtility::TextData> textData(CM_NEW(TextData, PoolAlloc) TextData(), &MemAllocDeleter<TextData, PoolAlloc>::deleter);
-		TextLine* curLine = CM_NEW(TextLine, ScratchAlloc) TextLine(fontData->fontDesc.baselineOffset, fontData->fontDesc.lineHeight, fontData->fontDesc.spaceWidth);
-		textData->mLines.push_back(curLine);
+		textData->mLines.push_back(TextLine(fontData->fontDesc.baselineOffset, fontData->fontDesc.lineHeight, fontData->fontDesc.spaceWidth));
+		TextLine* curLine = &textData->mLines.back();
 
 		UINT32 curHeight = fontData->fontDesc.lineHeight;
 		UINT32 charIdx = 0;
@@ -307,8 +295,9 @@ namespace CamelotFramework
 				if(heightIsLimited && (curHeight + fontData->fontDesc.lineHeight * 2) > height)
 					break; // Max height reached
 
-				curLine = CM_NEW(TextLine, ScratchAlloc) TextLine(fontData->fontDesc.baselineOffset, fontData->fontDesc.lineHeight, fontData->fontDesc.spaceWidth);
-				textData->mLines.push_back(curLine);
+				textData->mLines.push_back(TextLine(fontData->fontDesc.baselineOffset, fontData->fontDesc.lineHeight, fontData->fontDesc.spaceWidth));
+				curLine = &textData->mLines.back();
+
 				curHeight += fontData->fontDesc.lineHeight;
 
 				charIdx++;
@@ -340,19 +329,20 @@ namespace CamelotFramework
 			{
 				if(wordWrap)
 				{
-					TextWord* lastWord = curLine->removeLastWord();
-					if(lastWord->isSpacer())
+					TextWord lastWord = curLine->removeLastWord();
+					if(lastWord.isSpacer())
 						curLine->addWord(lastWord); // Spaces can stay on previous line even if they don't technically fit
 
 					// No more lines fit vertically so we're done
 					if(heightIsLimited && curHeight > height)
 						break;
 
-					curLine = CM_NEW(TextLine, ScratchAlloc) TextLine(fontData->fontDesc.baselineOffset, fontData->fontDesc.lineHeight, fontData->fontDesc.spaceWidth);
-					textData->mLines.push_back(curLine);
+					textData->mLines.push_back(TextLine(fontData->fontDesc.baselineOffset, fontData->fontDesc.lineHeight, fontData->fontDesc.spaceWidth));
+					curLine = &textData->mLines.back();
+
 					curHeight += fontData->fontDesc.lineHeight;
 
-					if(!lastWord->isSpacer())
+					if(!lastWord.isSpacer())
 						curLine->addWord(lastWord);
 				}
 				else
@@ -373,7 +363,7 @@ namespace CamelotFramework
 		UINT32 width = 0;
 
 		for(auto& line : mLines)
-			width = std::max(width, line->getWidth());
+			width = std::max(width, line.getWidth());
 
 		return width;
 	}
@@ -383,7 +373,7 @@ namespace CamelotFramework
 		UINT32 height = 0;
 
 		for(auto& line : mLines)
-			height += line->getHeight();
+			height += line.getHeight();
 
 		return height;
 	}

+ 0 - 1
CamelotUtility/CamelotUtility.vcxproj

@@ -189,7 +189,6 @@
     <ClInclude Include="Include\CmLog.h" />
     <ClInclude Include="Include\CmManagedDataBlock.h" />
     <ClInclude Include="Include\CmMathAsm.h" />
-    <ClInclude Include="Include\CmMemBlockPool.h" />
     <ClInclude Include="Include\CmMemoryAllocator.h" />
     <ClInclude Include="Include\CmModule.h" />
     <ClInclude Include="Include\CmORect.h" />

+ 0 - 3
CamelotUtility/CamelotUtility.vcxproj.filters

@@ -219,9 +219,6 @@
     <ClInclude Include="Include\CmMemStack.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="Include\CmMemBlockPool.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Include\CmAxisAlignedBox.cpp">

+ 0 - 194
CamelotUtility/Include/CmMemBlockPool.h

@@ -1,194 +0,0 @@
-#pragma once
-
-#include <vector>
-#include <cmath>
-
-namespace CamelotFramework
-{
-	/**
-	 * @brief	Memory block pool.
-	 *
-	 * @tparam	PageSizePow2	2^PageSizePow2 is the size of one page in the pool. This size divided by number of blocks per chunk
-	 * 							determines the maximum size you can allocate in the pool. Larger allocations will use a general allocator.
-	 * @tparam	BlocksPerChunkPow2 Pages are split into chunks and chunks are split into smaller chunks based on this value.
-	 * 							   Higher values generally guarantee less allocations and better performance, but potentially 
-	 * 							   more wasted memory. Actual blocks per chunk is calculated by 2^BlocksPerChunkPow2.
-	 * 							   Has to be equal or less than PageSizePow2. Must be equal or less than 8.
-	 * 							   (e.g. 0 means 1 block per chunk, 1 means 2 blocks per chunk, etc.)
-	 */
-	template <int PageSizePow2 = 20, int BlocksPerChunkPow2 = 5>
-	class MemBlockPool
-	{
-		struct MemChunk
-		{
-			MemChunk()
-				:firstFreeBlock(0), numAvailableBlocks(0), data(nullptr)
-			{ }
-
-			void init(unsigned char* _data, unsigned int blockSize, unsigned char numBlocks)
-			{
-				data = _data;
-				numAvailableBlocks = numBlocks;
-				firstFreeBlock = 0;
-
-				unsigned char* dataPtr = data;
-				for(unsigned char i = 0; i < numBlocks; ++i)
-				{
-					*dataPtr = i;
-					dataPtr += blockSize;
-				}
-			}
-
-			void release()
-			{
-
-			}
-
-			void* alloc(unsigned int blockSize)
-			{
-				if(numAvailableBlocks == 0) return nullptr;
-
-				unsigned char* result = data + (firstFreeBlock * blockSize);
-				firstFreeBlock = *result;
-
-				--numAvailableBlocks;
-				return result;
-			}
-
-			void dealloc(void* dataToRls, unsigned int blockSize)
-			{
-				unsigned char* toRelease = static_cast<unsigned char*>(dataToRls);
-				*toRelease = firstFreeBlock;
-				firstFreeBlock = (toRelease - data) / blockSize;
-
-				++numAvailableBlocks;
-			}
-
-			unsigned char* data;
-			unsigned char firstFreeBlock;
-			unsigned char numAvailableBlocks;
-		};
-
-		struct MemPool
-		{
-			std::vector<MemChunk> mChunks;
-			unsigned int mBlockSize;
-			MemChunk* mAllocChunk;
-			MemChunk* mDeallocChunk;
-		};
-
-	public:
-		MemBlockPool()
-		{
-			unsigned int blockSize = 1 << BlocksPerChunkPow2;
-			mNumPools = PageSizePow2 - BlocksPerChunkPow2;
-			for(int i = 0; i < mNumPools + 1; i++)
-			{
-				mPools[i].mBlockSize = blockSize;
-				mPools[i].mAllocChunk = nullptr;
-				mPools[i].mDeallocChunk = nullptr;
-				blockSize = blockSize << 1;
-			}
-
-			mBlocksPerChunk = 1;
-			for(int i = 0; i < BlocksPerChunkPow2; i++)
-				mBlocksPerChunk <<= 1;
-		}
-
-		~MemBlockPool()
-		{
-			// TODO - Handle release
-
-			//for(auto iter = mChunks.begin(); iter != mChunks.end(); ++iter)
-			//	iter->release();
-		}
-
-		void* alloc(unsigned int size)
-		{
-			unsigned int poolIdx = sizeToPool(size) - BlocksPerChunkPow2;
-
-			if(poolIdx >= mNumPools) 
-				return CM_NEW_BYTES(size, GenAlloc);
-
-			MemPool& pool = mPools[poolIdx];
-			if(pool.mAllocChunk == nullptr || pool.mAllocChunk->numAvailableBlocks == 0)
-			{
-				for(auto iter = pool.mChunks.begin();; ++iter)
-				{
-					if(iter == pool.mChunks.end())
-					{
-						pool.mChunks.reserve(pool.mChunks.size() + 1);
-
-						MemChunk newChunk;
-						newChunk.init((unsigned char*)alloc(pool.mBlockSize * mBlocksPerChunk), pool.mBlockSize, mBlocksPerChunk);
-
-						pool.mChunks.push_back(newChunk);
-						pool.mAllocChunk = &pool.mChunks.back();
-						pool.mDeallocChunk = &pool.mChunks.back();
-						break;
-					}
-
-					if(iter->numAvailableBlocks > 0)
-					{
-						pool.mAllocChunk = &*iter;
-						break;
-					}
-				}
-			}
-
-			return pool.mAllocChunk->alloc(pool.mBlockSize);
-		}
-
-		void dealloc(void* dataToRls, unsigned int size)
-		{
-			unsigned int poolIdx = sizeToPool(size) - BlocksPerChunkPow2;
-
-			if(poolIdx >= mNumPools) 
-				return CM_DELETE_BYTES(dataToRls, GenAlloc);
-
-			MemPool& pool = mPools[poolIdx];
-			if(pool.mDeallocChunk == nullptr || dataToRls < pool.mDeallocChunk->data || dataToRls >= (pool.mDeallocChunk->data + pool.mBlockSize * mBlocksPerChunk))
-			{
-				for(auto iter = pool.mChunks.begin();; ++iter)
-				{
-					assert(iter != pool.mChunks.end()); // Trying to dealloc memory that wasn't allocated by this allocator
-
-					if(dataToRls >= iter->data && dataToRls < (iter->data + pool.mBlockSize * mBlocksPerChunk))
-					{
-						pool.mDeallocChunk = &*iter;
-						break;
-					}
-				}
-			}
-		
-			pool.mDeallocChunk->dealloc(dataToRls, pool.mBlockSize);
-
-			// If chunk is empty, release it (either to a higher level chunk to re-use, or to the OS if the chunk is highest level)
-			if(pool.mDeallocChunk->numAvailableBlocks == mBlocksPerChunk) // Chunk is completely empty
-			{
-				auto findIter = std::find(pool.mChunks.begin(), pool.mChunks.end(), pool.mDeallocChunk);
-				pool.mChunks.erase(findIter);
-
-				dealloc(pool.mDeallocChunk->data, pool.mBlockSize * mBlocksPerChunk);
-
-				pool.mDeallocChunk = nullptr;
-			}
-		}
-
-	private:
-		MemPool mPools[PageSizePow2 + 1];
-		unsigned int mBlocksPerChunk;
-		unsigned int mNumPools;
-
-		unsigned int sizeToPool(unsigned int size)
-		{
-			// TODO - Size cannot be zero
-
-			unsigned int targetlevel = 0;
-			while (size >>= 1) // I can speed this up using a BSR instruction, in case compiler doesn't already do it
-				++targetlevel;
-
-			return targetlevel;
-		}
-	};
-}