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

COM_compositor.h « compositor « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: a7f9081f3fcd360d337054bf631ff41562e50a9c (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
/*
 * 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

#include "DNA_color_types.h"
#include "DNA_node_types.h"

#ifdef __cplusplus
extern "C" {
#endif

/* Keep ascii art. */
/* clang-format off */
/**
 * \defgroup Model The data model of the compositor
 * \defgroup Memory The memory management stuff
 * \defgroup Execution The execution logic
 * \defgroup Conversion Conversion logic
 * \defgroup Node All nodes of the compositor
 * \defgroup Operation All operations of the compositor
 *
 * \page Introduction of the Blender Compositor
 *
 * \section bcomp Blender compositor
 * This project redesigns the internals of Blender's compositor.
 * The project has been executed in 2011 by At Mind.
 * At Mind is a technology company located in Amsterdam, The Netherlands.
 * The project has been crowd-funded. This code has been released under GPL2 to be used in Blender.
 *
 * \section goals The goals of the project
 * the new compositor has 2 goals.
 *   - Make a faster compositor (speed of calculation)
 *   - Make the compositor work faster for you (workflow)
 *
 * \section speed Faster compositor
 * The speedup has been done by making better use of the hardware Blenders is working on.
 * The previous compositor only used a single threaded model to calculate a node.
 * The only exception to this is the Defocus node.
 * Only when it is possible to calculate two full nodes in parallel a second thread was used.
 * Current workstations have 8-16 threads available, and most of the time these are idle.
 *
 * In the new compositor we want to use as much of threads as possible.
 * Even new OpenCL capable GPU-hardware can be used for calculation.
 *
 * \section workflow Work faster
 * The previous compositor only showed the final image.
 * The compositor could wait a long time before seeing the result of his work.
 * The new compositor will work in a way that it will focus on
 * getting information back to the user. It will prioritize its work to get earlier user feedback.
 *
 * \page memory Memory model
 * The main issue is the type of memory model to use.
 * Blender is used by consumers and professionals.
 * Ranging from low-end machines to very high-end machines.
 * The system should work on high-end machines and on low-end machines.
 * \page executing Executing
 * \section prepare Prepare execution
 *
 * during the preparation of the execution All ReadBufferOperation will receive an offset.
 * This offset is used during execution as an optimization trick
 * Next all operations will be initialized for execution \see NodeOperation.initExecution
 * Next all ExecutionGroup's will be initialized for execution \see ExecutionGroup.initExecution
 * this all is controlled from \see ExecutionSystem.execute
 *
 * \section priority Render priority
 * Render priority is an priority of an output node.
 * A user has a different need of Render priorities of output nodes
 * than during editing.
 * for example. the Active ViewerNode has top priority during editing,
 * but during rendering a CompositeNode has.
 * All NodeOperation has a setting for their render-priority,
 * but only for output NodeOperation these have effect.
 * In ExecutionSystem.execute all priorities are checked.
 * For every priority the ExecutionGroup's are check if the
 * priority do match.
 * When match the ExecutionGroup will be executed (this happens in serial)
 *
 * \see ExecutionSystem.execute control of the Render priority
 * \see NodeOperation.getRenderPriority receive the render priority
 * \see ExecutionGroup.execute the main loop to execute a whole ExecutionGroup
 *
 * \section order Chunk order
 *
 * When a ExecutionGroup is executed, first the order of chunks are determined.
 * The settings are stored in the ViewerNode inside the ExecutionGroup.
 * ExecutionGroups that have no viewer-node,
 * will use a default one.
 * There are several possible chunk orders
 *  - [@ref ChunkOrdering.CenterOut]:
 *    Start calculating from a configurable point and order by nearest chunk.
 *  - [@ref ChunkOrdering.Random]:
 *    Randomize all chunks.
 *  - [@ref ChunkOrdering.TopDown]:
 *    Start calculation from the bottom to the top of the image.
 *  - [@ref ChunkOrdering.RuleOfThirds]:
 *    Experimental order based on 9 hot-spots in the image.
 *
 * When the chunk-order is determined, the first few chunks will be checked if they can be scheduled.
 * Chunks can have three states:
 *  - [@ref eWorkPackageState.NotScheduled]:
 *    Chunk is not yet scheduled, or dependencies are not met.
 *  - [@ref eWorkPackageState.Scheduled]:
 *    All dependencies are met, chunk is scheduled, but not finished.
 *  - [@ref eWorkPackageState.Executed]:
 *    Chunk is finished.
 *
 * \see ExecutionGroup.execute
 * \see ViewerOperation.getChunkOrder
 * \see ChunkOrdering
 *
 * \section interest Area of interest
 * An ExecutionGroup can have dependencies to other ExecutionGroup's.
 * Data passing from one ExecutionGroup to another one are stored in 'chunks'.
 * If not all input chunks are available the chunk execution will not be scheduled.
 * <pre>
 * +-------------------------------------+              +--------------------------------------+
 * | ExecutionGroup A                    |              | ExecutionGroup B                     |
 * | +----------------+  +-------------+ |              | +------------+   +-----------------+ |
 * | | NodeOperation a|  | WriteBuffer | |              | | ReadBuffer |   | ViewerOperation | |
 * | |                *==* Operation   | |              | | Operation  *===*                 | |
 * | |                |  |             | |              | |            |   |                 | |
 * | +----------------+  +-------------+ |              | +------------+   +-----------------+ |
 * |                                |    |              |   |                                  |
 * +--------------------------------|----+              +---|----------------------------------+
 *                                  |                       |
 *                                  |                       |
 *                                +---------------------------+
 *                                | MemoryProxy               |
 *                                | +----------+  +---------+ |
 *                                | | Chunk a  |  | Chunk b | |
 *                                | |          |  |         | |
 *                                | +----------+  +---------+ |
 *                                |                           |
 *                                +---------------------------+
 * </pre>
 *
 * In the above example ExecutionGroup B has an outputoperation (ViewerOperation)
 * and is being executed.
 * The first chunk is evaluated [@ref ExecutionGroup.scheduleChunkWhenPossible],
 * but not all input chunks are available.
 * The relevant ExecutionGroup (that can calculate the missing chunks; ExecutionGroup A)
 * is asked to calculate the area ExecutionGroup B is missing.
 * [@ref ExecutionGroup.scheduleAreaWhenPossible]
 * ExecutionGroup B checks what chunks the area spans, and tries to schedule these chunks.
 * If all input data is available these chunks are scheduled [@ref ExecutionGroup.scheduleChunk]
 *
 * <pre>
 *
 * +-------------------------+        +----------------+                           +----------------+
 * | ExecutionSystem.execute |        | ExecutionGroup |                           | ExecutionGroup |
 * +-------------------------+        | (B)            |                           | (A)            |
 *            O                       +----------------+                           +----------------+
 *            O                                |                                            |
 *            O       ExecutionGroup.execute   |                                            |
 *            O------------------------------->O                                            |
 *            .                                O                                            |
 *            .                                O-------\                                    |
 *            .                                .       | ExecutionGroup.scheduleChunkWhenPossible
 *            .                                .  O----/ (*)                                |
 *            .                                .  O                                         |
 *            .                                .  O                                         |
 *            .                                .  O  ExecutionGroup.scheduleAreaWhenPossible|
 *            .                                .  O---------------------------------------->O
 *            .                                .  .                                         O----------\ ExecutionGroup.scheduleChunkWhenPossible
 *            .                                .  .                                         .          | (*)
 *            .                                .  .                                         .  O-------/
 *            .                                .  .                                         .  O
 *            .                                .  .                                         .  O
 *            .                                .  .                                         .  O-------\ ExecutionGroup.scheduleChunk
 *            .                                .  .                                         .  .       |
 *            .                                .  .                                         .  .  O----/
 *            .                                .  .                                         .  O<=O
 *            .                                .  .                                         O<=O
 *            .                                .  .                                         O
 *            .                                .  O<========================================O
 *            .                                .  O                                         |
 *            .                                O<=O                                         |
 *            .                                O                                            |
 *            .                                O                                            |
 * </pre>
 *
 * This happens until all chunks of (ExecutionGroup B) are finished executing or the user break's the process.
 *
 * NodeOperation like the ScaleOperation can influence the area of interest by reimplementing the
 * [@ref NodeOperation.determineAreaOfInterest] method
 *
 * <pre>
 *
 * +--------------------------+                             +---------------------------------+
 * | ExecutionGroup A         |                             | ExecutionGroup B                |
 * |                          |                             |                                 |
 * +--------------------------+                             +---------------------------------+
 *           Needed chunks from ExecutionGroup A               |   Chunk of ExecutionGroup B (to be evaluated)
 *            +-------+ +-------+                              |                  +--------+
 *            |Chunk 1| |Chunk 2|               +----------------+                |Chunk 1 |
 *            |       | |       |               | ScaleOperation |                |        |
 *            +-------+ +-------+               +----------------+                +--------+
 *
 *            +-------+ +-------+
 *            |Chunk 3| |Chunk 4|
 *            |       | |       |
 *            +-------+ +-------+
 *
 * </pre>
 *
 * \see ExecutionGroup.execute Execute a complete ExecutionGroup.
 * Halts until finished or breaked by user
 * \see ExecutionGroup.scheduleChunkWhenPossible Tries to schedule a single chunk,
 * checks if all input data is available. Can trigger dependent chunks to be calculated
 * \see ExecutionGroup.scheduleAreaWhenPossible
 * Tries to schedule an area. This can be multiple chunks
 * (is called from [@ref ExecutionGroup.scheduleChunkWhenPossible])
 * \see ExecutionGroup.scheduleChunk Schedule a chunk on the WorkScheduler
 * \see NodeOperation.determineDependingAreaOfInterest Influence the area of interest of a chunk.
 * \see WriteBufferOperation Operation to write to a MemoryProxy/MemoryBuffer
 * \see ReadBufferOperation Operation to read from a MemoryProxy/MemoryBuffer
 * \see MemoryProxy proxy for information about memory image
 * (a image consist out of multiple chunks)
 * \see MemoryBuffer Allocated memory for a single chunk
 *
 * \section workscheduler WorkScheduler
 * the WorkScheduler is implemented as a static class. the responsibility of the WorkScheduler
 * is to balance WorkPackages to the available and free devices.
 * the work-scheduler can work in 2 states.
 * For witching these between the state you need to recompile blender
 *
 * \subsection multithread Multi threaded
 * Default the work-scheduler will place all work as WorkPackage in a queue.
 * For every CPUcore a working thread is created.
 * These working threads will ask the WorkScheduler if there is work
 * for a specific Device.
 * the work-scheduler will find work for the device and the device
 * will be asked to execute the WorkPackage.
 *
 * \subsection singlethread Single threaded
 * For debugging reasons the multi-threading can be disabled.
 * This is done by changing the `COM_threading_model`
 * to `ThreadingModel::SingleThreaded`. When compiling the work-scheduler
 * will be changes to support no threading and run everything on the CPU.
 *
 * \section devices Devices
 * A Device within the compositor context is a Hardware component that can used to calculate chunks.
 * This chunk is encapsulated in a WorkPackage.
 * the WorkScheduler controls the devices and selects the device where a
 * WorkPackage will be calculated.
 *
 * \subsection WS_Devices Workscheduler
 * The WorkScheduler controls all Devices.
 * When initializing the compositor the WorkScheduler selects all
 * devices that will be used during compositor.
 * There are two types of Devices, CPUDevice and OpenCLDevice.
 * When an ExecutionGroup schedules a Chunk the schedule method of the WorkScheduler
 * The Workscheduler determines if the chunk can be run on an OpenCLDevice
 * (and that there are available OpenCLDevice).
 * If this is the case the chunk will be added to the work-list for OpenCLDevice's
 * otherwise the chunk will be added to the work-list of CPUDevices.
 *
 * A thread will read the work-list and sends a workpackage to its device.
 *
 * \see WorkScheduler.schedule method that is called to schedule a chunk
 * \see Device.execute method called to execute a chunk
 *
 * \subsection CPUDevice CPUDevice
 * When a CPUDevice gets a WorkPackage the Device will get the inputbuffer that is needed to
 * calculate the chunk. Allocation is already done by the ExecutionGroup.
 * The outputbuffer of the chunk is being created.
 * The OutputOperation of the ExecutionGroup is called to execute the area of the outputbuffer.
 *
 * \see ExecutionGroup
 * \see NodeOperation.executeRegion executes a single chunk of a NodeOperation
 * \see CPUDevice.execute
 *
 * \subsection GPUDevice OpenCLDevice
 *
 * To be completed!
 * \see NodeOperation.executeOpenCLRegion
 * \see OpenCLDevice.execute
 *
 * \section executePixel executing a pixel
 * Finally the last step, the node functionality :)
 */

/**
 * \brief The main method that is used to execute the compositor tree.
 * It can be executed during editing (blenkernel/node.cc) or rendering
 * (renderer/pipeline.c)
 *
 * \param rd: [struct RenderData]
 *   Render data for this composite, this won't always belong to a scene.
 *
 * \param editingtree: [struct bNodeTree]
 *   reference to the compositor editing tree
 *
 * \param rendering: [true false]
 *    This parameter determines whether the function is called from rendering
 *    (true) or editing (false).
 *    based on this setting the system will work differently:
 *     - during rendering only Composite & the File output node will be calculated
 * \see NodeOperation.isOutputProgram(int rendering) of the specific operations
 *
 *     - during editing all output nodes will be calculated
 * \see NodeOperation.isOutputProgram(int rendering) of the specific operations
 *
 *     - another quality setting can be used bNodeTree.
 *       The quality is determined by the bNodeTree fields.
 *       quality can be modified by the user from within the node panels.
 * \see bNodeTree.edit_quality
 * \see bNodeTree.render_quality
 *
 *     - output nodes can have different priorities in the WorkScheduler.
 * This is implemented in the COM_execute function.
 *
 * \param viewSettings:
 *   reference to view settings used for color management
 *
 * \param displaySettings:
 *   reference to display settings used for color management
 *
 * OCIO_TODO: this options only used in rare cases, namely in output file node,
 *            so probably this settings could be passed in a nicer way.
 *            should be checked further, probably it'll be also needed for preview
 *            generation in display space
 */
/* clang-format off */

void COM_execute(RenderData *render_data,
                 Scene *scene,
                 bNodeTree *node_tree,
                 int rendering,
                 const ColorManagedViewSettings *viewSettings,
                 const ColorManagedDisplaySettings *displaySettings,
                 const char *viewName);

/**
 * \brief Deinitialize the compositor caches and allocated memory.
 * Use COM_clearCaches to only free the caches.
 */
void COM_deinitialize(void);

/**
 * \brief Clear all compositor caches. (Compositor system will still remain available).
 * To deinitialize the compositor use the COM_deinitialize method.
 */
// void COM_clearCaches(void); // NOT YET WRITTEN

#ifdef __cplusplus
}
#endif