diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index 0b9dbfacb07..dc28328e867 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -79,10 +79,6 @@ set(SRC intern/COM_MemoryProxy.h intern/COM_MemoryBuffer.cpp intern/COM_MemoryBuffer.h - intern/COM_MemoryManager.cpp - intern/COM_MemoryManager.h - intern/COM_MemoryManagerState.cpp - intern/COM_MemoryManagerState.h intern/COM_WorkScheduler.cpp intern/COM_WorkScheduler.h intern/COM_WorkPackage.cpp diff --git a/source/blender/compositor/intern/COM_CPUDevice.cpp b/source/blender/compositor/intern/COM_CPUDevice.cpp index 43ec892985a..f151afd75be 100644 --- a/source/blender/compositor/intern/COM_CPUDevice.cpp +++ b/source/blender/compositor/intern/COM_CPUDevice.cpp @@ -29,14 +29,10 @@ void CPUDevice::execute(WorkPackage *work) rcti rect; executionGroup->determineChunkRect(&rect, chunkNumber); - MemoryBuffer ** inputBuffers = executionGroup->getInputBuffers(chunkNumber); - MemoryBuffer * outputBuffer = executionGroup->allocateOutputBuffer(chunkNumber, &rect); + MemoryBuffer ** inputBuffers = executionGroup->getInputBuffersCPU(); executionGroup->getOutputNodeOperation()->executeRegion(&rect, chunkNumber, inputBuffers); executionGroup->finalizeChunkExecution(chunkNumber, inputBuffers); - if (outputBuffer != NULL) { - outputBuffer->setCreatedState(); - } } diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.cpp b/source/blender/compositor/intern/COM_ExecutionGroup.cpp index e4fefa6a904..7ac3f757d8e 100644 --- a/source/blender/compositor/intern/COM_ExecutionGroup.cpp +++ b/source/blender/compositor/intern/COM_ExecutionGroup.cpp @@ -34,7 +34,6 @@ #include "COM_ViewerOperation.h" #include #include "BLI_math.h" -#include "COM_MemoryManager.h" #include "PIL_time.h" #include "COM_ChunkOrder.h" #include @@ -362,7 +361,24 @@ void ExecutionGroup::execute(ExecutionSystem *graph) delete[] chunkOrder; } -MemoryBuffer** ExecutionGroup::getInputBuffers(int chunkNumber) +MemoryBuffer** ExecutionGroup::getInputBuffersCPU() +{ + vector memoryproxies; + unsigned int index; + + this->determineDependingMemoryProxies(&memoryproxies); + MemoryBuffer **memoryBuffers = new MemoryBuffer*[this->cachedMaxReadBufferOffset]; + for (index = 0 ; index < this->cachedMaxReadBufferOffset ; index ++) { + memoryBuffers[index] = NULL; + } + for (index = 0 ; index < this->cachedReadOperations.size(); index ++) { + ReadBufferOperation *readOperation = (ReadBufferOperation*)this->cachedReadOperations[index]; + memoryBuffers[readOperation->getOffset()] = readOperation->getMemoryProxy()->getBuffer(); + } + return memoryBuffers; +} + +MemoryBuffer** ExecutionGroup::getInputBuffersOpenCL(int chunkNumber) { rcti rect; vector memoryproxies; @@ -385,6 +401,8 @@ MemoryBuffer** ExecutionGroup::getInputBuffers(int chunkNumber) return memoryBuffers; } +// @todo: for opencl the memory buffers size needs to be same as the needed size +// currently this method is not called, but will be when opencl nodes are created MemoryBuffer *ExecutionGroup::constructConsolidatedMemoryBuffer(MemoryProxy *memoryProxy, rcti *rect) { // find all chunks inside the rect @@ -399,8 +417,7 @@ MemoryBuffer *ExecutionGroup::constructConsolidatedMemoryBuffer(MemoryProxy *mem const int maxychunk = ceil((rect->ymax-1)/chunkSizef); if (maxxchunk== minxchunk+1 && maxychunk == minychunk+1) { - const int chunkNumber = minxchunk+minychunk*numberOfXChunks; - MemoryBuffer *result = MemoryManager::getMemoryBuffer(memoryProxy, chunkNumber); + MemoryBuffer *result =memoryProxy->getBuffer(); return result; } @@ -420,7 +437,7 @@ MemoryBuffer *ExecutionGroup::constructConsolidatedMemoryBuffer(MemoryProxy *mem for (indexx = max(minxchunk, 0); indexxnumberOfXChunks, maxxchunk) ; indexx++) { for (indexy = max(minychunk, 0); indexynumberOfYChunks, maxychunk) ; indexy++) { int chunkNumber = indexx+indexy*this->numberOfXChunks; - MemoryBuffer *chunkBuffer = MemoryManager::getMemoryBuffer(memoryProxy, chunkNumber); + MemoryBuffer *chunkBuffer = memoryProxy->getBuffer(); result->copyContentFrom(chunkBuffer); } } @@ -432,8 +449,6 @@ void ExecutionGroup::finalizeChunkExecution(int chunkNumber, MemoryBuffer** memo { if (this->chunkExecutionStates[chunkNumber] == COM_ES_SCHEDULED) this->chunkExecutionStates[chunkNumber] = COM_ES_EXECUTED; - else - throw "Threading inconsistency"; this->chunksFinished++; if (memoryBuffers) { @@ -477,7 +492,7 @@ MemoryBuffer *ExecutionGroup::allocateOutputBuffer(int chunkNumber, rcti *rect) NodeOperation * operation = this->getOutputNodeOperation(); if (operation->isWriteBufferOperation()) { WriteBufferOperation *writeOperation = (WriteBufferOperation*)operation; - outputBuffer = MemoryManager::allocateMemoryBuffer(writeOperation->getMemoryProxy(), chunkNumber, rect); +// @todo outputBuffer = MemoryManager::allocateMemoryBuffer(writeOperation->getMemoryProxy(), chunkNumber, rect); } return outputBuffer; } diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.h b/source/blender/compositor/intern/COM_ExecutionGroup.h index adab7df4690..cbdc9bb1787 100644 --- a/source/blender/compositor/intern/COM_ExecutionGroup.h +++ b/source/blender/compositor/intern/COM_ExecutionGroup.h @@ -334,8 +334,16 @@ public: * @param chunkNumber the chunk to be calculated * @return MemoryBuffer** the inputbuffers */ - MemoryBuffer** getInputBuffers(int chunkNumber); - + 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 diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cpp b/source/blender/compositor/intern/COM_ExecutionSystem.cpp index 0d4c7cde68f..96d2a6f4434 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystem.cpp +++ b/source/blender/compositor/intern/COM_ExecutionSystem.cpp @@ -31,7 +31,6 @@ #include "COM_NodeBase.h" #include "COM_WorkScheduler.h" #include "COM_ReadBufferOperation.h" -#include "COM_MemoryManager.h" #include "stdio.h" #include "COM_GroupNode.h" #include "COM_WriteBufferOperation.h" @@ -114,8 +113,6 @@ void ExecutionSystem::execute() order ++; } } - - MemoryManager::initialize(); unsigned int index; for (index = 0 ; index < this->operations.size() ; index ++) { @@ -156,7 +153,6 @@ void ExecutionSystem::execute() ExecutionGroup * executionGroup = this->groups[index]; executionGroup->deinitExecution(); } - MemoryManager::clear(); } void ExecutionSystem::addOperation(NodeOperation *operation) diff --git a/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp b/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp index 94376f73de9..67554cd464b 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp +++ b/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp @@ -31,7 +31,6 @@ #include "COM_NodeBase.h" #include "COM_WorkScheduler.h" #include "COM_ReadBufferOperation.h" -#include "COM_MemoryManager.h" #include "stdio.h" #include "COM_GroupNode.h" #include "COM_WriteBufferOperation.h" diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.cpp b/source/blender/compositor/intern/COM_MemoryBuffer.cpp index 19c2c96a8f2..d22c75c922b 100644 --- a/source/blender/compositor/intern/COM_MemoryBuffer.cpp +++ b/source/blender/compositor/intern/COM_MemoryBuffer.cpp @@ -44,7 +44,7 @@ MemoryBuffer::MemoryBuffer(MemoryProxy * memoryProxy, unsigned int chunkNumber, BLI_init_rcti(&this->rect, rect->xmin, rect->xmax, rect->ymin, rect->ymax); this->memoryProxy = memoryProxy; this->chunkNumber = chunkNumber; - this->buffer = (float*)MEM_mallocN(sizeof(float)*determineBufferSize()*4, "COM_MemoryBuffer"); + this->buffer = (float*)MEM_mallocN(sizeof(float)*determineBufferSize()*COM_NUMBER_OF_CHANNELS, "COM_MemoryBuffer"); this->state = COM_MB_ALLOCATED; this->datatype = COM_DT_COLOR; this->chunkWidth = this->rect.xmax - this->rect.xmin; @@ -55,7 +55,7 @@ MemoryBuffer::MemoryBuffer(MemoryProxy * memoryProxy, rcti *rect) BLI_init_rcti(&this->rect, rect->xmin, rect->xmax, rect->ymin, rect->ymax); this->memoryProxy = memoryProxy; this->chunkNumber = -1; - this->buffer = (float*)MEM_mallocN(sizeof(float)*determineBufferSize()*4, "COM_MemoryBuffer"); + this->buffer = (float*)MEM_mallocN(sizeof(float)*determineBufferSize()*COM_NUMBER_OF_CHANNELS, "COM_MemoryBuffer"); this->state = COM_MB_TEMPORARILY; this->datatype = COM_DT_COLOR; this->chunkWidth = this->rect.xmax - this->rect.xmin; @@ -63,12 +63,12 @@ MemoryBuffer::MemoryBuffer(MemoryProxy * memoryProxy, rcti *rect) MemoryBuffer *MemoryBuffer::duplicate() { MemoryBuffer *result = new MemoryBuffer(this->memoryProxy, &this->rect); - memcpy(result->buffer, this->buffer, this->determineBufferSize()*4*sizeof(float)); + memcpy(result->buffer, this->buffer, this->determineBufferSize()*COM_NUMBER_OF_CHANNELS*sizeof(float)); return result; } void MemoryBuffer::clear() { - memset(this->buffer, 0, this->determineBufferSize()*4*sizeof(float)); + memset(this->buffer, 0, this->determineBufferSize()*COM_NUMBER_OF_CHANNELS*sizeof(float)); } float *MemoryBuffer::convertToValueBuffer() @@ -77,7 +77,7 @@ float *MemoryBuffer::convertToValueBuffer() int i; int offset4; float *result = new float[size]; - for (i = 0, offset4 = 0 ; i < size ; i ++, offset4 +=4) { + for (i = 0, offset4 = 0 ; i < size ; i ++, offset4 +=COM_NUMBER_OF_CHANNELS) { result[i] = this->buffer[offset4]; } @@ -107,9 +107,9 @@ void MemoryBuffer::copyContentFrom(MemoryBuffer *otherBuffer) for (otherY = minY ; otherYrect.ymin) * otherBuffer->chunkWidth + minX-otherBuffer->rect.xmin)*4; - offset = ((otherY - this->rect.ymin) * this->chunkWidth + minX-this->rect.xmin)*4; - memcpy(&this->buffer[offset], &otherBuffer->buffer[otherOffset], (maxX-minX) * 4*sizeof(float)); + otherOffset = ((otherY-otherBuffer->rect.ymin) * otherBuffer->chunkWidth + minX-otherBuffer->rect.xmin)*COM_NUMBER_OF_CHANNELS; + offset = ((otherY - this->rect.ymin) * this->chunkWidth + minX-this->rect.xmin)*COM_NUMBER_OF_CHANNELS; + memcpy(&this->buffer[offset], &otherBuffer->buffer[otherOffset], (maxX-minX) * COM_NUMBER_OF_CHANNELS*sizeof(float)); } } @@ -119,7 +119,7 @@ void MemoryBuffer::read(float *result, int x, int y) y>=this->rect.ymin && y < this->rect.ymax) { int dx = x-this->rect.xmin; int dy = y-this->rect.ymin; - int offset = (this->chunkWidth*dy+dx)*4; + int offset = (this->chunkWidth*dy+dx)*COM_NUMBER_OF_CHANNELS; result[0] = this->buffer[offset]; result[1] = this->buffer[offset+1]; result[2] = this->buffer[offset+2]; @@ -136,7 +136,7 @@ void MemoryBuffer::writePixel(int x, int y, float color[4]) { if (x>=this->rect.xmin && x < this->rect.xmax && y>=this->rect.ymin && y < this->rect.ymax) { - int offset = (this->chunkWidth*y+x)*4; + int offset = (this->chunkWidth*y+x)*COM_NUMBER_OF_CHANNELS; this->buffer[offset] = color[0]; this->buffer[offset+1] = color[1]; this->buffer[offset+2] = color[2]; diff --git a/source/blender/compositor/intern/COM_MemoryManager.cpp b/source/blender/compositor/intern/COM_MemoryManager.cpp deleted file mode 100644 index 4f97b0b1e80..00000000000 --- a/source/blender/compositor/intern/COM_MemoryManager.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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 - */ - -#include "COM_MemoryManager.h" -#include "BLI_threads.h" -#include -#include "COM_defines.h" - -vector buffers; - -ThreadMutex mutex; - -MemoryBuffer *MemoryManager::allocateMemoryBuffer(MemoryProxy *id, unsigned int chunkNumber, rcti *rect) -{ - MemoryBuffer *result = new MemoryBuffer(id, chunkNumber, rect); - MemoryManagerState * state = MemoryManager::getState(id); - state->addMemoryBuffer(result); - BLI_mutex_lock(&mutex); - buffers.push_back(result); - BLI_mutex_unlock(&mutex); - return result; -} - -void MemoryManager::addMemoryProxy(MemoryProxy *memoryProxy) -{ - MemoryManagerState * state = MemoryManager::getState(memoryProxy); - if (!state) { - state = new MemoryManagerState(memoryProxy); - memoryProxy->setState(state); - } -} -MemoryBuffer *MemoryManager::getMemoryBuffer(MemoryProxy *id, unsigned int chunkNumber) -{ - MemoryManagerState * state = MemoryManager::getState(id); - if (!state) { - return NULL; - } - MemoryBuffer *buffer = state->getMemoryBuffer(chunkNumber); - if (!buffer) return NULL; - return buffer; -} - -MemoryManagerState *MemoryManager::getState(MemoryProxy *memoryProxy) -{ - return memoryProxy->getState(); -} -void MemoryManager::initialize() -{ - BLI_mutex_init(&mutex); -} -void MemoryManager::clear() -{ - buffers.clear(); - BLI_mutex_end(&mutex); -} diff --git a/source/blender/compositor/intern/COM_MemoryManager.h b/source/blender/compositor/intern/COM_MemoryManager.h deleted file mode 100644 index 6194d40d9a5..00000000000 --- a/source/blender/compositor/intern/COM_MemoryManager.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * 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_MemoryManager_h_ -#define _COM_MemoryManager_h_ - -#include "COM_MemoryBuffer.h" -#include "COM_MemoryProxy.h" -#include "COM_ExecutionGroup.h" -#include "COM_MemoryManagerState.h" - -/** - * @page memorymanager The Memory Manager - * The compositor has its own MemoryManager. The goal of the MemoryManager is to manage the memory allocated by chunks. - * During execution new chunks will be created [MemoryManager.allocateMemoryBuffer] When calculation is finished the MemoryBuffer will get the state [MemoryBufferState.COM_MB_AVAILABLE]. - * From now on other ExecutionGroup and NodeOperations may read from the MemoryBuffer. - * The MemoryManager also has the capability to save MemoryBuffer's to disk in order to free some memory. - * - * @section S_MEM Memory manager - * The memory manager synchronize and optimize data across devices. - * Only one NodeOperation running on a device is able to write to a MemoryBuffer. This MemoryBuffer is only allocated on the main-device memory (CPU). - * The MemoryBuffer.state will be [MemoryBufferState.COM_MB_ALLOCATED]. As soon as the chunk has been executed the state changes to [MemoryBufferState.COM_MB_AVAILABLE]. This MemoryBuffer can now be used as inputBuffer of ExecutionGroup's. - * When needed the MemoryBuffer will be stored to a file. This will save memory that can be used by other tiles. - * @subsection S_MEM_1 Step one - * When a chunk of an ExecutionGroup is being executed by a device, the MemoryBuffer is allocated on the CPU. - *
-  * Allocation of the output MemoryBuffer
-  *  +----------------------------------------+
-  *  | Main device (CPU)                      |
-  *  | +----------------+   +--------------+  |
-  *  | | ExecutionGroup |   | MemoryBuffer |  |
-  *  | |                |   | Chunk a      |  |
-  *  | +----------------+   +--------------+  |
-  *  |                                        |
-  *  +----------------------------------------+
-  * 
- * @see MemoryManager.allocateMemoryBuffer - * - * @subsection S_MEM_2 Step two - * The Device will execute the ExecutionGroup. This differs per type of Device. CPUDevice will call the NodeOperation.executeRegion method of the outputnode of the ExecutionGroup. - * The [NodeOperation.executeRegion] writes the result to the allocated MemoryBuffer. When finished the state of the MemoryBuffer will be set to [MemoryBufferState.COM_MB_AVAILABLE]. - *
-  * Execute a chunk and store result to the MemoryBuffer
-  *  +----------------------------------------+
-  *  | Main device (CPU)                      |
-  *  | +----------------+   +--------------+  |
-  *  | | ExecutionGroup |   | MemoryBuffer |  |
-  *  | |                |   | Chunk a      |  |
-  *  | +----------------+   +--------------+  |
-  *  |         |                 ^            |
-  *  | +----------------+        |            |
-  *  | | NodeOperation  |--------+            |
-  *  | |                |     Write result    |
-  *  | +----------------+                     |
-  *  |                                        |
-  *  +----------------------------------------+
-  * 
- * @subsection S_MEM_3 Step 3 - * Other Chunks that depend on the MemoryBuffer can now use it. - * When a MemoryBuffer is being used its number of users are increased. When a 'user' is finished the number of users are decreased, If a MemoryBuffer has no users, the system can decide to store the data to disk and free some memory. - * @see MemoryBuffer.numberOfUsers - * @see MemoryBuffer.saveToDisk - * - * @subsection S_MEM_CON Temporarily MemoryBuffers - * Nodes like blur nodes can depend on multiple MemoryBuffer of the same MemoryProxy. These multiple buffers will be consolidated temporarily to a new MemoryBuffer. - * When execution is finished this temporarily memory buffer is deallicated. - *
-  *  Original MemoryBuffer's  Temporarily
-  *  +-------+ +-------+      MemoryBuffer
-  *  | MB A  | | MB B  |      +-------+-------+
-  *  +-------+ +-------+      | MB A  | MB B  |
-  *                       ==> +-------+-------+
-  *  +-------+ +-------+      | MB C  | MB D  |
-  *  | MB C  | | MB D  |      +-------+-------+
-  *  +-------+ +-------+
-  * 
- * @see ExecutionGroup.constructConsolidatedMemoryBuffer constructs the temporarily MemoryBuffer - * @see MemoryBuffer.state state is MemoryManagerState.COM_MB_TEMPORARILY - * @see ExecutionGroup.finalizeChunkExecution deallocate the temporarily MemoryBuffer - * @note this MemoryBuffer is not managed by the MemoryManager - */ - -/** - * @brief the memory manager for the compostor - * @ingroup Memory - */ -class MemoryManager { -private: - /** - * @brief retrieve the state of a certain MemoryProxy; - * @param memoryProxy the MemoryProxy to retrieve the state from - */ - static MemoryManagerState *getState(MemoryProxy *memoryProxy); -public: - /** - * @brief allocate a memory buffer - * @param memoryProxy the MemoryProxy to get a chunk from - * @param chunkNumber number of the chunk to receive - * @param rect size + position of the chunk - */ - static MemoryBuffer *allocateMemoryBuffer(MemoryProxy *memoryProxy, unsigned int chunkNumber, rcti *rect); - - /** - * @brief get a memory buffer - * @param memoryProxy the MemoryProxy to get a chunk from - * @param chunkNumber number of the chunk to receive - * @param addUser must we add a user to the chunk. - */ - static MemoryBuffer *getMemoryBuffer(MemoryProxy *memoryProxy, unsigned int chunkNumber); - - /** - * @brief add a MemoryProxy to the scope of the memory manager - * @param memoryProxy the MemoryProxy to add - */ - static void addMemoryProxy(MemoryProxy *memoryProxy); - - /** - * @brief clear the memory manager - */ - static void clear(); - - /** - * @brief initialize the memory manager. - */ - static void initialize(); -}; -#endif diff --git a/source/blender/compositor/intern/COM_MemoryManagerState.cpp b/source/blender/compositor/intern/COM_MemoryManagerState.cpp deleted file mode 100644 index 6098bf15569..00000000000 --- a/source/blender/compositor/intern/COM_MemoryManagerState.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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 - */ - -#include "COM_MemoryManagerState.h" - -MemoryManagerState::MemoryManagerState(MemoryProxy *memoryProxy) -{ - this->memoryProxy = memoryProxy; - this->currentSize = 0; - this->chunkBuffers = NULL; - BLI_mutex_init(&this->mutex); -} - -MemoryProxy * MemoryManagerState::getMemoryProxy() -{ - return this->memoryProxy; -} - -MemoryManagerState::~MemoryManagerState() -{ - this->memoryProxy = NULL; - unsigned int index; - for (index = 0 ; index < this->currentSize; index ++) { - MemoryBuffer *buffer = this->chunkBuffers[index]; - if (buffer) { - delete buffer; - } - } - delete [] this->chunkBuffers; - BLI_mutex_end(&this->mutex); -} - -void MemoryManagerState::addMemoryBuffer(MemoryBuffer *buffer) -{ - BLI_mutex_lock(&this->mutex); - unsigned int chunkNumber = buffer->getChunkNumber(); - unsigned int index; - while (this->currentSize <= chunkNumber) { - unsigned int newSize = this->currentSize + 1000; - MemoryBuffer** newbuffer = new MemoryBuffer*[newSize]; - MemoryBuffer** oldbuffer = this->chunkBuffers; - - for (index = 0 ; index < this->currentSize ; index++) { - newbuffer[index] = oldbuffer[index]; - } - for (index = currentSize ; index < newSize; index++) { - newbuffer[index] = NULL; - } - - this->chunkBuffers = newbuffer; - this->currentSize = newSize; - if (oldbuffer) delete oldbuffer; - } - - if (this->chunkBuffers[chunkNumber] == NULL) { - this->chunkBuffers[chunkNumber] = buffer; - } - else { - throw "ALREADY ALLOCATED!"; - } - BLI_mutex_unlock(&this->mutex); -} - -MemoryBuffer *MemoryManagerState::getMemoryBuffer(unsigned int chunkNumber) -{ - MemoryBuffer *result = NULL; - if (chunkNumber< this->currentSize) { - result = this->chunkBuffers[chunkNumber]; - if (result) { - return result; - } - } - - BLI_mutex_lock(&this->mutex); - if (chunkNumber< this->currentSize) { - result = this->chunkBuffers[chunkNumber]; - } - - BLI_mutex_unlock(&this->mutex); - return result; -} diff --git a/source/blender/compositor/intern/COM_MemoryManagerState.h b/source/blender/compositor/intern/COM_MemoryManagerState.h deleted file mode 100644 index 8e8cb484d1a..00000000000 --- a/source/blender/compositor/intern/COM_MemoryManagerState.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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 - */ - -class MemoryManagerState; - -#ifndef _COM_MemoryManagerState_h_ -#define _COM_MemoryManagerState_h_ - -#include "COM_MemoryProxy.h" -#include "COM_MemoryBuffer.h" -#include -extern "C" { - #include "BLI_threads.h" -} - -/** - * @brief State of a MemoryProxy in the MemoryManager. - * @ingroup Memory - */ -class MemoryManagerState { -private: - /** - * @brief reference to the MemoryProxy of this state - */ - MemoryProxy *memoryProxy; - - /** - * @brief list of all chunkbuffers - */ - MemoryBuffer** chunkBuffers; - - /** - * @brief size of the chunkBuffers - */ - unsigned int currentSize; - - /** - * @brief lock to this memory for multithreading - */ - ThreadMutex mutex; -public: - /** - * @brief creates a new MemoryManagerState for a certain MemoryProxy. - */ - MemoryManagerState(MemoryProxy * memoryProxy); - /** - * @brief destructor - */ - ~MemoryManagerState(); - - /** - * @brief get the reference to the MemoryProxy this state belongs to. - */ - MemoryProxy *getMemoryProxy(); - - /** - * @brief add a new memorybuffer to the state - */ - void addMemoryBuffer(MemoryBuffer *buffer); - - /** - * @brief get the MemoryBuffer assiciated to a chunk. - * @param chunkNumber the chunknumber - */ - MemoryBuffer *getMemoryBuffer(unsigned int chunkNumber); -}; - -#endif diff --git a/source/blender/compositor/intern/COM_MemoryProxy.cpp b/source/blender/compositor/intern/COM_MemoryProxy.cpp index 7ff4f4949f0..15df11a77d1 100644 --- a/source/blender/compositor/intern/COM_MemoryProxy.cpp +++ b/source/blender/compositor/intern/COM_MemoryProxy.cpp @@ -25,15 +25,26 @@ MemoryProxy::MemoryProxy() { - this->state = NULL; this->writeBufferOperation = NULL; this->executor = NULL; } -MemoryProxy::~MemoryProxy() +void MemoryProxy::allocate(unsigned int width, unsigned int height) { - if (this->state) { - delete this->state; - this->state = NULL; + rcti result; + result.xmin = 0; + result.xmax = width; + result.ymin = 0; + result.ymax = height; + + buffer = new MemoryBuffer(this, &result); +} + +void MemoryProxy::free() +{ + if (buffer) { + delete buffer; + buffer = NULL; } } + diff --git a/source/blender/compositor/intern/COM_MemoryProxy.h b/source/blender/compositor/intern/COM_MemoryProxy.h index 276ebeed1e2..e0ac72de0d3 100644 --- a/source/blender/compositor/intern/COM_MemoryProxy.h +++ b/source/blender/compositor/intern/COM_MemoryProxy.h @@ -26,7 +26,6 @@ class MemoryProxy; #ifndef _COM_MemoryProxy_h #define _COM_MemoryProxy_h #include "COM_ExecutionGroup.h" -#include "COM_MemoryManagerState.h" class ExecutionGroup; @@ -48,12 +47,6 @@ private: */ ExecutionGroup *executor; - /** - * @brief data of the different chunks. - * @note state is part of this class due to optimization in the MemoryManager - */ - MemoryManagerState * state; - /** * @brief datatype of this MemoryProxy */ @@ -63,9 +56,14 @@ private: * @brief channel information of this buffer */ ChannelInfo channelInfo[COM_NUMBER_OF_CHANNELS]; + + /** + * @brief the allocated memory + */ + MemoryBuffer* buffer; + public: MemoryProxy(); - ~MemoryProxy(); /** * @brief set the ExecutionGroup that can be scheduled to calculate a certain chunk. @@ -89,18 +87,21 @@ public: * @return WriteBufferOperation */ WriteBufferOperation *getWriteBufferOperation() {return this->writeBufferOperation;} - + /** - * @brief set the memorymanager state of this MemoryProxy, this is set from the MemoryManager - * @param state the state to set + * @brief allocate memory of size widht x height */ - void setState(MemoryManagerState *state) {this->state = state;} - + void allocate(unsigned int width, unsigned int height); + /** - * @brief get the state of this MemoryProxy - * @return MemoryManagerState reference to the state of this MemoryProxy. + * @brief free the allocated memory */ - MemoryManagerState *getState() {return this->state;} + void free(); + + /** + * @brief get the allocated memory + */ + inline MemoryBuffer* getBuffer() {return this->buffer;} }; #endif diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h index 9222ce8d53a..73ba5b472d7 100644 --- a/source/blender/compositor/intern/COM_NodeOperation.h +++ b/source/blender/compositor/intern/COM_NodeOperation.h @@ -33,6 +33,7 @@ class NodeOperation; #include "COM_SocketReader.h" #include "OCL_opencl.h" #include "list" +#include "BLI_threads.h" class ReadBufferOperation; diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.cpp b/source/blender/compositor/intern/COM_OpenCLDevice.cpp index 0945b426a4e..692b96f40b3 100644 --- a/source/blender/compositor/intern/COM_OpenCLDevice.cpp +++ b/source/blender/compositor/intern/COM_OpenCLDevice.cpp @@ -53,7 +53,7 @@ void OpenCLDevice::execute(WorkPackage *work) rcti rect; executionGroup->determineChunkRect(&rect, chunkNumber); - MemoryBuffer ** inputBuffers = executionGroup->getInputBuffers(chunkNumber); + MemoryBuffer ** inputBuffers = executionGroup->getInputBuffersOpenCL(chunkNumber); MemoryBuffer * outputBuffer = executionGroup->allocateOutputBuffer(chunkNumber, &rect); executionGroup->getOutputNodeOperation()->executeOpenCLRegion(this->context, this->program, this->queue, &rect, chunkNumber, inputBuffers); diff --git a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp index 3af914f8d0e..498add2fc87 100644 --- a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp +++ b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp @@ -22,10 +22,8 @@ #include "COM_WriteBufferOperation.h" #include "COM_defines.h" -#include "COM_MemoryManager.h" #include -/// @TODO: writebuffers don't have an actual data type set. WriteBufferOperation::WriteBufferOperation() :NodeOperation() { this->addInputSocket(COM_DT_COLOR); @@ -46,20 +44,23 @@ void WriteBufferOperation::executePixel(float *color, float x, float y, PixelSam { input->read(color, x, y, sampler, inputBuffers); } + void WriteBufferOperation::initExecution() { - this->input = this->getInputOperation(0); - MemoryManager::addMemoryProxy(this->memoryProxy); + this->input = this->getInputOperation(0); + this->memoryProxy->allocate(this->width, this->height); } + void WriteBufferOperation::deinitExecution() { this->input = NULL; + this->memoryProxy->free(); } - void WriteBufferOperation::executeRegion(rcti *rect, unsigned int tileNumber, MemoryBuffer** memoryBuffers) { - MemoryBuffer *memoryBuffer = MemoryManager::getMemoryBuffer(this->getMemoryProxy(), tileNumber); + //MemoryBuffer *memoryBuffer = MemoryManager::getMemoryBuffer(this->getMemoryProxy(), tileNumber); + MemoryBuffer *memoryBuffer = this->memoryProxy->getBuffer(); float *buffer = memoryBuffer->getBuffer(); if (this->input->isComplex()) { void *data = this->input->initializeTileData(rect, memoryBuffers); @@ -67,14 +68,14 @@ void WriteBufferOperation::executeRegion(rcti *rect, unsigned int tileNumber, Me int y1 = rect->ymin; int x2 = rect->xmax; int y2 = rect->ymax; - int offset4 = 0; int x; int y; bool breaked = false; for (y = y1 ; y < y2 && (!breaked) ; y++) { + int offset4 = (y*memoryBuffer->getWidth()+x1)*COM_NUMBER_OF_CHANNELS; for (x = x1 ; x < x2; x++) { input->read(&(buffer[offset4]), x, y, memoryBuffers, data); - offset4 +=4; + offset4 +=COM_NUMBER_OF_CHANNELS; } if (tree->test_break && tree->test_break(tree->tbh)) { @@ -92,14 +93,15 @@ void WriteBufferOperation::executeRegion(rcti *rect, unsigned int tileNumber, Me int y1 = rect->ymin; int x2 = rect->xmax; int y2 = rect->ymax; - int offset4 = 0; + int x; int y; bool breaked = false; for (y = y1 ; y < y2 && (!breaked) ; y++) { + int offset4 = (y*memoryBuffer->getWidth()+x1)*COM_NUMBER_OF_CHANNELS; for (x = x1 ; x < x2 ; x++) { input->read(&(buffer[offset4]), x, y, COM_PS_NEAREST, memoryBuffers); - offset4 +=4; + offset4 +=COM_NUMBER_OF_CHANNELS; } if (tree->test_break && tree->test_break(tree->tbh)) { breaked = true; @@ -111,7 +113,7 @@ void WriteBufferOperation::executeRegion(rcti *rect, unsigned int tileNumber, Me void WriteBufferOperation::executeOpenCLRegion(cl_context context, cl_program program, cl_command_queue queue, rcti *rect, unsigned int chunkNumber, MemoryBuffer** inputMemoryBuffers) { - MemoryBuffer *outputMemoryBuffer = MemoryManager::getMemoryBuffer(this->getMemoryProxy(), chunkNumber); + MemoryBuffer *outputMemoryBuffer = this->getMemoryProxy()->getBuffer();// @todo wrong implementation needs revision float *outputFloatBuffer = outputMemoryBuffer->getBuffer(); cl_int error; /*