BsMeshHeap.h 7.4 KB

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