Follow-up to b5a007a683
WIP to G-code export parallelization through pipelining: GCodeProcessor is called during the G-code export, the G-code is no more reopened and re-read, but it is pipelined from the G-code generator.
This commit is contained in:
parent
a8a7efddc5
commit
beee18f229
7 changed files with 57 additions and 28 deletions
|
@ -744,7 +744,8 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessor::Result* re
|
||||||
std::string path_tmp(path);
|
std::string path_tmp(path);
|
||||||
path_tmp += ".tmp";
|
path_tmp += ".tmp";
|
||||||
|
|
||||||
GCodeOutputStream file(boost::nowide::fopen(path_tmp.c_str(), "wb"));
|
m_processor.initialize(path_tmp);
|
||||||
|
GCodeOutputStream file(boost::nowide::fopen(path_tmp.c_str(), "wb"), m_processor);
|
||||||
if (! file.is_open())
|
if (! file.is_open())
|
||||||
throw Slic3r::RuntimeError(std::string("G-code export to ") + path + " failed.\nCannot open the file for writing.\n");
|
throw Slic3r::RuntimeError(std::string("G-code export to ") + path + " failed.\nCannot open the file for writing.\n");
|
||||||
|
|
||||||
|
@ -782,7 +783,7 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessor::Result* re
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Start processing gcode, " << log_memory_info();
|
BOOST_LOG_TRIVIAL(debug) << "Start processing gcode, " << log_memory_info();
|
||||||
m_processor.process_file(path_tmp, true, [print]() { print->throw_if_canceled(); });
|
m_processor.finalize();
|
||||||
// DoExport::update_print_estimated_times_stats(m_processor, print->m_print_statistics);
|
// DoExport::update_print_estimated_times_stats(m_processor, print->m_print_statistics);
|
||||||
DoExport::update_print_estimated_stats(m_processor, m_writer.extruders(), print->m_print_statistics);
|
DoExport::update_print_estimated_stats(m_processor, m_writer.extruders(), print->m_print_statistics);
|
||||||
if (result != nullptr) {
|
if (result != nullptr) {
|
||||||
|
@ -2666,6 +2667,8 @@ void GCode::GCodeOutputStream::write(const char *what)
|
||||||
const char* gcode = what;
|
const char* gcode = what;
|
||||||
// writes string to file
|
// writes string to file
|
||||||
fwrite(gcode, 1, ::strlen(gcode), this->f);
|
fwrite(gcode, 1, ::strlen(gcode), this->f);
|
||||||
|
//FIXME don't allocate a string, maybe process a batch of lines?
|
||||||
|
m_processor.process_buffer(std::string(gcode));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -186,7 +186,7 @@ public:
|
||||||
private:
|
private:
|
||||||
class GCodeOutputStream {
|
class GCodeOutputStream {
|
||||||
public:
|
public:
|
||||||
GCodeOutputStream(FILE *f) : f(f) {}
|
GCodeOutputStream(FILE *f, GCodeProcessor &processor) : f(f), m_processor(processor) {}
|
||||||
~GCodeOutputStream() { this->close(); }
|
~GCodeOutputStream() { this->close(); }
|
||||||
|
|
||||||
bool is_open() const { return f; }
|
bool is_open() const { return f; }
|
||||||
|
@ -209,6 +209,7 @@ private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FILE *f = nullptr;
|
FILE *f = nullptr;
|
||||||
|
GCodeProcessor &m_processor;
|
||||||
};
|
};
|
||||||
void _do_export(Print &print, GCodeOutputStream &file, ThumbnailsGeneratorCallback thumbnail_cb);
|
void _do_export(Print &print, GCodeOutputStream &file, ThumbnailsGeneratorCallback thumbnail_cb);
|
||||||
|
|
||||||
|
|
|
@ -1189,7 +1189,6 @@ void GCodeProcessor::reset()
|
||||||
m_cp_color.reset();
|
m_cp_color.reset();
|
||||||
|
|
||||||
m_producer = EProducer::Unknown;
|
m_producer = EProducer::Unknown;
|
||||||
m_producers_enabled = false;
|
|
||||||
|
|
||||||
m_time_processor.reset();
|
m_time_processor.reset();
|
||||||
m_used_filaments.reset();
|
m_used_filaments.reset();
|
||||||
|
@ -1209,7 +1208,7 @@ void GCodeProcessor::reset()
|
||||||
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCodeProcessor::process_file(const std::string& filename, bool apply_postprocess, std::function<void()> cancel_callback)
|
void GCodeProcessor::process_file(const std::string& filename, std::function<void()> cancel_callback)
|
||||||
{
|
{
|
||||||
CNumericLocalesSetter locales_setter;
|
CNumericLocalesSetter locales_setter;
|
||||||
|
|
||||||
|
@ -1219,7 +1218,7 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr
|
||||||
|
|
||||||
// pre-processing
|
// pre-processing
|
||||||
// parse the gcode file to detect its producer
|
// parse the gcode file to detect its producer
|
||||||
if (m_producers_enabled) {
|
{
|
||||||
m_parser.parse_file(filename, [this](GCodeReader& reader, const GCodeReader::GCodeLine& line) {
|
m_parser.parse_file(filename, [this](GCodeReader& reader, const GCodeReader::GCodeLine& line) {
|
||||||
const std::string_view cmd = line.cmd();
|
const std::string_view cmd = line.cmd();
|
||||||
if (cmd.empty()) {
|
if (cmd.empty()) {
|
||||||
|
@ -1228,6 +1227,7 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr
|
||||||
m_parser.quit_parsing();
|
m_parser.quit_parsing();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
m_parser.reset();
|
||||||
|
|
||||||
// if the gcode was produced by PrusaSlicer,
|
// if the gcode was produced by PrusaSlicer,
|
||||||
// extract the config from it
|
// extract the config from it
|
||||||
|
@ -1257,9 +1257,37 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr
|
||||||
if (cancel_callback)
|
if (cancel_callback)
|
||||||
cancel_callback();
|
cancel_callback();
|
||||||
}
|
}
|
||||||
this->process_gcode_line(line);
|
this->process_gcode_line(line, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this->finalize();
|
||||||
|
|
||||||
|
// post-process to add M73 lines into the gcode
|
||||||
|
#if ENABLE_GCODE_VIEWER_STATISTICS
|
||||||
|
m_result.time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start_time).count();
|
||||||
|
#endif // ENABLE_GCODE_VIEWER_STATISTICS
|
||||||
|
}
|
||||||
|
|
||||||
|
void GCodeProcessor::initialize(const std::string& filename)
|
||||||
|
{
|
||||||
|
assert(is_decimal_separator_point());
|
||||||
|
// process gcode
|
||||||
|
m_result.filename = filename;
|
||||||
|
m_result.id = ++s_result_id;
|
||||||
|
// 1st move must be a dummy move
|
||||||
|
m_result.moves.emplace_back(MoveVertex());
|
||||||
|
}
|
||||||
|
|
||||||
|
void GCodeProcessor::process_buffer(const std::string &buffer)
|
||||||
|
{
|
||||||
|
//FIXME maybe cache GCodeLine gline to be over multiple parse_buffer() invocations.
|
||||||
|
m_parser.parse_buffer(buffer, [this](GCodeReader&, const GCodeReader::GCodeLine& line) {
|
||||||
|
this->process_gcode_line(line, false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void GCodeProcessor::finalize()
|
||||||
|
{
|
||||||
// update width/height of wipe moves
|
// update width/height of wipe moves
|
||||||
for (MoveVertex& move : m_result.moves) {
|
for (MoveVertex& move : m_result.moves) {
|
||||||
if (move.type == EMoveType::Wipe) {
|
if (move.type == EMoveType::Wipe) {
|
||||||
|
@ -1281,10 +1309,6 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr
|
||||||
|
|
||||||
update_estimated_times_stats();
|
update_estimated_times_stats();
|
||||||
|
|
||||||
// post-process to add M73 lines into the gcode
|
|
||||||
if (apply_postprocess)
|
|
||||||
m_time_processor.post_process(filename, m_result.moves, m_result.lines_ends);
|
|
||||||
|
|
||||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
m_mm3_per_mm_compare.output();
|
m_mm3_per_mm_compare.output();
|
||||||
|
@ -1292,9 +1316,7 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr
|
||||||
m_width_compare.output();
|
m_width_compare.output();
|
||||||
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||||
|
|
||||||
#if ENABLE_GCODE_VIEWER_STATISTICS
|
m_time_processor.post_process(m_result.filename, m_result.moves, m_result.lines_ends);
|
||||||
m_result.time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start_time).count();
|
|
||||||
#endif // ENABLE_GCODE_VIEWER_STATISTICS
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float GCodeProcessor::get_time(PrintEstimatedStatistics::ETimeMode mode) const
|
float GCodeProcessor::get_time(PrintEstimatedStatistics::ETimeMode mode) const
|
||||||
|
@ -1432,7 +1454,7 @@ void GCodeProcessor::apply_config_simplify3d(const std::string& filename)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line)
|
void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line, bool producers_enabled)
|
||||||
{
|
{
|
||||||
/* std::cout << line.raw() << std::endl; */
|
/* std::cout << line.raw() << std::endl; */
|
||||||
|
|
||||||
|
@ -1615,7 +1637,7 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line)
|
||||||
if (comment.length() > 2 && comment.front() == ';')
|
if (comment.length() > 2 && comment.front() == ';')
|
||||||
// Process tags embedded into comments. Tag comments always start at the start of a line
|
// Process tags embedded into comments. Tag comments always start at the start of a line
|
||||||
// with a comment and continue with a tag without any whitespace separator.
|
// with a comment and continue with a tag without any whitespace separator.
|
||||||
process_tags(comment.substr(1));
|
process_tags(comment.substr(1), producers_enabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1664,10 +1686,10 @@ template<typename T>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCodeProcessor::process_tags(const std::string_view comment)
|
void GCodeProcessor::process_tags(const std::string_view comment, bool producers_enabled)
|
||||||
{
|
{
|
||||||
// producers tags
|
// producers tags
|
||||||
if (m_producers_enabled && process_producers_tags(comment))
|
if (producers_enabled && process_producers_tags(comment))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// extrusion role tag
|
// extrusion role tag
|
||||||
|
@ -1691,7 +1713,7 @@ void GCodeProcessor::process_tags(const std::string_view comment)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_producers_enabled || m_producer == EProducer::PrusaSlicer) {
|
if (!producers_enabled || m_producer == EProducer::PrusaSlicer) {
|
||||||
// height tag
|
// height tag
|
||||||
if (boost::starts_with(comment, reserved_tag(ETags::Height))) {
|
if (boost::starts_with(comment, reserved_tag(ETags::Height))) {
|
||||||
if (!parse_number(comment.substr(reserved_tag(ETags::Height).size()), m_forced_height))
|
if (!parse_number(comment.substr(reserved_tag(ETags::Height).size()), m_forced_height))
|
||||||
|
|
|
@ -513,7 +513,6 @@ namespace Slic3r {
|
||||||
|
|
||||||
static const std::vector<std::pair<GCodeProcessor::EProducer, std::string>> Producers;
|
static const std::vector<std::pair<GCodeProcessor::EProducer, std::string>> Producers;
|
||||||
EProducer m_producer;
|
EProducer m_producer;
|
||||||
bool m_producers_enabled;
|
|
||||||
|
|
||||||
TimeProcessor m_time_processor;
|
TimeProcessor m_time_processor;
|
||||||
UsedFilaments m_used_filaments;
|
UsedFilaments m_used_filaments;
|
||||||
|
@ -536,7 +535,6 @@ namespace Slic3r {
|
||||||
return m_time_processor.machines[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Stealth)].enabled;
|
return m_time_processor.machines[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Stealth)].enabled;
|
||||||
}
|
}
|
||||||
void enable_machine_envelope_processing(bool enabled) { m_time_processor.machine_envelope_processing_enabled = enabled; }
|
void enable_machine_envelope_processing(bool enabled) { m_time_processor.machine_envelope_processing_enabled = enabled; }
|
||||||
void enable_producers(bool enabled) { m_producers_enabled = enabled; }
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
const Result& get_result() const { return m_result; }
|
const Result& get_result() const { return m_result; }
|
||||||
|
@ -544,7 +542,12 @@ namespace Slic3r {
|
||||||
|
|
||||||
// Process the gcode contained in the file with the given filename
|
// Process the gcode contained in the file with the given filename
|
||||||
// throws CanceledException through print->throw_if_canceled() (sent by the caller as callback).
|
// throws CanceledException through print->throw_if_canceled() (sent by the caller as callback).
|
||||||
void process_file(const std::string& filename, bool apply_postprocess, std::function<void()> cancel_callback = nullptr);
|
void process_file(const std::string& filename, std::function<void()> cancel_callback = nullptr);
|
||||||
|
|
||||||
|
// Streaming interface, for processing G-codes just generated by PrusaSlicer in a pipelined fashion.
|
||||||
|
void initialize(const std::string& filename);
|
||||||
|
void process_buffer(const std::string& buffer);
|
||||||
|
void finalize();
|
||||||
|
|
||||||
float get_time(PrintEstimatedStatistics::ETimeMode mode) const;
|
float get_time(PrintEstimatedStatistics::ETimeMode mode) const;
|
||||||
std::string get_time_dhm(PrintEstimatedStatistics::ETimeMode mode) const;
|
std::string get_time_dhm(PrintEstimatedStatistics::ETimeMode mode) const;
|
||||||
|
@ -557,10 +560,10 @@ namespace Slic3r {
|
||||||
private:
|
private:
|
||||||
void apply_config(const DynamicPrintConfig& config);
|
void apply_config(const DynamicPrintConfig& config);
|
||||||
void apply_config_simplify3d(const std::string& filename);
|
void apply_config_simplify3d(const std::string& filename);
|
||||||
void process_gcode_line(const GCodeReader::GCodeLine& line);
|
void process_gcode_line(const GCodeReader::GCodeLine& line, bool producers_enabled);
|
||||||
|
|
||||||
// Process tags embedded into comments
|
// Process tags embedded into comments
|
||||||
void process_tags(const std::string_view comment);
|
void process_tags(const std::string_view comment, bool producers_enabled);
|
||||||
bool process_producers_tags(const std::string_view comment);
|
bool process_producers_tags(const std::string_view comment);
|
||||||
bool process_prusaslicer_tags(const std::string_view comment);
|
bool process_prusaslicer_tags(const std::string_view comment);
|
||||||
bool process_cura_tags(const std::string_view comment);
|
bool process_cura_tags(const std::string_view comment);
|
||||||
|
|
|
@ -77,7 +77,8 @@ public:
|
||||||
|
|
||||||
typedef std::function<void(GCodeReader&, const GCodeLine&)> callback_t;
|
typedef std::function<void(GCodeReader&, const GCodeLine&)> callback_t;
|
||||||
|
|
||||||
GCodeReader() : m_verbose(false), m_extrusion_axis('E') { memset(m_position, 0, sizeof(m_position)); }
|
GCodeReader() : m_verbose(false), m_extrusion_axis('E') { this->reset(); }
|
||||||
|
void reset() { memset(m_position, 0, sizeof(m_position)); }
|
||||||
void apply_config(const GCodeConfig &config);
|
void apply_config(const GCodeConfig &config);
|
||||||
void apply_config(const DynamicPrintConfig &config);
|
void apply_config(const DynamicPrintConfig &config);
|
||||||
|
|
||||||
|
|
|
@ -1190,7 +1190,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
|
||||||
};
|
};
|
||||||
auto add_indices_as_line = [](const GCodeProcessor::MoveVertex& prev, const GCodeProcessor::MoveVertex& curr, TBuffer& buffer,
|
auto add_indices_as_line = [](const GCodeProcessor::MoveVertex& prev, const GCodeProcessor::MoveVertex& curr, TBuffer& buffer,
|
||||||
unsigned int ibuffer_id, IndexBuffer& indices, size_t move_id) {
|
unsigned int ibuffer_id, IndexBuffer& indices, size_t move_id) {
|
||||||
if (prev.type != curr.type || !buffer.paths.back().matches(curr)) {
|
if (buffer.paths.empty() || prev.type != curr.type || !buffer.paths.back().matches(curr)) {
|
||||||
// add starting index
|
// add starting index
|
||||||
indices.push_back(static_cast<IBufferType>(indices.size()));
|
indices.push_back(static_cast<IBufferType>(indices.size()));
|
||||||
buffer.add_path(curr, ibuffer_id, indices.size() - 1, move_id - 1);
|
buffer.add_path(curr, ibuffer_id, indices.size() - 1, move_id - 1);
|
||||||
|
|
|
@ -4871,10 +4871,9 @@ void Plater::load_gcode(const wxString& filename)
|
||||||
|
|
||||||
// process gcode
|
// process gcode
|
||||||
GCodeProcessor processor;
|
GCodeProcessor processor;
|
||||||
processor.enable_producers(true);
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
processor.process_file(filename.ToUTF8().data(), false);
|
processor.process_file(filename.ToUTF8().data());
|
||||||
}
|
}
|
||||||
catch (const std::exception& ex)
|
catch (const std::exception& ex)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue