BsMeshHeap.h 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. #pragma once
  2. #include "BsCorePrerequisites.h"
  3. #include "BsCoreObject.h"
  4. #include "BsDrawOps.h"
  5. #include "BsIndexBuffer.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 BS_CORE_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. TransientMeshPtr mesh;
  53. };
  54. /**
  55. * @brief Data about a GPU query.
  56. */
  57. struct QueryData
  58. {
  59. EventQueryPtr query;
  60. UINT32 queryId;
  61. };
  62. public:
  63. ~MeshHeap();
  64. /**
  65. * @brief Allocates a new mesh in the heap, expanding the heap if needed. Mesh will be initialized
  66. * with the provided meshData. You may use the returned transient mesh for drawing.
  67. *
  68. * @note Offsets provided by MeshData are ignored. MeshHeap will determine
  69. * where the data will be written internally.
  70. */
  71. TransientMeshPtr alloc(const MeshDataPtr& meshData, DrawOperationType drawOp = DOT_TRIANGLE_LIST);
  72. /**
  73. * @brief Deallocates the provided mesh and makes that room on the heap re-usable as soon as the GPU
  74. * is also done with the mesh.
  75. */
  76. void dealloc(const TransientMeshPtr& mesh);
  77. /**
  78. * @brief Creates a new mesh heap.
  79. *
  80. * @param numVertices Initial number of vertices the heap may store. This will grow automatically if needed.
  81. * @param numIndices Initial number of indices the heap may store. This will grow automatically if needed.
  82. * @param vertexDesc Description of the stored vertices.
  83. * @param indexType Type of the stored indices.
  84. */
  85. static MeshHeapPtr create(UINT32 numVertices, UINT32 numIndices,
  86. const VertexDataDescPtr& vertexDesc, IndexType indexType = IT_32BIT);
  87. private:
  88. friend class TransientMesh;
  89. /**
  90. * @copydoc create
  91. */
  92. MeshHeap(UINT32 numVertices, UINT32 numIndices,
  93. const VertexDataDescPtr& vertexDesc, IndexType indexType = IT_32BIT);
  94. /**
  95. * @copydoc CoreObject::initialize_internal()
  96. */
  97. virtual void initialize_internal();
  98. /**
  99. * @copydoc CoreObject::destroy_internal()
  100. */
  101. virtual void destroy_internal();
  102. /**
  103. * @brief Allocates a new mesh in the heap, expanding the heap if needed.
  104. *
  105. * @param meshId Mesh for which we are allocating the data.
  106. * @param meshData Data to initialize the new mesh with.
  107. *
  108. * @note Core thread.
  109. */
  110. void allocInternal(TransientMeshPtr mesh, const MeshDataPtr& meshData);
  111. /**
  112. * @brief Deallocates the provided mesh Freed memory
  113. * will be re-used as soon as the GPU is done with the mesh
  114. *
  115. * @note Core thread.
  116. */
  117. void deallocInternal(TransientMeshPtr mesh);
  118. /**
  119. * @brief Resizes the vertex buffers so they max contain the provided
  120. * number of vertices.
  121. *
  122. * @note Core thread.
  123. */
  124. void growVertexBuffer(UINT32 numVertices);
  125. /**
  126. * @brief Resizes the index buffer so they max contain the provided
  127. * number of indices.
  128. *
  129. * @note Core thread.
  130. */
  131. void growIndexBuffer(UINT32 numIndices);
  132. /**
  133. * @brief Creates a new event query or returns an existing one from the pool
  134. * if available. Returned value is an index into mEventQueries array.
  135. *
  136. * @note Core thread.
  137. */
  138. UINT32 createEventQuery();
  139. /**
  140. * @brief Frees the event query with the specified index and returns it to the
  141. * pool so it may be reused later.
  142. *
  143. * @note Core thread.
  144. */
  145. void freeEventQuery(UINT32 idx);
  146. /**
  147. * @brief Gets internal vertex data for all the meshes.
  148. */
  149. SPtr<VertexData> _getVertexData() const;
  150. /**
  151. * @brief Gets internal index data for all the meshes.
  152. */
  153. SPtr<IndexBufferCore> _getIndexBuffer() const;
  154. /**
  155. * @brief Returns the offset in vertices from the start of the buffer
  156. * to the first vertex of the mesh with the provided ID.
  157. */
  158. UINT32 getVertexOffset(UINT32 meshId) const;
  159. /**
  160. * @brief Returns the offset in indices from the start of the buffer
  161. * to the first index of the mesh with the provided ID.
  162. */
  163. UINT32 getIndexOffset(UINT32 meshId) const;
  164. /**
  165. * @brief Called by the render system when a mesh gets queued to the GPU.
  166. */
  167. void notifyUsedOnGPU(UINT32 meshId);
  168. /**
  169. * @brief Called by an GPU event query when GPU processes the query. Normally
  170. * signals the heap that the GPU is done with the mesh.
  171. */
  172. static void queryTriggered(MeshHeapPtr thisPtr, UINT32 meshId, UINT32 queryId);
  173. /**
  174. * @brief Attempts to reorganize the vertex and index buffer chunks in order to
  175. * in order to make free memory contigous.
  176. *
  177. * @note This will not actually copy any data from index/vertex buffers, and will only
  178. * modify the chunk descriptors.
  179. */
  180. void mergeWithNearbyChunks(UINT32 chunkVertIdx, UINT32 chunkIdxIdx);
  181. private:
  182. UINT32 mNumVertices; // Core thread
  183. UINT32 mNumIndices; // Core thread
  184. Vector<UINT8*> mCPUVertexData; // Core thread
  185. UINT8* mCPUIndexData; // Core thread
  186. SPtr<VertexData> mVertexData; // Core thread
  187. SPtr<IndexBufferCore> mIndexBuffer; // Core thread
  188. Map<UINT32, AllocatedData> mMeshAllocData; // Core thread
  189. VertexDataDescPtr mVertexDesc; // Immutable
  190. IndexType mIndexType; // Immutable
  191. Map<UINT32, TransientMeshPtr> mMeshes; // Sim thread
  192. UINT32 mNextFreeId; // Sim thread
  193. Vector<ChunkData> mVertChunks; // Core thread
  194. Vector<ChunkData> mIdxChunks; // Core thread
  195. Stack<UINT32> mEmptyVertChunks; // Core thread
  196. Stack<UINT32> mEmptyIdxChunks; // Core thread
  197. List<UINT32> mFreeVertChunks; // Core thread
  198. List<UINT32> mFreeIdxChunks; // Core thread
  199. Vector<QueryData> mEventQueries; // Core thread
  200. Stack<UINT32> mFreeEventQueries; // Core thread
  201. UINT32 mNextQueryId;
  202. static const float GrowPercent;
  203. };
  204. }