Fix of slow update when dragging the vertical slider in G-code viewer

with volumetric flow color mapping enabled.
Fixes "Volumetric flow rate computes very slowly #5572"
This commit is contained in:
Vojtech Bubnik 2021-01-06 15:32:22 +01:00
parent 615356b69c
commit daa0bbdb0c
3 changed files with 52 additions and 24 deletions

View File

@ -354,8 +354,12 @@ inline std::string get_time_dhm(float time_in_secs)
#if WIN32 #if WIN32
#define SLIC3R_STDVEC_MEMSIZE(NAME, TYPE) NAME.capacity() * ((sizeof(TYPE) + __alignof(TYPE) - 1) / __alignof(TYPE)) * __alignof(TYPE) #define SLIC3R_STDVEC_MEMSIZE(NAME, TYPE) NAME.capacity() * ((sizeof(TYPE) + __alignof(TYPE) - 1) / __alignof(TYPE)) * __alignof(TYPE)
//FIXME this is an inprecise hack. Add the hash table size and possibly some estimate of the linked list at each of the used bin.
#define SLIC3R_STDUNORDEREDSET_MEMSIZE(NAME, TYPE) NAME.size() * ((sizeof(TYPE) + __alignof(TYPE) - 1) / __alignof(TYPE)) * __alignof(TYPE)
#else #else
#define SLIC3R_STDVEC_MEMSIZE(NAME, TYPE) NAME.capacity() * ((sizeof(TYPE) + alignof(TYPE) - 1) / alignof(TYPE)) * alignof(TYPE) #define SLIC3R_STDVEC_MEMSIZE(NAME, TYPE) NAME.capacity() * ((sizeof(TYPE) + alignof(TYPE) - 1) / alignof(TYPE)) * alignof(TYPE)
//FIXME this is an inprecise hack. Add the hash table size and possibly some estimate of the linked list at each of the used bin.
#define SLIC3R_STDUNORDEREDSET_MEMSIZE(NAME, TYPE) NAME.size() * ((sizeof(TYPE) + alignof(TYPE) - 1) / alignof(TYPE)) * alignof(TYPE)
#endif #endif
#endif // slic3r_Utils_hpp_ #endif // slic3r_Utils_hpp_

View File

