BsCoreObjectManager.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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. // Note: Optimization possibilities
  68. // - Iterating over every single object takes too long. Instead dirty objects should be added to a separate array
  69. // and then just directly iterated over.
  70. // - Retrieving dependencies takes too long. A better system should be implemented so I can immediately tell
  71. // what depends on a dependency at the moment it is marked dirty. Then we can queue it into the same array above.
  72. // - e.g. Whenever dependencies change (e.g. object is created or modified) register the dependencies so we
  73. // can look them up later.
  74. // Order in which objects are recursed in matters, ones with lower ID will have been created before
  75. // ones with higher ones and should be updated first.
  76. for (auto& objectData : mObjects)
  77. {
  78. std::function<void(CoreObject*)> syncObject = [&](CoreObject* curObj)
  79. {
  80. // Sync dependencies before dependants
  81. // Note: I don't check for recursion. Possible infinite loop if two objects
  82. // are dependent on one another.
  83. FrameVector<SPtr<CoreObject>> dependencies;
  84. curObj->getCoreDependencies(dependencies);
  85. for (auto& dependency : dependencies)
  86. syncObject(dependency.get());
  87. if (curObj->isCoreDirty())
  88. {
  89. SPtr<CoreObjectCore> objectCore = curObj->getCore();
  90. if (objectCore == nullptr)
  91. return;
  92. CoreSyncData objSyncData = curObj->syncToCore(allocator);
  93. curObj->markCoreClean();
  94. syncData.entries.push_back(CoreStoredSyncObjData(objectCore.get(),
  95. curObj->getInternalID(), objSyncData));
  96. }
  97. };
  98. CoreObject* object = objectData.second;
  99. syncObject(object);
  100. }
  101. bs_frame_clear();
  102. }
  103. void CoreObjectManager::syncUpload()
  104. {
  105. BS_LOCK_MUTEX(mObjectsMutex);
  106. if (mCoreSyncData.size() == 0)
  107. return;
  108. CoreStoredSyncData& syncData = mCoreSyncData.front();
  109. for (auto& iter = syncData.entries.begin(); iter != syncData.entries.end(); ++iter)
  110. {
  111. const CoreStoredSyncObjData& objSyncData = *iter;
  112. objSyncData.destinationObj->syncToCore(objSyncData.syncData);
  113. UINT8* data = objSyncData.syncData.getBuffer();
  114. if (data != nullptr)
  115. syncData.alloc->dealloc(data);
  116. }
  117. syncData.entries.clear();
  118. mCoreSyncData.pop_front();
  119. }
  120. }