Fixed some memory allocation issues of the new C++ 3d path preview

(reserved memory has to be shrank around the collected data).

Initial implementation of the vertex buffer objects for the 3d path preview.
This commit is contained in:
bubnikv 2017-03-15 20:45:03 +01:00
parent d18e10c7c9
commit 93cab990c7
4 changed files with 110 additions and 23 deletions

View file

@ -1254,20 +1254,54 @@ sub draw_volumes {
glPushMatrix(); glPushMatrix();
glTranslatef(@{$volume->origin}); glTranslatef(@{$volume->origin});
glCullFace(GL_BACK); glCullFace(GL_BACK);
if (1) {
if ($volume->indexed) { if ($volume->indexed) {
my $quads_cnt = $volume->indexed_quads_to_render_cnt; my $quads_cnt = $volume->indexed_quads_to_render_cnt;
my $triangles_cnt = $volume->indexed_triangles_to_render_cnt; my $triangles_cnt = $volume->indexed_triangles_to_render_cnt;
if ($quads_cnt + $triangles_cnt > 0) { if ($quads_cnt + $triangles_cnt > 0) {
glInterleavedArrays_c(GL_N3F_V3F, 0, $volume->triangles_to_render_ptr); if ($self->{use_VBOs}) {
glDrawElements_c(GL_QUADS, $quads_cnt, GL_UNSIGNED_INT, $volume->quad_indices_to_render_ptr ) if ($quads_cnt); my ($name_geometry, $name_triangle_indices, $name_quad_indices) = glGenBuffersARB_p(3);
glDrawElements_c(GL_TRIANGLES, $triangles_cnt, GL_UNSIGNED_INT, $volume->triangle_indices_to_render_ptr) if ($triangles_cnt); glBindBufferARB(GL_ARRAY_BUFFER_ARB, $name_geometry);
glInterleavedArrays_c(GL_N3F_V3F, 0, 0); glBufferDataARB_c(GL_ARRAY_BUFFER_ARB, $volume->geometry_size, $volume->triangles_to_render_ptr, GL_STATIC_DRAW_ARB);
glInterleavedArrays_c(GL_N3F_V3F, 0, 0);
if ($quads_cnt) {
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, $name_quad_indices);
glBufferDataARB_c(GL_ELEMENT_ARRAY_BUFFER_ARB, $volume->indexed_quads_cnt * 4, $volume->quad_indices_ptr, GL_STATIC_DRAW_ARB);
glDrawElements_c(GL_QUADS, $quads_cnt, GL_UNSIGNED_INT, $volume->quad_indices_to_render_offset * 4);
}
if ($triangles_cnt) {
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, $name_triangle_indices);
glBufferDataARB_c(GL_ELEMENT_ARRAY_BUFFER_ARB, $volume->indexed_triangles_cnt * 4, $volume->triangle_indices_ptr, GL_STATIC_DRAW_ARB);
glDrawElements_c(GL_TRIANGLES, $triangles_cnt, GL_UNSIGNED_INT, $volume->triangle_indices_to_render_offset * 4);
}
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
glDeleteBuffersARB_p(($name_geometry, $name_triangle_indices, $name_quad_indices));
} else {
glInterleavedArrays_c(GL_N3F_V3F, 0, $volume->triangles_to_render_ptr);
glDrawElements_c(GL_QUADS, $quads_cnt, GL_UNSIGNED_INT, $volume->quad_indices_ptr + $volume->quad_indices_to_render_offset * 4)
if ($quads_cnt);
glDrawElements_c(GL_TRIANGLES, $triangles_cnt, GL_UNSIGNED_INT, $volume->triangle_indices_ptr + $volume->triangle_indices_to_render_offset * 4)
if ($triangles_cnt);
glInterleavedArrays_c(GL_N3F_V3F, 0, 0);
}
} }
} elsif (! $volume->empty) { } elsif (! $volume->empty) {
glInterleavedArrays_c(GL_N3F_V3F, 0, $volume->triangles_to_render_ptr); if ($self->{use_VBOs}) {
glDrawArrays(GL_TRIANGLES, 0, $volume->triangles_to_render_cnt); my ($name_geometry) = glGenBuffersARB_p(1);
glInterleavedArrays_c(GL_N3F_V3F, 0, 0); glBindBufferARB(GL_ARRAY_BUFFER_ARB, $name_geometry);
glBufferDataARB_c(GL_ARRAY_BUFFER_ARB, $volume->triangles_to_render_cnt * 6 * 4, $volume->triangles_to_render_ptr, GL_STATIC_DRAW_ARB);
glInterleavedArrays_c(GL_N3F_V3F, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, $volume->triangles_to_render_cnt);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glDeleteBuffersARB_p(($name_geometry));
} else {
glInterleavedArrays_c(GL_N3F_V3F, 0, $volume->triangles_to_render_ptr);
glDrawArrays(GL_TRIANGLES, 0, $volume->triangles_to_render_cnt);
glInterleavedArrays_c(GL_N3F_V3F, 0, 0);
}
} }
}
glPopMatrix(); glPopMatrix();
if ($shader_active) { if ($shader_active) {

View file

@ -594,7 +594,7 @@ void _3DScene::_load_print_object_toolpaths(
//FIXME Improve the heuristics for a grain size. //FIXME Improve the heuristics for a grain size.
size_t grain_size = std::max(ctxt.layers.size() / 16, size_t(1)); size_t grain_size = std::max(ctxt.layers.size() / 16, size_t(1));
std::vector<GLVolumeCollection> volumes_per_thread(ctxt.layers.size(), GLVolumeCollection()); std::vector<GLVolumeCollection> volumes_per_thread(ctxt.layers.size());
tbb::parallel_for( tbb::parallel_for(
tbb::blocked_range<size_t>(0, ctxt.layers.size(), grain_size), tbb::blocked_range<size_t>(0, ctxt.layers.size(), grain_size),
[&ctxt, &volumes_per_thread](const tbb::blocked_range<size_t>& range) { [&ctxt, &volumes_per_thread](const tbb::blocked_range<size_t>& range) {
@ -636,17 +636,24 @@ void _3DScene::_load_print_object_toolpaths(
for (size_t i = 0; i < 3; ++ i) { for (size_t i = 0; i < 3; ++ i) {
GLVolume &vol = *volumes[vols[i]]; GLVolume &vol = *volumes[vols[i]];
if (vol.indexed_vertex_array.vertices_and_normals_interleaved.size() / 6 > ctxt.alloc_size_max()) { if (vol.indexed_vertex_array.vertices_and_normals_interleaved.size() / 6 > ctxt.alloc_size_max()) {
// Shrink the old vectors to preserve memory. // Store the vertex arrays and restart their containers,
vol.indexed_vertex_array.shrink_to_fit();
// Store the vertex arrays and restart their containers.
vols[i] = volumes.size(); vols[i] = volumes.size();
volumes.emplace_back(new GLVolume(vol.color)); volumes.emplace_back(new GLVolume(vol.color));
GLVolume &vol_new = *volumes.back(); GLVolume &vol_new = *volumes.back();
vol_new.bounding_box = ctxt.bbox; vol_new.bounding_box = ctxt.bbox;
vol_new.indexed_vertex_array.reserve(ctxt.alloc_size_reserve()); // Assign the large pre-allocated buffers to the new GLVolume.
vol_new.indexed_vertex_array = std::move(vol.indexed_vertex_array);
// Copy the content back to the old GLVolume.
vol.indexed_vertex_array = vol_new.indexed_vertex_array;
// Clear the buffers, but keep them pre-allocated.
vol_new.indexed_vertex_array.clear();
// Just make sure that clear did not clear the reserved memory.
vol_new.indexed_vertex_array.reserve(ctx.alloc_size_reserve());
} }
} }
} }
for (size_t i = 0; i < 3; ++ i)
volumes[vols[i]]->indexed_vertex_array.shrink_to_fit();
while (! volumes.empty() && volumes.back()->empty()) { while (! volumes.empty() && volumes.back()->empty()) {
delete volumes.back(); delete volumes.back();
volumes.pop_back(); volumes.pop_back();
@ -665,7 +672,7 @@ void _3DScene::_load_print_object_toolpaths(
volume_ptr += v.volumes.size(); volume_ptr += v.volumes.size();
v.volumes.clear(); v.volumes.clear();
} }
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - end"; BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - end";
} }

View file

@ -18,6 +18,32 @@ class ModelObject;
class GLIndexedVertexArray { class GLIndexedVertexArray {
public: public:
GLIndexedVertexArray() {} GLIndexedVertexArray() {}
GLIndexedVertexArray(const GLIndexedVertexArray &rhs) :
vertices_and_normals_interleaved(rhs.vertices_and_normals_interleaved),
triangle_indices(rhs.triangle_indices),
quad_indices(rhs.quad_indices)
{}
GLIndexedVertexArray(GLIndexedVertexArray &&rhs) :
vertices_and_normals_interleaved(std::move(rhs.vertices_and_normals_interleaved)),
triangle_indices(std::move(rhs.triangle_indices)),
quad_indices(std::move(rhs.quad_indices))
{}
GLIndexedVertexArray& operator=(const GLIndexedVertexArray &rhs)
{
this->vertices_and_normals_interleaved = rhs.vertices_and_normals_interleaved;
this->triangle_indices = rhs.triangle_indices;
this->quad_indices = rhs.quad_indices;
return *this;
}
GLIndexedVertexArray& operator=(GLIndexedVertexArray &&rhs)
{
this->vertices_and_normals_interleaved = std::move(rhs.vertices_and_normals_interleaved);
this->triangle_indices = std::move(rhs.triangle_indices);
this->quad_indices = std::move(rhs.quad_indices);
return *this;
}
// Vertices and their normals, interleaved to be used by void glInterleavedArrays(GL_N3F_V3F, 0, x) // Vertices and their normals, interleaved to be used by void glInterleavedArrays(GL_N3F_V3F, 0, x)
std::vector<float> vertices_and_normals_interleaved; std::vector<float> vertices_and_normals_interleaved;
@ -52,6 +78,12 @@ public:
// Is this object indexed, or is it just a set of triangles? // Is this object indexed, or is it just a set of triangles?
bool indexed() const { return ! this->empty() && (! this->triangle_indices.empty() || ! this->quad_indices.empty()); } bool indexed() const { return ! this->empty() && (! this->triangle_indices.empty() || ! this->quad_indices.empty()); }
void clear() {
this->vertices_and_normals_interleaved.clear();
this->triangle_indices.clear();
this->quad_indices.clear();
}
// Shrink the internal storage to tighly fit the data stored. // Shrink the internal storage to tighly fit the data stored.
void shrink_to_fit() { void shrink_to_fit() {
this->vertices_and_normals_interleaved.shrink_to_fit(); this->vertices_and_normals_interleaved.shrink_to_fit();
@ -173,15 +205,20 @@ public:
// Non-indexed interleaved vertices & normals, likely forming triangles. // Non-indexed interleaved vertices & normals, likely forming triangles.
void* triangles_to_render_ptr() { return indexed_vertex_array.vertices_and_normals_interleaved.data(); } void* triangles_to_render_ptr() { return indexed_vertex_array.vertices_and_normals_interleaved.data(); }
size_t triangles_to_render_cnt() { return indexed_vertex_array.vertices_and_normals_interleaved.size() / (3 * 2); } size_t triangles_to_render_cnt() { return indexed_vertex_array.vertices_and_normals_interleaved.size() / (3 * 2); }
// Indexed triangles & quads. // Indexed triangles & quads, complete set for storing into a vertex buffer.
void* triangle_indices_to_render_ptr() { return indexed_vertex_array.triangle_indices.data() + tverts_range.first; } size_t geometry_size() const { return indexed_vertex_array.vertices_and_normals_interleaved.size() * 4; }
void* quad_indices_to_render_ptr() { return indexed_vertex_array.quad_indices.data() + qverts_range.first; } void* triangle_indices_ptr() { return indexed_vertex_array.triangle_indices.data(); }
size_t indexed_triangles_to_render_cnt() { return std::min(indexed_vertex_array.triangle_indices.size(), tverts_range.second - tverts_range.first); } void* quad_indices_ptr() { return indexed_vertex_array.quad_indices.data(); }
size_t indexed_quads_to_render_cnt() { return std::min(indexed_vertex_array.quad_indices.size(), qverts_range.second - qverts_range.first); } size_t indexed_triangles_cnt() { return indexed_vertex_array.triangle_indices.size(); }
size_t indexed_quads_cnt() { return indexed_vertex_array.quad_indices.size(); }
// Indexed triangles & quads, to be painted in an immediate mode.
size_t triangle_indices_to_render_offset() const { return tverts_range.first; }
size_t quad_indices_to_render_offset() const { return qverts_range.first; }
size_t indexed_triangles_to_render_cnt() const { return std::min(indexed_vertex_array.triangle_indices.size(), tverts_range.second - tverts_range.first); }
size_t indexed_quads_to_render_cnt() const { return std::min(indexed_vertex_array.quad_indices.size(), qverts_range.second - qverts_range.first); }
void render_VBOs() const; void render_VBOs() const;
/************************************************ Layer height texture ****************************************************/ /************************************************ Layer height texture ****************************************************/
std::shared_ptr<GLTexture> layer_height_texture; std::shared_ptr<GLTexture> layer_height_texture;
@ -228,6 +265,10 @@ public:
bool empty() const { return volumes.empty(); } bool empty() const { return volumes.empty(); }
void set_range(double low, double high) { for (GLVolume *vol : this->volumes) vol->set_range(low, high); } void set_range(double low, double high) { for (GLVolume *vol : this->volumes) vol->set_range(low, high); }
void render_VBOs() const { for (GLVolume *vol : this->volumes) vol->render_VBOs(); } void render_VBOs() const { for (GLVolume *vol : this->volumes) vol->render_VBOs(); }
private:
GLVolumeCollection(const GLVolumeCollection &other);
GLVolumeCollection& operator=(const GLVolumeCollection &);
}; };
class _3DScene class _3DScene

View file

@ -40,10 +40,15 @@
void* triangles_to_render_ptr(); void* triangles_to_render_ptr();
size_t triangles_to_render_cnt(); size_t triangles_to_render_cnt();
void* triangle_indices_to_render_ptr(); size_t geometry_size() const;
void* quad_indices_to_render_ptr(); void* triangle_indices_ptr();
size_t indexed_triangles_to_render_cnt(); void* quad_indices_ptr();
size_t indexed_quads_to_render_cnt(); size_t indexed_triangles_cnt();
size_t indexed_quads_cnt();
size_t triangle_indices_to_render_offset() const;
size_t quad_indices_to_render_offset() const;
size_t indexed_triangles_to_render_cnt() const;
size_t indexed_quads_to_render_cnt() const;
bool has_layer_height_texture(); bool has_layer_height_texture();
int layer_height_texture_width(); int layer_height_texture_width();