[Bf-blender-cvs] [4a3dc6233e6] temp-compositor-scheduling: Fix: Loosing Workerthreads During Execution.
Jeroen Bakker
noreply at git.blender.org
Fri Apr 2 09:35:51 CEST 2021
Commit: 4a3dc6233e64e8461fdc0368052d355f8710678c
Author: Jeroen Bakker
Date: Fri Apr 2 09:35:13 2021 +0200
Branches: temp-compositor-scheduling
https://developer.blender.org/rB4a3dc6233e64e8461fdc0368052d355f8710678c
Fix: Loosing Workerthreads During Execution.
===================================================================
M source/blender/compositor/COM_defines.h
M source/blender/compositor/intern/COM_ExecutionSystem.cc
M source/blender/compositor/intern/COM_WorkScheduler.cc
===================================================================
diff --git a/source/blender/compositor/COM_defines.h b/source/blender/compositor/COM_defines.h
index 590234d0562..9e3f99cd49d 100644
--- a/source/blender/compositor/COM_defines.h
+++ b/source/blender/compositor/COM_defines.h
@@ -83,18 +83,18 @@ enum class CompositorPriority {
enum class eSchedulingMode {
/**
- * Scheduling mode where inputs (render layers/images) are scheduled and when finished the next
- * work will be scheduled where all] inputs are finished.
+ * Input based scheduling mode. Scheduling starts from input nodes. When a work package is
+ * finished, other work packages are scheduled where all inputs have been executed..
*/
InputToOutput,
/**
* Scheduling mode where outputs are scheduled when all its inputs have been completed. When
- * inputs aren't completed it tries to schedule these inputs.
+ * inputs aren't completed it tries to schedule these inputs recursivly.
*/
OutputToInput,
};
-static constexpr eSchedulingMode COM_SCHEDULING_MODE = eSchedulingMode::InputToOutput;
+static constexpr eSchedulingMode COM_SCHEDULING_MODE = eSchedulingMode::OutputToInput;
/**
* \brief the execution state of a chunk in an ExecutionGroup
diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cc b/source/blender/compositor/intern/COM_ExecutionSystem.cc
index 88bb313f095..cb2c05c5217 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystem.cc
+++ b/source/blender/compositor/intern/COM_ExecutionSystem.cc
@@ -270,19 +270,42 @@ void ExecutionSystem::execute()
}
}
+static bool is_completed(Vector<ExecutionGroup *> &groups)
+{
+ for (ExecutionGroup *group : groups) {
+ for (WorkPackage &work_package : group->get_work_packages()) {
+ if (work_package.state != eChunkExecutionState::Executed) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+static void wait_for_completion(Vector<ExecutionGroup *> &groups)
+{
+ /* Todo: check for break! */
+ while (!is_completed(groups)) {
+ PIL_sleep_ms(100);
+ }
+}
+
void ExecutionSystem::execute_groups(CompositorPriority priority)
{
switch (COM_SCHEDULING_MODE) {
case eSchedulingMode::InputToOutput: {
const bNodeTree *bnodetree = this->m_context.getbNodeTree();
+ Vector<ExecutionGroup *> groups;
for (ExecutionGroup *execution_group : m_groups) {
if (execution_group->get_flags().is_output &&
execution_group->getRenderPriority() == priority) {
execution_group->set_btree(bnodetree);
mark_priority(execution_group->get_work_packages(), priority);
+ groups.append(execution_group);
}
}
schedule_root_work_packages(m_groups);
+ wait_for_completion(groups);
break;
}
case eSchedulingMode::OutputToInput: {
diff --git a/source/blender/compositor/intern/COM_WorkScheduler.cc b/source/blender/compositor/intern/COM_WorkScheduler.cc
index 209e39255af..2fdca10e67d 100644
--- a/source/blender/compositor/intern/COM_WorkScheduler.cc
+++ b/source/blender/compositor/intern/COM_WorkScheduler.cc
@@ -66,8 +66,15 @@ constexpr bool COM_is_opencl_enabled()
return COM_threading_model() != ThreadingModel::SingleThreaded;
}
+enum class eWorkSchedulerState {
+ Idle,
+ Running,
+ Stopping,
+};
+
static ThreadLocal(CPUDevice *) g_thread_device;
static struct {
+ eWorkSchedulerState state = eWorkSchedulerState::Idle;
struct {
/** \brief list of all CPUDevices. for every hardware thread an instance of CPUDevice is
* created
@@ -114,13 +121,14 @@ static void CL_CALLBACK clContextError(const char *errinfo,
static void *thread_execute_gpu(void *data)
{
- Device *device = (Device *)data;
+ OpenCLDevice *device = (OpenCLDevice *)data;
WorkPackage *work;
-
- while ((work = (WorkPackage *)BLI_thread_queue_pop(g_work_scheduler.opencl.queue))) {
- device->execute(work);
+ while (g_work_scheduler.state == eWorkSchedulerState::Running) {
+ work = (WorkPackage *)BLI_thread_queue_pop(g_work_scheduler.opencl.queue);
+ if (work) {
+ device->execute(work);
+ }
}
-
return nullptr;
}
@@ -318,10 +326,12 @@ static void *threading_model_queue_execute(void *data)
CPUDevice *device = (CPUDevice *)data;
WorkPackage *work;
BLI_thread_local_set(g_thread_device, device);
- while ((work = (WorkPackage *)BLI_thread_queue_pop(g_work_scheduler.queue.queue))) {
- device->execute(work);
+ while (g_work_scheduler.state == eWorkSchedulerState::Running) {
+ work = (WorkPackage *)BLI_thread_queue_pop(g_work_scheduler.queue.queue);
+ if (work) {
+ device->execute(work);
+ }
}
-
return nullptr;
}
@@ -432,6 +442,10 @@ static void threading_model_task_stop()
void WorkScheduler::schedule(WorkPackage *package)
{
+ BLI_assert(g_work_scheduler.state != eWorkSchedulerState::Idle);
+ if (g_work_scheduler.state == eWorkSchedulerState::Stopping) {
+ return;
+ }
// TODO: race condition..... we should add a mutex to the work package.
if (package->state != eChunkExecutionState::NotScheduled) {
return;
@@ -464,6 +478,9 @@ void WorkScheduler::schedule(WorkPackage *package)
void WorkScheduler::start(CompositorContext &context)
{
+ BLI_assert(g_work_scheduler.state == eWorkSchedulerState::Idle);
+ g_work_scheduler.state = eWorkSchedulerState::Running;
+
if (COM_is_opencl_enabled()) {
opencl_start(context);
}
@@ -485,6 +502,7 @@ void WorkScheduler::start(CompositorContext &context)
void WorkScheduler::finish()
{
+ BLI_assert(g_work_scheduler.state == eWorkSchedulerState::Running);
if (COM_is_opencl_enabled()) {
opencl_finish();
}
@@ -506,6 +524,8 @@ void WorkScheduler::finish()
void WorkScheduler::stop()
{
+ BLI_assert(g_work_scheduler.state == eWorkSchedulerState::Running);
+ g_work_scheduler.state = eWorkSchedulerState::Stopping;
if (COM_is_opencl_enabled()) {
opencl_stop();
}
@@ -523,6 +543,7 @@ void WorkScheduler::stop()
threading_model_task_stop();
break;
}
+ g_work_scheduler.state = eWorkSchedulerState::Idle;
}
bool WorkScheduler::has_gpu_devices()
@@ -535,6 +556,7 @@ bool WorkScheduler::has_gpu_devices()
void WorkScheduler::initialize(bool use_opencl, int num_cpu_threads)
{
+ g_work_scheduler.state = eWorkSchedulerState::Idle;
if (COM_is_opencl_enabled()) {
opencl_initialize(use_opencl);
}
@@ -556,6 +578,7 @@ void WorkScheduler::initialize(bool use_opencl, int num_cpu_threads)
void WorkScheduler::deinitialize()
{
+ BLI_assert(g_work_scheduler.state == eWorkSchedulerState::Idle);
if (COM_is_opencl_enabled()) {
opencl_deinitialize();
}
More information about the Bf-blender-cvs
mailing list