BsMeshHeap.h 7.5 KB

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