BsFrameAlloc.cpp 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. #include "BsFrameAlloc.h"
  2. #include "BsException.h"
  3. namespace BansheeEngine
  4. {
  5. FrameAlloc::MemBlock::MemBlock(UINT32 size)
  6. :mData(nullptr), mFreePtr(0), mSize(size)
  7. { }
  8. FrameAlloc::MemBlock::~MemBlock()
  9. { }
  10. UINT8* FrameAlloc::MemBlock::alloc(UINT8 amount)
  11. {
  12. UINT8* freePtr = &mData[mFreePtr];
  13. mFreePtr += amount;
  14. return freePtr;
  15. }
  16. void FrameAlloc::MemBlock::clear()
  17. {
  18. mFreePtr = 0;
  19. }
  20. FrameAlloc::FrameAlloc(UINT32 blockSize)
  21. :mTotalAllocBytes(0), mFreeBlock(nullptr), mBlockSize(blockSize)
  22. {
  23. allocBlock(mBlockSize);
  24. }
  25. FrameAlloc::~FrameAlloc()
  26. {
  27. for(auto& block : mBlocks)
  28. deallocBlock(block);
  29. }
  30. UINT8* FrameAlloc::alloc(UINT32 amount)
  31. {
  32. #if BS_DEBUG_MODE
  33. amount += sizeof(UINT32);
  34. #endif
  35. UINT32 freeMem = mFreeBlock->mSize - mFreeBlock->mFreePtr;
  36. if(amount > freeMem)
  37. allocBlock(amount);
  38. UINT8* data = mFreeBlock->alloc(amount);
  39. #if BS_DEBUG_MODE
  40. mTotalAllocBytes += amount;
  41. UINT32* storedSize = reinterpret_cast<UINT32*>(data);
  42. *storedSize = amount;
  43. return data + sizeof(UINT32);
  44. #else
  45. return data;
  46. #endif
  47. }
  48. void FrameAlloc::dealloc(UINT8* data)
  49. {
  50. // Dealloc is only used for debug and can be removed if needed. All the actual deallocation
  51. // happens in "clear"
  52. #if BS_DEBUG_MODE
  53. data -= sizeof(UINT32);
  54. UINT32* storedSize = reinterpret_cast<UINT32*>(data);
  55. mTotalAllocBytes -= *storedSize;
  56. #endif
  57. }
  58. void FrameAlloc::clear()
  59. {
  60. #if BS_DEBUG_MODE
  61. if(mTotalAllocBytes.load() > 0)
  62. BS_EXCEPT(InvalidStateException, "Not all frame allocated bytes were properly released.");
  63. #endif
  64. // Merge all blocks into one
  65. UINT32 totalBytes = 0;
  66. for(auto& block : mBlocks)
  67. {
  68. totalBytes += block->mSize;
  69. deallocBlock(block);
  70. }
  71. mBlocks.clear();
  72. allocBlock(totalBytes);
  73. }
  74. FrameAlloc::MemBlock* FrameAlloc::allocBlock(UINT32 wantedSize)
  75. {
  76. UINT32 blockSize = mBlockSize;
  77. if(wantedSize > blockSize)
  78. blockSize = wantedSize;
  79. UINT8* data = (UINT8*)reinterpret_cast<UINT8*>(bs_alloc(blockSize + sizeof(MemBlock)));
  80. MemBlock* newBlock = new (data) MemBlock(blockSize);
  81. data += sizeof(MemBlock);
  82. newBlock->mData = data;
  83. mBlocks.push_back(newBlock);
  84. mFreeBlock = newBlock; // If previous block had some empty space it is lost until next "clear"
  85. return newBlock;
  86. }
  87. void FrameAlloc::deallocBlock(MemBlock* block)
  88. {
  89. block->~MemBlock();
  90. bs_free(block);
  91. }
  92. }