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-09-10 12:43:53 +0300
committerVojtech Bubnik <bubnikv@gmail.com>2021-09-10 12:43:59 +0300
commit03b60486840f32e32dc54103dc3051f94e79b35a (patch)
tree9f55144edb1360560af593f399c613f89da1526b
parent410b5e610b42ee39491ab252d018c3cf22ba46b2 (diff)
Follow-up to beee18f22991e369b1722a43bbcb692fa0d68af0
WIP to G-code export parallelization through pipelining: Decoupled CoolingBuffer from GCode / GCodeWriter, ready to be pipelined on a different thread.
-rw-r--r--src/libslic3r/GCode.cpp6
-rw-r--r--src/libslic3r/GCode/CoolingBuffer.cpp65
-rw-r--r--src/libslic3r/GCode/CoolingBuffer.hpp23
-rw-r--r--src/libslic3r/GCodeWriter.cpp74
-rw-r--r--src/libslic3r/GCodeWriter.hpp10
-rw-r--r--t/cooling.t2
-rw-r--r--xs/xsp/GCode.xsp1
7 files changed, 96 insertions, 85 deletions
diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp
index efea240e5..7e1afb5a8 100644
--- a/src/libslic3r/GCode.cpp
+++ b/src/libslic3r/GCode.cpp
@@ -1219,7 +1219,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
// Disable fan.
if (! print.config().cooling.get_at(initial_extruder_id) || print.config().disable_fan_first_layers.get_at(initial_extruder_id))
- file.write(m_writer.set_fan(0, true));
+ file.write(m_writer.set_fan(0));
// Let the start-up script prime the 1st printing tool.
m_placeholder_parser.set("initial_tool", initial_extruder_id);
@@ -1334,7 +1334,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
file.writeln(between_objects_gcode);
}
// Reset the cooling buffer internal state (the current position, feed rate, accelerations).
- m_cooling_buffer->reset();
+ m_cooling_buffer->reset(this->writer().get_position());
m_cooling_buffer->set_current_extruder(initial_extruder_id);
// Pair the object layers with the support layers by z, extrude them.
std::vector<LayerToPrint> layers_to_print = collect_layers_to_print(object);
@@ -1420,7 +1420,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
// Write end commands to file.
file.write(this->retract());
- file.write(m_writer.set_fan(false));
+ file.write(m_writer.set_fan(0));
// adds tag for processor
file.write_format(";%s%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role).c_str(), ExtrusionEntity::role_to_string(erCustom).c_str());
diff --git a/src/libslic3r/GCode/CoolingBuffer.cpp b/src/libslic3r/GCode/CoolingBuffer.cpp
index 17f3e0b73..9ca85c728 100644
--- a/src/libslic3r/GCode/CoolingBuffer.cpp
+++ b/src/libslic3r/GCode/CoolingBuffer.cpp
@@ -16,19 +16,25 @@
namespace Slic3r {
-CoolingBuffer::CoolingBuffer(GCode &gcodegen) : m_gcodegen(gcodegen), m_current_extruder(0)
+CoolingBuffer::CoolingBuffer(GCode &gcodegen) : m_config(gcodegen.config()), m_toolchange_prefix(gcodegen.writer().toolchange_prefix()), m_current_extruder(0)
{
- this->reset();
+ this->reset(gcodegen.writer().get_position());
+
+ const std::vector<Extruder> &extruders = gcodegen.writer().extruders();
+ m_extruder_ids.reserve(extruders.size());
+ for (const Extruder &ex : extruders) {
+ m_num_extruders = std::max(ex.id() + 1, m_num_extruders);
+ m_extruder_ids.emplace_back(ex.id());
+ }
}
-void CoolingBuffer::reset()
+void CoolingBuffer::reset(const Vec3d &position)
{
m_current_pos.assign(5, 0.f);
- Vec3d pos = m_gcodegen.writer().get_position();
- m_current_pos[0] = float(pos(0));
- m_current_pos[1] = float(pos(1));
- m_current_pos[2] = float(pos(2));
- m_current_pos[4] = float(m_gcodegen.config().travel_speed.value);
+ m_current_pos[0] = float(position.x());
+ m_current_pos[1] = float(position.y());
+ m_current_pos[2] = float(position.z());
+ m_current_pos[4] = float(m_config.travel_speed.value);
}
struct CoolingLine
@@ -303,30 +309,23 @@ std::string CoolingBuffer::process_layer(std::string &&gcode, size_t layer_id, b
// Return the list of parsed lines, bucketed by an extruder.
std::vector<PerExtruderAdjustments> CoolingBuffer::parse_layer_gcode(const std::string &gcode, std::vector<float> &current_pos) const
{
- const FullPrintConfig &config = m_gcodegen.config();
- const std::vector<Extruder> &extruders = m_gcodegen.writer().extruders();
- unsigned int num_extruders = 0;
- for (const Extruder &ex : extruders)
- num_extruders = std::max(ex.id() + 1, num_extruders);
-
- std::vector<PerExtruderAdjustments> per_extruder_adjustments(extruders.size());
- std::vector<size_t> map_extruder_to_per_extruder_adjustment(num_extruders, 0);
- for (size_t i = 0; i < extruders.size(); ++ i) {
+ std::vector<PerExtruderAdjustments> per_extruder_adjustments(m_extruder_ids.size());
+ std::vector<size_t> map_extruder_to_per_extruder_adjustment(m_num_extruders, 0);
+ for (size_t i = 0; i < m_extruder_ids.size(); ++ i) {
PerExtruderAdjustments &adj = per_extruder_adjustments[i];
- unsigned int extruder_id = extruders[i].id();
+ unsigned int extruder_id = m_extruder_ids[i];
adj.extruder_id = extruder_id;
- adj.cooling_slow_down_enabled = config.cooling.get_at(extruder_id);
- adj.slowdown_below_layer_time = float(config.slowdown_below_layer_time.get_at(extruder_id));
- adj.min_print_speed = float(config.min_print_speed.get_at(extruder_id));
+ adj.cooling_slow_down_enabled = m_config.cooling.get_at(extruder_id);
+ adj.slowdown_below_layer_time = float(m_config.slowdown_below_layer_time.get_at(extruder_id));
+ adj.min_print_speed = float(m_config.min_print_speed.get_at(extruder_id));
map_extruder_to_per_extruder_adjustment[extruder_id] = i;
}
- const std::string toolchange_prefix = m_gcodegen.writer().toolchange_prefix();
unsigned int current_extruder = m_current_extruder;
PerExtruderAdjustments *adjustment = &per_extruder_adjustments[map_extruder_to_per_extruder_adjustment[current_extruder]];
const char *line_start = gcode.c_str();
const char *line_end = line_start;
- const char extrusion_axis = get_extrusion_axis(config)[0];
+ const char extrusion_axis = get_extrusion_axis(m_config)[0];
// Index of an existing CoolingLine of the current adjustment, which holds the feedrate setting command
// for a sequence of extrusion moves.
size_t active_speed_modifier = size_t(-1);
@@ -387,7 +386,7 @@ std::vector<PerExtruderAdjustments> CoolingBuffer::parse_layer_gcode(const std::
}
if ((line.type & CoolingLine::TYPE_G92) == 0) {
// G0 or G1. Calculate the duration.
- if (config.use_relative_e_distances.value)
+ if (m_config.use_relative_e_distances.value)
// Reset extruder accumulator.
current_pos[3] = 0.f;
float dif[4];
@@ -430,8 +429,8 @@ std::vector<PerExtruderAdjustments> CoolingBuffer::parse_layer_gcode(const std::
} else if (boost::starts_with(sline, ";_EXTRUDE_END")) {
line.type = CoolingLine::TYPE_EXTRUDE_END;
active_speed_modifier = size_t(-1);
- } else if (boost::starts_with(sline, toolchange_prefix)) {
- unsigned int new_extruder = (unsigned int)atoi(sline.c_str() + toolchange_prefix.size());
+ } else if (boost::starts_with(sline, m_toolchange_prefix)) {
+ unsigned int new_extruder = (unsigned int)atoi(sline.c_str() + m_toolchange_prefix.size());
// Only change extruder in case the number is meaningful. User could provide an out-of-range index through custom gcodes - those shall be ignored.
if (new_extruder < map_extruder_to_per_extruder_adjustment.size()) {
if (new_extruder != current_extruder) {
@@ -641,7 +640,7 @@ float CoolingBuffer::calculate_layer_slowdown(std::vector<PerExtruderAdjustments
if (total > slowdown_below_layer_time) {
// The current total time is above the minimum threshold of the rest of the extruders, don't adjust anything.
} else {
- // Adjust this and all the following (higher config.slowdown_below_layer_time) extruders.
+ // Adjust this and all the following (higher m_config.slowdown_below_layer_time) extruders.
// Sum maximum slow down time as if everything was slowed down including the external perimeters.
float max_time = elapsed_time_total0;
for (auto it = cur_begin; it != by_slowdown_time.end(); ++ it)
@@ -694,8 +693,7 @@ std::string CoolingBuffer::apply_layer_cooldown(
bool bridge_fan_control = false;
int bridge_fan_speed = 0;
auto change_extruder_set_fan = [ this, layer_id, layer_time, &new_gcode, &fan_speed, &bridge_fan_control, &bridge_fan_speed ]() {
- const FullPrintConfig &config = m_gcodegen.config();
-#define EXTRUDER_CONFIG(OPT) config.OPT.get_at(m_current_extruder)
+#define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_current_extruder)
int min_fan_speed = EXTRUDER_CONFIG(min_fan_speed);
int fan_speed_new = EXTRUDER_CONFIG(fan_always_on) ? min_fan_speed : 0;
int disable_fan_first_layers = EXTRUDER_CONFIG(disable_fan_first_layers);
@@ -737,13 +735,12 @@ std::string CoolingBuffer::apply_layer_cooldown(
}
if (fan_speed_new != fan_speed) {
fan_speed = fan_speed_new;
- new_gcode += m_gcodegen.writer().set_fan(fan_speed);
+ new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_config.gcode_comments, fan_speed);
}
};
const char *pos = gcode.c_str();
int current_feedrate = 0;
- const std::string toolchange_prefix = m_gcodegen.writer().toolchange_prefix();
change_extruder_set_fan();
for (const CoolingLine *line : lines) {
const char *line_start = gcode.c_str() + line->line_start;
@@ -751,7 +748,7 @@ std::string CoolingBuffer::apply_layer_cooldown(
if (line_start > pos)
new_gcode.append(pos, line_start - pos);
if (line->type & CoolingLine::TYPE_SET_TOOL) {
- unsigned int new_extruder = (unsigned int)atoi(line_start + toolchange_prefix.size());
+ unsigned int new_extruder = (unsigned int)atoi(line_start + m_toolchange_prefix.size());
if (new_extruder != m_current_extruder) {
m_current_extruder = new_extruder;
change_extruder_set_fan();
@@ -759,10 +756,10 @@ std::string CoolingBuffer::apply_layer_cooldown(
new_gcode.append(line_start, line_end - line_start);
} else if (line->type & CoolingLine::TYPE_BRIDGE_FAN_START) {
if (bridge_fan_control)
- new_gcode += m_gcodegen.writer().set_fan(bridge_fan_speed, true);
+ new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_config.gcode_comments, bridge_fan_speed);
} else if (line->type & CoolingLine::TYPE_BRIDGE_FAN_END) {
if (bridge_fan_control)
- new_gcode += m_gcodegen.writer().set_fan(fan_speed, true);
+ new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_config.gcode_comments, fan_speed);
} else if (line->type & CoolingLine::TYPE_EXTRUDE_END) {
// Just remove this comment.
} else if (line->type & (CoolingLine::TYPE_ADJUSTABLE | CoolingLine::TYPE_EXTERNAL_PERIMETER | CoolingLine::TYPE_WIPE | CoolingLine::TYPE_HAS_F)) {
diff --git a/src/libslic3r/GCode/CoolingBuffer.hpp b/src/libslic3r/GCode/CoolingBuffer.hpp
index 0932d62d3..5f49ef455 100644
--- a/src/libslic3r/GCode/CoolingBuffer.hpp
+++ b/src/libslic3r/GCode/CoolingBuffer.hpp
@@ -23,10 +23,9 @@ struct PerExtruderAdjustments;
class CoolingBuffer {
public:
CoolingBuffer(GCode &gcodegen);
- void reset();
+ void reset(const Vec3d &position);
void set_current_extruder(unsigned int extruder_id) { m_current_extruder = extruder_id; }
std::string process_layer(std::string &&gcode, size_t layer_id, bool flush);
- GCode* gcodegen() { return &m_gcodegen; }
private:
CoolingBuffer& operator=(const CoolingBuffer&) = delete;
@@ -36,17 +35,25 @@ private:
// Returns the adjusted G-code.
std::string apply_layer_cooldown(const std::string &gcode, size_t layer_id, float layer_time, std::vector<PerExtruderAdjustments> &per_extruder_adjustments);
- GCode& m_gcodegen;
// G-code snippet cached for the support layers preceding an object layer.
- std::string m_gcode;
+ std::string m_gcode;
// Internal data.
// X,Y,Z,E,F
- std::vector<char> m_axis;
- std::vector<float> m_current_pos;
- unsigned int m_current_extruder;
+ std::vector<char> m_axis;
+ std::vector<float> m_current_pos;
+ // Cached from GCodeWriter.
+ // Printing extruder IDs, zero based.
+ std::vector<unsigned int> m_extruder_ids;
+ // Highest of m_extruder_ids plus 1.
+ unsigned int m_num_extruders { 0 };
+ const std::string m_toolchange_prefix;
+ // Referencs GCode::m_config, which is FullPrintConfig. While the PrintObjectConfig slice of FullPrintConfig is being modified,
+ // the PrintConfig slice of FullPrintConfig is constant, thus no thread synchronization is required.
+ const PrintConfig &m_config;
+ unsigned int m_current_extruder;
// Old logic: proportional.
- bool m_cooling_logic_proportional = false;
+ bool m_cooling_logic_proportional = false;
};
}
diff --git a/src/libslic3r/GCodeWriter.cpp b/src/libslic3r/GCodeWriter.cpp
index c97180982..793a66675 100644
--- a/src/libslic3r/GCodeWriter.cpp
+++ b/src/libslic3r/GCodeWriter.cpp
@@ -156,41 +156,6 @@ std::string GCodeWriter::set_bed_temperature(unsigned int temperature, bool wait
return gcode.str();
}
-std::string GCodeWriter::set_fan(unsigned int speed, bool dont_save)
-{
- std::ostringstream gcode;
- if (m_last_fan_speed != speed || dont_save) {
- if (!dont_save) m_last_fan_speed = speed;
-
- if (speed == 0) {
- if (FLAVOR_IS(gcfTeacup)) {
- gcode << "M106 S0";
- } else if (FLAVOR_IS(gcfMakerWare) || FLAVOR_IS(gcfSailfish)) {
- gcode << "M127";
- } else {
- gcode << "M107";
- }
- if (this->config.gcode_comments) gcode << " ; disable fan";
- gcode << "\n";
- } else {
- if (FLAVOR_IS(gcfMakerWare) || FLAVOR_IS(gcfSailfish)) {
- gcode << "M126";
- } else {
- gcode << "M106 ";
- if (FLAVOR_IS(gcfMach3) || FLAVOR_IS(gcfMachinekit)) {
- gcode << "P";
- } else {
- gcode << "S";
- }
- gcode << (255.0 * speed / 100.0);
- }
- if (this->config.gcode_comments) gcode << " ; enable fan";
- gcode << "\n";
- }
- }
- return gcode.str();
-}
-
std::string GCodeWriter::set_acceleration(unsigned int acceleration)
{
// Clamp the acceleration to the allowed maximum.
@@ -611,4 +576,43 @@ std::string GCodeWriter::unlift()
return gcode;
}
+std::string GCodeWriter::set_fan(const GCodeFlavor gcode_flavor, bool gcode_comments, unsigned int speed)
+{
+ std::ostringstream gcode;
+ if (speed == 0) {
+ switch (gcode_flavor) {
+ case gcfTeacup:
+ gcode << "M106 S0"; break;
+ case gcfMakerWare:
+ case gcfSailfish:
+ gcode << "M127"; break;
+ default:
+ gcode << "M107"; break;
+ }
+ if (gcode_comments)
+ gcode << " ; disable fan";
+ gcode << "\n";
+ } else {
+ switch (gcode_flavor) {
+ case gcfMakerWare:
+ case gcfSailfish:
+ gcode << "M126"; break;
+ case gcfMach3:
+ case gcfMachinekit:
+ gcode << "M106 P" << 255.0 * speed / 100.0; break;
+ default:
+ gcode << "M106 S" << 255.0 * speed / 100.0; break;
+ }
+ if (gcode_comments)
+ gcode << " ; enable fan";
+ gcode << "\n";
+ }
+ return gcode.str();
+}
+
+std::string GCodeWriter::set_fan(unsigned int speed) const
+{
+ return GCodeWriter::set_fan(this->config.gcode_flavor, this->config.gcode_comments, speed);
+}
+
}
diff --git a/src/libslic3r/GCodeWriter.hpp b/src/libslic3r/GCodeWriter.hpp
index 2de95ecc5..dd602ca80 100644
--- a/src/libslic3r/GCodeWriter.hpp
+++ b/src/libslic3r/GCodeWriter.hpp
@@ -18,7 +18,7 @@ public:
GCodeWriter() :
multiple_extruders(false), m_extrusion_axis("E"), m_extruder(nullptr),
m_single_extruder_multi_material(false),
- m_last_acceleration(0), m_max_acceleration(0), m_last_fan_speed(0),
+ m_last_acceleration(0), m_max_acceleration(0),
m_last_bed_temperature(0), m_last_bed_temperature_reached(true),
m_lifted(0)
{}
@@ -42,7 +42,6 @@ public:
std::string postamble() const;
std::string set_temperature(unsigned int temperature, bool wait = false, int tool = -1) const;
std::string set_bed_temperature(unsigned int temperature, bool wait = false);
- std::string set_fan(unsigned int speed, bool dont_save = false);
std::string set_acceleration(unsigned int acceleration);
std::string reset_e(bool force = false);
std::string update_progress(unsigned int num, unsigned int tot, bool allow_100 = false) const;
@@ -69,6 +68,12 @@ public:
std::string unlift();
Vec3d get_position() const { return m_pos; }
+ // To be called by the CoolingBuffer from another thread.
+ static std::string set_fan(const GCodeFlavor gcode_flavor, bool gcode_comments, unsigned int speed);
+ // To be called by the main thread. It always emits the G-code, it does not remember the previous state.
+ // Keeping the state is left to the CoolingBuffer, which runs asynchronously on another thread.
+ std::string set_fan(unsigned int speed) const;
+
private:
// Extruders are sorted by their ID, so that binary search is possible.
std::vector<Extruder> m_extruders;
@@ -79,7 +84,6 @@ private:
// Limit for setting the acceleration, to respect the machine limits set for the Marlin firmware.
// If set to zero, the limit is not in action.
unsigned int m_max_acceleration;
- unsigned int m_last_fan_speed;
unsigned int m_last_bed_temperature;
bool m_last_bed_temperature_reached;
double m_lifted;
diff --git a/t/cooling.t b/t/cooling.t
index 2f444cf9d..a7720fd07 100644
--- a/t/cooling.t
+++ b/t/cooling.t
@@ -132,7 +132,7 @@ $config->set('disable_fan_first_layers', [ 0 ]);
'fan_below_layer_time' => [ $print_time2 + 1, $print_time2 + 1 ],
'slowdown_below_layer_time' => [ $print_time2 + 2, $print_time2 + 2 ]
});
- $buffer->gcodegen->set_extruders([ 0, 1 ]);
+ $gcodegen->set_extruders([ 0, 1 ]);
my $gcode = $buffer->process_layer($gcode1 . "T1\nG1 X0 E1 F3000\n", 0);
like $gcode, qr/^M106/, 'fan is activated for the 1st tool';
like $gcode, qr/.*M107/, 'fan is disabled for the 2nd tool';
diff --git a/xs/xsp/GCode.xsp b/xs/xsp/GCode.xsp
index 78a5dde37..4c2583894 100644
--- a/xs/xsp/GCode.xsp
+++ b/xs/xsp/GCode.xsp
@@ -10,7 +10,6 @@
CoolingBuffer(GCode* gcode)
%code{% RETVAL = new CoolingBuffer(*gcode); %};
~CoolingBuffer();
- Ref<GCode> gcodegen();
std::string process_layer(std::string gcode, size_t layer_id)
%code{% RETVAL = THIS->process_layer(std::move(gcode), layer_id, true); %};