@@ -25,70 +25,79 @@ struct vertex_data_t {
25
25
26
26
class BufferBase {
27
27
public:
28
- virtual ~BufferBase () {
29
- if (m_vbo) glDeleteBuffers (1 , &m_vbo);
30
- if (m_vao) glDeleteBuffers (1 , &m_vao);
31
- }
28
+ virtual ~BufferBase () { }
29
+ virtual void destroy () = 0;
32
30
virtual void generate () = 0;
33
- virtual void bind () = 0;
34
- virtual void upload () = 0;
35
- virtual void render () = 0;
36
- GLuint m_vao = 0 ;
37
- GLuint m_vbo = 0 ;
38
- size_t m_geometry_offset = 0 ;
39
- GLuint m_storage_hint = GL_STATIC_DRAW;
31
+ virtual bool bind () = 0;
32
+ virtual void upload () = 0;
33
+ virtual void render () = 0;
34
+
35
+ GLuint m_vao = 0 ;
36
+ GLuint m_vbo = 0 ;
37
+ size_t m_geometry_offset = 0 ;
38
+ GLuint m_storage_hint = GL_STATIC_DRAW;
40
39
Primitive m_geometry_type = Primitive::TRIANGLES;
41
- bool m_dirty = true ;
42
- bool m_generated = false ;
40
+ bool m_dirty = true ;
41
+ bool m_generated = false ;
42
+ std::mutex m_data_mutex {};
43
43
};
44
44
45
- template <typename ElementType> class Buffer : public BufferBase {
45
+ template <typename ElementType> class Buffer : public BufferBase {
46
46
public:
47
47
virtual void generate () override {
48
- glGenVertexArrays ( 1 , &m_vao );
49
- glGenBuffers ( 1 , &m_vbo );
50
- glBindVertexArray ( m_vao );
51
- glBindBuffer ( GL_ARRAY_BUFFER, m_vbo );
48
+ glGenVertexArrays (1 , &m_vao);
49
+ glGenBuffers (1 , &m_vbo);
50
+ glBindVertexArray (m_vao);
51
+ glBindBuffer (GL_ARRAY_BUFFER, m_vbo);
52
52
53
53
size_t index = 0 , offset = 0 ;
54
54
for (auto & attrib : ElementType::descriptor) {
55
55
glEnableVertexAttribArray (index );
56
- glVertexAttribPointer (index , attrib.elements , attrib.gl_enum , GL_FALSE, sizeof (ElementType), (void *)offset);
56
+ glVertexAttribPointer (index , attrib.elements , attrib.gl_enum , GL_FALSE, sizeof (ElementType), (void *)offset);
57
57
++index ;
58
58
offset += attrib.length ;
59
59
}
60
60
m_generated = true ;
61
61
}
62
62
63
- virtual void bind () override {
63
+ virtual void destroy () override {
64
+ if (m_vbo) glDeleteBuffers (1 , &m_vbo);
65
+ if (m_vao) glDeleteBuffers (1 , &m_vao);
66
+ m_vbo = m_vao = 0 ;
67
+ }
68
+
69
+ virtual bool bind () override {
64
70
if (!m_generated) generate ();
65
- glBindVertexArray ( m_vao );
66
- glBindBuffer ( GL_ARRAY_BUFFER, m_vbo );
71
+ if (m_vao == 0 || m_vbo == 0 ) return false ;
72
+ glBindVertexArray (m_vao);
73
+ glBindBuffer (GL_ARRAY_BUFFER, m_vbo);
74
+ return true ;
67
75
}
68
76
69
77
virtual void upload () override {
70
78
if (m_dirty) {
71
- glBufferData ( GL_ARRAY_BUFFER, m_data.size () * sizeof (ElementType), &m_data[0 ], m_storage_hint );
79
+ glBufferData (GL_ARRAY_BUFFER, m_data.size () * sizeof (ElementType), &m_data[0 ], m_storage_hint);
72
80
m_dirty = false ;
73
81
}
74
82
}
75
83
76
84
virtual void render () override {
77
- bind ();
78
- upload ();
79
- glDrawArrays ( (GLenum)m_geometry_type, m_geometry_offset, m_data.size ());
85
+ if (bind ()) {
86
+ upload ();
87
+ glDrawArrays ((GLenum)m_geometry_type, m_geometry_offset, m_data.size ());
88
+ }
80
89
}
81
90
82
91
static std::shared_ptr<Buffer<ElementType>> create () {
83
- return std::shared_ptr<Buffer<ElementType>>( new Buffer<ElementType>() );
92
+ return std::shared_ptr<Buffer<ElementType>>(new Buffer<ElementType>());
84
93
}
85
94
86
95
std::vector<ElementType>& data () {
87
96
m_dirty = true ;
88
97
return m_data;
89
98
}
90
99
91
- std::vector<ElementType> const & cdata () const {
100
+ std::vector<ElementType> const & cdata () const {
92
101
return m_data;
93
102
}
94
103
@@ -110,80 +119,99 @@ class Mesh {
110
119
public:
111
120
void render (glm::mat4 global_transform) {
112
121
if (!m_visible) return ;
113
- if (m_dirty ) {
122
+ if (m_transform_dirty ) {
114
123
build_transform ();
115
- m_dirty = false ;
124
+ m_transform_dirty = false ;
116
125
}
117
126
if (m_shader_dirty) {
118
127
update_shader_locations ();
119
128
m_shader_dirty = false ;
120
129
}
121
- glUseProgram ( m_shader_program );
130
+ glUseProgram (m_shader_program);
122
131
global_transform = global_transform * m_transform;
123
- glUniformMatrix4fv ( m_shader_index_mvp, 1 , GL_FALSE, glm::value_ptr (global_transform));
132
+ glUniformMatrix4fv (m_shader_index_mvp, 1 , GL_FALSE, glm::value_ptr (global_transform));
124
133
for (auto buffer : m_buffer) {
125
134
buffer->render ();
126
135
}
127
136
}
128
137
138
+ void free_gpu_resources () {
139
+ for (auto buffer : m_buffer) {
140
+ buffer->destroy ();
141
+ }
142
+ }
143
+
129
144
void build_transform () {
130
145
m_transform = glm::translate (glm::mat4 (1.0 ), m_position);
131
146
m_transform = m_transform * glm::mat4_cast (m_rotation);
132
147
m_transform = glm::scale (m_transform, m_scale);
133
148
m_transform = glm::translate (m_transform, m_origin);
134
149
}
135
150
136
- template <typename VertexType> static std::shared_ptr<Mesh> create (std::shared_ptr<VertexType> buffer) {
151
+ template <typename VertexType> static std::shared_ptr<Mesh> create (std::shared_ptr<VertexType> buffer) {
137
152
auto mesh = std::shared_ptr<Mesh>(new Mesh ());
138
153
mesh->m_buffer .push_back (buffer);
139
154
return mesh;
140
155
}
141
156
142
- template <typename VertexType> static std::shared_ptr<Mesh> create () {
157
+ template <typename VertexType> static std::shared_ptr<Mesh> create () {
143
158
auto mesh = std::shared_ptr<Mesh>(new Mesh ());
144
159
mesh->m_buffer .push_back (Buffer<VertexType>::create ());
145
160
return mesh;
146
161
}
147
162
148
- template <typename VertexType> std::shared_ptr<Buffer<VertexType>> buffer () {
163
+ template <typename VertexType> std::shared_ptr<Buffer<VertexType>> buffer () {
149
164
return std::reinterpret_pointer_cast<Buffer<VertexType>>(m_buffer.back ());
150
165
}
151
166
152
- template <typename VertexType> std::vector<std::shared_ptr<Buffer<VertexType>>>& buffer_vector () {
167
+ template <typename VertexType> std::vector<std::shared_ptr<Buffer<VertexType>>>& buffer_vector () {
153
168
return *reinterpret_cast <std::vector<std::shared_ptr<Buffer<VertexType>>>*>(&m_buffer);
154
169
}
155
170
156
171
void update_shader_locations () {
157
- m_shader_index_mvp = glGetUniformLocation ( m_shader_program, " u_mvp" );
172
+ m_shader_index_mvp = glGetUniformLocation (m_shader_program, " u_mvp" );
158
173
}
159
174
160
175
void set_shader_program (GLuint program) {
161
176
m_shader_program = program;
162
177
}
163
178
164
- glm::mat4 m_transform {1.0 };
165
- glm::vec3 m_origin {0.0 , 0.0 , 0.0 };
166
- glm::vec3 m_position {0.0 , 0.0 , 0.0 };
167
- glm::vec3 m_scale {1.0 , 1.0 , 1.0 };
179
+ glm::mat4 m_transform { 1.0 };
180
+ glm::vec3 m_origin { 0.0 , 0.0 , 0.0 };
181
+ glm::vec3 m_position { 0.0 , 0.0 , 0.0 };
182
+ glm::vec3 m_scale { 1.0 , 1.0 , 1.0 };
168
183
glm::quat m_rotation {};
169
- bool m_visible = true ;
170
- bool m_dirty = true ;
171
- bool m_shader_dirty = true ;
172
- bool m_delete = false ;
184
+ bool m_visible = true ;
185
+ bool m_transform_dirty = true ;
186
+ bool m_shader_dirty = true ;
187
+ bool m_delete = false ;
188
+ std::mutex m_buffer_modification_mutex {};
173
189
std::vector<std::shared_ptr<BufferBase>> m_buffer {};
174
190
175
- GLuint m_shader_program = 0 ;
191
+ GLuint m_shader_program = 0 ;
176
192
GLuint m_shader_index_mvp = 0 ;
177
193
178
194
private:
179
- Mesh () {}
195
+ Mesh () { }
180
196
};
181
197
182
198
class Renderer {
183
199
public:
184
200
void render (glm::mat4 global_transform) {
185
- // TODO: mutex for modifying mesh vector
186
- m_mesh.erase (std::remove_if (m_mesh.begin (), m_mesh.end (), [](auto & mesh) { return mesh->m_delete ; }), m_mesh.end ());
201
+ m_mesh.erase (
202
+ std::remove_if (
203
+ m_mesh.begin (), m_mesh.end (),
204
+ [](auto & mesh) {
205
+ if (mesh->m_delete ) {
206
+ mesh->free_gpu_resources ();
207
+ return true ;
208
+ }
209
+ return false ;
210
+ }
211
+ ),
212
+ m_mesh.end ()
213
+ );
214
+
187
215
for (auto & mesh : m_mesh) {
188
216
mesh->render (global_transform);
189
217
}
0 commit comments