LCOV - code coverage report
Current view: top level - source/renderer - VertexBuffer.h (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 2 3 66.7 %
Date: 2023-01-19 00:18:29 Functions: 2 3 66.7 %

          Line data    Source code
       1             : /* Copyright (C) 2022 Wildfire Games.
       2             :  * This file is part of 0 A.D.
       3             :  *
       4             :  * 0 A.D. is free software: you can redistribute it and/or modify
       5             :  * it under the terms of the GNU General Public License as published by
       6             :  * the Free Software Foundation, either version 2 of the License, or
       7             :  * (at your option) any later version.
       8             :  *
       9             :  * 0 A.D. is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :  * GNU General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License
      15             :  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : /*
      19             :  * Encapsulation of backend buffers with batching and sharing.
      20             :  */
      21             : 
      22             : #ifndef INCLUDED_VERTEXBUFFER
      23             : #define INCLUDED_VERTEXBUFFER
      24             : 
      25             : #include "renderer/backend/IBuffer.h"
      26             : #include "renderer/backend/IDeviceCommandContext.h"
      27             : 
      28             : #include <memory>
      29             : #include <vector>
      30             : 
      31             : /**
      32             :  * CVertexBuffer: encapsulation of backend buffers, also supplying
      33             :  * some additional functionality for sharing buffers between multiple objects.
      34             :  *
      35             :  * The class can be used in two modes, depending on the usage parameter:
      36             :  *
      37             :  * Static buffer: Call Allocate() with backingStore = nullptr. Then call
      38             :  * UpdateChunkVertices() with any pointer - the data will be immediately copied
      39             :  * to the buffer. This should be used for vertex data that rarely changes.
      40             :  *
      41             :  * Dynamic buffer: Call Allocate() with backingStore pointing
      42             :  * at some memory that will remain valid for the lifetime of the CVertexBuffer.
      43             :  * This should be used for vertex data that may change every frame.
      44             :  * Rendering is expected to occur in two phases:
      45             :  *   - "Prepare" phase:
      46             :  *       If this chunk is going to be used for rendering during the next rendering phase,
      47             :  *       you must call PrepareForRendering().
      48             :  *       If the vertex data in backingStore has been modified since the last uploading phase,
      49             :  *       you must call UpdateChunkVertices().
      50             :  *   - "Upload" phase:
      51             :  *       UploadedIfNeeded() can be called (multiple times). The vertex data will be uploaded
      52             :  *       to the GPU if necessary.
      53             :  * It is okay to have multiple prepare/upload cycles per frame (though slightly less
      54             :  * efficient), but they must occur sequentially.
      55             :  */
      56             : class CVertexBuffer
      57             : {
      58             :     NONCOPYABLE(CVertexBuffer);
      59             : 
      60             : public:
      61             : 
      62             :     // VBChunk: describes a portion of this vertex buffer
      63             :     struct VBChunk
      64             :     {
      65             :         // Owning (parent) vertex buffer
      66             :         CVertexBuffer* m_Owner;
      67             :         // Start index of this chunk in owner
      68             :         size_t m_Index;
      69             :         // Number of vertices used by chunk
      70             :         size_t m_Count;
      71             :         // If UseStreaming() is true, points at the data for this chunk
      72             :         void* m_BackingStore;
      73             : 
      74             :         // If true, the backend buffer is not consistent with the chunk's
      75             :         // backing store (and will need to be re-uploaded before rendering with
      76             :         // this chunk).
      77             :         bool m_Dirty;
      78             : 
      79             :         // If true, we have been told this chunk is going to be used for
      80             :         // rendering in the next uploading phase and will need to be uploaded
      81             :         bool m_Needed;
      82             : 
      83             :     private:
      84             :         // Only CVertexBuffer can construct/delete these
      85             :         // (Other people should use g_VBMan.AllocateChunk)
      86             :         friend class CVertexBuffer;
      87           7 :         VBChunk() {}
      88           7 :         ~VBChunk() {}
      89             :     };
      90             : 
      91             : public:
      92             :     // constructor, destructor
      93             :     CVertexBuffer(
      94             :         const char* name, const size_t vertexSize,
      95             :         const Renderer::Backend::IBuffer::Type type, const bool dynamic);
      96             :     CVertexBuffer(
      97             :         const char* name, const size_t vertexSize,
      98             :         const Renderer::Backend::IBuffer::Type type, const bool dynamic,
      99             :         const size_t maximumBufferSize);
     100             :     ~CVertexBuffer();
     101             : 
     102             :     void UploadIfNeeded(Renderer::Backend::IDeviceCommandContext* deviceCommandContext);
     103             : 
     104             :     /// Make the vertex data available for the next usage.
     105             :     void PrepareForRendering(VBChunk* chunk);
     106             : 
     107             :     /// Update vertex data for given chunk. Transfers the provided data to the actual OpenGL vertex buffer.
     108             :     void UpdateChunkVertices(VBChunk* chunk, void* data);
     109             : 
     110             :     size_t GetVertexSize() const { return m_VertexSize; }
     111             :     size_t GetBytesReserved() const;
     112             :     size_t GetBytesAllocated() const;
     113             : 
     114             :     /// Returns true if this vertex buffer is compatible with the specified vertex type and intended usage.
     115             :     bool CompatibleVertexType(
     116             :         const size_t vertexSize, const Renderer::Backend::IBuffer::Type type,
     117             :         const bool dynamic) const;
     118             : 
     119             :     void DumpStatus() const;
     120             : 
     121             :     /**
     122             :      * Given the usage flags of a buffer that has been (or will be) allocated:
     123             :      *
     124             :      * If true, we assume the buffer is going to be modified on every frame,
     125             :      * so we will re-upload the entire buffer every frame using glMapBuffer.
     126             :      * This requires the buffer's owner to hold onto its backing store.
     127             :      *
     128             :      * If false, we assume it will change rarely, and use direct upload to
     129             :      * update it incrementally. The backing store can be freed to save memory.
     130             :      */
     131             :     static bool UseStreaming(const bool dynamic);
     132             : 
     133           0 :     Renderer::Backend::IBuffer* GetBuffer() { return m_Buffer.get(); }
     134             : 
     135             : private:
     136             :     friend class CVertexBufferManager;      // allow allocate only via CVertexBufferManager
     137             : 
     138             :     /// Try to allocate a buffer of given number of vertices (each of given size),
     139             :     /// and with the given type - return null if no free chunks available
     140             :     VBChunk* Allocate(
     141             :         const size_t vertexSize, const size_t numberOfVertices,
     142             :         const Renderer::Backend::IBuffer::Type type, const bool dynamic,
     143             :         void* backingStore);
     144             :     /// Return given chunk to this buffer
     145             :     void Release(VBChunk* chunk);
     146             : 
     147             :     /// Vertex size of this vertex buffer
     148             :     size_t m_VertexSize;
     149             :     /// Number of vertices of above size in this buffer
     150             :     size_t m_MaxVertices;
     151             :     /// List of free chunks in this buffer
     152             :     std::vector<VBChunk*> m_FreeList;
     153             :     /// List of allocated chunks
     154             :     std::vector<VBChunk*> m_AllocList;
     155             :     /// Available free vertices - total of all free vertices in the free list
     156             :     size_t m_FreeVertices;
     157             : 
     158             :     std::unique_ptr<Renderer::Backend::IBuffer> m_Buffer;
     159             : 
     160             :     bool m_HasNeededChunks;
     161             : };
     162             : 
     163             : #endif // INCLUDED_VERTEXBUFFER

Generated by: LCOV version 1.13