66 os <<
"single_threaded,";
74 this->m_bTree =
nullptr;
77 this->m_max_read_buffer_offset = 0;
78 this->m_x_chunks_len = 0;
79 this->m_y_chunks_len = 0;
80 this->m_chunks_len = 0;
81 this->m_chunks_finished = 0;
83 this->m_executionStartTime = 0;
88 os <<
"ExecutionGroup(id=" << execution_group.
get_id();
89 os <<
",flags={" << execution_group.
get_flags() <<
"}";
131 if (!can_contain(*operation)) {
143 m_operations.append(operation);
154 void ExecutionGroup::init_work_packages()
156 m_work_packages.clear();
157 if (this->m_chunks_len != 0) {
158 m_work_packages.resize(this->m_chunks_len);
159 for (
unsigned int index = 0; index < m_chunks_len; index++) {
161 m_work_packages[index].execution_group =
this;
162 m_work_packages[index].chunk_number = index;
163 determineChunkRect(&m_work_packages[index].rect, index);
168 void ExecutionGroup::init_read_buffer_operations()
170 unsigned int max_offset = 0;
171 for (NodeOperation *operation : m_operations) {
173 ReadBufferOperation *readOperation =
static_cast<ReadBufferOperation *
>(operation);
174 this->m_read_operations.append(readOperation);
175 max_offset =
MAX2(max_offset, readOperation->getOffset());
179 this->m_max_read_buffer_offset = max_offset;
184 init_number_of_chunks();
185 init_work_packages();
186 init_read_buffer_operations();
191 m_work_packages.clear();
192 this->m_chunks_len = 0;
193 this->m_x_chunks_len = 0;
194 this->m_y_chunks_len = 0;
195 this->m_read_operations.clear();
196 this->m_bTree =
nullptr;
202 resolution[0] = operation->
getWidth();
205 BLI_rcti_init(&this->m_viewerBorder, 0, this->m_width, 0, this->m_height);
208 void ExecutionGroup::init_number_of_chunks()
211 this->m_x_chunks_len = 1;
212 this->m_y_chunks_len = 1;
213 this->m_chunks_len = 1;
216 const float chunkSizef = this->m_chunkSize;
219 this->m_x_chunks_len =
ceil(border_width / chunkSizef);
220 this->m_y_chunks_len =
ceil(border_height / chunkSizef);
221 this->m_chunks_len = this->m_x_chunks_len * this->m_y_chunks_len;
228 for (
int chunk_index = 0; chunk_index < this->m_chunks_len; chunk_index++) {
229 chunk_order[chunk_index] = chunk_index;
233 float centerX = 0.5f;
234 float centerY = 0.5f;
237 if (operation->get_flags().is_viewer_operation) {
238 ViewerOperation *viewer = (ViewerOperation *)operation;
239 centerX = viewer->getCenterX();
240 centerY = viewer->getCenterY();
241 order_type = viewer->getChunkOrder();
247 switch (order_type) {
257 ChunkOrderHotspot hotspot(border_width * centerX, border_height * centerY, 0.0f);
259 for (index = 0; index < this->m_chunks_len; index++) {
260 const WorkPackage &work_package = m_work_packages[index];
261 chunk_orders[index].index = index;
262 chunk_orders[index].x = work_package.rect.xmin - this->m_viewerBorder.
xmin;
263 chunk_orders[index].y = work_package.rect.ymin - this->m_viewerBorder.
ymin;
264 chunk_orders[index].update_distance(&hotspot, 1);
267 std::sort(&chunk_orders[0], &chunk_orders[this->m_chunks_len - 1]);
268 for (index = 0; index < this->m_chunks_len; index++) {
269 chunk_order[index] = chunk_orders[index].index;
275 unsigned int tx = border_width / 6;
276 unsigned int ty = border_height / 6;
277 unsigned int mx = border_width / 2;
278 unsigned int my = border_height / 2;
279 unsigned int bx = mx + 2 * tx;
280 unsigned int by = my + 2 * ty;
283 ChunkOrderHotspot hotspots[9]{
284 ChunkOrderHotspot(mx, my, addition * 0),
285 ChunkOrderHotspot(tx, my, addition * 1),
286 ChunkOrderHotspot(bx, my, addition * 2),
287 ChunkOrderHotspot(bx, by, addition * 3),
288 ChunkOrderHotspot(tx, ty, addition * 4),
289 ChunkOrderHotspot(bx, ty, addition * 5),
290 ChunkOrderHotspot(tx, by, addition * 6),
291 ChunkOrderHotspot(mx, ty, addition * 7),
292 ChunkOrderHotspot(mx, by, addition * 8),
296 for (index = 0; index < this->m_chunks_len; index++) {
297 const WorkPackage &work_package = m_work_packages[index];
298 chunk_orders[index].index = index;
299 chunk_orders[index].x = work_package.rect.xmin - this->m_viewerBorder.
xmin;
300 chunk_orders[index].y = work_package.rect.ymin - this->m_viewerBorder.
ymin;
301 chunk_orders[index].update_distance(hotspots, 9);
304 std::sort(&chunk_orders[0], &chunk_orders[this->m_chunks_len]);
306 for (index = 0; index < this->m_chunks_len; index++) {
307 chunk_order[index] = chunk_orders[index].index;
327 if (this->m_width == 0 || this->m_height == 0) {
333 if (this->m_chunks_len == 0) {
336 unsigned int chunk_index;
340 this->m_chunks_finished = 0;
341 this->m_bTree = bTree;
348 bool breaked =
false;
349 bool finished =
false;
350 unsigned int startIndex = 0;
353 while (!finished && !breaked) {
354 bool startEvaluated =
false;
356 int numberEvaluated = 0;
358 for (
int index = startIndex;
359 index < this->m_chunks_len && numberEvaluated < maxNumberEvaluated;
361 chunk_index = chunk_order[index];
362 int yChunk = chunk_index / this->m_x_chunks_len;
363 int xChunk = chunk_index - (yChunk * this->m_x_chunks_len);
364 const WorkPackage &work_package = m_work_packages[chunk_index];
365 switch (work_package.state) {
367 scheduleChunkWhenPossible(
graph, xChunk, yChunk);
369 startEvaluated =
true;
379 startEvaluated =
true;
384 if (!startEvaluated) {
385 startIndex = index + 1;
403 WorkPackage &work_package = m_work_packages[chunkNumber];
406 sizeof(
MemoryBuffer *) * this->m_max_read_buffer_offset, __func__);
409 MemoryProxy *memoryProxy = readOperation->getMemoryProxy();
410 this->determineDependingAreaOfInterest(&work_package.
rect, readOperation, &
output);
413 memoryBuffers[readOperation->getOffset()] = memoryBuffer;
415 return memoryBuffers;
423 result->fill_from(*imageBuffer);
429 WorkPackage &work_package = m_work_packages[chunkNumber];
436 for (
unsigned int index = 0; index < this->m_max_read_buffer_offset; index++) {
439 if (
buffer->isTemporarily()) {
440 memoryBuffers[index] =
nullptr;
449 float progress = this->m_chunks_finished;
450 progress /= this->m_chunks_len;
451 this->m_bTree->
progress(this->m_bTree->
prh, progress);
456 TIP_(
"Compositing | Tile %u-%u"),
457 this->m_chunks_finished,
463 inline void ExecutionGroup::determineChunkRect(
rcti *r_rect,
464 const unsigned int xChunk,
465 const unsigned int yChunk)
const
472 r_rect, this->m_viewerBorder.
xmin, border_width, this->m_viewerBorder.ymin, border_height);
475 const unsigned int minx = xChunk * this->m_chunkSize + this->m_viewerBorder.
xmin;
476 const unsigned int miny = yChunk * this->m_chunkSize + this->m_viewerBorder.
ymin;
477 const unsigned int width =
MIN2((
unsigned int)this->m_viewerBorder.
xmax, this->m_width);
478 const unsigned int height =
MIN2((
unsigned int)this->m_viewerBorder.
ymax, this->m_height);
480 MIN2(minx, this->m_width),
482 MIN2(miny, this->m_height),
487 void ExecutionGroup::determineChunkRect(
rcti *r_rect,
const unsigned int chunkNumber)
const
489 const unsigned int yChunk = chunkNumber / this->m_x_chunks_len;
490 const unsigned int xChunk = chunkNumber - (yChunk * this->m_x_chunks_len);
491 determineChunkRect(r_rect, xChunk, yChunk);
510 return scheduleChunkWhenPossible(
graph, 0, 0);
520 int minxchunk = minx / (int)m_chunkSize;
521 int maxxchunk = (maxx + (int)m_chunkSize - 1) / (int)m_chunkSize;
522 int minychunk = miny / (int)m_chunkSize;
523 int maxychunk = (maxy + (int)m_chunkSize - 1) / (int)m_chunkSize;
524 minxchunk =
max_ii(minxchunk, 0);
525 minychunk =
max_ii(minychunk, 0);
526 maxxchunk =
min_ii(maxxchunk, (
int)m_x_chunks_len);
527 maxychunk =
min_ii(maxychunk, (
int)m_y_chunks_len);
530 for (indexx = minxchunk; indexx < maxxchunk; indexx++) {
531 for (indexy = minychunk; indexy < maxychunk; indexy++) {
532 if (!scheduleChunkWhenPossible(
graph, indexx, indexy)) {
541 bool ExecutionGroup::scheduleChunk(
unsigned int chunkNumber)
543 WorkPackage &work_package = m_work_packages[chunkNumber];
552 bool ExecutionGroup::scheduleChunkWhenPossible(ExecutionSystem *
graph,
556 if (chunk_x < 0 || chunk_x >= (
int)this->m_x_chunks_len) {
559 if (chunk_y < 0 || chunk_y >= (
int)this->m_y_chunks_len) {
564 const int chunk_index = chunk_y * this->m_x_chunks_len + chunk_x;
565 WorkPackage &work_package = m_work_packages[chunk_index];
573 bool can_be_executed =
true;
576 for (ReadBufferOperation *read_operation : m_read_operations) {
578 MemoryProxy *memory_proxy = read_operation->getMemoryProxy();
579 determineDependingAreaOfInterest(&work_package.rect, read_operation, &
area);
582 if (!group->scheduleAreaWhenPossible(
graph, &
area)) {
583 can_be_executed =
false;
587 if (can_be_executed) {
588 scheduleChunk(chunk_index);
594 void ExecutionGroup::determineDependingAreaOfInterest(
rcti *input,
595 ReadBufferOperation *readOperation,
606 xmin * this->m_width,
607 xmax * this->m_width,
608 ymin * this->m_height,
609 ymax * this->m_height);
618 xmin * this->m_width,
619 xmax * this->m_width,
620 ymin * this->m_height,
621 ymax * this->m_height);
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
void BLI_rcti_init(struct rcti *rect, int xmin, int xmax, int ymin, int ymax)
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
int BLI_system_thread_count(void)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
Read Guarded memory(de)allocation.
Platform independent time functions.
Provides wrapper around system-specific atomic primitives, and some extensions (faked-atomic operatio...
ATOMIC_INLINE unsigned int atomic_add_and_fetch_u(unsigned int *p, unsigned int x)
void sort(btMatrix3x3 &U, btVector3 &sigma, btMatrix3x3 &V, int t)
Helper function of 3X3 SVD for sorting singular values.
void shuffle(MutableSpan< T > values)
Overall context of the compositor.
static void execution_group_started(const ExecutionGroup *group)
static void graphviz(const ExecutionSystem *system)
static void execution_group_finished(const ExecutionGroup *group)
Class ExecutionGroup is a group of Operations that are executed as one. This grouping is used to comb...
eCompositorPriority getRenderPriority()
get the Render priority of this ExecutionGroup
void execute(ExecutionSystem *graph)
schedule an ExecutionGroup
void setViewerBorder(float xmin, float xmax, float ymin, float ymax)
set border for viewer operation
MemoryBuffer * constructConsolidatedMemoryBuffer(MemoryProxy &memoryProxy, rcti &rect)
compose multiple chunks into a single chunk
MemoryBuffer * allocateOutputBuffer(rcti &rect)
allocate the outputbuffer of a chunk
const ExecutionGroupFlags get_flags() const
MemoryBuffer ** getInputBuffersOpenCL(int chunkNumber)
get all inputbuffers needed to calculate an chunk
void deinitExecution()
deinitExecution is called just after execution the whole graph.
NodeOperation * getOutputOperation() const
get the output operation of this ExecutionGroup
bool addOperation(NodeOperation *operation)
add an operation to this ExecutionGroup
void initExecution()
initExecution is called just before the execution of the whole graph will be done.
void setResolution(unsigned int resolution[2])
set the resolution of this executiongroup
void setRenderBorder(float xmin, float xmax, float ymin, float ymax)
void finalizeChunkExecution(int chunkNumber, MemoryBuffer **memoryBuffers)
after a chunk is executed the needed resources can be freed or unlocked.
void determineResolution(unsigned int resolution[2])
determine the resolution of this ExecutionGroup
the ExecutionSystem contains the whole compositor tree.
a MemoryBuffer contains access to the data of a chunk
A MemoryProxy is a unique identifier for a memory buffer. A single MemoryProxy is used among all chun...
ExecutionGroup * getExecutor() const
get the ExecutionGroup that can be scheduled to calculate a certain chunk.
MemoryBuffer * getBuffer()
get the allocated memory
NodeOperation contains calculation logic.
virtual eCompositorPriority getRenderPriority() const
get the render priority of this node.
unsigned int getHeight() const
const NodeOperationFlags get_flags() const
unsigned int getWidth() const
virtual bool isOutputOperation(bool) const
isOutputOperation determines whether this operation is an output of the ExecutionSystem during render...
virtual bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
NodeOperation to write to a tile.
MemoryProxy * getMemoryProxy()
eCompositorPriority
Possible priority settings.
ChunkOrdering
The order of chunks to be scheduled.
@ NotScheduled
chunk is not yet scheduled
@ Scheduled
chunk is scheduled, but not yet executed
@ Executed
chunk is executed.
@ RuleOfThirds
experimental ordering with 9 hot-spots.
@ CenterOut
order from a distance to centerX/centerY
@ Temporary
chunk is consolidated from other chunks. special state.
__kernel void ccl_constant KernelData ccl_global void ccl_global char ccl_global int ccl_global char ccl_global unsigned int ccl_global float * buffer
void(* MEM_freeN)(void *vmemh)
void *(* MEM_callocN)(size_t len, const char *str)
static void area(int d1, int d2, int e1, int e2, float weights[2])
constexpr float COM_RULE_OF_THIRDS_DIVIDER
std::ostream & operator<<(std::ostream &os, const eCompositorPriority &priority)
void(* progress)(void *, float progress)
int(* test_break)(void *)
void(* update_draw)(void *)
void(* stats_draw)(void *, const char *str)
bool is_write_buffer_operation
bool is_read_buffer_operation
contains data about work that can be scheduled
static void schedule(WorkPackage *package)
schedule a chunk of a group to be calculated. An execution group schedules a chunk in the WorkSchedul...
static void finish()
wait for all work to be completed.
double PIL_check_seconds_timer(void)
ccl_device_inline float3 ceil(const float3 &a)