BsCoreObjectManager.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. #include "BsCoreObjectManager.h"
  2. #include "BsCoreObject.h"
  3. #include "BsCoreObjectCore.h"
  4. #include "BsException.h"
  5. #include "BsMath.h"
  6. #include "BsFrameAlloc.h"
  7. #include "BsCoreThread.h"
  8. namespace BansheeEngine
  9. {
  10. CoreObjectManager::CoreObjectManager()
  11. :mNextAvailableID(1)
  12. {
  13. }
  14. CoreObjectManager::~CoreObjectManager()
  15. {
  16. #if BS_DEBUG_MODE
  17. BS_LOCK_MUTEX(mObjectsMutex);
  18. if(mObjects.size() > 0)
  19. {
  20. // All objects MUST be destroyed at this point, otherwise there might be memory corruption.
  21. // (Reason: This is called on application shutdown and at that point we also unload any dynamic libraries,
  22. // which will invalidate any pointers to objects created from those libraries. Therefore we require of the user to
  23. // clean up all objects manually before shutting down the application).
  24. BS_EXCEPT(InternalErrorException, "Core object manager shut down, but not all objects were released. Application must release ALL " \
  25. "engine objects before shutdown.");
  26. }
  27. #endif
  28. }
  29. UINT64 CoreObjectManager::registerObject(CoreObject* object)
  30. {
  31. assert(object != nullptr);
  32. BS_LOCK_MUTEX(mObjectsMutex);
  33. mObjects[mNextAvailableID] = object;
  34. return mNextAvailableID++;
  35. }
  36. void CoreObjectManager::unregisterObject(CoreObject* object)
  37. {
  38. assert(object != nullptr);
  39. BS_LOCK_MUTEX(mObjectsMutex);
  40. UINT64 internalId = object->getInternalID();
  41. mObjects.erase(internalId);
  42. for (auto& syncData : mCoreSyncData)
  43. {
  44. auto iterFind = std::find_if(syncData.entries.begin(), syncData.entries.end(),
  45. [&](const CoreStoredSyncObjData& data) { return data.internalId == internalId; });
  46. if (iterFind != syncData.entries.end())
  47. {
  48. UINT8* data = iterFind->syncData.getBuffer();
  49. if (data != nullptr && syncData.alloc != nullptr)
  50. syncData.alloc->dealloc(data);
  51. syncData.entries.erase(iterFind);
  52. }
  53. }
  54. }
  55. void CoreObjectManager::syncToCore(CoreAccessor& accessor)
  56. {
  57. syncDownload(gCoreThread().getFrameAlloc());
  58. accessor.queueCommand(std::bind(&CoreObjectManager::syncUpload, this));
  59. }
  60. void CoreObjectManager::syncDownload(FrameAlloc* allocator)
  61. {
  62. BS_LOCK_MUTEX(mObjectsMutex);
  63. mCoreSyncData.push_back(CoreStoredSyncData());
  64. CoreStoredSyncData& syncData = mCoreSyncData.back();
  65. syncData.alloc = allocator;
  66. bs_frame_mark();
  67. // Order in which objects are recursed in matters, ones with lower ID will have been created before
  68. // ones with higher ones and should be updated first.
  69. for (auto& objectData : mObjects)
  70. {
  71. std::function<void(CoreObject*)> syncObject = [&](CoreObject* curObj)
  72. {
  73. // Sync dependencies before dependants
  74. // Note: I don't check for recursion. Possible infinite loop if two objects
  75. // are dependent on one another.
  76. FrameVector<SPtr<CoreObject>> dependencies;
  77. curObj->getCoreDependencies(dependencies);
  78. for (auto& dependency : dependencies)
  79. syncObject(dependency.get());
  80. if (curObj->isCoreDirty())
  81. {
  82. SPtr<CoreObjectCore> objectCore = curObj->getCore();
  83. if (objectCore == nullptr)
  84. return;
  85. CoreSyncData objSyncData = curObj->syncToCore(allocator);
  86. curObj->markCoreClean();
  87. syncData.entries.push_back(CoreStoredSyncObjData(objectCore.get(),
  88. curObj->getInternalID(), objSyncData));
  89. }
  90. };
  91. CoreObject* object = objectData.second;
  92. syncObject(object);
  93. }
  94. bs_frame_clear();
  95. }
  96. void CoreObjectManager::syncUpload()
  97. {
  98. BS_LOCK_MUTEX(mObjectsMutex);
  99. if (mCoreSyncData.size() == 0)
  100. return;
  101. CoreStoredSyncData& syncData = mCoreSyncData.front();
  102. for (auto& iter = syncData.entries.begin(); iter != syncData.entries.end(); ++iter)
  103. {
  104. const CoreStoredSyncObjData& objSyncData = *iter;
  105. objSyncData.destinationObj->syncToCore(objSyncData.syncData);
  106. UINT8* data = objSyncData.syncData.getBuffer();
  107. if (data != nullptr)
  108. syncData.alloc->dealloc(data);
  109. }
  110. syncData.entries.clear();
  111. mCoreSyncData.pop_front();
  112. }
  113. }