Pyrogenesis  trunk
VertexBuffer.h
Go to the documentation of this file.
1 /* Copyright (C) 2015 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 VBOs with batching and sharing
20  */
21 
22 #ifndef INCLUDED_VERTEXBUFFER
23 #define INCLUDED_VERTEXBUFFER
24 
26 
27 #include <list>
28 #include <vector>
29 
30 /**
31  * CVertexBuffer: encapsulation of ARB_vertex_buffer_object, also supplying
32  * some additional functionality for sharing buffers between multiple objects.
33  *
34  * The class can be used in two modes, depending on the usage parameter:
35  *
36  * GL_STATIC_DRAW: Call Allocate() with backingStore = NULL. Then call
37  * UpdateChunkVertices() with any pointer - the data will be immediately copied
38  * to the VBO. This should be used for vertex data that rarely changes.
39  *
40  * GL_DYNAMIC_DRAW, GL_STREAM_DRAW: Call Allocate() with backingStore pointing
41  * at some memory that will remain valid for the lifetime of the CVertexBuffer.
42  * This should be used for vertex data that may change every frame.
43  * Rendering is expected to occur in two phases:
44  * - "Prepare" phase:
45  * If this chunk is going to be used for rendering during the next Bind phase,
46  * you must call PrepareForRendering().
47  * If the vertex data in backingStore has been modified since the last Bind phase,
48  * you must call UpdateChunkVertices().
49  * - "Bind" phase:
50  * Bind() can be called (multiple times). The vertex data will be uploaded
51  * to the GPU if necessary.
52  * It is okay to have multiple prepare/bind cycles per frame (though slightly less
53  * efficient), but they must occur sequentially.
54  */
56 {
58 
59 public:
60 
61  /// VBChunk: describes a portion of this vertex buffer
62  struct VBChunk
63  {
64  /// Owning (parent) vertex buffer
66  /// Start index of this chunk in owner
67  size_t m_Index;
68  /// Number of vertices used by chunk
69  size_t m_Count;
70  /// If UseStreaming() is true, points at the data for this chunk
72 
73  /// If true, the VBO is not consistent with the chunk's backing store
74  /// (and will need to be re-uploaded before rendering with this chunk)
75  bool m_Dirty;
76 
77  /// If true, we have been told this chunk is going to be used for
78  /// rendering in the next bind phase and will need to be uploaded
79  bool m_Needed;
80 
81  private:
82  // Only CVertexBuffer can construct/delete these
83  // (Other people should use g_VBMan.Allocate, g_VBMan.Release)
84  friend class CVertexBuffer;
85  VBChunk() {}
86  ~VBChunk() {}
87  };
88 
89 public:
90  // constructor, destructor
91  CVertexBuffer(size_t vertexSize, GLenum usage, GLenum target);
93 
94  /// Bind to this buffer; return pointer to address required as parameter
95  /// to glVertexPointer ( + etc) calls
96  u8* Bind();
97 
98  /// Get the address that Bind() will return, without actually binding
99  u8* GetBindAddress();
100 
101  /// Unbind any currently-bound buffer, so glVertexPointer etc calls will not attempt to use it
102  static void Unbind();
103 
104  /// Make the vertex data available for the next call to Bind()
105  void PrepareForRendering(VBChunk* chunk) { chunk->m_Needed = true; }
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(size_t vertexSize, GLenum usage, GLenum target);
116 
117  void DumpStatus();
118 
119  /**
120  * Given the usage flags of a buffer that has been (or will be) allocated:
121  *
122  * If true, we assume the buffer is going to be modified on every frame,
123  * so we will re-upload the entire buffer every frame using glMapBuffer.
124  * This requires the buffer's owner to hold onto its backing store.
125  *
126  * If false, we assume it will change rarely, and use glSubBufferData to
127  * update it incrementally. The backing store can be freed to save memory.
128  */
129  static bool UseStreaming(GLenum usage);
130 
131 protected:
132  friend class CVertexBufferManager; // allow allocate only via CVertexBufferManager
133 
134  /// Try to allocate a buffer of given number of vertices (each of given size),
135  /// and with the given type - return null if no free chunks available
136  VBChunk* Allocate(size_t vertexSize, size_t numVertices, GLenum usage, GLenum target, void* backingStore);
137  /// Return given chunk to this buffer
138  void Release(VBChunk* chunk);
139 
140 
141 private:
142 
143  /// Vertex size of this vertex buffer
144  size_t m_VertexSize;
145  /// Number of vertices of above size in this buffer
147  /// List of free chunks in this buffer
148  std::list<VBChunk*> m_FreeList;
149  /// List of allocated chunks
150  std::list<VBChunk*> m_AllocList;
151  /// Available free vertices - total of all free vertices in the free list
153  /// Handle to the actual GL vertex buffer object
154  GLuint m_Handle;
155  /// Raw system memory for systems not supporting VBOs
157  /// Usage type of the buffer (GL_STATIC_DRAW etc)
158  GLenum m_Usage;
159  /// Buffer target (GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER)
160  GLenum m_Target;
161 };
162 
163 #endif
size_t GetVertexSize() const
Definition: VertexBuffer.h:110
size_t m_Index
Start index of this chunk in owner.
Definition: VertexBuffer.h:67
static bool UseStreaming(GLenum usage)
Given the usage flags of a buffer that has been (or will be) allocated:
Definition: VertexBuffer.cpp:352
void DumpStatus()
Definition: VertexBuffer.cpp:338
void PrepareForRendering(VBChunk *chunk)
Make the vertex data available for the next call to Bind()
Definition: VertexBuffer.h:105
bool m_Needed
If true, we have been told this chunk is going to be used for rendering in the next bind phase and wi...
Definition: VertexBuffer.h:79
std::list< VBChunk * > m_AllocList
List of allocated chunks.
Definition: VertexBuffer.h:150
friend class CVertexBuffer
Definition: VertexBuffer.h:84
VBChunk()
Definition: VertexBuffer.h:85
Definition: VertexBufferManager.h:30
VBChunk * Allocate(size_t vertexSize, size_t numVertices, GLenum usage, GLenum target, void *backingStore)
Try to allocate a buffer of given number of vertices (each of given size), and with the given type - ...
Definition: VertexBuffer.cpp:102
u8 * Bind()
Bind to this buffer; return pointer to address required as parameter to glVertexPointer ( + etc) call...
Definition: VertexBuffer.cpp:228
size_t GetBytesReserved() const
Definition: VertexBuffer.cpp:328
GLenum m_Usage
Usage type of the buffer (GL_STATIC_DRAW etc)
Definition: VertexBuffer.h:158
VBChunk: describes a portion of this vertex buffer.
Definition: VertexBuffer.h:62
uint8_t u8
Definition: types.h:37
GLenum m_Target
Buffer target (GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER)
Definition: VertexBuffer.h:160
CVertexBuffer: encapsulation of ARB_vertex_buffer_object, also supplying some additional functionalit...
Definition: VertexBuffer.h:55
u8 * GetBindAddress()
Get the address that Bind() will return, without actually binding.
Definition: VertexBuffer.cpp:311
u8 * m_SysMem
Raw system memory for systems not supporting VBOs.
Definition: VertexBuffer.h:156
std::list< VBChunk * > m_FreeList
List of free chunks in this buffer.
Definition: VertexBuffer.h:148
size_t m_FreeVertices
Available free vertices - total of all free vertices in the free list.
Definition: VertexBuffer.h:152
NONCOPYABLE(CVertexBuffer)
~VBChunk()
Definition: VertexBuffer.h:86
void UpdateChunkVertices(VBChunk *chunk, void *data)
Update vertex data for given chunk. Transfers the provided data to the actual OpenGL vertex buffer...
Definition: VertexBuffer.cpp:197
void Release(VBChunk *chunk)
Return given chunk to this buffer.
Definition: VertexBuffer.cpp:160
size_t m_Count
Number of vertices used by chunk.
Definition: VertexBuffer.h:69
size_t m_MaxVertices
Number of vertices of above size in this buffer.
Definition: VertexBuffer.h:146
CVertexBuffer * m_Owner
Owning (parent) vertex buffer.
Definition: VertexBuffer.h:65
size_t GetBytesAllocated() const
Definition: VertexBuffer.cpp:333
GLuint m_Handle
Handle to the actual GL vertex buffer object.
Definition: VertexBuffer.h:154
size_t m_VertexSize
Vertex size of this vertex buffer.
Definition: VertexBuffer.h:144
bool CompatibleVertexType(size_t vertexSize, GLenum usage, GLenum target)
Returns true if this vertex buffer is compatible with the specified vertex type and intended usage...
Definition: VertexBuffer.cpp:90
void * m_BackingStore
If UseStreaming() is true, points at the data for this chunk.
Definition: VertexBuffer.h:71
bool m_Dirty
If true, the VBO is not consistent with the chunk&#39;s backing store (and will need to be re-uploaded be...
Definition: VertexBuffer.h:75
static void Unbind()
Unbind any currently-bound buffer, so glVertexPointer etc calls will not attempt to use it...
Definition: VertexBuffer.cpp:319
~CVertexBuffer()
Definition: VertexBuffer.cpp:74