BsMeshHeap.h 7.5 KB

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