Merge branch 'master' into fs_emboss

# Conflicts:
#	src/libslic3r/Technologies.hpp
This commit is contained in:
Filip Sykala - NTB T15p 2022-09-29 08:00:21 +02:00
commit 28decf6f15
8 changed files with 99 additions and 127 deletions

View File

@ -9,6 +9,7 @@
#include "GCode/WipeTower.hpp"
#include "ShortestPath.hpp"
#include "Print.hpp"
#include "Thread.hpp"
#include "Utils.hpp"
#include "ClipperUtils.hpp"
#include "libslic3r.h"
@ -34,8 +35,6 @@
#include "SVG.hpp"
#include <tbb/parallel_for.h>
#include <tbb/task_scheduler_observer.h>
#include <tbb/enumerable_thread_specific.h>
// Intel redesigned some TBB interface considerably when merging TBB with their oneAPI set of libraries, see GH #7332.
// We are using quite an old TBB 2017 U7. Before we update our build servers, let's use the old API, which is deprecated in up to date TBB.
@ -1469,32 +1468,6 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
print.throw_if_canceled();
}
// For unknown reasons and in sporadic cases when GCode export is processing, some participating thread
// in tbb::parallel_pipeline has not set locales to "C", probably because this thread is newly spawned.
// So in this class method on_scheduler_entry is called for every thread before it starts participating
// in tbb::parallel_pipeline to ensure that locales are set correctly
// For tbb::parallel_pipeline, it seems that on_scheduler_entry is called for every layer and every filter.
// We ensure using thread-local storage that locales will be set to "C" just once for any participating thread.
class TBBLocalesSetter : public tbb::task_scheduler_observer
{
public:
TBBLocalesSetter() { this->observe(true); }
~TBBLocalesSetter() override { this->observe(false); };
void on_scheduler_entry(bool is_worker) override
{
if (bool &is_locales_sets = m_is_locales_sets.local(); !is_locales_sets) {
// Set locales of the worker thread to "C".
set_c_locales();
is_locales_sets = true;
}
}
private:
tbb::enumerable_thread_specific<bool, tbb::cache_aligned_allocator<bool>, tbb::ets_key_usage_type::ets_key_per_instance> m_is_locales_sets{false};
};
// Process all layers of all objects (non-sequential mode) with a parallel pipeline:
// Generate G-code, run the filters (vase mode, cooling buffer), run the G-code analyser
// and export G-code into file.

View File

@ -43,8 +43,6 @@
#define ENABLE_PREVIEW_LAYOUT (1 && ENABLE_2_5_0_ALPHA1)
// Enable drawing the items in legend toolbar using icons
#define ENABLE_LEGEND_TOOLBAR_ICONS (1 && ENABLE_PREVIEW_LAYOUT)
// Enable coloring of toolpaths in preview by layer time
#define ENABLE_PREVIEW_LAYER_TIME (1 && ENABLE_2_5_0_ALPHA1)
// Enable showing time estimate for travel moves in legend
#define ENABLE_TRAVEL_TIME (1 && ENABLE_2_5_0_ALPHA1)
// Enable removal of wipe tower magic object_id equal to 1000

View File

@ -4,6 +4,9 @@
#else
// any posix system
#include <pthread.h>
#ifdef __APPLE__
#include <pthread/qos.h>
#endif // __APPLE__
#endif
#include <atomic>
@ -241,4 +244,26 @@ void name_tbb_thread_pool_threads_set_locale()
});
}
void set_current_thread_qos()
{
#ifdef __APPLE__
// OSX specific: Set Quality of Service to "user initiated", so that the threads will be scheduled to high performance
// cores if available.
pthread_set_qos_class_self_np(QOS_CLASS_USER_INITIATED, 0);
#endif // __APPLE__
}
void TBBLocalesSetter::on_scheduler_entry(bool is_worker)
{
// static std::atomic<int> cnt = 0;
// std::cout << "TBBLocalesSetter Entering " << cnt ++ << " ID " << std::this_thread::get_id() << "\n";
if (bool& is_locales_sets = m_is_locales_sets.local(); !is_locales_sets) {
// Set locales of the worker thread to "C".
set_c_locales();
// OSX specific: Elevate QOS on Apple Silicon.
set_current_thread_qos();
is_locales_sets = true;
}
}
}

