2
0

BsFrameAlloc.cpp 2.7 KB

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