[Bf-blender-cvs] [f996dfc35bd] temp-compositor-scheduling: Compositor: Scheduling.
Jeroen Bakker
noreply at git.blender.org
Thu Apr 1 15:09:36 CEST 2021
Commit: f996dfc35bdb0dc9254fd109a453cce2db5f0393
Author: Jeroen Bakker
Date: Wed Mar 31 16:10:40 2021 +0200
Branches: temp-compositor-scheduling
https://developer.blender.org/rBf996dfc35bdb0dc9254fd109a453cce2db5f0393
Compositor: Scheduling.
===================================================================
M source/blender/compositor/COM_defines.h
M source/blender/compositor/intern/COM_CPUDevice.cc
M source/blender/compositor/intern/COM_ExecutionGroup.cc
M source/blender/compositor/intern/COM_ExecutionGroup.h
M source/blender/compositor/intern/COM_ExecutionSystem.cc
M source/blender/compositor/intern/COM_ExecutionSystem.h
M source/blender/compositor/intern/COM_NodeOperationBuilder.cc
M source/blender/compositor/intern/COM_OpenCLDevice.cc
M source/blender/compositor/intern/COM_WorkPackage.cc
M source/blender/compositor/intern/COM_WorkPackage.h
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 5a5868f1909..df92b09e063 100644
--- a/source/blender/compositor/COM_defines.h
+++ b/source/blender/compositor/COM_defines.h
@@ -79,6 +79,21 @@ enum class CompositorPriority {
Low = 0,
};
+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.
+ */
+ 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.
+ */
+ OutputToInput,
+};
+static constexpr eSchedulingMode COM_SCHEDULING_MODE = eSchedulingMode::InputToOutput;
+
/**
* \brief the execution state of a chunk in an ExecutionGroup
* \ingroup Execution
diff --git a/source/blender/compositor/intern/COM_CPUDevice.cc b/source/blender/compositor/intern/COM_CPUDevice.cc
index 29a82bec636..fc2543c807c 100644
--- a/source/blender/compositor/intern/COM_CPUDevice.cc
+++ b/source/blender/compositor/intern/COM_CPUDevice.cc
@@ -35,6 +35,7 @@ void CPUDevice::execute(WorkPackage *work_package)
executionGroup->getOutputOperation()->executeRegion(&work_package->rect, chunkNumber);
executionGroup->finalizeChunkExecution(chunkNumber, nullptr);
+ work_package->state = eChunkExecutionState::Executed;
}
} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.cc b/source/blender/compositor/intern/COM_ExecutionGroup.cc
index 71c22e3b473..89c65cf0a53 100644
--- a/source/blender/compositor/intern/COM_ExecutionGroup.cc
+++ b/source/blender/compositor/intern/COM_ExecutionGroup.cc
@@ -48,8 +48,36 @@
namespace blender::compositor {
-ExecutionGroup::ExecutionGroup()
+std::ostream &operator<<(std::ostream &os, const ExecutionGroupFlags &flags)
{
+ os << flags.str();
+ return os;
+}
+
+std::string ExecutionGroupFlags::str() const
+{
+ std::stringstream ss;
+ if (initialized) {
+ ss << "init,";
+ }
+ if (is_output) {
+ ss << "output,";
+ }
+ if (complex) {
+ ss << "complex,";
+ }
+ if (open_cl) {
+ ss << "open_cl,";
+ }
+ if (single_threaded) {
+ ss << "single_threaded,";
+ }
+ return ss.str();
+}
+
+ExecutionGroup::ExecutionGroup(int id)
+{
+ m_id = id;
this->m_bTree = nullptr;
this->m_height = 0;
this->m_width = 0;
@@ -57,11 +85,17 @@ ExecutionGroup::ExecutionGroup()
this->m_x_chunks_len = 0;
this->m_y_chunks_len = 0;
this->m_chunks_len = 0;
- this->m_chunks_finished = 0;
BLI_rcti_init(&this->m_viewerBorder, 0, 0, 0, 0);
this->m_executionStartTime = 0;
}
+std::ostream &operator<<(std::ostream &os, const ExecutionGroup &execution_group)
+{
+ os << "ExecutionGroup(id=" << execution_group.get_id()
+ << ",flags=" << execution_group.get_flags() << ")";
+ return os;
+}
+
CompositorPriority ExecutionGroup::getRenderPriority()
{
return this->getOutputOperation()->getRenderPriority();
@@ -290,6 +324,7 @@ blender::Array<unsigned int> ExecutionGroup::get_execution_order() const
* this method is called for the top execution groups. containing the compositor node or the
* preview node or the viewer node)
*/
+/* TODO: Move to execution system. Might need to split... */
void ExecutionGroup::execute(ExecutionSystem *graph)
{
const CompositorContext &context = graph->getContext();
@@ -329,12 +364,10 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
index < this->m_chunks_len && numberEvaluated < maxNumberEvaluated;
index++) {
chunk_index = chunk_order[index];
- int yChunk = chunk_index / this->m_x_chunks_len;
- int xChunk = chunk_index - (yChunk * this->m_x_chunks_len);
- const WorkPackage &work_package = m_work_packages[chunk_index];
+ WorkPackage &work_package = m_work_packages[chunk_index];
switch (work_package.state) {
case eChunkExecutionState::NotScheduled: {
- scheduleChunkWhenPossible(graph, xChunk, yChunk);
+ scheduleChunkWhenPossible(graph, work_package);
finished = false;
startEvaluated = true;
numberEvaluated++;
@@ -397,11 +430,15 @@ MemoryBuffer *ExecutionGroup::constructConsolidatedMemoryBuffer(MemoryProxy &mem
void ExecutionGroup::finalizeChunkExecution(int chunkNumber, MemoryBuffer **memoryBuffers)
{
WorkPackage &work_package = m_work_packages[chunkNumber];
- if (work_package.state == eChunkExecutionState::Scheduled) {
- work_package.state = eChunkExecutionState::Executed;
+ for (WorkPackage *child : work_package.children) {
+ if (child->parent_finished()) {
+ if (COM_SCHEDULING_MODE == eSchedulingMode::InputToOutput) {
+ /* TODO: Do not schedule lower priority children. */
+ WorkScheduler::schedule(child);
+ }
+ }
}
- atomic_add_and_fetch_u(&this->m_chunks_finished, 1);
if (memoryBuffers) {
for (unsigned int index = 0; index < this->m_max_read_buffer_offset; index++) {
MemoryBuffer *buffer = memoryBuffers[index];
@@ -415,6 +452,7 @@ void ExecutionGroup::finalizeChunkExecution(int chunkNumber, MemoryBuffer **memo
MEM_freeN(memoryBuffers);
}
if (this->m_bTree) {
+ atomic_add_and_fetch_u(&this->m_chunks_finished, 1);
// status report is only performed for top level Execution Groups.
float progress = this->m_chunks_finished;
progress /= this->m_chunks_len;
@@ -474,65 +512,9 @@ MemoryBuffer *ExecutionGroup::allocateOutputBuffer(rcti &rect)
return nullptr;
}
-bool ExecutionGroup::scheduleAreaWhenPossible(ExecutionSystem *graph, rcti *area)
-{
- if (this->m_flags.single_threaded) {
- return scheduleChunkWhenPossible(graph, 0, 0);
- }
- // find all chunks inside the rect
- // determine minxchunk, minychunk, maxxchunk, maxychunk where x and y are chunknumbers
-
- int indexx, indexy;
- int minx = max_ii(area->xmin - m_viewerBorder.xmin, 0);
- int maxx = min_ii(area->xmax - m_viewerBorder.xmin, m_viewerBorder.xmax - m_viewerBorder.xmin);
- int miny = max_ii(area->ymin - m_viewerBorder.ymin, 0);
- int maxy = min_ii(area->ymax - m_viewerBorder.ymin, m_viewerBorder.ymax - m_viewerBorder.ymin);
- int minxchunk = minx / (int)m_chunkSize;
- int maxxchunk = (maxx + (int)m_chunkSize - 1) / (int)m_chunkSize;
- int minychunk = miny / (int)m_chunkSize;
- int maxychunk = (maxy + (int)m_chunkSize - 1) / (int)m_chunkSize;
- minxchunk = max_ii(minxchunk, 0);
- minychunk = max_ii(minychunk, 0);
- maxxchunk = min_ii(maxxchunk, (int)m_x_chunks_len);
- maxychunk = min_ii(maxychunk, (int)m_y_chunks_len);
-
- bool result = true;
- for (indexx = minxchunk; indexx < maxxchunk; indexx++) {
- for (indexy = minychunk; indexy < maxychunk; indexy++) {
- if (!scheduleChunkWhenPossible(graph, indexx, indexy)) {
- result = false;
- }
- }
- }
-
- return result;
-}
-
-bool ExecutionGroup::scheduleChunk(unsigned int chunkNumber)
+bool ExecutionGroup::scheduleChunkWhenPossible(ExecutionSystem *graph, WorkPackage &work_package)
{
- WorkPackage &work_package = m_work_packages[chunkNumber];
- if (work_package.state == eChunkExecutionState::NotScheduled) {
- work_package.state = eChunkExecutionState::Scheduled;
- WorkScheduler::schedule(&work_package);
- return true;
- }
- return false;
-}
-
-bool ExecutionGroup::scheduleChunkWhenPossible(ExecutionSystem *graph,
- const int chunk_x,
- const int chunk_y)
-{
- if (chunk_x < 0 || chunk_x >= (int)this->m_x_chunks_len) {
- return true;
- }
- if (chunk_y < 0 || chunk_y >= (int)this->m_y_chunks_len) {
- return true;
- }
-
// Check if chunk is already executed or scheduled and not yet executed.
- const int chunk_index = chunk_y * this->m_x_chunks_len + chunk_x;
- WorkPackage &work_package = m_work_packages[chunk_index];
if (work_package.state == eChunkExecutionState::Executed) {
return true;
}
@@ -541,21 +523,14 @@ bool ExecutionGroup::scheduleChunkWhenPossible(ExecutionSystem *graph,
}
bool can_be_executed = true;
- rcti area;
-
- for (ReadBufferOperation *read_operation : m_read_operations) {
- BLI_rcti_init(&area, 0, 0, 0, 0);
- MemoryProxy *memory_proxy = read_operation->getMemoryProxy();
- determineDependingAreaOfInterest(&work_package.rect, read_operation, &area);
- ExecutionGroup *group = memory_proxy->getExecutor();
-
- if (!group->scheduleAreaWhenPossible(graph, &area)) {
+ for (WorkPackage *parent : work_package.parents) {
+ if (!parent->execution_group->scheduleChunkWhenPossible(graph, *parent)) {
can_be_executed = false;
}
}
if (can_be_executed) {
- scheduleChunk(chunk_index);
+ WorkScheduler::schedule(&work_package);
}
return false;
@@ -568,6 +543,22 @@ void ExecutionGroup::determineDependingAreaOfInterest(rcti *input,
this->getOutputOperation()->determineDependingAreaOfInterest(input, readOperation, output);
}
+void ExecutionGroup::link_child_work_packages(WorkPackage *child, rcti *area)
+{
+ for (WorkPackage &work_package : m_work_packages) {
+ rcti isect;
+ if (!BLI_rcti_isect(&work_package.rect, area, &isect)) {
+ continue;
+ }
+
+ // TODO(jbakker): `BLI_rcti_isect` assumes inclusive. we use exclusive. added area check to
+ // counteract this.
+ if (BLI_rcti_size_x(&isect) * BLI_rcti_size_y(&isect) > 0) {
+ work_package.add_child(child);
+ }
+ }
+}
+
void ExecutionGroup::setViewerBorder(float xmin, float xmax, float ymin, float ymax)
{
const NodeOperation &operation = *this->getOutputOperation();
diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.h b/source/blender/compositor/intern/COM_ExecutionGroup.h
index 0d8fb47b5be..1b91f74e605 100644
--- a/source/blender/compositor/intern/COM_ExecutionGroup.h
+++ b/source/blender/compositor/intern/COM_ExecutionGroup.h
@@ -71,8 +71,12 @@ struct ExecutionGroupFlags {
open_cl = false;
single_threaded = false;
}
+
+ std::string str() const;
};
+std::ostream &operator<<(std::ostream &os, const ExecutionGroupFlags &flags);
+
/**
* \b
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list