CmMeshHeap.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. #pragma once
  2. #include "CmPrerequisites.h"
  3. #include "CmCoreObject.h"
  4. #include "CmIndexData.h"
  5. #include "CmDrawOps.h"
  6. namespace BansheeEngine
  7. {
  8. /**
  9. * @brief Mesh heap allows you to quickly allocate and deallocate a large amounts of temporary
  10. * meshes without the large overhead of normal Mesh creation.
  11. * Only requirement is that meshes share the same vertex description and index type.
  12. *
  13. * @note This class should be considered as a replacement for a normal Mesh if you are constantly
  14. * updating the mesh (e.g. every frame) and you are not able to discard entire mesh contents
  15. * on each update. Not using discard flag on normal meshes may introduce GPU-CPU sync points
  16. * which may severely limit performance. Primary purpose of this class is to avoid
  17. * those sync points by not forcing you to discard contents.
  18. *
  19. * Downside is that this class may allocate 2-3x (or more) memory than it is actually needed
  20. * for your data.
  21. *
  22. * Sim thread except where noted otherwise.
  23. */
  24. class CM_EXPORT MeshHeap : public CoreObject
  25. {
  26. /**
  27. * @brief Signifies how is a data chunk used.
  28. */
  29. enum class UseFlags
  30. {
  31. Used, /**< Data chunk is used by both CPU and GPU. */
  32. CPUFree, /**< Data chunk was released by CPU but not GPU. */
  33. GPUFree, /**< Data chunk was released by GPU but not CPU. */
  34. Free /**< Data chunk was released by both CPU and GPU. */
  35. };
  36. /**
  37. * @brief Represents a continuous chunk of memory.
  38. */
  39. struct ChunkData
  40. {
  41. UINT32 start, size;
  42. };
  43. /**
  44. * @brief Represents an allocated piece of data representing a mesh.
  45. */
  46. struct AllocatedData
  47. {
  48. UINT32 vertChunkIdx;
  49. UINT32 idxChunkIdx;
  50. UseFlags useFlags;
  51. UINT32 eventQueryIdx;
  52. };
  53. /**
  54. * @brief Data about a GPU query.
  55. */
  56. struct QueryData
  57. {
  58. EventQueryPtr query;
  59. UINT32 queryId;
  60. };
  61. public:
  62. ~MeshHeap();
  63. /**
  64. * @brief Allocates a new mesh in the heap, expanding the heap if needed. Mesh will be initialized
  65. * with the provided meshData. You may use the returned transient mesh for drawing.
  66. *
  67. * @note Offsets provided by MeshData are ignored. MeshHeap will determine
  68. * where the data will be written internally.
  69. */
  70. TransientMeshPtr alloc(const MeshDataPtr& meshData, DrawOperationType drawOp = DOT_TRIANGLE_LIST);
  71. /**
  72. * @brief Deallocates the provided mesh and makes that room on the heap re-usable as soon as the GPU
  73. * is also done with the mesh.
  74. */
  75. void dealloc(const TransientMeshPtr& mesh);
  76. /**
  77. * @brief Creates a new mesh heap.
  78. *
  79. * @param numVertices Initial number of vertices the heap may store. This will grow automatically if needed.
  80. * @param numIndices Initial number of indices the heap may store. This will grow automatically if needed.
  81. * @param vertexDesc Description of the stored vertices.
  82. * @param indexType Type of the stored indices.
  83. */
  84. static MeshHeapPtr create(UINT32 numVertices, UINT32 numIndices,
  85. const VertexDataDescPtr& vertexDesc, IndexBuffer::IndexType indexType = IndexBuffer::IT_32BIT);
  86. private:
  87. friend class TransientMesh;
  88. /**
  89. * @copydoc create
  90. */
  91. MeshHeap(UINT32 numVertices, UINT32 numIndices,
  92. const VertexDataDescPtr& vertexDesc, IndexBuffer::IndexType indexType = IndexBuffer::IT_32BIT);
  93. /**
  94. * @copydoc Resource::initialize_internal()
  95. */
  96. virtual void initialize_internal();
  97. /**
  98. * @copydoc Resource::destroy_internal()
  99. */
  100. virtual void destroy_internal();
  101. /**
  102. * @brief Allocates a new mesh in the heap, expanding the heap if needed.
  103. *
  104. * @param meshId Unique mesh ID.
  105. * @param meshData Data to initialize the new mesh with.
  106. *
  107. * @note Core thread.
  108. */
  109. void allocInternal(UINT32 meshId, const MeshDataPtr& meshData);
  110. /**
  111. * @brief Deallocates the mesh with the provided ID. Freed memory
  112. * will be re-used as soon as the GPU is done with the mesh
  113. *
  114. * @note Core thread.
  115. */
  116. void deallocInternal(UINT32 meshId);
  117. /**
  118. * @brief Resizes the vertex buffers so they max contain the provided
  119. * number of vertices.
  120. *
  121. * @note Core thread.
  122. */
  123. void growVertexBuffer(UINT32 numVertices);
  124. /**
  125. * @brief Resizes the index buffer so they max contain the provided
  126. * number of indices.
  127. *
  128. * @note Core thread.
  129. */
  130. void growIndexBuffer(UINT32 numIndices);
  131. /**
  132. * @brief Creates a new event query or returns an existing one from the pool
  133. * if available. Returned value is an index into mEventQueries array.
  134. *
  135. * @note Core thread.
  136. */
  137. UINT32 createEventQuery();
  138. /**
  139. * @brief Frees the event query with the specified index and returns it to the
  140. * pool so it may be reused later.
  141. *
  142. * @note Core thread.
  143. */
  144. void freeEventQuery(UINT32 idx);
  145. /**
  146. * @brief Gets internal vertex data for all the meshes.
  147. */
  148. std::shared_ptr<VertexData> getVertexData() const;
  149. /**
  150. * @brief Gets internal index data for all the meshes.
  151. */
  152. std::shared_ptr<IndexData> getIndexData() const;
  153. /**
  154. * @brief Returns the offset in vertices from the start of the buffer
  155. * to the first vertex of the mesh with the provided ID.
  156. */
  157. UINT32 getVertexOffset(UINT32 meshId) const;
  158. /**
  159. * @brief Returns the offset in indices from the start of the buffer
  160. * to the first index of the mesh with the provided ID.
  161. */
  162. UINT32 getIndexOffset(UINT32 meshId) const;
  163. /**
  164. * @brief Called by the render system when a mesh gets queued to the GPU.
  165. */
  166. void notifyUsedOnGPU(UINT32 meshId);
  167. /**
  168. * @brief Called by an GPU event query when GPU processes the query. Normally
  169. * signals the heap that the GPU is done with the mesh.
  170. */
  171. void queryTriggered(UINT32 meshId, UINT32 queryId);
  172. /**
  173. * @brief Attempts to reorganize the vertex and index buffer chunks in order to
  174. * in order to make free memory contigous.
  175. *
  176. * @note This will not actually copy any data from index/vertex buffers, and will only
  177. * modify the chunk descriptors.
  178. */
  179. void mergeWithNearbyChunks(UINT32 chunkVertIdx, UINT32 chunkIdxIdx);
  180. private:
  181. UINT32 mNumVertices; // Core thread
  182. UINT32 mNumIndices; // Core thread
  183. std::shared_ptr<VertexData> mVertexData; // Core thread
  184. std::shared_ptr<IndexData> mIndexData; // Core thread
  185. Vector<UINT8*> mCPUVertexData; // Core thread
  186. UINT8* mCPUIndexData; // Core thread
  187. VertexDataDescPtr mVertexDesc; // Immutable
  188. IndexBuffer::IndexType mIndexType; // Immutable
  189. Map<UINT32, TransientMeshPtr> mMeshes; // Sim thread
  190. UINT32 mNextFreeId; // Sim thread
  191. Map<UINT32, AllocatedData> mMeshAllocData; // Core thread
  192. Vector<ChunkData> mVertChunks; // Core thread
  193. Vector<ChunkData> mIdxChunks; // Core thread
  194. Stack<UINT32> mEmptyVertChunks; // Core thread
  195. Stack<UINT32> mEmptyIdxChunks; // Core thread
  196. List<UINT32> mFreeVertChunks; // Core thread
  197. List<UINT32> mFreeIdxChunks; // Core thread
  198. Vector<QueryData> mEventQueries; // Core thread
  199. Stack<UINT32> mFreeEventQueries; // Core thread
  200. UINT32 mNextQueryId;
  201. static const float GrowPercent;
  202. };
  203. }