5 #include <unordered_map>
8 #include "../../meshes/mesh.h"
9 #include "../../generic/managed.h"
10 #include "../../time_keeper.h"
11 #include "../glad/glad/glad.h"
12 #include "../../utils/gl_error.h"
13 #include "../batching/renderable.h"
15 #include "../../logging.h"
17 #define __LOGGER__ "/smlt/vbo"
19 #define L_DEBUG_VBO(txt) smlt::get_logger(__LOGGER__)->debug(txt, __FILE__, __LINE__)
20 #define L_INFO_VBO(txt) smlt::get_logger(__LOGGER__)->info(txt, __FILE__, __LINE__)
21 #define L_WARN_VBO(txt) smlt::get_logger(__LOGGER__)->warn(txt, __FILE__, __LINE__)
22 #define L_ERROR_VBO(txt) smlt::get_logger(__LOGGER__)->error(txt, __FILE__, __LINE__)
27 const uint32_t VBO_SIZE = 1024 * 512;
29 typedef uint32_t VBOSlot;
35 VBO* vertex_vbo =
nullptr;
36 VBO* index_vbo =
nullptr;
38 VBOSlot vertex_vbo_slot;
39 VBOSlot index_vbo_slot;
41 void sync_data_from_renderable(
Renderable* renderable);
46 VBO_SLOT_SIZE_1K = (1 << 10),
47 VBO_SLOT_SIZE_2K = (1 << 11),
48 VBO_SLOT_SIZE_4K = (1 << 12),
49 VBO_SLOT_SIZE_8K = (1 << 13),
50 VBO_SLOT_SIZE_16K = (1 << 14),
51 VBO_SLOT_SIZE_32K = (1 << 15),
52 VBO_SLOT_SIZE_64K = (1 << 16),
53 VBO_SLOT_SIZE_128K = (1 << 17),
54 VBO_SLOT_SIZE_256K = (1 << 18),
55 VBO_SLOT_SIZE_512K = (1 << 19)
58 const int VBO_SLOT_SIZE_COUNT = 11;
64 virtual GLenum target()
const = 0;
65 virtual void upload(VBOSlot,
const VertexData* vertex_data) = 0;
66 virtual void upload(VBOSlot,
const IndexData* index_data) = 0;
67 virtual void bind(VBOSlot) = 0;
68 virtual uint64_t slot_last_updated(VBOSlot slot) = 0;
69 virtual uint32_t byte_offset(VBOSlot slot) = 0;
70 virtual uint32_t slot_size_in_bytes()
const = 0;
72 virtual VBOSlot allocate_slot() = 0;
73 virtual void release_slot(VBOSlot slot) = 0;
75 virtual uint32_t used_slot_count()
const = 0;
76 virtual uint32_t free_slot_count()
const = 0;
87 type_(GL_ARRAY_BUFFER) {}
91 index_type_(index_type),
92 type_(GL_ELEMENT_ARRAY_BUFFER) {}
96 if(gl_id_) glDeleteBuffers(1, &gl_id_);
98 S_WARN(
"Exception while deleting GL VBO");
102 uint64_t slot_last_updated(VBOSlot slot) { assert(slot == 0);
return last_updated_; }
103 GLenum target()
const {
return type_; }
105 void upload(VBOSlot,
const VertexData* vertex_data);
106 void upload(VBOSlot,
const IndexData* index_data);
109 uint32_t byte_offset(VBOSlot slot) {
114 uint32_t slot_size_in_bytes()
const {
115 return size_in_bytes_;
118 VBOSlot allocate_slot();
119 void release_slot(VBOSlot slot);
121 uint32_t used_slot_count()
const {
122 return (allocated_) ? 1 : 0;
125 uint32_t free_slot_count()
const {
126 return (allocated_) ? 0 : 1;
129 uint32_t size_in_bytes_;
131 IndexType index_type_;
134 uint64_t last_updated_ = 0;
135 bool allocated_ =
false;
145 slot_size_(slot_size),
146 slot_size_in_bytes_(
int(slot_size)),
148 type_(GL_ARRAY_BUFFER) {}
150 SharedVBO(VBOSlotSize slot_size, IndexType type):
151 slot_size_(slot_size),
152 slot_size_in_bytes_(
int(slot_size)),
154 type_(GL_ELEMENT_ARRAY_BUFFER) {}
156 uint64_t slot_last_updated(VBOSlot slot) {
157 assert(slot < metas_.size());
158 return metas_[slot].last_updated;
161 GLenum target()
const {
return type_; }
163 VBOSlot allocate_slot();
165 void release_slot(VBOSlot slot);
167 void upload(VBOSlot slot,
const VertexData* vertex_data);
168 void upload(VBOSlot slot,
const IndexData* index_data);
169 void bind(VBOSlot slot);
171 VBOSlotSize slot_size()
const {
return slot_size_; }
172 uint32_t slot_size_in_bytes()
const {
return int(slot_size_); }
174 uint32_t byte_offset(VBOSlot slot) {
175 const int SLOTS_PER_BUFFER = (VBO_SIZE / slot_size_in_bytes_);
176 return (slot % SLOTS_PER_BUFFER) * slot_size_in_bytes_;
179 uint32_t used_slot_count()
const {
180 return metas_.size() - free_slots_.size();
183 uint32_t free_slot_count()
const {
184 return free_slots_.size();
188 void allocate_new_gl_buffer();
190 VBOSlotSize slot_size_;
191 uint32_t slot_size_in_bytes_;
194 IndexType index_type_;
196 std::queue<VBOSlot> free_slots_;
197 std::vector<GLuint> gl_ids_;
200 uint64_t last_updated = 0;
201 uint32_t uploaded_size = 0;
204 std::vector<SlotMeta> metas_;
212 uint32_t dedicated_buffer_count()
const;
215 VBOSlotSize calc_vbo_slot_size(uint32_t required_size_in_bytes);
217 std::pair<VBO*, VBOSlot> allocate_slot(
const VertexData* vertex_data);
218 std::pair<VBO*, VBOSlot> allocate_slot(
const IndexData* index_data);
220 void release_slot(
const VertexData* vertex_data);
221 void release_slot(
const IndexData* index_data);
225 std::unordered_map<VertexSpecification, SharedVBO::ptr>,
227 > shared_vertex_vbos_;
230 std::unordered_map<IndexType, SharedVBO::ptr>,
232 > shared_index_vbos_;
234 typedef std::unordered_map<uuid64, DedicatedVBO::ptr> DedicatedMap;
235 typedef std::unordered_map<uuid64, std::pair<VBO*, VBOSlot>> SlotMap;
237 DedicatedMap dedicated_vertex_vbos_;
238 DedicatedMap dedicated_index_vbos_;
240 SlotMap vertex_data_slots_;
241 SlotMap index_data_slots_;
243 std::unordered_map<uuid64, sig::connection> vdata_destruction_connections_;
244 std::unordered_map<uuid64, sig::connection> idata_destruction_connections_;
246 void connect_destruction_signal(
const VertexData *vertex_data);
247 void connect_destruction_signal(
const IndexData *vertex_data);
248 void disconnect_destruction_signal(
const VertexData *vertex_data);
249 void disconnect_destruction_signal(
const IndexData *vertex_data);
251 void on_vertex_data_destroyed(
VertexData* vertex_data);
252 void on_index_data_destroyed(
IndexData* vertex_data);
254 template<
typename Data>
255 std::pair<VBO*, VBOSlot> perform_fetch_or_upload(
const Data*, VBOManager::DedicatedMap&, VBOManager::SlotMap&);