@ -147,9 +147,9 @@ void GCodeViewer::TBuffer::reset()
} }
// release cpu memory // release cpu memory
indices = std::vector<IBuffer>(); indices.clear();
paths = std::vector<Path>(); paths.clear();
render_paths = std::vector<RenderPath>(); render_paths.clear();
} }
void GCodeViewer::TBuffer::add_path(const GCodeProcessor::MoveVertex& move, unsigned int b_id, size_t i_id, size_t s_id) void GCodeViewer::TBuffer::add_path(const GCodeProcessor::MoveVertex& move, unsigned int b_id, size_t i_id, size_t s_id)
@ -781,9 +781,9 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const
unsigned int start_vertex_offset = buffer.start_segment_vertex_offset(); unsigned int start_vertex_offset = buffer.start_segment_vertex_offset();
unsigned int end_vertex_offset = buffer.end_segment_vertex_offset(); unsigned int end_vertex_offset = buffer.end_segment_vertex_offset();
for (size_t i = 0; i < buffer.render_paths.size(); ++i) { size_t i = 0;
for (const RenderPath& render_path : buffer.render_paths) {
// get paths segments from buffer paths // get paths segments from buffer paths
const RenderPath& render_path = buffer.render_paths[i];
const IndexBuffer& ibuffer = indices[render_path.index_buffer_id]; const IndexBuffer& ibuffer = indices[render_path.index_buffer_id];
const Path& path = buffer.paths[render_path.path_id]; const Path& path = buffer.paths[render_path.path_id];
float half_width = 0.5f * path.width; float half_width = 0.5f * path.width;
@ -948,6 +948,8 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const
for (const Triangle& t : out_triangles) { for (const Triangle& t : out_triangles) {
fprintf(fp, "f %zu//%zu %zu//%zu %zu//%zu\n", t[0], t[0], t[1], t[1], t[2], t[2]); fprintf(fp, "f %zu//%zu %zu//%zu %zu//%zu\n", t[0], t[0], t[1], t[1], t[2], t[2]);
} }
++ i;
} }
fclose(fp); fclose(fp);
@ -1900,6 +1902,7 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
} }
// second pass: filter paths by sequential data and collect them by color // second pass: filter paths by sequential data and collect them by color
RenderPath *render_path = nullptr;
for (const auto& [buffer, index_buffer_id, path_id] : paths) { for (const auto& [buffer, index_buffer_id, path_id] : paths) {
const Path& path = buffer->paths[path_id]; const Path& path = buffer->paths[path_id];
if (m_sequential_view.current.last <= path.first.s_id || path.last.s_id <= m_sequential_view.current.first) if (m_sequential_view.current.last <= path.first.s_id || path.last.s_id <= m_sequential_view.current.first)
@ -1930,16 +1933,9 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
default: { color = { 0.0f, 0.0f, 0.0f }; break; } default: { color = { 0.0f, 0.0f, 0.0f }; break; }
} }
unsigned int ibuffer_id = index_buffer_id; RenderPath key{ color, static_cast<unsigned int>(index_buffer_id), path_id };
auto it = std::find_if(buffer->render_paths.begin(), buffer->render_paths.end(), if (render_path == nullptr || ! RenderPathPropertyEqual()(*render_path, key))
[color, ibuffer_id](const RenderPath& path) { return path.index_buffer_id == ibuffer_id && path.color == color; }); render_path = const_cast<RenderPath*>(&(*buffer->render_paths.emplace(key).first));
if (it == buffer->render_paths.end()) {
it = buffer->render_paths.insert(buffer->render_paths.end(), RenderPath());
it->color = color;
it->path_id = path_id;
it->index_buffer_id = index_buffer_id;
}
unsigned int segments_count = std::min(m_sequential_view.current.last, path.last.s_id) - std::max(m_sequential_view.current.first, path.first.s_id) + 1; unsigned int segments_count = std::min(m_sequential_view.current.last, path.last.s_id) - std::max(m_sequential_view.current.first, path.first.s_id) + 1;
unsigned int size_in_indices = 0; unsigned int size_in_indices = 0;
switch (buffer->render_primitive_type) switch (buffer->render_primitive_type)
@ -1948,7 +1944,7 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
case TBuffer::ERenderPrimitiveType::Line: case TBuffer::ERenderPrimitiveType::Line:
case TBuffer::ERenderPrimitiveType::Triangle: { size_in_indices = buffer->indices_per_segment() * (segments_count - 1); break; } case TBuffer::ERenderPrimitiveType::Triangle: { size_in_indices = buffer->indices_per_segment() * (segments_count - 1); break; }
} }
it->sizes.push_back(size_in_indices); render_path->sizes.push_back(size_in_indices);
unsigned int delta_1st = 0; unsigned int delta_1st = 0;
if (path.first.s_id < m_sequential_view.current.first && m_sequential_view.current.first <= path.last.s_id) if (path.first.s_id < m_sequential_view.current.first && m_sequential_view.current.first <= path.last.s_id)
@ -1957,7 +1953,7 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
if (buffer->render_primitive_type == TBuffer::ERenderPrimitiveType::Triangle) if (buffer->render_primitive_type == TBuffer::ERenderPrimitiveType::Triangle)
delta_1st *= buffer->indices_per_segment(); delta_1st *= buffer->indices_per_segment();
it->offsets.push_back(static_cast<size_t>((path.first.i_id + delta_1st) * sizeof(unsigned int))); render_path->offsets.push_back(static_cast<size_t>((path.first.i_id + delta_1st) * sizeof(unsigned int)));
} }
// set sequential data to their final value // set sequential data to their final value
@ -2943,7 +2939,7 @@ void GCodeViewer::log_memory_used(const std::string& label, int64_t additional)
int64_t render_paths_size = 0; int64_t render_paths_size = 0;
for (const TBuffer& buffer : m_buffers) { for (const TBuffer& buffer : m_buffers) {
paths_size += SLIC3R_STDVEC_MEMSIZE(buffer.paths, Path); paths_size += SLIC3R_STDVEC_MEMSIZE(buffer.paths, Path);
render_paths_size += SLIC3R_STDVEC_MEMSIZE(buffer.render_paths, RenderPath); render_paths_size += SLIC3R_STDUNORDEREDSET_MEMSIZE(buffer.render_paths, RenderPath);
for (const RenderPath& path : buffer.render_paths) { for (const RenderPath& path : buffer.render_paths) {
render_paths_size += SLIC3R_STDVEC_MEMSIZE(path.sizes, unsigned int); render_paths_size += SLIC3R_STDVEC_MEMSIZE(path.sizes, unsigned int);
render_paths_size += SLIC3R_STDVEC_MEMSIZE(path.offsets, size_t); render_paths_size += SLIC3R_STDVEC_MEMSIZE(path.offsets, size_t);

View File

@ -7,6 +7,8 @@
#include <cstdint> #include <cstdint>
#include <float.h> #include <float.h>
#include <set>
#include <unordered_set>
namespace Slic3r { namespace Slic3r {
@ -146,11 +148,35 @@ class GCodeViewer
// Used to batch the indices needed to render paths // Used to batch the indices needed to render paths
struct RenderPath struct RenderPath
{ {
Color color; // Render path property
unsigned int path_id; Color color;
unsigned int index_buffer_id; unsigned int index_buffer_id;
std::vector<unsigned int> sizes; // Render path content
std::vector<size_t> offsets; // use size_t because we need an unsigned int whose size matches pointer's size (used in the call glMultiDrawElements()) unsigned int path_id;
std::vector<unsigned int> sizes;
std::vector<size_t> offsets; // use size_t because we need an unsigned int whose size matches pointer's size (used in the call glMultiDrawElements())
};
struct RenderPathPropertyHash {
size_t operator() (const RenderPath &p) const {
// Conver the RGB value to an integer hash.
// return (size_t(int(p.color[0] * 255) + 255 * int(p.color[1] * 255) + (255 * 255) * int(p.color[2] * 255)) * 7919) ^ size_t(p.index_buffer_id);
return size_t(int(p.color[0] * 255) + 255 * int(p.color[1] * 255) + (255 * 255) * int(p.color[2] * 255)) ^ size_t(p.index_buffer_id);
}
};
struct RenderPathPropertyLower {
bool operator() (const RenderPath &l, const RenderPath &r) const {
for (int i = 0; i < 3; ++ i)
if (l.color[i] < r.color[i])
return true;
else if (l.color[i] > r.color[i])
return false;
return l.index_buffer_id < r.index_buffer_id;
}
};
struct RenderPathPropertyEqual {
bool operator() (const RenderPath &l, const RenderPath &r) const {
return l.color == r.color && l.index_buffer_id == r.index_buffer_id;
}
}; };
// buffer containing data for rendering a specific toolpath type // buffer containing data for rendering a specific toolpath type
@ -169,7 +195,9 @@ class GCodeViewer
std::string shader; std::string shader;
std::vector<Path> paths; std::vector<Path> paths;
std::vector<RenderPath> render_paths; // std::set seems to perform singificantly better, at least on Windows.
// std::unordered_set<RenderPath, RenderPathPropertyHash, RenderPathPropertyEqual> render_paths;
std::set<RenderPath, RenderPathPropertyLower> render_paths;
bool visible{ false }; bool visible{ false };
void reset(); void reset();