Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVojtech Bubnik <bubnikv@gmail.com>2021-12-06 13:52:19 +0300
committerVojtech Bubnik <bubnikv@gmail.com>2021-12-06 13:52:27 +0300
commitc37090a64d41ec58e7a6add5cb8a0c55efbbde9c (patch)
tree9f755ad7ed2277a992f5f9fe438359dec051ebf6 /src/slic3r/GUI
parent68d5a47121eaad42a390fe8d7b85cbff551cf90e (diff)
Optimization of G-code rendering, may improve speed issues mentioned in #7415
Diffstat (limited to 'src/slic3r/GUI')
-rw-r--r--src/slic3r/GUI/GCodeViewer.cpp101
1 files changed, 59 insertions, 42 deletions
diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp
index 9fcef6a65..347f781e7 100644
--- a/src/slic3r/GUI/GCodeViewer.cpp
+++ b/src/slic3r/GUI/GCodeViewer.cpp
@@ -2636,12 +2636,7 @@ void GCodeViewer::render_toolpaths()
float near_plane_height = camera.get_type() == Camera::EType::Perspective ? static_cast<float>(viewport[3]) / (2.0f * static_cast<float>(2.0 * std::tan(0.5 * Geometry::deg2rad(camera.get_fov())))) :
static_cast<float>(viewport[3]) * 0.0005;
-#if ENABLE_GCODE_VIEWER_STATISTICS
- auto render_as_points = [this, zoom, point_size, near_plane_height]
-#else
- auto render_as_points = [zoom, point_size, near_plane_height]
-#endif // ENABLE_GCODE_VIEWER_STATISTICS
- (const TBuffer& buffer, unsigned int ibuffer_id, GLShaderProgram& shader) {
+ auto shader_init_as_points = [zoom, point_size, near_plane_height](GLShaderProgram& shader) {
#if ENABLE_FIXED_SCREEN_SIZE_POINT_MARKERS
shader.set_uniform("use_fixed_screen_size", 1);
#else
@@ -2652,65 +2647,67 @@ void GCodeViewer::render_toolpaths()
shader.set_uniform("percent_center_radius", 0.33f);
shader.set_uniform("point_size", point_size);
shader.set_uniform("near_plane_height", near_plane_height);
+ };
+ auto render_as_points = [
+#if ENABLE_GCODE_VIEWER_STATISTICS
+ this
+#endif // ENABLE_GCODE_VIEWER_STATISTICS
+ ](std::vector<const RenderPath*>::iterator it_path, std::vector<const RenderPath*>::iterator it_end, GLShaderProgram& shader, int uniform_color) {
glsafe(::glEnable(GL_VERTEX_PROGRAM_POINT_SIZE));
glsafe(::glEnable(GL_POINT_SPRITE));
- for (const RenderPath& path : buffer.render_paths) {
- if (path.ibuffer_id == ibuffer_id) {
- shader.set_uniform("uniform_color", path.color);
- glsafe(::glMultiDrawElements(GL_POINTS, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size()));
+ for (auto it = it_path; it != it_end && (*it_path)->ibuffer_id == (*it)->ibuffer_id; ++ it) {
+ const RenderPath& path = **it;
+ glsafe(::glUniform4fv(uniform_color, 1, static_cast<const GLfloat*>(path.color.data())));
+ glsafe(::glMultiDrawElements(GL_POINTS, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size()));
#if ENABLE_GCODE_VIEWER_STATISTICS
- ++m_statistics.gl_multi_points_calls_count;
+ ++m_statistics.gl_multi_points_calls_count;
#endif // ENABLE_GCODE_VIEWER_STATISTICS
- }
}
glsafe(::glDisable(GL_POINT_SPRITE));
glsafe(::glDisable(GL_VERTEX_PROGRAM_POINT_SIZE));
};
+ auto shader_init_as_lines = [light_intensity](GLShaderProgram &shader) {
+ shader.set_uniform("light_intensity", light_intensity);
+ };
+ auto render_as_lines = [
#if ENABLE_GCODE_VIEWER_STATISTICS
- auto render_as_lines = [this, light_intensity]
-#else
- auto render_as_lines = [light_intensity]
+ this
#endif // ENABLE_GCODE_VIEWER_STATISTICS
- (const TBuffer& buffer, unsigned int ibuffer_id, GLShaderProgram& shader) {
- shader.set_uniform("light_intensity", light_intensity);
- for (const RenderPath& path : buffer.render_paths) {
- if (path.ibuffer_id == ibuffer_id) {
- shader.set_uniform("uniform_color", path.color);
- glsafe(::glMultiDrawElements(GL_LINES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size()));
+ ](std::vector<const RenderPath*>::iterator it_path, std::vector<const RenderPath*>::iterator it_end, GLShaderProgram &shader, int uniform_color) {
+ for (auto it = it_path; it != it_end && (*it_path)->ibuffer_id == (*it)->ibuffer_id; ++it) {
+ const RenderPath& path = **it;
+ glsafe(::glUniform4fv(uniform_color, 1, static_cast<const GLfloat*>(path.color.data())));
+ glsafe(::glMultiDrawElements(GL_LINES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size()));
#if ENABLE_GCODE_VIEWER_STATISTICS
- ++m_statistics.gl_multi_lines_calls_count;
+ ++m_statistics.gl_multi_lines_calls_count;
#endif // ENABLE_GCODE_VIEWER_STATISTICS
- }
}
};
+ auto render_as_triangles = [
#if ENABLE_GCODE_VIEWER_STATISTICS
- auto render_as_triangles = [this]
-#else
- auto render_as_triangles = []
+ this
#endif // ENABLE_GCODE_VIEWER_STATISTICS
- (const TBuffer& buffer, unsigned int ibuffer_id, GLShaderProgram& shader) {
- for (const RenderPath& path : buffer.render_paths) {
- if (path.ibuffer_id == ibuffer_id) {
- shader.set_uniform("uniform_color", path.color);
- glsafe(::glMultiDrawElements(GL_TRIANGLES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size()));
+ ](std::vector<const RenderPath*>::iterator it_path, std::vector<const RenderPath*>::iterator it_end, GLShaderProgram &shader, int uniform_color) {
+ for (auto it = it_path; it != it_end && (*it_path)->ibuffer_id == (*it)->ibuffer_id; ++it) {
+ const RenderPath& path = **it;
+ glsafe(::glUniform4fv(uniform_color, 1, static_cast<const GLfloat*>(path.color.data())));
+ glsafe(::glMultiDrawElements(GL_TRIANGLES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size()));
#if ENABLE_GCODE_VIEWER_STATISTICS
- ++m_statistics.gl_multi_triangles_calls_count;
+ ++m_statistics.gl_multi_triangles_calls_count;
#endif // ENABLE_GCODE_VIEWER_STATISTICS
- }
}
};
+ auto render_as_instanced_model = [
#if ENABLE_GCODE_VIEWER_STATISTICS
- auto render_as_instanced_model = [this]
-#else
- auto render_as_instanced_model = []
+ this
#endif // ENABLE_GCODE_VIEWER_STATISTICS
- (TBuffer& buffer, GLShaderProgram & shader) {
+ ](TBuffer& buffer, GLShaderProgram & shader) {
for (auto& range : buffer.model.instances.render_ranges.ranges) {
if (range.vbo == 0 && range.count > 0) {
glsafe(::glGenBuffers(1, &range.vbo));
@@ -2815,8 +2812,27 @@ void GCodeViewer::render_toolpaths()
shader->set_uniform("emission_factor", 0.0f);
}
else {
- for (size_t j = 0; j < buffer.indices.size(); ++j) {
- const IBuffer& i_buffer = buffer.indices[j];
+ switch (buffer.render_primitive_type) {
+ case TBuffer::ERenderPrimitiveType::Point: shader_init_as_points(*shader); break;
+ case TBuffer::ERenderPrimitiveType::Line: shader_init_as_lines(*shader); break;
+ default: break;
+ }
+ int uniform_color = shader->get_uniform_location("uniform_color");
+ // Render paths are sorted by ibuffer_id.
+ std::vector<const RenderPath*> paths;
+ paths.reserve(buffer.render_paths.size());
+ for (const RenderPath& path : buffer.render_paths)
+ paths.emplace_back(&path);
+ std::stable_sort(paths.begin(), paths.end(), [](const auto* l, const auto* r){ return l->ibuffer_id < r->ibuffer_id; });
+ //FIXME maybe std::sort would suffice?
+ auto it_path = paths.begin();
+ for (unsigned int ibuffer_id = 0; ibuffer_id < static_cast<unsigned int>(buffer.indices.size()); ++ibuffer_id) {
+ const IBuffer& i_buffer = buffer.indices[ibuffer_id];
+ // Skip all paths with ibuffer_id < ibuffer_id.
+ for (; it_path != paths.end() && (*it_path)->ibuffer_id < ibuffer_id; ++ it_path) ;
+ if (it_path == paths.end() || (*it_path)->ibuffer_id > ibuffer_id)
+ // Not found. This shall not happen.
+ continue;
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, i_buffer.vbo));
glsafe(::glVertexPointer(buffer.vertices.position_size_floats(), GL_FLOAT, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.position_offset_bytes()));
@@ -2829,19 +2845,20 @@ void GCodeViewer::render_toolpaths()
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo));
+ // Render all elements with it_path->ibuffer_id == ibuffer_id, possible with varying colors.
switch (buffer.render_primitive_type)
{
case TBuffer::ERenderPrimitiveType::Point: {
- render_as_points(buffer, static_cast<unsigned int>(j), *shader);
+ render_as_points(it_path, paths.end(), *shader, uniform_color);
break;
}
case TBuffer::ERenderPrimitiveType::Line: {
glsafe(::glLineWidth(static_cast<GLfloat>(line_width(zoom))));
- render_as_lines(buffer, static_cast<unsigned int>(j), *shader);
+ render_as_lines(it_path, paths.end(), *shader, uniform_color);
break;
}
case TBuffer::ERenderPrimitiveType::Triangle: {
- render_as_triangles(buffer, static_cast<unsigned int>(j), *shader);
+ render_as_triangles(it_path, paths.end(), *shader, uniform_color);
break;
}
default: { break; }