36 os <<
"single_threaded,";
47 max_read_buffer_offset_ = 0;
53 execution_start_time_ = 0;
58 os <<
"ExecutionGroup(id=" << execution_group.
get_id();
59 os <<
",flags={" << execution_group.
get_flags() <<
"}";
101 if (!can_contain(*operation)) {
113 operations_.append(operation);
124 void ExecutionGroup::init_work_packages()
126 work_packages_.clear();
127 if (chunks_len_ != 0) {
128 work_packages_.resize(chunks_len_);
129 for (
unsigned int index = 0; index < chunks_len_; index++) {
132 work_packages_[index].execution_group =
this;
133 work_packages_[index].chunk_number = index;
134 determine_chunk_rect(&work_packages_[index].rect, index);
139 void ExecutionGroup::init_read_buffer_operations()
141 unsigned int max_offset = 0;
142 for (NodeOperation *operation : operations_) {
144 ReadBufferOperation *read_operation =
static_cast<ReadBufferOperation *
>(operation);
145 read_operations_.append(read_operation);
146 max_offset =
MAX2(max_offset, read_operation->get_offset());
150 max_read_buffer_offset_ = max_offset;
155 init_number_of_chunks();
156 init_work_packages();
157 init_read_buffer_operations();
162 work_packages_.clear();
166 read_operations_.clear();
179 void ExecutionGroup::init_number_of_chunks()
187 const float chunk_sizef = chunk_size_;
190 x_chunks_len_ =
ceil(border_width / chunk_sizef);
191 y_chunks_len_ =
ceil(border_height / chunk_sizef);
192 chunks_len_ = x_chunks_len_ * y_chunks_len_;
199 for (
int chunk_index = 0; chunk_index < chunks_len_; chunk_index++) {
200 chunk_order[chunk_index] = chunk_index;
204 float centerX = 0.5f;
205 float centerY = 0.5f;
208 if (operation->get_flags().is_viewer_operation) {
209 ViewerOperation *viewer = (ViewerOperation *)operation;
210 centerX = viewer->getCenterX();
211 centerY = viewer->getCenterY();
212 order_type = viewer->get_chunk_order();
218 switch (order_type) {
228 ChunkOrderHotspot hotspot(border_width * centerX, border_height * centerY, 0.0f);
230 for (index = 0; index < chunks_len_; index++) {
231 const WorkPackage &work_package = work_packages_[index];
232 chunk_orders[index].index = index;
233 chunk_orders[index].x = work_package.rect.xmin - viewer_border_.
xmin;
234 chunk_orders[index].y = work_package.rect.ymin - viewer_border_.
ymin;
235 chunk_orders[index].update_distance(&hotspot, 1);
238 std::sort(&chunk_orders[0], &chunk_orders[chunks_len_ - 1]);
239 for (index = 0; index < chunks_len_; index++) {
240 chunk_order[index] = chunk_orders[index].index;
246 unsigned int tx = border_width / 6;
247 unsigned int ty = border_height / 6;
248 unsigned int mx = border_width / 2;
249 unsigned int my = border_height / 2;
250 unsigned int bx = mx + 2 * tx;
251 unsigned int by = my + 2 * ty;
254 ChunkOrderHotspot hotspots[9]{
255 ChunkOrderHotspot(mx, my, addition * 0),
256 ChunkOrderHotspot(tx, my, addition * 1),
257 ChunkOrderHotspot(bx, my, addition * 2),
258 ChunkOrderHotspot(bx, by, addition * 3),
259 ChunkOrderHotspot(tx, ty, addition * 4),
260 ChunkOrderHotspot(bx, ty, addition * 5),
261 ChunkOrderHotspot(tx, by, addition * 6),
262 ChunkOrderHotspot(mx, ty, addition * 7),
263 ChunkOrderHotspot(mx, by, addition * 8),
267 for (index = 0; index < chunks_len_; index++) {
268 const WorkPackage &work_package = work_packages_[index];
269 chunk_orders[index].index = index;
270 chunk_orders[index].x = work_package.rect.xmin - viewer_border_.
xmin;
271 chunk_orders[index].y = work_package.rect.ymin - viewer_border_.
ymin;
272 chunk_orders[index].update_distance(hotspots, 9);
275 std::sort(&chunk_orders[0], &chunk_orders[chunks_len_]);
277 for (index = 0; index < chunks_len_; index++) {
278 chunk_order[index] = chunk_orders[index].index;
294 if (width_ == 0 || height_ == 0) {
300 if (chunks_len_ == 0) {
303 unsigned int chunk_index;
307 chunks_finished_ = 0;
315 bool breaked =
false;
316 bool finished =
false;
317 unsigned int start_index = 0;
320 while (!finished && !breaked) {
321 bool start_evaluated =
false;
323 int number_evaluated = 0;
325 for (
int index = start_index; index < chunks_len_ && number_evaluated < max_number_evaluated;
327 chunk_index = chunk_order[index];
328 int y_chunk = chunk_index / x_chunks_len_;
329 int x_chunk = chunk_index - (y_chunk * x_chunks_len_);
330 const WorkPackage &work_package = work_packages_[chunk_index];
331 switch (work_package.state) {
333 schedule_chunk_when_possible(
graph, x_chunk, y_chunk);
335 start_evaluated =
true;
345 start_evaluated =
true;
350 if (!start_evaluated) {
351 start_index = index + 1;
369 WorkPackage &work_package = work_packages_[chunk_number];
372 sizeof(
MemoryBuffer *) * max_read_buffer_offset_, __func__);
375 MemoryProxy *memory_proxy = read_operation->get_memory_proxy();
376 this->determine_depending_area_of_interest(&work_package.
rect, read_operation, &
output);
379 memory_buffers[read_operation->get_offset()] = memory_buffer;
381 return memory_buffers;
389 result->fill_from(*image_buffer);
395 WorkPackage &work_package = work_packages_[chunk_number];
401 if (memory_buffers) {
402 for (
unsigned int index = 0; index < max_read_buffer_offset_; index++) {
405 if (
buffer->is_temporarily()) {
406 memory_buffers[index] =
nullptr;
415 float progress = chunks_finished_;
416 progress /= chunks_len_;
421 buf,
sizeof(buf),
TIP_(
"Compositing | Tile %u-%u"), chunks_finished_, chunks_len_);
426 inline void ExecutionGroup::determine_chunk_rect(
rcti *r_rect,
427 const unsigned int x_chunk,
428 const unsigned int y_chunk)
const
437 const unsigned int minx = x_chunk * chunk_size_ + viewer_border_.
xmin;
438 const unsigned int miny = y_chunk * chunk_size_ + viewer_border_.
ymin;
439 const unsigned int width =
MIN2((
unsigned int)viewer_border_.
xmax, width_);
440 const unsigned int height =
MIN2((
unsigned int)viewer_border_.
ymax, height_);
449 void ExecutionGroup::determine_chunk_rect(
rcti *r_rect,
const unsigned int chunk_number)
const
451 const unsigned int y_chunk = chunk_number / x_chunks_len_;
452 const unsigned int x_chunk = chunk_number - (y_chunk * x_chunks_len_);
453 determine_chunk_rect(r_rect, x_chunk, y_chunk);
472 return schedule_chunk_when_possible(
graph, 0, 0);
483 int minxchunk = minx / (int)chunk_size_;
484 int maxxchunk = (maxx + (int)chunk_size_ - 1) / (int)chunk_size_;
485 int minychunk = miny / (int)chunk_size_;
486 int maxychunk = (maxy + (int)chunk_size_ - 1) / (int)chunk_size_;
487 minxchunk =
max_ii(minxchunk, 0);
488 minychunk =
max_ii(minychunk, 0);
489 maxxchunk =
min_ii(maxxchunk, (
int)x_chunks_len_);
490 maxychunk =
min_ii(maxychunk, (
int)y_chunks_len_);
493 for (indexx = minxchunk; indexx < maxxchunk; indexx++) {
494 for (indexy = minychunk; indexy < maxychunk; indexy++) {
495 if (!schedule_chunk_when_possible(
graph, indexx, indexy)) {
504 bool ExecutionGroup::schedule_chunk(
unsigned int chunk_number)
506 WorkPackage &work_package = work_packages_[chunk_number];
515 bool ExecutionGroup::schedule_chunk_when_possible(ExecutionSystem *
graph,
519 if (chunk_x < 0 || chunk_x >= (
int)x_chunks_len_) {
522 if (chunk_y < 0 || chunk_y >= (
int)y_chunks_len_) {
527 const int chunk_index = chunk_y * x_chunks_len_ + chunk_x;
528 WorkPackage &work_package = work_packages_[chunk_index];
536 bool can_be_executed =
true;
539 for (ReadBufferOperation *read_operation : read_operations_) {
541 MemoryProxy *memory_proxy = read_operation->get_memory_proxy();
542 determine_depending_area_of_interest(&work_package.rect, read_operation, &
area);
545 if (!group->schedule_area_when_possible(
graph, &
area)) {
546 can_be_executed =
false;
550 if (can_be_executed) {
551 schedule_chunk(chunk_index);
557 void ExecutionGroup::determine_depending_area_of_interest(
rcti *
input,
558 ReadBufferOperation *read_operation,
562 input, read_operation,
output);
569 BLI_rcti_init(&viewer_border_, xmin * width_, xmax * width_, ymin * height_, ymax * height_);
577 BLI_rcti_init(&viewer_border_, xmin * width_, xmax * width_, ymin * height_, ymax * 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 height
_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
Platform independent time functions.
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 execution_group_finished(const ExecutionGroup *group)
static void graphviz(const ExecutionSystem *system, StringRefNull name="")
Class ExecutionGroup is a group of Operations that are executed as one. This grouping is used to comb...
void finalize_chunk_execution(int chunk_number, MemoryBuffer **memory_buffers)
after a chunk is executed the needed resources can be freed or unlocked.
void set_resolution(unsigned int resolution[2])
set the resolution of this executiongroup
void execute(ExecutionSystem *graph)
schedule an ExecutionGroup
bool add_operation(NodeOperation *operation)
add an operation to this ExecutionGroup
NodeOperation * get_output_operation() const
get the output operation of this ExecutionGroup
const ExecutionGroupFlags get_flags() const
MemoryBuffer * construct_consolidated_memory_buffer(MemoryProxy &memory_proxy, rcti &rect)
compose multiple chunks into a single chunk
MemoryBuffer ** get_input_buffers_opencl(int chunk_number)
get all inputbuffers needed to calculate an chunk
MemoryBuffer * allocate_output_buffer(rcti &rect)
allocate the outputbuffer of a chunk
void init_execution()
init_execution is called just before the execution of the whole graph will be done.
eCompositorPriority get_render_priority()
get the Render priority of this ExecutionGroup
void determine_resolution(unsigned int resolution[2])
determine the resolution of this ExecutionGroup
void set_render_border(float xmin, float xmax, float ymin, float ymax)
void set_viewer_border(float xmin, float xmax, float ymin, float ymax)
set border for viewer operation
void deinit_execution()
deinit_execution is called just after execution the whole graph.
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 * get_executor() const
get the ExecutionGroup that can be scheduled to calculate a certain chunk.
MemoryBuffer * get_buffer()
get the allocated memory
NodeOperation contains calculation logic.
unsigned int get_height() const
virtual bool is_output_operation(bool) const
is_output_operation determines whether this operation is an output of the ExecutionSystem during rend...
const NodeOperationFlags get_flags() const
unsigned int get_width() const
virtual bool determine_depending_area_of_interest(rcti *input, ReadBufferOperation *read_operation, rcti *output)
virtual eCompositorPriority get_render_priority() const
get the render priority of this node.
NodeOperation to write to a tile.
MemoryProxy * get_memory_proxy()
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
@ Tile
Executes an execution group tile.
@ Temporary
chunk is consolidated from other chunks. special state.
ccl_global float * buffer
ccl_global KernelShaderEvalInput ccl_global float * output
ccl_global KernelShaderEvalInput * input
void(* MEM_freeN)(void *vmemh)
void *(* MEM_callocN)(size_t len, const char *str)
ccl_device_inline float3 ceil(const float3 &a)
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)