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:
parent
d18e10c7c9
commit
93cab990c7
4 changed files with 110 additions and 23 deletions
|
@ -1254,20 +1254,54 @@ sub draw_volumes {
|
|||
glPushMatrix();
|
||||
glTranslatef(@{$volume->origin});
|
||||
glCullFace(GL_BACK);
|
||||
if (1) {
|
||||
if ($volume->indexed) {
|
||||
my $quads_cnt = $volume->indexed_quads_to_render_cnt;
|
||||
my $triangles_cnt = $volume->indexed_triangles_to_render_cnt;
|
||||
if ($quads_cnt + $triangles_cnt > 0) {
|
||||
glInterleavedArrays_c(GL_N3F_V3F, 0, $volume->triangles_to_render_ptr);
|
||||
glDrawElements_c(GL_QUADS, $quads_cnt, GL_UNSIGNED_INT, $volume->quad_indices_to_render_ptr ) if ($quads_cnt);
|
||||
glDrawElements_c(GL_TRIANGLES, $triangles_cnt, GL_UNSIGNED_INT, $volume->triangle_indices_to_render_ptr) if ($triangles_cnt);
|
||||
glInterleavedArrays_c(GL_N3F_V3F, 0, 0);
|
||||
if ($self->{use_VBOs}) {
|
||||
my ($name_geometry, $name_triangle_indices, $name_quad_indices) = glGenBuffersARB_p(3);
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, $name_geometry);
|
||||
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) {
|
||||
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);
|
||||
if ($self->{use_VBOs}) {
|
||||
my ($name_geometry) = glGenBuffersARB_p(1);
|
||||
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();
|
||||
|
||||
if ($shader_active) {
|
||||
|
|
|
@ -594,7 +594,7 @@ void _3DScene::_load_print_object_toolpaths(
|
|||
|
||||
//FIXME Improve the heuristics for a grain size.
|
||||
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::blocked_range<size_t>(0, ctxt.layers.size(), grain_size),
|
||||
[&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) {
|
||||
GLVolume &vol = *volumes[vols[i]];
|
||||
if (vol.indexed_vertex_array.vertices_and_normals_interleaved.size() / 6 > ctxt.alloc_size_max()) {
|
||||
// Shrink the old vectors to preserve memory.
|
||||
vol.indexed_vertex_array.shrink_to_fit();
|
||||
// Store the vertex arrays and restart their containers.
|
||||
// Store the vertex arrays and restart their containers,
|
||||
vols[i] = volumes.size();
|
||||
volumes.emplace_back(new GLVolume(vol.color));
|
||||
GLVolume &vol_new = *volumes.back();
|
||||
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()) {
|
||||
delete volumes.back();
|
||||
volumes.pop_back();
|
||||
|
@ -665,7 +672,7 @@ void _3DScene::_load_print_object_toolpaths(
|
|||
volume_ptr += v.volumes.size();
|
||||
v.volumes.clear();
|
||||
}
|
||||
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - end";
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,32 @@ class ModelObject;
|
|||
class GLIndexedVertexArray {
|
||||
public:
|
||||
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)
|
||||
std::vector<float> vertices_and_normals_interleaved;
|
||||
|
@ -52,6 +78,12 @@ public:
|
|||
// 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()); }
|
||||
|
||||
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.
|
||||
void shrink_to_fit() {
|
||||
this->vertices_and_normals_interleaved.shrink_to_fit();
|
||||
|
@ -173,15 +205,20 @@ public:
|
|||
// Non-indexed interleaved vertices & normals, likely forming triangles.
|
||||
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); }
|
||||
// Indexed triangles & quads.
|
||||
void* triangle_indices_to_render_ptr() { return indexed_vertex_array.triangle_indices.data() + tverts_range.first; }
|
||||
void* quad_indices_to_render_ptr() { return indexed_vertex_array.quad_indices.data() + qverts_range.first; }
|
||||
size_t indexed_triangles_to_render_cnt() { return std::min(indexed_vertex_array.triangle_indices.size(), tverts_range.second - tverts_range.first); }
|
||||
size_t indexed_quads_to_render_cnt() { return std::min(indexed_vertex_array.quad_indices.size(), qverts_range.second - qverts_range.first); }
|
||||
// Indexed triangles & quads, complete set for storing into a vertex buffer.
|
||||
size_t geometry_size() const { return indexed_vertex_array.vertices_and_normals_interleaved.size() * 4; }
|
||||
void* triangle_indices_ptr() { return indexed_vertex_array.triangle_indices.data(); }
|
||||
void* quad_indices_ptr() { return indexed_vertex_array.quad_indices.data(); }
|
||||
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;
|
||||
|
||||
|
||||
/************************************************ Layer height texture ****************************************************/
|
||||
std::shared_ptr<GLTexture> layer_height_texture;
|
||||
|
||||
|
@ -228,6 +265,10 @@ public:
|
|||
bool empty() const { return volumes.empty(); }
|
||||
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(); }
|
||||
|
||||
private:
|
||||
GLVolumeCollection(const GLVolumeCollection &other);
|
||||
GLVolumeCollection& operator=(const GLVolumeCollection &);
|
||||
};
|
||||
|
||||
class _3DScene
|
||||
|
|
|
@ -40,10 +40,15 @@
|
|||
|
||||
void* triangles_to_render_ptr();
|
||||
size_t triangles_to_render_cnt();
|
||||
void* triangle_indices_to_render_ptr();
|
||||
void* quad_indices_to_render_ptr();
|
||||
size_t indexed_triangles_to_render_cnt();
|
||||
size_t indexed_quads_to_render_cnt();
|
||||
size_t geometry_size() const;
|
||||
void* triangle_indices_ptr();
|
||||
void* quad_indices_ptr();
|
||||
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();
|
||||
int layer_height_texture_width();
|
||||
|
|
Loading…
Reference in a new issue