From 6ea57817099ca72139bfa3a46fd1dd8a03749734 Mon Sep 17 00:00:00 2001
From: Vojtech Bubnik <bubnikv@gmail.com>
Date: Tue, 16 Feb 2021 11:30:49 +0100
Subject: [PATCH] Fix of Supports printed too slowly. #984 Processing of
 CoolingBuffer is newly staggered for support layers until the 1st object
 layer above supports is received by CoolingBuffer.

---
 src/libslic3r/GCode.cpp               | 14 +++++++++-----
 src/libslic3r/GCode.hpp               |  1 +
 src/libslic3r/GCode/CoolingBuffer.cpp | 21 +++++++++++++++++----
 src/libslic3r/GCode/CoolingBuffer.hpp |  3 ++-
 4 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp
index 40392466d..d836bb14f 100644
--- a/src/libslic3r/GCode.cpp
+++ b/src/libslic3r/GCode.cpp
@@ -1224,7 +1224,8 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
             for (const LayerToPrint &ltp : layers_to_print) {
                 std::vector<LayerToPrint> lrs;
                 lrs.emplace_back(std::move(ltp));
-                this->process_layer(file, print, lrs, tool_ordering.tools_for_layer(ltp.print_z()), nullptr, *print_object_instance_sequential_active - object.instances().data());
+                this->process_layer(file, print, lrs, tool_ordering.tools_for_layer(ltp.print_z()), &ltp == &layers_to_print.back(), 
+                    nullptr, *print_object_instance_sequential_active - object.instances().data());
                 print.throw_if_canceled();
             }
 #ifdef HAS_PRESSURE_EQUALIZER
@@ -1288,7 +1289,7 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
             const LayerTools &layer_tools = tool_ordering.tools_for_layer(layer.first);
             if (m_wipe_tower && layer_tools.has_wipe_tower)
                 m_wipe_tower->next_layer();
-            this->process_layer(file, print, layer.second, layer_tools, &print_object_instances_ordering, size_t(-1));
+            this->process_layer(file, print, layer.second, layer_tools, &layer == &layers_to_print.back(), &print_object_instances_ordering, size_t(-1));
             print.throw_if_canceled();
         }
 #ifdef HAS_PRESSURE_EQUALIZER
@@ -1757,6 +1758,7 @@ void GCode::process_layer(
     // Set of object & print layers of the same PrintObject and with the same print_z.
     const std::vector<LayerToPrint> 		&layers,
     const LayerTools        		        &layer_tools,
+    const bool                               last_layer,
     // Pairs of PrintObject index and its instance index.
     const std::vector<const PrintInstance*> *ordering,
     // If set to size_t(-1), then print all copies of all objects.
@@ -2140,11 +2142,13 @@ void GCode::process_layer(
     // we apply spiral vase at this stage because it requires a full layer.
     // Just a reminder: A spiral vase mode is allowed for a single object per layer, single material print only.
     if (m_spiral_vase)
-        gcode = m_spiral_vase->process_layer(gcode);
+        gcode = m_spiral_vase->process_layer(std::move(gcode));
 
     // Apply cooling logic; this may alter speeds.
     if (m_cooling_buffer)
-        gcode = m_cooling_buffer->process_layer(gcode, layer.id());
+        gcode = m_cooling_buffer->process_layer(std::move(gcode), layer.id(),
+            // Flush the cooling buffer at each object layer or possibly at the last layer, even if it contains just supports (This should not happen).
+            object_layer || last_layer);
 
 #ifdef HAS_PRESSURE_EQUALIZER
     // Apply pressure equalization if enabled;
@@ -2156,7 +2160,7 @@ void GCode::process_layer(
 
     _write(file, gcode);
     BOOST_LOG_TRIVIAL(trace) << "Exported layer " << layer.id() << " print_z " << print_z <<
-        log_memory_info();
+    log_memory_info();
 }
 
 void GCode::apply_print_config(const PrintConfig &print_config)
diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp
index 1dbb153dd..483fb3dac 100644
--- a/src/libslic3r/GCode.hpp
+++ b/src/libslic3r/GCode.hpp
@@ -201,6 +201,7 @@ private:
         // Set of object & print layers of the same PrintObject and with the same print_z.
         const std::vector<LayerToPrint> &layers,
         const LayerTools  				&layer_tools,
+        const bool                       last_layer,
 		// Pairs of PrintObject index and its instance index.
 		const std::vector<const PrintInstance*> *ordering,
         // If set to size_t(-1), then print all copies of all objects.
diff --git a/src/libslic3r/GCode/CoolingBuffer.cpp b/src/libslic3r/GCode/CoolingBuffer.cpp
index 3c9c62fc5..7f48aae80 100644
--- a/src/libslic3r/GCode/CoolingBuffer.cpp
+++ b/src/libslic3r/GCode/CoolingBuffer.cpp
@@ -279,11 +279,24 @@ finished:
 	return new_feedrate;
 }
 
-std::string CoolingBuffer::process_layer(const std::string &gcode, size_t layer_id)
+std::string CoolingBuffer::process_layer(std::string &&gcode, size_t layer_id, bool flush)
 {
-    std::vector<PerExtruderAdjustments> per_extruder_adjustments = this->parse_layer_gcode(gcode, m_current_pos);
-    float layer_time_stretched = this->calculate_layer_slowdown(per_extruder_adjustments);
-    return this->apply_layer_cooldown(gcode, layer_id, layer_time_stretched, per_extruder_adjustments);
+    // Cache the input G-code.
+    if (m_gcode.empty())
+        m_gcode = std::move(gcode);
+    else
+        m_gcode += gcode;
+
+    std::string out;
+    if (flush) {
+        // This is either an object layer or the very last print layer. Calculate cool down over the collected support layers
+        // and one object layer.
+        std::vector<PerExtruderAdjustments> per_extruder_adjustments = this->parse_layer_gcode(m_gcode, m_current_pos);
+        float layer_time_stretched = this->calculate_layer_slowdown(per_extruder_adjustments);
+        out = this->apply_layer_cooldown(m_gcode, layer_id, layer_time_stretched, per_extruder_adjustments);
+        m_gcode.clear();
+    }
+    return out;
 }
 
 // Parse the layer G-code for the moves, which could be adjusted.
diff --git a/src/libslic3r/GCode/CoolingBuffer.hpp b/src/libslic3r/GCode/CoolingBuffer.hpp
index b0c35ecc5..0932d62d3 100644
--- a/src/libslic3r/GCode/CoolingBuffer.hpp
+++ b/src/libslic3r/GCode/CoolingBuffer.hpp
@@ -25,7 +25,7 @@ public:
     CoolingBuffer(GCode &gcodegen);
     void        reset();
     void        set_current_extruder(unsigned int extruder_id) { m_current_extruder = extruder_id; }
-    std::string process_layer(const std::string &gcode, size_t layer_id);
+    std::string process_layer(std::string &&gcode, size_t layer_id, bool flush);
     GCode* 	    gcodegen() { return &m_gcodegen; }
 
 private:
@@ -37,6 +37,7 @@ private:
     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;
     // Internal data.
     // X,Y,Z,E,F