CmCoreObject.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. #pragma once
  2. #include "CmPrerequisites.h"
  3. #include "CmAsyncOp.h"
  4. #include <boost/function.hpp>
  5. #include <boost/preprocessor.hpp>
  6. namespace CamelotFramework
  7. {
  8. /**
  9. * @brief This class provides some common functionality that all low-level GPU-related objects
  10. * need to implement.
  11. *
  12. * @note This involves initializing, keeping track of, and releasing all GPU resources.
  13. * All core GPU objects are initialized on the core thread, and destroyed on the core thread,
  14. * so majority of these methods will just schedule object initialization/destruction.
  15. */
  16. class CM_EXPORT CoreObject
  17. {
  18. protected:
  19. enum Flags
  20. {
  21. CGO_INITIALIZED = 0x01,
  22. CGO_INIT_ON_RENDER_THREAD = 0x02,
  23. CGO_SCHEDULED_FOR_INIT = 0x04,
  24. CGO_SCHEDULED_FOR_DELETE = 0x08,
  25. CGO_DESTROYED = 0x16
  26. };
  27. public:
  28. CoreObject(bool requiresGpuInit = true);
  29. virtual ~CoreObject();
  30. /**
  31. * @brief Destroys all GPU resources of this object.
  32. o *
  33. * @note Destruction is not done immediately, and is instead just scheduled on the
  34. * core thread. Unless called from core thread in which case it is executed right away.
  35. */
  36. virtual void destroy();
  37. /**
  38. * @brief Initializes all the internal resources of this object. Should be called by the
  39. * factory creation methods automatically after construction and not by user directly.
  40. *
  41. * @note Initialization is not done immediately, and is instead just scheduled on the
  42. * core thread. Unless called from core thread in which case it is executed right away.
  43. */
  44. virtual void initialize();
  45. /**
  46. * @brief Returns true if the object has been properly initialized. You are not
  47. * allowed to call any methods on the resource until you are sure resource is initialized.
  48. */
  49. bool isInitialized() const { return (mFlags & CGO_INITIALIZED) != 0; }
  50. /**
  51. * @brief Blocks the current thread until the resource is fully initialized.
  52. * If you call this without calling initialize first a deadlock will occurr.
  53. */
  54. void synchronize();
  55. /**
  56. * @brief Sets a shared this pointer to this object. This MUST be called immediately after construction.
  57. *
  58. * @note Called automatically by the factory creation methods so user should not call this manually.
  59. */
  60. void setThisPtr(std::shared_ptr<CoreObject> ptrThis);
  61. /**
  62. * @brief Returns an unique identifier for this object.
  63. */
  64. UINT64 getInternalID() const { return mInternalID; }
  65. /**
  66. * @brief Schedules the object to be destroyed, and then deleted.
  67. *
  68. * @note You should never call this manually. It's meant for internal use only.
  69. */
  70. template<class T, class MemAlloc>
  71. static void _deleteDelayed(CoreObject* obj)
  72. {
  73. _deleteDelayedInternal(obj);
  74. if(obj->isInitialized())
  75. {
  76. std::shared_ptr<CoreObject> thisPtr(obj);
  77. obj->setThisPtr(thisPtr);
  78. obj->destroy();
  79. }
  80. else
  81. {
  82. cm_delete<MemAlloc, T>((T*)obj);
  83. }
  84. }
  85. /**
  86. * @brief Returns a shared_ptr version of "this" pointer.
  87. */
  88. std::shared_ptr<CoreObject> getThisPtr() const { return mThis.lock(); }
  89. protected:
  90. /**
  91. * @brief Frees all of the objects dynamically allocated memory. All derived classes that have something to free
  92. * should do it here instead of their destructor. All derived classes need to call this base method when they're done.
  93. *
  94. * @note Since this is scheduled to be executed on the core thread, normally you want to destroy all GPU specific resources here.
  95. */
  96. virtual void destroy_internal();
  97. /**
  98. * @brief Initializes all the internal resources of this object. Needs to be called before doing
  99. * any operations with the object. All derived classes also need to call this base method.
  100. *
  101. * @note Since this is scheduled to be executed on the core thread, normally you want to initialize all GPU specific resources here.
  102. */
  103. virtual void initialize_internal();
  104. static void _deleteDelayedInternal(CoreObject* obj);
  105. /**
  106. * @brief Queues a command to be executed on the core thread, without a return value.
  107. *
  108. * @note Requires a shared pointer to the object this function will be executed on, in order to
  109. * make sure the object is not deleted before the command executes. Can be null if the
  110. * function is static or global.
  111. */
  112. static void queueGpuCommand(std::shared_ptr<CoreObject>& obj, boost::function<void()> func);
  113. /**
  114. * @brief Queues a command to be executed on the core thread, with a return value in the form of AsyncOp.
  115. *
  116. * @see AsyncOp
  117. *
  118. * @note Requires a shared pointer to the object this function will be executed on, in order to
  119. * make sure the object is not deleted before the command executes. Can be null if the
  120. * function is static or global.
  121. */
  122. static AsyncOp queueReturnGpuCommand(std::shared_ptr<CoreObject>& obj, boost::function<void(AsyncOp&)> func);
  123. bool isScheduledToBeInitialized() const { return (mFlags & CGO_SCHEDULED_FOR_INIT) != 0; }
  124. bool isScheduledToBeDeleted() const { return (mFlags & CGO_SCHEDULED_FOR_DELETE) != 0; }
  125. bool requiresInitOnRenderThread() const { return (mFlags & CGO_INIT_ON_RENDER_THREAD) != 0; }
  126. void setIsInitialized(bool initialized) { mFlags = initialized ? mFlags | CGO_INITIALIZED : mFlags & ~CGO_INITIALIZED; }
  127. void setScheduledToBeInitialized(bool scheduled) { mFlags = scheduled ? mFlags | CGO_SCHEDULED_FOR_INIT : mFlags & ~CGO_SCHEDULED_FOR_INIT; }
  128. void setScheduledToBeDeleted(bool scheduled) { mFlags = scheduled ? mFlags | CGO_SCHEDULED_FOR_DELETE : mFlags & ~CGO_SCHEDULED_FOR_DELETE; }
  129. private:
  130. friend class CoreGpuObjectManager;
  131. volatile UINT8 mFlags;
  132. UINT64 mInternalID; // ID == 0 is not a valid ID
  133. std::weak_ptr<CoreObject> mThis;
  134. CM_STATIC_THREAD_SYNCHRONISER(mCoreGpuObjectLoadedCondition)
  135. CM_STATIC_MUTEX(mCoreGpuObjectLoadedMutex)
  136. static void queueInitializeGpuCommand(std::shared_ptr<CoreObject>& obj);
  137. static void queueDestroyGpuCommand(std::shared_ptr<CoreObject>& obj);
  138. static void executeGpuCommand(std::shared_ptr<CoreObject>& obj, boost::function<void()> func);
  139. static void executeReturnGpuCommand(std::shared_ptr<CoreObject>& obj, boost::function<void(AsyncOp&)> func, AsyncOp& op);
  140. };
  141. #define MAKE_CM_NEW_CORE(z, n, unused) \
  142. template<class Type, class MainAlloc, class PtrDataAlloc BOOST_PP_ENUM_TRAILING_PARAMS(n, class T)> \
  143. std::shared_ptr<Type> cm_core_ptr(BOOST_PP_ENUM_BINARY_PARAMS(n, T, t) ) { \
  144. return std::shared_ptr<Type>(cm_new<Type, MainAlloc>(BOOST_PP_ENUM_PARAMS (n, t)), &CoreObject::_deleteDelayed<Type, MainAlloc>, StdAlloc<PtrDataAlloc>()); \
  145. }
  146. BOOST_PP_REPEAT(15, MAKE_CM_NEW_CORE, ~)
  147. #undef MAKE_CM_NEW_CORE
  148. #define MAKE_CM_NEW_CORE(z, n, unused) \
  149. template<class Type, class MainAlloc BOOST_PP_ENUM_TRAILING_PARAMS(n, class T)> \
  150. std::shared_ptr<Type> cm_core_ptr(BOOST_PP_ENUM_BINARY_PARAMS(n, T, t) ) { \
  151. return std::shared_ptr<Type>(cm_new<Type, MainAlloc>(BOOST_PP_ENUM_PARAMS (n, t)), &CoreObject::_deleteDelayed<Type, MainAlloc>, StdAlloc<GenAlloc>()); \
  152. }
  153. BOOST_PP_REPEAT(15, MAKE_CM_NEW_CORE, ~)
  154. #undef MAKE_CM_NEW_CORE
  155. #define MAKE_CM_NEW_CORE(z, n, unused) \
  156. template<class Type BOOST_PP_ENUM_TRAILING_PARAMS(n, class T)> \
  157. std::shared_ptr<Type> cm_core_ptr(BOOST_PP_ENUM_BINARY_PARAMS(n, T, t) ) { \
  158. return std::shared_ptr<Type>(cm_new<Type, GenAlloc>(BOOST_PP_ENUM_PARAMS (n, t)), &CoreObject::_deleteDelayed<Type, GenAlloc>, StdAlloc<GenAlloc>()); \
  159. }
  160. BOOST_PP_REPEAT(15, MAKE_CM_NEW_CORE, ~)
  161. #undef MAKE_CM_NEW_CORE
  162. template<class Type, class MainAlloc>
  163. std::shared_ptr<Type> cm_core_ptr(Type* data)
  164. {
  165. return std::shared_ptr<Type>(data, &CoreObject::_deleteDelayed<Type, MainAlloc>, StdAlloc<GenAlloc>());
  166. }
  167. template<class Type, class MainAlloc, class PtrDataAlloc>
  168. std::shared_ptr<Type> cm_core_ptr(Type* data)
  169. {
  170. return std::shared_ptr<Type>(data, &CoreObject::_deleteDelayed<Type, MainAlloc>, StdAlloc<PtrDataAlloc>());
  171. }
  172. }