[Bf-blender-cvs] [1657fa039dc] master: Compositor: Fix crash when executing works in constant folding

Manuel Castilla noreply at git.blender.org
Wed Jul 7 01:22:58 CEST 2021


Commit: 1657fa039dcbf969b5e514ab77d72880817a7f9e
Author: Manuel Castilla
Date:   Wed Jul 7 00:06:46 2021 +0200
Branches: master
https://developer.blender.org/rB1657fa039dcbf969b5e514ab77d72880817a7f9e

Compositor: Fix crash when executing works in constant folding

Work scheduler needed initialization and execution models are
not created during constant folding. This moves work execution
method to execution system.

===================================================================

M	source/blender/compositor/intern/COM_ConstantFolder.cc
M	source/blender/compositor/intern/COM_ExecutionModel.cc
M	source/blender/compositor/intern/COM_ExecutionModel.h
M	source/blender/compositor/intern/COM_ExecutionSystem.cc
M	source/blender/compositor/intern/COM_ExecutionSystem.h
M	source/blender/compositor/intern/COM_FullFrameExecutionModel.cc
M	source/blender/compositor/intern/COM_FullFrameExecutionModel.h
M	source/blender/compositor/intern/COM_WorkScheduler.cc
M	source/blender/compositor/intern/COM_WorkScheduler.h

===================================================================

diff --git a/source/blender/compositor/intern/COM_ConstantFolder.cc b/source/blender/compositor/intern/COM_ConstantFolder.cc
index 0612c25cf94..8e25ef03aba 100644
--- a/source/blender/compositor/intern/COM_ConstantFolder.cc
+++ b/source/blender/compositor/intern/COM_ConstantFolder.cc
@@ -23,6 +23,7 @@
 #include "COM_SetColorOperation.h"
 #include "COM_SetValueOperation.h"
 #include "COM_SetVectorOperation.h"
