| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- #pragma once
- #include "BsCorePrerequisites.h"
- #include "BsCoreObject.h"
- #include "BsDrawOps.h"
- #include "BsIndexBuffer.h"
- namespace BansheeEngine
- {
- /**
- * @brief Core thread version of MeshHeap.
- *
- * @see MeshHeap
- *
- * @note Core thread only.
- */
- class BS_CORE_EXPORT MeshHeapCore : public CoreObjectCore
- {
- /**
- * @brief Signifies how is a data chunk used.
- */
- enum class UseFlags
- {
- Used, /**< Data chunk is used by both CPU and GPU. */
- CPUFree, /**< Data chunk was released by CPU but not GPU. */
- GPUFree, /**< Data chunk was released by GPU but not CPU. */
- Free /**< Data chunk was released by both CPU and GPU. */
- };
- /**
- * @brief Represents a continuous chunk of memory.
- */
- struct ChunkData
- {
- UINT32 start, size;
- };
- /**
- * @brief Represents an allocated piece of data representing a mesh.
- */
- struct AllocatedData
- {
- UINT32 vertChunkIdx;
- UINT32 idxChunkIdx;
- UseFlags useFlags;
- UINT32 eventQueryIdx;
- SPtr<TransientMeshCore> mesh;
- };
- /**
- * @brief Data about a GPU query.
- */
- struct QueryData
- {
- EventQueryPtr query;
- UINT32 queryId;
- };
- public:
- ~MeshHeapCore();
- private:
- friend class MeshHeap;
- friend class TransientMesh;
- friend class TransientMeshCore;
- MeshHeapCore(UINT32 numVertices, UINT32 numIndices,
- const VertexDataDescPtr& vertexDesc, IndexType indexType = IT_32BIT);
- /**
- * @copydoc CoreObjectCore::initialize()
- */
- virtual void initialize() override;
- /**
- * @brief Allocates a new mesh in the heap, expanding the heap if needed.
- *
- * @param meshId Mesh for which we are allocating the data.
- * @param meshData Data to initialize the new mesh with.
- */
- void alloc(SPtr<TransientMeshCore> mesh, const MeshDataPtr& meshData);
- /**
- * @brief Deallocates the provided mesh Freed memory
- * will be re-used as soon as the GPU is done with the mesh
- */
- void dealloc(SPtr<TransientMeshCore> mesh);
- /**
- * @brief Resizes the vertex buffers so they max contain the provided
- * number of vertices.
- */
- void growVertexBuffer(UINT32 numVertices);
- /**
- * @brief Resizes the index buffer so they max contain the provided
- * number of indices.
- */
- void growIndexBuffer(UINT32 numIndices);
- /**
- * @brief Creates a new event query or returns an existing one from the pool
- * if available. Returned value is an index into mEventQueries array.
- */
- UINT32 createEventQuery();
- /**
- * @brief Frees the event query with the specified index and returns it to the
- * pool so it may be reused later.
- */
- void freeEventQuery(UINT32 idx);
- /**
- * @brief Gets internal vertex data for all the meshes.
- */
- SPtr<VertexData> getVertexData() const;
- /**
- * @brief Gets internal index data for all the meshes.
- */
- SPtr<IndexBufferCore> getIndexBuffer() const;
- /**
- * @brief Returns the offset in vertices from the start of the buffer
- * to the first vertex of the mesh with the provided ID.
- */
- UINT32 getVertexOffset(UINT32 meshId) const;
- /**
- * @brief Returns the offset in indices from the start of the buffer
- * to the first index of the mesh with the provided ID.
- */
- UINT32 getIndexOffset(UINT32 meshId) const;
- /**
- * @brief Called by the render system when a mesh gets queued to the GPU.
- */
- void notifyUsedOnGPU(UINT32 meshId);
- /**
- * @brief Called by an GPU event query when GPU processes the query. Normally
- * signals the heap that the GPU is done with the mesh.
- */
- static void queryTriggered(SPtr<MeshHeapCore> thisPtr, UINT32 meshId, UINT32 queryId);
- /**
- * @brief Attempts to reorganize the vertex and index buffer chunks in order to
- * in order to make free memory contigous.
- *
- * @note This will not actually copy any data from index/vertex buffers, and will only
- * modify the chunk descriptors.
- */
- void mergeWithNearbyChunks(UINT32 chunkVertIdx, UINT32 chunkIdxIdx);
- private:
- UINT32 mNumVertices;
- UINT32 mNumIndices;
- Vector<UINT8*> mCPUVertexData;
- UINT8* mCPUIndexData;
- SPtr<VertexData> mVertexData;
- SPtr<IndexBufferCore> mIndexBuffer;
- Map<UINT32, AllocatedData> mMeshAllocData;
- VertexDataDescPtr mVertexDesc;
- IndexType mIndexType;
- Vector<ChunkData> mVertChunks;
- Vector<ChunkData> mIdxChunks;
- Stack<UINT32> mEmptyVertChunks;
- Stack<UINT32> mEmptyIdxChunks;
- List<UINT32> mFreeVertChunks;
- List<UINT32> mFreeIdxChunks;
- Vector<QueryData> mEventQueries;
- Stack<UINT32> mFreeEventQueries;
- UINT32 mNextQueryId;
- static const float GrowPercent;
- };
- /**
- * @brief Mesh heap allows you to quickly allocate and deallocate a large amounts of temporary
- * meshes without the large overhead of normal Mesh creation.
- * Only requirement is that meshes share the same vertex description and index type.
- *
- * @note This class should be considered as a replacement for a normal Mesh if you are constantly
- * updating the mesh (e.g. every frame) and you are not able to discard entire mesh contents
- * on each update. Not using discard flag on normal meshes may introduce GPU-CPU sync points
- * which may severely limit performance. Primary purpose of this class is to avoid
- * those sync points by not forcing you to discard contents.
- *
- * Downside is that this class may allocate 2-3x (or more) memory than it is actually needed
- * for your data.
- *
- * Sim thread only
- */
- class BS_CORE_EXPORT MeshHeap : public CoreObject
- {
- public:
- /**
- * @brief Allocates a new mesh in the heap, expanding the heap if needed. Mesh will be initialized
- * with the provided meshData. You may use the returned transient mesh for drawing.
- *
- * @note Offsets provided by MeshData are ignored. MeshHeap will determine
- * where the data will be written internally.
- */
- TransientMeshPtr alloc(const MeshDataPtr& meshData, DrawOperationType drawOp = DOT_TRIANGLE_LIST);
- /**
- * @brief Deallocates the provided mesh and makes that room on the heap re-usable as soon as the GPU
- * is also done with the mesh.
- */
- void dealloc(const TransientMeshPtr& mesh);
- /**
- * @brief Retrieves a core implementation of a mesh heap usable only from the
- * core thread.
- */
- SPtr<MeshHeapCore> getCore() const;
- /**
- * @brief Creates a new mesh heap.
- *
- * @param numVertices Initial number of vertices the heap may store. This will grow automatically if needed.
- * @param numIndices Initial number of indices the heap may store. This will grow automatically if needed.
- * @param vertexDesc Description of the stored vertices.
- * @param indexType Type of the stored indices.
- */
- static MeshHeapPtr create(UINT32 numVertices, UINT32 numIndices,
- const VertexDataDescPtr& vertexDesc, IndexType indexType = IT_32BIT);
- private:
- /**
- * @copydoc create
- */
- MeshHeap(UINT32 numVertices, UINT32 numIndices,
- const VertexDataDescPtr& vertexDesc, IndexType indexType = IT_32BIT);
- /**
- * @copydoc CoreObject::createCore
- */
- SPtr<CoreObjectCore> createCore() const override;
- private:
- UINT32 mNumVertices;
- UINT32 mNumIndices;
- VertexDataDescPtr mVertexDesc;
- IndexType mIndexType;
- Map<UINT32, TransientMeshPtr> mMeshes;
- UINT32 mNextFreeId;
- };
- }
|