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 "BsIndexBuffer.h"
  7. namespace BansheeEngine
  8. {
  9. /** @addtogroup Resources-Internal
  10. * @{
  11. */
  12. /**
  13. * Core thread version of MeshHeap.
  14. *
  15. * @note Core thread only.
  16. */
  17. class BS_CORE_EXPORT MeshHeapCore : public CoreObjectCore
  18. {
  19. /** Signifies how is a data chunk used. */
  20. enum class UseFlags
  21. {
  22. Used, /**< Data chunk is used by both CPU and GPU. */
  23. CPUFree, /**< Data chunk was released by CPU but not GPU. */
  24. GPUFree, /**< Data chunk was released by GPU but not CPU. */
  25. Free /**< Data chunk was released by both CPU and GPU. */
  26. };
  27. /** Represents a continuous chunk of memory. */
  28. struct ChunkData
  29. {
  30. UINT32 start, size;
  31. };
  32. /** Represents an allocated piece of data representing a mesh. */
  33. struct AllocatedData
  34. {
  35. UINT32 vertChunkIdx;
  36. UINT32 idxChunkIdx;
  37. UseFlags useFlags;
  38. UINT32 eventQueryIdx;
  39. SPtr<TransientMeshCore> mesh;
  40. };
  41. /** Data about a GPU query. */
  42. struct QueryData
  43. {
  44. SPtr<EventQuery> query;
  45. UINT32 queryId;
  46. };
  47. public:
  48. ~MeshHeapCore();
  49. private:
  50. friend class MeshHeap;
  51. friend class TransientMesh;
  52. friend class TransientMeshCore;
  53. MeshHeapCore(UINT32 numVertices, UINT32 numIndices,
  54. const SPtr<VertexDataDesc>& vertexDesc, IndexType indexType, GpuDeviceFlags deviceMask);
  55. /** @copydoc CoreObjectCore::initialize() */
  56. void initialize() override;
  57. /**
  58. * Allocates a new mesh in the heap, expanding the heap if needed.
  59. *
  60. * @param[in] mesh Mesh for which we are allocating the data.
  61. * @param[in] meshData Data to initialize the new mesh with.
  62. */
  63. void alloc(SPtr<TransientMeshCore> mesh, const SPtr<MeshData>& meshData);
  64. /** Deallocates the provided mesh. Freed memory will be re-used as soon as the GPU is done with the mesh. */
  65. void dealloc(SPtr<TransientMeshCore> mesh);
  66. /** Resizes the vertex buffers so they max contain the provided number of vertices. */
  67. void growVertexBuffer(UINT32 numVertices);
  68. /** Resizes the index buffer so they max contain the provided number of indices. */
  69. void growIndexBuffer(UINT32 numIndices);
  70. /**
  71. * Creates a new event query or returns an existing one from the pool if available. Returned value is an index
  72. * into event query array.
  73. */
  74. UINT32 createEventQuery();
  75. /** Frees the event query with the specified index and returns it to the pool so it may be reused later. */
  76. void freeEventQuery(UINT32 idx);
  77. /** Gets internal vertex data for all the meshes. */
  78. SPtr<VertexData> getVertexData() const;
  79. /** Gets internal index data for all the meshes. */
  80. SPtr<IndexBufferCore> getIndexBuffer() const;
  81. /** Returns a structure that describes how are the vertices stored in the mesh's vertex buffer. */
  82. SPtr<VertexDataDesc> getVertexDesc() const;
  83. /**
  84. * Returns the offset in vertices from the start of the buffer to the first vertex of the mesh with the provided ID.
  85. */
  86. UINT32 getVertexOffset(UINT32 meshId) const;
  87. /**
  88. * Returns the offset in indices from the start of the buffer to the first index of the mesh with the provided ID.
  89. */
  90. UINT32 getIndexOffset(UINT32 meshId) const;
  91. /** Called by the render system when a mesh gets queued to the GPU. */
  92. void notifyUsedOnGPU(UINT32 meshId);
  93. /**
  94. * Called by an GPU event query when GPU processes the query. Normally signals the heap that the GPU is done with
  95. * the mesh.
  96. */
  97. static void queryTriggered(SPtr<MeshHeapCore> thisPtr, UINT32 meshId, UINT32 queryId);
  98. /**
  99. * Attempts to reorganize the vertex and index buffer chunks in order to in order to make free memory contigous.
  100. *
  101. * @note
  102. * This will not actually copy any data from index/vertex buffers, and will only modify the chunk descriptors.
  103. */
  104. void mergeWithNearbyChunks(UINT32 chunkVertIdx, UINT32 chunkIdxIdx);
  105. private:
  106. UINT32 mNumVertices;
  107. UINT32 mNumIndices;
  108. Vector<UINT8*> mCPUVertexData;
  109. UINT8* mCPUIndexData;
  110. SPtr<VertexData> mVertexData;
  111. SPtr<IndexBufferCore> mIndexBuffer;
  112. Map<UINT32, AllocatedData> mMeshAllocData;
  113. SPtr<VertexDataDesc> mVertexDesc;
  114. IndexType mIndexType;
  115. GpuDeviceFlags mDeviceMask;
  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. }