+#include "COM_WorkScheduler.h"
 
 namespace blender::compositor {
 
@@ -147,6 +148,7 @@ Vector<ConstantOperation *> ConstantFolder::try_fold_operations(Span<NodeOperati
  */
 int ConstantFolder::fold_operations()
 {
+  WorkScheduler::start(operations_builder_.context());
   Vector<ConstantOperation *> last_folds = try_fold_operations(
       operations_builder_.get_operations());
   int folds_count = last_folds.size();
@@ -158,6 +160,7 @@ int ConstantFolder::fold_operations()
     last_folds = try_fold_operations(ops_to_fold);
     folds_count += last_folds.size();
   }
+  WorkScheduler::stop();
 
   delete_constant_buffers();
 
diff --git a/source/blender/compositor/intern/COM_ExecutionModel.cc b/source/blender/compositor/intern/COM_ExecutionModel.cc
index 4d7f62e091b..b75b277e92c 100644
--- a/source/blender/compositor/intern/COM_ExecutionModel.cc
+++ b/source/blender/compositor/intern/COM_ExecutionModel.cc
@@ -39,10 +39,4 @@ ExecutionModel::ExecutionModel(CompositorContext &context, Span<NodeOperation *>
   border_.render_border = &rd->border;
 }
 
-bool ExecutionModel::is_breaked() const
-{
-  const bNodeTree *btree = context_.getbNodeTree();
-  return btree->test_break(btree->tbh);
-}
-
 }  // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_ExecutionModel.h b/source/blender/compositor/intern/COM_ExecutionModel.h
index 9e8466b9282..452861ae4be 100644
--- a/source/blender/compositor/intern/COM_ExecutionModel.h
+++ b/source/blender/compositor/intern/COM_ExecutionModel.h
@@ -67,15 +67,6 @@ class ExecutionModel {
 
   virtual void execute(ExecutionSystem &exec_system) = 0;
 
-  virtual void execute_work(const rcti &UNUSED(work_rect),
-                            std::function<void(const rcti &split_rect)> UNUSED(work_func))
-  {
-    BLI_assert(!"Method not supported by current execution model");
-  }
-
- protected:
-  bool is_breaked() const;
-
 #ifdef WITH_CXX_GUARDEDALLOC
   MEM_CXX_CLASS_ALLOC_FUNCS("COM:BaseExecutionModel")
 #endif
diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cc b/source/blender/compositor/intern/COM_ExecutionSystem.cc
index 07f4082573c..dfcf76cdd0a 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystem.cc
+++ b/source/blender/compositor/intern/COM_ExecutionSystem.cc
@@ -63,6 +63,9 @@ ExecutionSystem::ExecutionSystem(RenderData *rd,
   this->m_context.setViewSettings(viewSettings);
   this->m_context.setDisplaySettings(displaySettings);
 
+  BLI_mutex_init(&work_mutex_);
+  BLI_condition_init(&work_finished_cond_);
+
   {
     NodeOperationBuilder builder(&m_context, editingtree, this);
     builder.convertToOperations(this);
@@ -83,6 +86,9 @@ ExecutionSystem::ExecutionSystem(RenderData *rd,
 
 ExecutionSystem::~ExecutionSystem()
 {
+  BLI_condition_end(&work_finished_cond_);
+  BLI_mutex_end(&work_mutex_);
+
   delete execution_model_;
 
   for (NodeOperation *operation : m_operations) {
@@ -109,10 +115,74 @@ void ExecutionSystem::execute()
   execution_model_->execute(*this);
 }
 
+/**
+ * Multi-threadedly execute given work function passing work_rect splits as argument.
+ */
 void ExecutionSystem::execute_work(const rcti &work_rect,
                                    std::function<void(const rcti &split_rect)> work_func)
 {
-  execution_model_->execute_work(work_rect, work_func);
+  if (is_breaked()) {
+    return;
+  }
+
+  /* Split work vertically to maximize continuous memory. */
+  const int work_height = BLI_rcti_size_y(&work_rect);
+  const int num_sub_works = MIN2(WorkScheduler::get_num_cpu_threads(), work_height);
+  const int split_height = num_sub_works == 0 ? 0 : work_height / num_sub_works;
+  int remaining_height = work_height - split_height * num_sub_works;
+
+  Vector<WorkPackage> sub_works(num_sub_works);
+  int sub_work_y = work_rect.ymin;
+  int num_sub_works_finished = 0;
+  for (int i = 0; i < num_sub_works; i++) {
+    int sub_work_height = split_height;
+
+    /* Distribute remaining height between sub-works. */
+    if (remaining_height > 0) {
+      sub_work_height++;
+      remaining_height--;
+    }
+
+    WorkPackage &sub_work = sub_works[i];
+    sub_work.type = eWorkPackageType::CustomFunction;
+    sub_work.execute_fn = [=, &work_func, &work_rect]() {
+      if (is_breaked()) {
+        return;
+      }
+      rcti split_rect;
+      BLI_rcti_init(
+          &split_rect, work_rect.xmin, work_rect.xmax, sub_work_y, sub_work_y + sub_work_height);
+      work_func(split_rect);
+    };
+    sub_work.executed_fn = [&]() {
+      BLI_mutex_lock(&work_mutex_);
+      num_sub_works_finished++;
+      if (num_sub_works_finished == num_sub_works) {
+        BLI_condition_notify_one(&work_finished_cond_);
+      }
+      BLI_mutex_unlock(&work_mutex_);
+    };
+    WorkScheduler::schedule(&sub_work);
+    sub_work_y += sub_work_height;
+  }
+  BLI_assert(sub_work_y == work_rect.ymax);
+
+  WorkScheduler::finish();
+
+  /* Ensure all sub-works finished.
+   * TODO: This a workaround for WorkScheduler::finish() not waiting all works on queue threading
+   * model. Sync code should be removed once it's fixed. */
+  BLI_mutex_lock(&work_mutex_);
+  if (num_sub_works_finished < num_sub_works) {
+    BLI_condition_wait(&work_finished_cond_, &work_mutex_);
+  }
+  BLI_mutex_unlock(&work_mutex_);
+}
+
+bool ExecutionSystem::is_breaked() const
+{
+  const bNodeTree *btree = m_context.getbNodeTree();
+  return btree->test_break(btree->tbh);
 }
 
 }  // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.h b/source/blender/compositor/intern/COM_ExecutionSystem.h
index e106209651c..38c3432a8ec 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystem.h
+++ b/source/blender/compositor/intern/COM_ExecutionSystem.h
@@ -150,7 +150,9 @@ class ExecutionSystem {
    */
   ExecutionModel *execution_model_;
 
- private:  // methods
+  ThreadMutex work_mutex_;
+  ThreadCondition work_finished_cond_;
+
  public:
   /**
    * \brief Create a new ExecutionSystem and initialize it with the
@@ -199,6 +201,8 @@ class ExecutionSystem {
 
   void execute_work(const rcti &work_rect, std::function<void(const rcti &split_rect)> work_func);
 
+  bool is_breaked() const;
+
  private:
   /* allow the DebugInfo class to look at internals */
   friend class DebugInfo;
diff --git a/source/blender/compositor/intern/COM_FullFrameExecutionModel.cc b/source/blender/compositor/intern/COM_FullFrameExecutionModel.cc
index c61512ef49e..3b0a9172871 100644
--- a/source/blender/compositor/intern/COM_FullFrameExecutionModel.cc
+++ b/source/blender/compositor/intern/COM_FullFrameExecutionModel.cc
@@ -35,24 +35,13 @@ FullFrameExecutionModel::FullFrameExecutionModel(CompositorContext &context,
                                                  Span<NodeOperation *> operations)
     : ExecutionModel(context, operations),
       active_buffers_(shared_buffers),
-      num_operations_finished_(0),
-      work_mutex_(),
-      work_finished_cond_()
+      num_operations_finished_(0)
 {
   priorities_.append(eCompositorPriority::High);
   if (!context.isFastCalculation()) {
     priorities_.append(eCompositorPriority::Medium);
     priorities_.append(eCompositorPriority::Low);
   }
-
-  BLI_mutex_init(&work_mutex_);
-  BLI_condition_init(&work_finished_cond_);
-}
-
-FullFrameExecutionModel::~FullFrameExecutionModel()
-{
-  BLI_condition_end(&work_finished_cond_);
-  BLI_mutex_end(&work_mutex_);
 }
 
 void FullFrameExecutionModel::execute(ExecutionSystem &exec_system)
@@ -263,70 +252,6 @@ void FullFrameExecutionModel::get_output_render_area(NodeOperation *output_op, r
   }
 }
 
-/**
- * Multi-threadedly execute given work function passing work_rect splits as argument.
- */
-void FullFrameExecutionModel::execute_work(const rcti &work_rect,
-                                           std::function<void(const rcti &split_rect)> work_func)
-{
-  if (is_breaked()) {
-    return;
-  }
-
-  /* Split work vertically to maximize continuous memory. */
-  const int work_height = BLI_rcti_size_y(&work_rect);
-  const int num_sub_works = MIN2(WorkScheduler::get_num_cpu_threads(), work_height);
-  const int split_height = num_sub_works == 0 ? 0 : work_height / num_sub_works;
-  int remaining_height = work_height - split_height * num_sub_works;
-
-  Vector<WorkPackage> sub_works(num_sub_works);
-  int sub_work_y = work_rect.ymin;
-  int num_sub_works_finished = 0;
-  for (int i = 0; i < num_sub_works; i++) {
-    int sub_work_height = split_height;
-
-    /* Distribute remaining height between sub-works. */
-    if (remaining_height > 0) {
-      sub_work_height++;
-      remaining_height--;
-    }
-
-    WorkPackage &sub_work = sub_works[i];
-    sub_work.type = eWorkPackageType::CustomFunction;
-    sub_work.execute_fn = [=, &work_func, &work_rect]() {
-      if (is_breaked()) {
-        return;
-      }
-      rcti split_rect;
-      BLI_rcti_init(
-          &split_rect, work_rect.xmin, work_rect.xmax, sub_work_y, sub_work_y + sub_work_height);
-      work_func(split_rect);
-    };
-    sub_work.executed_fn = [&]() {
-      BLI_mutex_lock(&work_mutex_);
-      num_sub_works_finished++;
-      if (num_sub_works_finished == num_sub_works) {
-        BLI_condition_notify_one(&work_finished_cond_);
-      }
-      BLI_mutex_unlock(&work_mutex_);
-    };
-    WorkScheduler::schedule(&sub_work);
-    sub_work_y += sub_work_height;
-  }
-  BLI_assert(sub_work_y == work_rect.ymax);
-
-  WorkScheduler::finish();
-
-  /* Ensure all sub-works finished.
-   * TODO: This a workaround for WorkScheduler::finish() not waiting all works on queue threading
-   * model. Sync code should be removed once it's fixed. */
-  BLI_mutex_lock(&work_mutex_);
-  if (num_sub_works_finished < num_sub_works) {
-    BLI_condition_wait(&work_finished_cond_, &work_mutex_);
-  }
-  BLI_m

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list