diff options
Diffstat (limited to 'source/blender/compositor/intern/COM_ExecutionGroup.h')
-rw-r--r-- | source/blender/compositor/intern/COM_ExecutionGroup.h | 404 |
1 files changed, 404 insertions, 0 deletions
diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.h b/source/blender/compositor/intern/COM_ExecutionGroup.h new file mode 100644 index 00000000000..2d5e0965297 --- /dev/null +++ b/source/blender/compositor/intern/COM_ExecutionGroup.h @@ -0,0 +1,404 @@ +/* + * Copyright 2011, Blender Foundation. + * + * 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. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + */ + +#ifndef _COM_ExecutionGroup_h +#define _COM_ExecutionGroup_h + +#include "COM_Node.h" +#include "COM_NodeOperation.h" +#include <vector> +#include "BLI_rect.h" +#include "COM_MemoryProxy.h" +#include "COM_Device.h" +#include "COM_CompositorContext.h" + + +/** + * @brief the execution state of a chunk in an ExecutionGroup + * @ingroup Execution + */ +typedef enum ChunkExecutionState { + /** + * @brief chunk is not yet scheduled + */ + COM_ES_NOT_SCHEDULED = 0, + /** + * @brief chunk is scheduled, but not yet executed + */ + COM_ES_SCHEDULED = 1, + /** + * @brief chunk is executed. + */ + COM_ES_EXECUTED = 2 +} ChunkExecutionState; + +class MemoryProxy; +class ReadBufferOperation; +class Device; + +/** + * @brief Class ExecutionGroup is a group of NodeOperations 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 + /** + * @brief unique identifier of this node. + */ + string id; + + /** + * @brief list of operations in this ExecutionGroup + */ + vector<NodeOperation*> operations; + + /** + * @brief is this ExecutionGroup an input ExecutionGroup + * an input execution group is a group that is at the end of the calculation (the output is important for the user) + */ + int isOutput; + + /** + * @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 chunkSize; + + /** + * @brief number of chunks in the x-axis + */ + unsigned int numberOfXChunks; + + /** + * @brief number of chunks in the y-axis + */ + unsigned int numberOfYChunks; + + /** + * @brief total number of chunks + */ + unsigned int numberOfChunks; + + /** + * @brief contains this ExecutionGroup a complex NodeOperation. + */ + bool complex; + + /** + * @brief can this ExecutionGroup be scheduled on an OpenCLDevice + */ + bool openCL; + + /** + * @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 cachedMaxReadBufferOffset; + + /** + * @brief a cached vector of all read operations in the execution group. + */ + vector<NodeOperation*> cachedReadOperations; + + /** + * @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 chunksFinished; + + /** + * @brief the chunkExecutionStates holds per chunk the execution state. this state can be + * - COM_ES_NOT_SCHEDULED: not scheduled + * - COM_ES_SCHEDULED: scheduled + * - COM_ES_EXECUTED: executed + */ + ChunkExecutionState *chunkExecutionStates; + + /** + * @brief indicator when this ExecutionGroup has valid NodeOperations in its vector for Execution + * @note When building the ExecutionGroup NodeOperations are added via recursion. First a WriteBufferOperations is added, then the + * @note Operation containing the settings that is important for the ExecutiongGroup is added, + * @note When this occurs, these settings are copied over from the node to the ExecutionGroup + * @note and the Initialized flag is set to true. + * @see complex + * @see openCL + */ + bool initialized; + + // methods + /** + * @brief check whether parameter operation can be added to the execution group + * @param operation the operation to be added + */ + bool canContainOperation(NodeOperation* operation); + + /** + * @brief get the Render priority of this ExecutionGroup + * @see ExecutionSystem.execute + */ + int getRenderPriotrity(); + + /** + * @brief calculate the actual chunk size of this execution group. + * @note A chunk size is an unsigned int that is both the height and width of a chunk. + * @note The chunk size will not be stored in the chunkSize field. This needs to be done + * @note by the calling method. + */ + unsigned int determineChunkSize(); + + + /** + * @brief Determine the rect (minx, maxx, miny, maxy) of a chunk at a position. + * @note Only gives usefull results ater the determination of the chunksize + * @see determineChunkSize() + */ + void determineChunkRect(rcti* rect, const unsigned int xChunk, const unsigned int yChunk) const; + + /** + * @brief determine the number of chunks, based on the chunkSize, width and height. + * @note The result are stored in the fields numberOfChunks, numberOfXChunks, numberOfYChunks + */ + void determineNumberOfChunks(); + + /** + * @brief try to schedule a specific chunk. + * @note scheduling succeeds when all input requirements are met and the chunks hasen't been scheduled yet. + * @param graph + * @param xChunk + * @param yChunk + * @return [true:false] + * true: package(s) are scheduled + * false: scheduling is deferred (depending workpackages are scheduled) + */ + bool scheduleChunkWhenPossible(ExecutionSystem * graph, int xChunk, int yChunk); + + /** + * @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 rect + * @return [true:false] + * true: package(s) are scheduled + * false: scheduling is deferred (depending workpackages are scheduled) + */ + bool scheduleAreaWhenPossible(ExecutionSystem * graph, rcti * rect); + + /** + * @brief add a chunk to the WorkScheduler. + * @param chunknumber + */ + bool scheduleChunk(unsigned int chunkNumber); + + /** + * @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 readOperation The ReadBufferOperation where the area needs to be evaluated + * @param output the area needed of the ReadBufferOperation. Result + */ + void determineDependingAreaOfInterest(rcti * input, ReadBufferOperation* readOperation, rcti* output); + + +public: + // constructors + ExecutionGroup(); + + /** + * @brief set the id of this ExecutionGroup + * @param id + */ + void setId(string id) {this->id = id;} + + /** + * @brief return the id of this ExecutionGroup + */ + const string getId() const {return this->id;} + + // methods + /** + * @brief check to see if a NodeOperation is already inside this execution group + * @param operation the NodeOperation to check + * @return [true,false] + */ + bool containsOperation(NodeOperation* operation); + + /** + * @brief add an operation to this ExecutionGroup + * @note this method will add input of the operations recursivly + * @note this method can create multiple ExecutionGroup's + * @param system + * @param operation + */ + void addOperation(ExecutionSystem* system, NodeOperation *operation); + + /** + * @brief is this ExecutionGroup an output ExecutionGroup + * @note An OutputExecution group are groups containing a + * @note ViewerOperation, CompositeOperation, PreviewOperation. + * @see NodeOperation.isOutputOperation + */ + const int isOutputExecutionGroup() const {return this->isOutput;} + + /** + * @brief set whether this ExecutionGroup is an output + * @param isOutput + */ + void setOutputExecutionGroup(int isOutput) {this->isOutput = isOutput;} + + /** + * @brief determine the resolution of this ExecutionGroup + * @param resolution + */ + void determineResolution(unsigned int resolution[]); + + /** + * @brief set the resolution of this executiongroup + * @param resolution + */ + void setResolution(unsigned int resolution[]) {this->width = resolution[0];this->height = resolution[1];} + + /** + * @brief get the width of this execution group + */ + const unsigned int getWidth() {return this->width;} + + /** + * @brief get the height of this execution group + */ + const unsigned int getHeight() {return this->height;} + + /** + * @brief does this ExecutionGroup contains a complex NodeOperation + */ + const bool isComplex() const; + + + /** + * @brief get the output operation of this ExecutionGroup + * @return NodeOperation* output operation + */ + NodeOperation* getOutputNodeOperation() const; + + /** + * @brief compose multiple chunks into a single chunk + * @return Memorybuffer* consolidated chunk + */ + MemoryBuffer* constructConsolidatedMemoryBuffer(MemoryProxy *memoryProxy, rcti *output); + + /** + * @brief initExecution is called just before the execution of the whole graph will be done. + * @note The implementation will calculate the chunkSize of this execution group. + */ + void initExecution(); + + /** + * @brief get all inputbuffers needed to calculate an chunk + * @note all inputbuffers must be executed + * @param chunkNumber the chunk to be calculated + * @return MemoryBuffer** the inputbuffers + */ + MemoryBuffer** getInputBuffers(int chunkNumber); + + /** + * @brief allocate the outputbuffer of a chunk + * @param chunkNumber the number of the chunk in the ExecutionGroup + * @param rect the rect of that chunk + * @see determineChunkRect + */ + MemoryBuffer* allocateOutputBuffer(int chunkNumber, rcti *rect); + + /** + * @brief after a chunk is executed the needed resources can be freed or unlocked. + * @param chunknumber + * @param memorybuffers + */ + void finalizeChunkExecution(int chunkNumber, MemoryBuffer** memoryBuffers); + + /** + * @brief deinitExecution is called just after execution the whole graph. + * @note It will release all needed resources + */ + void deinitExecution(); + + + /** + * @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 system + */ + void execute(ExecutionSystem* system); + + /** + * @brief this method determines the MemoryProxy's where this execution group depends on. + * @note After this method determineDependingAreaOfInterest can be called to determine + * @note the area of the MemoryProxy.creator thas has to be executed. + * @param memoryProxies result + */ + void determineDependingMemoryProxies(vector<MemoryProxy*> *memoryProxies); + + /** + * @brief Determine the rect (minx, maxx, miny, maxy) of a chunk. + * @note Only gives usefull results ater the determination of the chunksize + * @see determineChunkSize() + */ + void determineChunkRect(rcti* rect, const unsigned int chunkNumber) const; + + + bool operator ==(const ExecutionGroup &executionGroup) const; + + /** + * @brief can this ExecutionGroup be scheduled on an OpenCLDevice + * @see WorkScheduler.schedule + */ + bool isOpenCL(); + + void setChunksize(int chunksize) {this->chunkSize = chunksize;} +}; + +#endif |