Skip to content

Commit

Permalink
improved concurrency for perimeter & infill (doesn't block the compli…
Browse files Browse the repository at this point in the history
…cated stuff on only one thread)

and various little modification (types, debug test)
  • Loading branch information
supermerill committed Jun 11, 2024
1 parent 7deffa0 commit eb16ec2
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 25 deletions.
24 changes: 19 additions & 5 deletions src/libslic3r/Fill/Fill.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -716,11 +716,25 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
for(auto &t : temp) real_surface += t.area();
assert(compute_volume.volume < unscaled(unscaled(surface_fill.surface.area())) * surface_fill.params.layer_height + EPSILON);
double area = unscaled(unscaled(real_surface));
assert(compute_volume.volume <= area * surface_fill.params.layer_height * 1.001 || f->debug_verify_flow_mult <= 0.8);
if(compute_volume.volume > 0) //can fail for thin regions
assert(compute_volume.volume >= area * surface_fill.params.layer_height * 0.999 || f->debug_verify_flow_mult >= 1.3 || f->debug_verify_flow_mult == 0 // sawtooth output more filament,as it's 3D (debug_verify_flow_mult==0)
|| area < std::max(1.,surface_fill.params.config->solid_infill_below_area.value) || area < std::max(1.,surface_fill.params.config->solid_infill_below_layer_area.value));
}
if(surface_fill.surface.has_pos_top())
area *= surface_fill.params.config->fill_top_flow_ratio.value;
if(surface_fill.surface.has_pos_bottom() && f->layer_id == 0)
area *= surface_fill.params.config->first_layer_flow_ratio.value;
if(surface_fill.surface.has_mod_bridge() && f->layer_id == 0)
area *= surface_fill.params.config->first_layer_flow_ratio.value;
//TODO: over-bridge mod
if(surface_fill.params.config->over_bridge_flow_ratio.value == 1){
assert(compute_volume.volume <= area * surface_fill.params.layer_height * 1.001 || f->debug_verify_flow_mult <= 0.8);
if(compute_volume.volume > 0) //can fail for thin regions
assert(
compute_volume.volume >= area * surface_fill.params.layer_height * 0.999 ||
f->debug_verify_flow_mult >= 1.3 ||
f->debug_verify_flow_mult ==
0 // sawtooth output more filament,as it's 3D (debug_verify_flow_mult==0)
|| area < std::max(1., surface_fill.params.config->solid_infill_below_area.value) ||
area < std::max(1., surface_fill.params.config->solid_infill_below_layer_area.value));
}
}
#endif
}
}
Expand Down
12 changes: 12 additions & 0 deletions src/libslic3r/GCode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4142,6 +4142,18 @@ void GCode::split_at_seam_pos(ExtrusionLoop& loop, bool was_clockwise)
if (loop.paths.empty())
return;

#if _DEBUG
ExtrusionLoop old_loop = loop;
for (const ExtrusionPath &path : loop.paths)
for (int i = 1; i < path.polyline.get_points().size(); ++i)
assert(!path.polyline.get_points()[i - 1].coincides_with_epsilon(path.polyline.get_points()[i]));
for (auto it = std::next(loop.paths.begin()); it != loop.paths.end(); ++it) {
assert(it->polyline.size() >= 2);
assert(std::prev(it)->polyline.back() == it->polyline.front());
}
assert(loop.first_point() == loop.last_point());
#endif

// SeamPosition seam_position = m_config.seam_position;
// if (loop.loop_role() == elrSkirt)
// seam_position = spNearest;
Expand Down
10 changes: 5 additions & 5 deletions src/libslic3r/MultiPoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,16 @@ int MultiPoint::find_point(const Point &point) const
return -1; // not found
}

