From 146554fe0d684fe448c7a79eb4c7fd6dce4a467e Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Tue, 29 Mar 2022 10:46:53 +0200 Subject: [PATCH] WIP FFF background slicing for a single object only: Moved the step enabled flag to step status. --- src/libslic3r/GCode.cpp | 8 +++- src/libslic3r/PrintBase.hpp | 77 +++++++++++++++++++++++-------------- src/libslic3r/SLAPrint.cpp | 3 -- 3 files changed, 54 insertions(+), 34 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index ad32f5facf..d07e4f61ec 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -736,9 +736,13 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessorResult* resu CNumericLocalesSetter locales_setter; // Does the file exist? If so, we hope that it is still valid. - if (print->is_step_done(psGCodeExport) && boost::filesystem::exists(boost::filesystem::path(path))) - return; + { + PrintStateBase::StateWithTimeStamp state = print->step_state_with_timestamp(psGCodeExport); + if (! state.enabled || (state.state == PrintStateBase::DONE && boost::filesystem::exists(boost::filesystem::path(path)))) + return; + } + // Enabled and either not done, or marked as done while the output file is missing. print->set_started(psGCodeExport); // check if any custom gcode contains keywords used by the gcode processor to diff --git a/src/libslic3r/PrintBase.hpp b/src/libslic3r/PrintBase.hpp index f91a70553b..fbadccfb13 100644 --- a/src/libslic3r/PrintBase.hpp +++ b/src/libslic3r/PrintBase.hpp @@ -39,9 +39,9 @@ public: // A new unique timestamp is being assigned to the step every time the step changes its state. struct StateWithTimeStamp { - StateWithTimeStamp() : state(INVALID), timestamp(0) {} - State state; - TimeStamp timestamp; + State state { INVALID }; + TimeStamp timestamp { 0 }; + bool enabled { true }; }; struct Warning @@ -112,10 +112,24 @@ public: return this->state_with_timestamp_unguarded(step).state == DONE; } + void enable_unguarded(StepType step, bool enable) { + m_state[step].enabled = enable; + } + + void enable_all_unguarded(bool enable) { + for (int istep = 0; istep < COUNT; ++ istep) + m_state[istep].enabled = enable; + } + + bool is_enabled_unguarded(StepType step) const { + return this->state_with_timestamp_unguarded(step).enabled; + } + // Set the step as started. Block on mutex while the Print / PrintObject / PrintRegion objects are being // modified by the UI thread. // This is necessary to block until the Print::apply() updates its state, which may // influence the processing step being entered. + // Returns false if the step is not enabled or if the step has already been finished (it is done). template bool set_started(StepType step, std::mutex &mtx, ThrowIfCanceled throw_if_canceled) { std::scoped_lock lock(mtx); @@ -134,9 +148,9 @@ public: // for (int i = 0; i < int(COUNT); ++ i) // assert(m_state[i].state != STARTED); #endif // NDEBUG - if (m_state[step].state == DONE) - return false; PrintStateBase::StateWithWarnings &state = m_state[step]; + if (! state.enabled || state.state == DONE) + return false; state.state = STARTED; state.timestamp = ++ g_last_timestamp; state.mark_warnings_non_current(); @@ -518,14 +532,14 @@ public: using PrintStepEnum = PrintStepEnumType; static constexpr const size_t PrintStepEnumSize = COUNT; - PrintBaseWithState() { m_stepmask.fill(true); } + PrintBaseWithState() = default; bool is_step_done(PrintStepEnum step) const { return m_state.is_done(step, this->state_mutex()); } PrintStateBase::StateWithTimeStamp step_state_with_timestamp(PrintStepEnum step) const { return m_state.state_with_timestamp(step, this->state_mutex()); } PrintStateBase::StateWithWarnings step_state_with_warnings(PrintStepEnum step) const { return m_state.state_with_warnings(step, this->state_mutex()); } protected: - bool set_started(PrintStepEnum step) { return m_stepmask[step] && m_state.set_started(step, this->state_mutex(), [this](){ this->throw_if_canceled(); }); } + bool set_started(PrintStepEnum step) { return m_state.set_started(step, this->state_mutex(), [this](){ this->throw_if_canceled(); }); } PrintStateBase::TimeStamp set_done(PrintStepEnum step) { std::pair status = m_state.set_done(step, this->state_mutex(), [this](){ this->throw_if_canceled(); }); if (status.second) @@ -559,12 +573,14 @@ protected: template void set_task_impl(const TaskParams ¶ms, std::vector &print_objects) { + static constexpr const auto PrintObjectStepEnumSize = int(PrintObject::PrintObjectStepEnumSize); + using PrintObjectStepEnum = typename PrintObject::PrintObjectStepEnum; // Grab the lock for the Print / PrintObject milestones. std::scoped_lock lock(this->state_mutex()); int n_object_steps = int(params.to_object_step) + 1; if (n_object_steps == 0) - n_object_steps = int(PrintObject::PrintObjectStepEnumSize); + n_object_steps = PrintObjectStepEnumSize; if (params.single_model_object.valid()) { // Find the print object to be processed with priority. @@ -579,11 +595,10 @@ protected: // Find out whether the priority print object is being currently processed. bool running = false; for (int istep = 0; istep < n_object_steps; ++ istep) { - if (! print_object->m_stepmask[size_t(istep)]) + if (! print_object->is_step_enabled_unguarded(PrintObjectStepEnum(istep))) // Step was skipped, cancel. break; - if (print_object->is_step_started_unguarded( - PrintObject::PrintObjectStepEnum(istep))) { + if (print_object->is_step_started_unguarded(PrintObjectStepEnum(istep))) { // No step was skipped, and a wanted step is being processed. Don't cancel. running = true; break; @@ -596,8 +611,8 @@ protected: if (params.single_model_instance_only) { // Suppress all the steps of other instances. for (PrintObject *po : print_objects) - for (size_t istep = 0; istep < PrintObject::PrintObjectStepEnumSize; ++ istep) - po->m_stepmask[istep] = false; + for (size_t istep = 0; istep < PrintObjectStepEnumSize; ++ istep) + po->enable_step_unguarded(PrintObjectStepEnum(istep), false); } else if (! running) { // Swap the print objects, so that the selected print_object is first in the row. // At this point the background processing must be stopped, so it is safe to shuffle print objects. @@ -606,19 +621,19 @@ protected: } // and set the steps for the current object. for (int istep = 0; istep < n_object_steps; ++ istep) - print_object->m_stepmask[size_t(istep)] = true; - for (int istep = n_object_steps; istep < int(PrintObject::PrintObjectStepEnumSize); ++ istep) - print_object->m_stepmask[size_t(istep)] = false; + print_object->enable_step_unguarded(PrintObjectStepEnum(istep), true); + for (int istep = n_object_steps; istep < PrintObjectStepEnumSize; ++ istep) + print_object->enable_step_unguarded(PrintObjectStepEnum(istep), false); } else { // Slicing all objects. bool running = false; for (PrintObject *print_object : print_objects) for (int istep = 0; istep < n_object_steps; ++ istep) { - if (! print_object->m_stepmask[size_t(istep)]) { + if (! print_object->is_step_enabled_unguarded(PrintObjectStepEnum(istep))) { // Step may have been skipped. Restart. goto loop_end; } - if (print_object->is_step_started_unguarded(PrintObject::PrintObjectStepEnum(istep))) { + if (print_object->is_step_started_unguarded(PrintObjectStepEnum(istep))) { // This step is running, and the state cannot be changed due to the this->state_mutex() being locked. // It is safe to manipulate m_stepmask of other PrintObjects and Print now. running = true; @@ -630,17 +645,17 @@ protected: this->call_cancel_callback(); for (PrintObject *po : print_objects) { for (int istep = 0; istep < n_object_steps; ++ istep) - po->m_stepmask[size_t(istep)] = true; - for (auto istep = size_t(n_object_steps); istep < PrintObject::PrintObjectStepEnumSize; ++ istep) - po->m_stepmask[istep] = false; + po->enable_step_unguarded(PrintObjectStepEnum(istep), true); + for (int istep = n_object_steps; istep < PrintObjectStepEnumSize; ++ istep) + po->enable_step_unguarded(PrintObjectStepEnum(istep), false); } } if (params.to_object_step != -1 || params.to_print_step != -1) { // Limit the print steps. size_t istep = (params.to_object_step != -1) ? 0 : size_t(params.to_print_step) + 1; - for (; istep < m_stepmask.size(); ++ istep) - m_stepmask[istep] = false; + for (; istep < PrintStepEnumSize; ++ istep) + m_state.enable_unguarded(PrintStepEnum(istep), false); } } @@ -649,14 +664,15 @@ protected: template void finalize_impl(std::vector &print_objects) { + // Grab the lock for the Print / PrintObject milestones. + std::scoped_lock lock(this->state_mutex()); for (auto *po : print_objects) - po->m_stepmask.fill(true); - m_stepmask.fill(true); + po->enable_all_steps_unguarded(true); + m_state.enable_all_unguarded(true); } private: PrintState m_state; - std::array m_stepmask; }; template @@ -675,10 +691,10 @@ public: PrintStateBase::StateWithWarnings step_state_with_warnings(PrintObjectStepEnum step) const { return m_state.state_with_warnings(step, PrintObjectBase::state_mutex(m_print)); } protected: - PrintObjectBaseWithState(PrintType *print, ModelObject *model_object) : PrintObjectBase(model_object), m_print(print) { m_stepmask.fill(true); } + PrintObjectBaseWithState(PrintType *print, ModelObject *model_object) : PrintObjectBase(model_object), m_print(print) {} bool set_started(PrintObjectStepEnum step) - { return m_stepmask[step] && m_state.set_started(step, PrintObjectBase::state_mutex(m_print), [this](){ this->throw_if_canceled(); }); } + { return m_state.set_started(step, PrintObjectBase::state_mutex(m_print), [this](){ this->throw_if_canceled(); }); } PrintStateBase::TimeStamp set_done(PrintObjectStepEnum step) { std::pair status = m_state.set_done(step, PrintObjectBase::state_mutex(m_print), [this](){ this->throw_if_canceled(); }); if (status.second) @@ -699,6 +715,10 @@ protected: bool is_step_started_unguarded(PrintObjectStepEnum step) const { return m_state.is_started_unguarded(step); } bool is_step_done_unguarded(PrintObjectStepEnum step) const { return m_state.is_done_unguarded(step); } + bool is_step_enabled_unguarded(PrintObjectStepEnum step) const { return m_state.is_enabled_unguarded(step); } + void enable_step_unguarded(PrintObjectStepEnum step, bool enable) { m_state.enable_unguarded(step, enable); } + void enable_all_steps_unguarded(bool enable) { m_state.enable_all_unguarded(enable); } + // Add a slicing warning to the active PrintObject step and send a status notification. // This method could be called multiple times between this->set_started() and this->set_done(). void active_step_add_warning(PrintStateBase::WarningLevel warning_level, const std::string &message, int message_id = 0) { @@ -714,7 +734,6 @@ protected: friend PrintType; PrintType *m_print; - std::array m_stepmask; private: PrintState m_state; diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 3432d1db73..203393e9cc 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -661,9 +661,6 @@ void SLAPrint::process() apply_steps_on_objects(level1_obj_steps); apply_steps_on_objects(level2_obj_steps); - // this would disable the rasterization step - // std::fill(m_stepmask.begin(), m_stepmask.end(), false); - st = Steps::max_objstatus; for(SLAPrintStep currentstep : print_steps) { throw_if_canceled();