View File

@ -6,6 +6,9 @@
#include <thread>
#include <boost/thread.hpp>
#include <tbb/task_scheduler_observer.h>
#include <tbb/enumerable_thread_specific.h>
namespace Slic3r {
// Set / get thread name.
@ -26,6 +29,10 @@ inline bool set_thread_name(boost::thread &thread, const std::string &thread_nam
bool set_current_thread_name(const char *thread_name);
inline bool set_current_thread_name(const std::string &thread_name) { return set_current_thread_name(thread_name.c_str()); }
// OSX specific: Set Quality of Service to "user initiated", so that the threads will be scheduled to high performance
// cores if available.
void set_current_thread_qos();
// Returns nullopt if not supported.
// Not supported by OSX.
// Naming threads is only supported on newer Windows 10.
@ -53,6 +60,25 @@ template<class Fn> inline boost::thread create_thread(Fn &&fn)
return create_thread(attrs, std::forward<Fn>(fn));
}
// For unknown reasons and in sporadic cases when GCode export is processing, some participating thread
// in tbb::parallel_pipeline has not set locales to "C", probably because this thread is newly spawned.
// So in this class method on_scheduler_entry is called for every thread before it starts participating
// in tbb::parallel_pipeline to ensure that locales are set correctly
//
// For tbb::parallel_pipeline, it seems that on_scheduler_entry is called for every layer and every filter.
// We ensure using thread-local storage that locales will be set to "C" just once for any participating thread.
class TBBLocalesSetter : public tbb::task_scheduler_observer
{
public:
TBBLocalesSetter() { this->observe(true); }
~TBBLocalesSetter() override { this->observe(false); };
void on_scheduler_entry(bool is_worker) override;
private:
tbb::enumerable_thread_specific<bool, tbb::cache_aligned_allocator<bool>, tbb::ets_key_usage_type::ets_key_per_instance> m_is_locales_sets{ false };
};
}
#endif // GUI_THREAD_HPP

View File

@ -211,6 +211,12 @@ void BackgroundSlicingProcess::thread_proc()
set_current_thread_name("slic3r_BgSlcPcs");
name_tbb_thread_pool_threads_set_locale();
// Set "C" locales and enforce OSX QoS level on all threads entering an arena.
// The cost of the callback is quite low: The callback is called once per thread
// entering a parallel loop and the callback is guarded with a thread local
// variable to be executed just once.
TBBLocalesSetter setter;
assert(m_print != nullptr);
assert(m_print == m_fff_print || m_print == m_sla_print);
std::unique_lock<std::mutex> lck(m_mutex);

View File

