Welcome to mirror list, hosted at ThFree Co, Russian Federation.

COM_ExecutionGroup.h « intern « compositor « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: d37bfe29306e320ca52c323b291da78794c0463c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
/*
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * Copyright 2011, Blender Foundation.
 */

#pragma once

#ifdef WITH_CXX_GUARDEDALLOC
#  include "MEM_guardedalloc.h"
#endif

#include <iostream>

#include "BLI_array.hh"
#include "BLI_vector.hh"

#include "COM_Enums.h"
#include "COM_WorkPackage.h"

#include "DNA_node_types.h"
#include "DNA_vec_types.h"

namespace blender::compositor {

class ExecutionSystem;
class NodeOperation;
class MemoryProxy;
class MemoryBuffer;
class ReadBufferOperation;

struct ExecutionGroupFlags {
  bool initialized : 1;
  /**
   * Is this ExecutionGroup an output ExecutionGroup
   * An OutputExecution group are groups containing a
   * ViewerOperation, CompositeOperation, PreviewOperation.
   */
  bool is_output : 1;
  bool complex : 1;

  /**
   * Can this ExecutionGroup be scheduled on an OpenCLDevice.
   */
  bool open_cl : 1;

  /**
   * Schedule this execution group as a single chunk. This
   * chunk will be executed by a single thread.
   */
  bool single_threaded : 1;

  ExecutionGroupFlags()
  {
    initialized = false;
    is_output = false;
    complex = false;
    open_cl = false;
    single_threaded = false;
  }
};

std::ostream &operator<<(std::ostream &os, const ExecutionGroupFlags &flags);

/**
 * \brief Class ExecutionGroup is a group of Operations that are executed as one.
 * This grouping is used to combine Operations that can be executed as one whole when
 * multi-processing.
 * \ingroup Execution
 */
class ExecutionGroup {
 private:
  // fields
  /**
   * Id of the execution group. For debugging purposes.
   */
  int id_;

  /**
   * \brief list of operations in this ExecutionGroup
   */
  Vector<NodeOperation *> operations_;

  ExecutionGroupFlags flags_;

  /**
   * \brief Width of the output
   */
  unsigned int width_;

  /**
   * \brief Height of the output
   */
  unsigned int height_;

  /**
   * \brief size of a single chunk, being Width or of height
   * a chunk is always a square, except at the edges of the MemoryBuffer
   */
  unsigned int chunk_size_;

  /**
   * \brief number of chunks in the x-axis
   */
  unsigned int x_chunks_len_;

  /**
   * \brief number of chunks in the y-axis
   */
  unsigned int y_chunks_len_;

  /**
   * \brief total number of chunks
   */
  unsigned int chunks_len_;

  /**
   * \brief what is the maximum number field of all ReadBufferOperation in this ExecutionGroup.
   * \note this is used to construct the MemoryBuffers that will be passed during execution.
   */
  unsigned int max_read_buffer_offset_;

  /**
   * \brief All read operations of this execution group.
   */
  Vector<ReadBufferOperation *> read_operations_;

  /**
   * \brief reference to the original bNodeTree,
   * this field is only set for the 'top' execution group.
   * \note can only be used to call the callbacks for progress, status and break.
   */
  const bNodeTree *bTree_;

  /**
   * \brief total number of chunks that have been calculated for this ExecutionGroup
   */
  unsigned int chunks_finished_;

  /**
   * \brief work_packages_ holds all unit of work.
   */
  Vector<WorkPackage> work_packages_;

  /**
   * \brief denotes boundary for border compositing
   * \note measured in pixel space
   */
  rcti viewer_border_;

  /**
   * \brief start time of execution
   */
  double execution_start_time_;

  // methods
  /**
   * \brief check whether parameter operation can be added to the execution group
   * \param operation: the operation to be added
   */
  bool can_contain(NodeOperation &operation);

  /**
   * \brief Determine the rect (minx, maxx, miny, maxy) of a chunk at a position.
   */
  void determine_chunk_rect(rcti *r_rect, unsigned int x_chunk, unsigned int y_chunk) const;

  /**
   * \brief determine the number of chunks, based on the chunk_size, width and height.
   * \note The result are stored in the fields number_of_chunks, number_of_xchunks,
   * number_of_ychunks
   */
  void init_number_of_chunks();

  /**
   * \brief try to schedule a specific chunk.
   * \note scheduling succeeds when all input requirements are met and the chunks hasn't been
   * scheduled yet.
   * \param graph:
   * \param x_chunk:
   * \param y_chunk:
   * \return [true:false]
   * true: package(s) are scheduled
   * false: scheduling is deferred (depending workpackages are scheduled)
   */
  bool schedule_chunk_when_possible(ExecutionSystem *graph, int chunk_x, int chunk_y);

  /**
   * \brief try to schedule a specific area.
   * \note Check if a certain area is available, when not available this are will be checked.
   * \note This method is called from other ExecutionGroup's.
   * \param graph:
   * \param area:
   * \return [true:false]
   * true: package(s) are scheduled
   * false: scheduling is deferred (depending workpackages are scheduled)
   */
  bool schedule_area_when_possible(ExecutionSystem *graph, rcti *area);

