404 lines
12 KiB
C++
404 lines
12 KiB
C++
/*
|
|
* 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 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 Is this Execution group SingleThreaded
|
|
*/
|
|
bool singleThreaded;
|
|
|
|
/**
|
|
* @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 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();
|
|
|
|
// 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 **getInputBuffersCPU();
|
|
|
|
/**
|
|
* @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 **getInputBuffersOpenCL(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;
|
|
|
|
/**
|
|
* @brief can this ExecutionGroup be scheduled on an OpenCLDevice
|
|
* @see WorkScheduler.schedule
|
|
*/
|
|
bool isOpenCL();
|
|
|
|
void setChunksize(int chunksize) { this->chunkSize = chunksize; }
|
|
|
|
/**
|
|
* @brief get the Render priority of this ExecutionGroup
|
|
* @see ExecutionSystem.execute
|
|
*/
|
|
CompositorPriority getRenderPriotrity();
|
|
|
|
#ifdef WITH_CXX_GUARDEDALLOC
|
|
MEM_CXX_CLASS_ALLOC_FUNCS("COM:ExecutionGroup")
|
|
#endif
|
|
};
|
|
|
|
#endif
|