@ -250,7 +250,6 @@ void GCodeViewer::COG::render()
//ImGui::PopStyleVar();
}
#if ENABLE_PREVIEW_LAYER_TIME
float GCodeViewer::Extrusions::Range::step_size(EType type) const
{
switch (type)
@ -262,12 +261,8 @@ float GCodeViewer::Extrusions::Range::step_size(EType type) const
}
ColorRGBA GCodeViewer::Extrusions::Range::get_color_at(float value, EType type) const
#else
ColorRGBA GCodeViewer::Extrusions::Range::get_color_at(float value) const
#endif // ENABLE_PREVIEW_LAYER_TIME
{
// Input value scaled to the colors range
#if ENABLE_PREVIEW_LAYER_TIME
float global_t = 0.0f;
const float step = step_size(type);
if (step > 0.0f) {
@ -278,10 +273,6 @@ ColorRGBA GCodeViewer::Extrusions::Range::get_color_at(float value) const
case EType::Logarithmic: { global_t = (value > min && min > 0.0f) ? ::log(value / min) / step : 0.0f; break; }
}
}
#else
const float step = step_size();
const float global_t = (step != 0.0f) ? std::max(0.0f, value - min) / step : 0.0f; // lower limit of 0.0f
#endif // ENABLE_PREVIEW_LAYER_TIME
const size_t color_max_idx = Range_Colors.size() - 1;
@ -901,7 +892,6 @@ void GCodeViewer::refresh(const GCodeProcessorResult& gcode_result, const std::v
}
}
#if ENABLE_PREVIEW_LAYER_TIME
for (size_t i = 0; i < gcode_result.print_statistics.modes.size(); ++i) {
m_layers_times[i] = gcode_result.print_statistics.modes[i].layers_times;
}
@ -911,7 +901,6 @@ void GCodeViewer::refresh(const GCodeProcessorResult& gcode_result, const std::v
m_extrusions.ranges.layer_time[i].update_from(time);
}
}
#endif // ENABLE_PREVIEW_LAYER_TIME
#if ENABLE_GCODE_VIEWER_STATISTICS
m_statistics.refresh_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start_time).count();
@ -960,11 +949,9 @@ void GCodeViewer::reset()
m_layers_z_range = { 0, 0 };
m_roles = std::vector<ExtrusionRole>();
m_print_statistics.reset();
#if ENABLE_PREVIEW_LAYER_TIME
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
m_layers_times[i] = std::vector<float>();
}
#endif // ENABLE_PREVIEW_LAYER_TIME
m_custom_gcode_per_print_z = std::vector<CustomGCode::Item>();
m_sequential_view.gcode_window.reset();
#if ENABLE_GCODE_VIEWER_STATISTICS
@ -2435,7 +2422,6 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
case EViewType::Feedrate: { color = m_extrusions.ranges.feedrate.get_color_at(path.feedrate); break; }
case EViewType::FanSpeed: { color = m_extrusions.ranges.fan_speed.get_color_at(path.fan_speed); break; }
case EViewType::Temperature: { color = m_extrusions.ranges.temperature.get_color_at(path.temperature); break; }
#if ENABLE_PREVIEW_LAYER_TIME
case EViewType::LayerTimeLinear:
case EViewType::LayerTimeLogarithmic: {
const Path::Sub_Path& sub_path = path.sub_paths.front();
@ -2454,7 +2440,6 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
}
break;
}
#endif // ENABLE_PREVIEW_LAYER_TIME
case EViewType::VolumetricRate: { color = m_extrusions.ranges.volumetric_rate.get_color_at(path.volumetric_rate); break; }
case EViewType::Tool: { color = m_tool_colors[path.extruder_id]; break; }
case EViewType::ColorPrint: {
@ -3464,14 +3449,9 @@ void GCodeViewer::render_legend(float& legend_height)
};
const PrintEstimatedStatistics::Mode& time_mode = m_print_statistics.modes[static_cast<size_t>(m_time_estimate_mode)];
#if ENABLE_PREVIEW_LAYER_TIME
bool show_estimated_time = time_mode.time > 0.0f && (m_view_type == EViewType::FeatureType ||
m_view_type == EViewType::LayerTimeLinear || m_view_type == EViewType::LayerTimeLogarithmic ||
(m_view_type == EViewType::ColorPrint && !time_mode.custom_gcode_times.empty()));
#else
bool show_estimated_time = time_mode.time > 0.0f && (m_view_type == EViewType::FeatureType ||
(m_view_type == EViewType::ColorPrint && !time_mode.custom_gcode_times.empty()));
#endif // ENABLE_PREVIEW_LAYER_TIME
const float icon_size = ImGui::GetTextLineHeight();
const float percent_bar_size = 2.0f * ImGui::GetTextLineHeight();
@ -3613,7 +3593,6 @@ void GCodeViewer::render_legend(float& legend_height)
}
};
#if ENABLE_PREVIEW_LAYER_TIME
auto append_time_range = [append_item](const Extrusions::Range& range, Extrusions::Range::EType type) {
auto append_range_item = [append_item](int i, float value) {
std::string str_value = get_time_dhms(value);
@ -3644,7 +3623,6 @@ void GCodeViewer::render_legend(float& legend_height)
}
}
};
#endif // ENABLE_PREVIEW_LAYER_TIME
auto append_headers = [&imgui](const std::array<std::string, 5>& texts, const std::array<float, 4>& offsets) {
size_t i = 0;
@ -3836,10 +3814,8 @@ void GCodeViewer::render_legend(float& legend_height)
_u8L("Fan speed (%)"),
_u8L("Temperature (°C)"),
_u8L("Volumetric flow rate (mm³/s)"),
#if ENABLE_PREVIEW_LAYER_TIME
_u8L("Layer time (linear)"),
_u8L("Layer time (logarithmic)"),
#endif // ENABLE_PREVIEW_LAYER_TIME
_u8L("Tool"),
_u8L("Color Print") }, view_type, ImGuiComboFlags_HeightLargest);
ImGui::PopStyleColor(2);
@ -3873,10 +3849,8 @@ void GCodeViewer::render_legend(float& legend_height)
case EViewType::FanSpeed: { imgui.title(_u8L("Fan Speed (%)")); break; }
case EViewType::Temperature: { imgui.title(_u8L("Temperature (°C)")); break; }
case EViewType::VolumetricRate: { imgui.title(_u8L("Volumetric flow rate (mm³/s)")); break; }
#if ENABLE_PREVIEW_LAYER_TIME
case EViewType::LayerTimeLinear: { imgui.title(_u8L("Layer time (linear)")); break; }
case EViewType::LayerTimeLogarithmic: { imgui.title(_u8L("Layer time (logarithmic)")); break; }
#endif // ENABLE_PREVIEW_LAYER_TIME
case EViewType::Tool: {
append_headers({ _u8L("Tool"), _u8L("Used filament") }, offsets);
break;
@ -3931,10 +3905,8 @@ void GCodeViewer::render_legend(float& legend_height)
case EViewType::FanSpeed: { append_range(m_extrusions.ranges.fan_speed, 0); break; }
case EViewType::Temperature: { append_range(m_extrusions.ranges.temperature, 0); break; }
case EViewType::VolumetricRate: { append_range(m_extrusions.ranges.volumetric_rate, 3); break; }
#if ENABLE_PREVIEW_LAYER_TIME
case EViewType::LayerTimeLinear: { append_time_range(m_extrusions.ranges.layer_time[static_cast<size_t>(m_time_estimate_mode)], Extrusions::Range::EType::Linear); break; }
case EViewType::LayerTimeLogarithmic: { append_time_range(m_extrusions.ranges.layer_time[static_cast<size_t>(m_time_estimate_mode)], Extrusions::Range::EType::Logarithmic); break; }
#endif // ENABLE_PREVIEW_LAYER_TIME
case EViewType::Tool: {
// shows only extruders actually used
for (unsigned char extruder_id : m_extruder_ids) {
@ -4275,6 +4247,14 @@ void GCodeViewer::render_legend(float& legend_height)
}
#endif // !ENABLE_PREVIEW_LAYOUT
auto add_strings_row_to_table = [&imgui](const std::string& col_1, const ImVec4& col_1_color, const std::string& col_2, const ImVec4& col_2_color) {
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
imgui.text_colored(col_1_color, col_1.c_str());
ImGui::TableSetColumnIndex(1);
imgui.text_colored(col_2_color, col_2.c_str());
};
// settings section
bool has_settings = false;
has_settings |= !m_settings_ids.print.empty();
@ -4289,47 +4269,37 @@ void GCodeViewer::render_legend(float& legend_height)
show_settings &= (m_view_type == EViewType::FeatureType || m_view_type == EViewType::Tool);
show_settings &= has_settings;
if (show_settings) {
auto calc_offset = [this]() {
float ret = 0.0f;
if (!m_settings_ids.printer.empty())
ret = std::max(ret, ImGui::CalcTextSize((_u8L("Printer") + std::string(":")).c_str()).x);
if (!m_settings_ids.print.empty())
ret = std::max(ret, ImGui::CalcTextSize((_u8L("Print settings") + std::string(":")).c_str()).x);
if (!m_settings_ids.filament.empty()) {
for (unsigned char i : m_extruder_ids) {
ret = std::max(ret, ImGui::CalcTextSize((_u8L("Filament") + " " + std::to_string(i + 1) + ":").c_str()).x);
}
}
if (ret > 0.0f)
ret += 2.0f * ImGui::GetStyle().ItemSpacing.x;
return ret;
};
ImGui::Spacing();
imgui.title(_u8L("Settings"));
float offset = calc_offset();
auto trim_text_if_needed = [](const std::string& txt) {
const float max_length = 250.0f;
const float length = ImGui::CalcTextSize(txt.c_str()).x;
if (length > max_length) {
const size_t new_len = txt.length() * max_length / length;
return txt.substr(0, new_len) + "...";
}
return txt;
};
if (!m_settings_ids.printer.empty()) {
imgui.text(_u8L("Printer") + ":");
ImGui::SameLine(offset);
imgui.text(m_settings_ids.printer);
}
if (!m_settings_ids.print.empty()) {
imgui.text(_u8L("Print settings") + ":");
ImGui::SameLine(offset);
imgui.text(m_settings_ids.print);
}
if (!m_settings_ids.filament.empty()) {
for (unsigned char i : m_extruder_ids) {
if (i < static_cast<unsigned char>(m_settings_ids.filament.size()) && !m_settings_ids.filament[i].empty()) {
std::string txt = _u8L("Filament");
txt += (m_extruder_ids.size() == 1) ? ":" : " " + std::to_string(i + 1);
imgui.text(txt);
ImGui::SameLine(offset);
imgui.text(m_settings_ids.filament[i]);
if (ImGui::BeginTable("Settings", 2)) {
if (!m_settings_ids.printer.empty())
add_strings_row_to_table(_u8L("Printer") + ":", ImGuiWrapper::COL_ORANGE_LIGHT,
trim_text_if_needed(m_settings_ids.printer), ImGuiWrapper::to_ImVec4(ColorRGBA::WHITE()));
if (!m_settings_ids.print.empty())
add_strings_row_to_table(_u8L("Print settings") + ":", ImGuiWrapper::COL_ORANGE_LIGHT,
trim_text_if_needed(m_settings_ids.print), ImGuiWrapper::to_ImVec4(ColorRGBA::WHITE()));
if (!m_settings_ids.filament.empty()) {
for (unsigned char i : m_extruder_ids) {
if (i < static_cast<unsigned char>(m_settings_ids.filament.size()) && !m_settings_ids.filament[i].empty()) {
std::string txt = _u8L("Filament");
txt += (m_extruder_ids.size() == 1) ? ":" : " " + std::to_string(i + 1);
add_strings_row_to_table(txt, ImGuiWrapper::COL_ORANGE_LIGHT,
trim_text_if_needed(m_settings_ids.filament[i]), ImGuiWrapper::to_ImVec4(ColorRGBA::WHITE()));
}
}
}
ImGui::EndTable();
}
}
@ -4363,33 +4333,24 @@ void GCodeViewer::render_legend(float& legend_height)
imgui.title(time_title + ":");
std::string first_str = _u8L("First layer");
std::string total_str = _u8L("Total");
if (ImGui::BeginTable("Times", 2)) {
if (!time_mode.layers_times.empty()) {
add_strings_row_to_table(_u8L("First layer") + ":", ImGuiWrapper::COL_ORANGE_LIGHT,
short_time(get_time_dhms(time_mode.layers_times.front())), ImGuiWrapper::to_ImVec4(ColorRGBA::WHITE()));
}
float max_len = 10.0f + ImGui::GetStyle().ItemSpacing.x;
if (time_mode.layers_times.empty())
max_len += ImGui::CalcTextSize(total_str.c_str()).x;
else
max_len += std::max(ImGui::CalcTextSize(first_str.c_str()).x, ImGui::CalcTextSize(total_str.c_str()).x);
add_strings_row_to_table(_u8L("Total") + ":", ImGuiWrapper::COL_ORANGE_LIGHT,
short_time(get_time_dhms(time_mode.time)), ImGuiWrapper::to_ImVec4(ColorRGBA::WHITE()));
if (!time_mode.layers_times.empty()) {
imgui.text(first_str + ":");
ImGui::SameLine(max_len);
imgui.text(short_time(get_time_dhms(time_mode.layers_times.front())));
ImGui::EndTable();
}
imgui.text(total_str + ":");
ImGui::SameLine(max_len);
imgui.text(short_time(get_time_dhms(time_mode.time)));
auto show_mode_button = [this, &imgui, can_show_mode_button](const wxString& label, PrintEstimatedStatistics::ETimeMode mode) {
if (can_show_mode_button(mode)) {
if (imgui.button(label)) {
m_time_estimate_mode = mode;
#if ENABLE_PREVIEW_LAYER_TIME
if (m_view_type == EViewType::LayerTimeLinear || m_view_type == EViewType::LayerTimeLogarithmic)
refresh_render_paths(false, false);
#endif // ENABLE_PREVIEW_LAYER_TIME
imgui.set_requires_extra_frame();
}
}

View File

@ -432,13 +432,11 @@ class GCodeViewer
{
struct Range
{
#if ENABLE_PREVIEW_LAYER_TIME
enum class EType : unsigned char
{
Linear,
Logarithmic
};
#endif // ENABLE_PREVIEW_LAYER_TIME
float min;
float max;
@ -454,13 +452,8 @@ class GCodeViewer
}
void reset() { min = FLT_MAX; max = -FLT_MAX; count = 0; }
#if ENABLE_PREVIEW_LAYER_TIME
float step_size(EType type = EType::Linear) const;
ColorRGBA get_color_at(float value, EType type = EType::Linear) const;
#else
float step_size() const { return (max - min) / (static_cast<float>(Range_Colors.size()) - 1.0f); }
ColorRGBA get_color_at(float value) const;
#endif // ENABLE_PREVIEW_LAYER_TIME
};
struct Ranges
@ -477,10 +470,8 @@ class GCodeViewer
Range volumetric_rate;
// Color mapping by extrusion temperature.
Range temperature;
#if ENABLE_PREVIEW_LAYER_TIME
// Color mapping by layer time.
std::array<Range, static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count)> layer_time;
#endif // ENABLE_PREVIEW_LAYER_TIME
void reset() {
height.reset();
@ -489,11 +480,9 @@ class GCodeViewer
fan_speed.reset();
volumetric_rate.reset();
temperature.reset();
#if ENABLE_PREVIEW_LAYER_TIME
for (auto& range : layer_time) {
range.reset();
}
#endif // ENABLE_PREVIEW_LAYER_TIME
}
};
@ -752,10 +741,8 @@ public:
FanSpeed,
Temperature,
VolumetricRate,
#if ENABLE_PREVIEW_LAYER_TIME
LayerTimeLinear,
LayerTimeLogarithmic,
#endif // ENABLE_PREVIEW_LAYER_TIME
Tool,
ColorPrint,
Count
@ -801,9 +788,7 @@ private:
#endif // ENABLE_GCODE_VIEWER_STATISTICS
GCodeProcessorResult::SettingsIds m_settings_ids;
std::array<SequentialRangeCap, 2> m_sequential_range_caps;
#if ENABLE_PREVIEW_LAYER_TIME
std::array<std::vector<float>, static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count)> m_layers_times;
#endif // ENABLE_PREVIEW_LAYER_TIME
std::vector<CustomGCode::Item> m_custom_gcode_per_print_z;

View File

@ -222,10 +222,8 @@ bool Preview::init(wxWindow* parent, Bed3D& bed, Model* model)
m_choice_view_type->Append(_L("Fan speed"));
m_choice_view_type->Append(_L("Temperature"));
m_choice_view_type->Append(_L("Volumetric flow rate"));
#if ENABLE_PREVIEW_LAYER_TIME
m_choice_view_type->Append(_L("Layer time (linear)"));
m_choice_view_type->Append(_L("Layer time (logarithmic)"));
#endif // ENABLE_PREVIEW_LAYER_TIME
m_choice_view_type->Append(_L("Tool"));
m_choice_view_type->Append(_L("Color Print"));
m_choice_view_type->SetSelection(0);