  /**
   * \brief add a chunk to the WorkScheduler.
   * \param chunknumber:
   */
  bool schedule_chunk(unsigned int chunk_number);

  /**
   * \brief determine the area of interest of a certain input area
   * \note This method only evaluates a single ReadBufferOperation
   * \param input: the input area
   * \param read_operation: The ReadBufferOperation where the area needs to be evaluated
   * \param output: the area needed of the ReadBufferOperation. Result
   */
  void determine_depending_area_of_interest(rcti *input,
                                            ReadBufferOperation *read_operation,
                                            rcti *output);

  /**
   * Return the execution order of the user visible chunks.
   */
  blender::Array<unsigned int> get_execution_order() const;

  void init_read_buffer_operations();
  void init_work_packages();

 public:
  // constructors
  ExecutionGroup(int id);

  int get_id() const
  {
    return id_;
  }

  const ExecutionGroupFlags get_flags() const
  {
    return flags_;
  }

  // methods
  /**
   * \brief add an operation to this ExecutionGroup
   * \note this method will add input of the operations recursively
   * \note this method can create multiple ExecutionGroup's
   * \param system:
   * \param operation:
   * \return True if the operation was successfully added
   */
  bool add_operation(NodeOperation *operation);

  /**
   * \brief set whether this ExecutionGroup is an output
   * \param is_output:
   */
  void set_output_execution_group(bool is_output)
  {
    flags_.is_output = is_output;
  }

  /**
   * \brief determine the resolution of this ExecutionGroup
   * \param resolution:
   */
  void determine_resolution(unsigned int resolution[2]);

  /**
   * \brief set the resolution of this executiongroup
   * \param resolution:
   */
  void set_resolution(unsigned int resolution[2])
  {
    width_ = resolution[0];
    height_ = resolution[1];
  }

  /**
   * \brief get the width of this execution group
   */
  unsigned int get_width() const
  {
    return width_;
  }

  /**
   * \brief get the height of this execution group
   */
  unsigned int get_height() const
  {
    return height_;
  }

  /**
   * \brief get the output operation of this ExecutionGroup
   * \return NodeOperation *output operation
   */
  NodeOperation *get_output_operation() const;

  /**
   * \brief compose multiple chunks into a single chunk
   * \return Memorybuffer *consolidated chunk
   */
  MemoryBuffer *construct_consolidated_memory_buffer(MemoryProxy &memory_proxy, rcti &rect);

  /**
   * \brief init_execution is called just before the execution of the whole graph will be done.
   * \note The implementation will calculate the chunk_size of this execution group.
   */
  void init_execution();

  /**
   * \brief get all inputbuffers needed to calculate an chunk
   * \note all inputbuffers must be executed
   * \param chunk_number: the chunk to be calculated
   * \return (MemoryBuffer **) the inputbuffers
   */
  MemoryBuffer **get_input_buffers_opencl(int chunk_number);

  /**
   * \brief allocate the outputbuffer of a chunk
   * \param chunk_number: the number of the chunk in the ExecutionGroup
   * \param rect: the rect of that chunk
   * \see determine_chunk_rect
   */
  MemoryBuffer *allocate_output_buffer(rcti &rect);

  /**
   * \brief after a chunk is executed the needed resources can be freed or unlocked.
   * \param chunknumber:
   * \param memorybuffers:
   */
  void finalize_chunk_execution(int chunk_number, MemoryBuffer **memory_buffers);

  /**
   * \brief deinit_execution is called just after execution the whole graph.
   * \note It will release all needed resources
   */
  void deinit_execution();

  /**
   * \brief schedule an ExecutionGroup
   * \note this method will return when all chunks have been calculated, or the execution has
   * breaked (by user)
   *
   * first the order of the chunks will be determined. This is determined by finding the
   * ViewerOperation and get the relevant information from it.
   *   - ChunkOrdering
   *   - CenterX
   *   - CenterY
   *
   * After determining the order of the chunks the chunks will be scheduled
   *
   * \see ViewerOperation
   * \param graph:
   */
  /**
   * This method is called for the top execution groups. containing the compositor node or the
   * preview node or the viewer node).
   */
  void execute(ExecutionSystem *graph);

  /**
   * \brief Determine the rect (minx, maxx, miny, maxy) of a chunk.
   */
  void determine_chunk_rect(rcti *r_rect, unsigned int chunk_number) const;

  void set_chunksize(int chunksize)
  {
    chunk_size_ = chunksize;
  }

  /**
   * \brief get the Render priority of this ExecutionGroup
   * \see ExecutionSystem.execute
   */
  eCompositorPriority get_render_priority();

  /**
   * \brief set border for viewer operation
   * \note all the coordinates are assumed to be in normalized space
   */
  void set_viewer_border(float xmin, float xmax, float ymin, float ymax);

  void set_render_border(float xmin, float xmax, float ymin, float ymax);

  /* allow the DebugInfo class to look at internals */
  friend class DebugInfo;

#ifdef WITH_CXX_GUARDEDALLOC
  MEM_CXX_CLASS_ALLOC_FUNCS("COM:ExecutionGroup")
#endif
};

std::ostream &operator<<(std::ostream &os, const ExecutionGroup &execution_group);

}  // namespace blender::compositor