Optimization of G-code rendering, may improve speed issues mentioned in #7415

This commit is contained in:
Vojtech Bubnik 2021-12-06 11:52:19 +01:00
parent 68d5a47121
commit c37090a64d

View File

@ -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));
};
#if ENABLE_GCODE_VIEWER_STATISTICS
auto render_as_lines = [this, light_intensity]
#else
auto render_as_lines = [light_intensity]
#endif // ENABLE_GCODE_VIEWER_STATISTICS
(const TBuffer& buffer, unsigned int ibuffer_id, GLShaderProgram& shader) {
auto shader_init_as_lines = [light_intensity](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()));
};
auto render_as_lines = [
#if ENABLE_GCODE_VIEWER_STATISTICS
++m_statistics.gl_multi_lines_calls_count;
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) {
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;
#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; }