int MultiPoint::find_point(const Point &point, double scaled_epsilon) const
int MultiPoint::find_point(const Point &point, coordf_t scaled_epsilon) const
{
if (scaled_epsilon == 0)
return this->find_point(point);

auto dist2_min = std::numeric_limits<double>::max();
auto eps2 = scaled_epsilon * scaled_epsilon;
int idx_min = -1;
coordf_t dist2_min = std::numeric_limits<coordf_t>::max();
coordf_t eps2 = scaled_epsilon * scaled_epsilon;
int idx_min = -1;
for (const Point &pt : this->points) {
double d2 = (pt - point).cast<double>().squaredNorm();
coordf_t d2 = pt.distance_to_square(point); //(pt - point).cast<coordf_t>().squaredNorm();
if (d2 < dist2_min) {
idx_min = int(&pt - &this->points.front());
dist2_min = d2;
Expand Down
2 changes: 1 addition & 1 deletion src/libslic3r/MultiPoint.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class MultiPoint
int find_point(const Point &point) const;
// Return index of the closest point to point closer than scaled_epsilon.
// Return -1 if no such point exists.
int find_point(const Point &point, const double scaled_epsilon) const;
int find_point(const Point &point, const coordf_t scaled_epsilon) const;
bool has_boundary_point(const Point &point) const;
int closest_point_index(const Point &point) const {
int idx = -1;
Expand Down
10 changes: 5 additions & 5 deletions src/libslic3r/Point.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,13 +179,13 @@ class Point : public Vec2crd
Point projection_onto(const Line &line) const;
Point interpolate(const double percent, const Point &p) const;

double distance_to(const Point &point) const { return (point - *this).cast<double>().norm(); }
double distance_to_square(const Point &point) const {
double dx = double(point.x() - this->x());
double dy = double(point.y() - this->y());
coordf_t distance_to(const Point &point) const { return (point - *this).cast<coordf_t>().norm(); }
coordf_t distance_to_square(const Point &point) const {
coordf_t dx = double(point.x() - this->x());
coordf_t dy = double(point.y() - this->y());
return dx*dx + dy*dy;
}
double distance_to(const Line &line) const;
coordf_t distance_to(const Line &line) const;
bool coincides_with(const Point &point) const { return this->x() == point.x() && this->y() == point.y(); }
bool coincides_with_epsilon(const Point &point) const {
return std::abs(this->x() - point.x()) < SCALED_EPSILON/2 && std::abs(this->y() - point.y()) < SCALED_EPSILON/2;
Expand Down
27 changes: 18 additions & 9 deletions src/libslic3r/PrintObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,16 +150,20 @@ namespace Slic3r {
// but we don't generate any extra perimeter if fill density is zero, as they would be floating
// inside the object - infill_only_where_needed should be the method of choice for printing
// hollow objects
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id) {
const PrintRegion &region = this->printing_region(region_id);
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id) {
const PrintRegion &region = this->printing_region(region_id);
if (!region.config().extra_perimeters || region.config().perimeters == 0 || region.config().fill_density == 0 || this->layer_count() < 2)
continue;

// use an antomic idx instead of the range, to avoid a thread being very late because it's on the difficult layers.
//TODO: sort the layers by difficulty (difficult first) (number of points, region, surfaces, .. ?)
std::atomic_size_t next_layer_idx(0);
BOOST_LOG_TRIVIAL(debug) << "Generating extra perimeters for region " << region_id << " in parallel - start";
tbb::parallel_for(
tbb::blocked_range<size_t>(0, m_layers.size() - 1),
[this, &region, region_id](const tbb::blocked_range<size_t>& range) {
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
[this, &region, region_id, &next_layer_idx](const tbb::blocked_range<size_t>& range) {
//TODO: find a better wya to just fire the threads.
//for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
for (size_t layer_idx = next_layer_idx++; layer_idx < m_layers.size() - 1; layer_idx = next_layer_idx++) {
m_print->throw_if_canceled();
LayerRegion &layerm = *m_layers[layer_idx]->get_region(region_id);
const LayerRegion &upper_layerm = *m_layers[layer_idx+1]->get_region(region_id);
Expand Down Expand Up @@ -214,10 +218,12 @@ namespace Slic3r {
}

BOOST_LOG_TRIVIAL(debug) << "Generating perimeters in parallel - start";
std::atomic_size_t next_layer_idx(0);
tbb::parallel_for(
tbb::blocked_range<size_t>(0, m_layers.size()),
[this, &atomic_count, nb_layers_update](const tbb::blocked_range<size_t>& range) {
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
[this, &atomic_count, nb_layers_update, &next_layer_idx](const tbb::blocked_range<size_t>& range) {
//for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
for (size_t layer_idx = next_layer_idx++; layer_idx < m_layers.size(); layer_idx = next_layer_idx++) {
std::chrono::time_point<std::chrono::system_clock> start_make_perimeter = std::chrono::system_clock::now();
m_print->throw_if_canceled();
m_layers[layer_idx]->make_perimeters();
Expand Down Expand Up @@ -456,10 +462,13 @@ namespace Slic3r {
const int nb_layers_update = std::max(1, (int)m_layers.size() / 20);

BOOST_LOG_TRIVIAL(debug) << "Filling layers in parallel - start";
std::atomic_size_t next_layer_idx(0);
tbb::parallel_for(
tbb::blocked_range<size_t>(0, m_layers.size()),
[this, &adaptive_fill_octree = adaptive_fill_octree, &support_fill_octree = support_fill_octree, &lightning_generator, &atomic_count, nb_layers_update](const tbb::blocked_range<size_t>& range) {
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
[this, &adaptive_fill_octree = adaptive_fill_octree, &support_fill_octree = support_fill_octree, &lightning_generator, &atomic_count, nb_layers_update, &next_layer_idx]
(const tbb::blocked_range<size_t>& range) {
//for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
for (size_t layer_idx = next_layer_idx++; layer_idx < m_layers.size(); layer_idx = next_layer_idx++) {
std::chrono::time_point<std::chrono::system_clock> start_make_fill = std::chrono::system_clock::now();
m_print->throw_if_canceled();
m_layers[layer_idx]->make_fills(adaptive_fill_octree.get(), support_fill_octree.get(), lightning_generator.get());
Expand Down

0 comments on commit eb16ec2

Please sign in to comment.