Replaced tile based memory manager with a single aligned buffer
- should increase speed with large node setups - enables caching of buffers in the node editor (in the future) - OpenCL part still needs some work
This commit is contained in:
@@ -79,10 +79,6 @@ set(SRC
|
|||||||
intern/COM_MemoryProxy.h
|
intern/COM_MemoryProxy.h
|
||||||
intern/COM_MemoryBuffer.cpp
|
intern/COM_MemoryBuffer.cpp
|
||||||
intern/COM_MemoryBuffer.h
|
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.cpp
|
||||||
intern/COM_WorkScheduler.h
|
intern/COM_WorkScheduler.h
|
||||||
intern/COM_WorkPackage.cpp
|
intern/COM_WorkPackage.cpp
|
||||||
|
|||||||
@@ -29,14 +29,10 @@ void CPUDevice::execute(WorkPackage *work)
|
|||||||
rcti rect;
|
rcti rect;
|
||||||
|
|
||||||
executionGroup->determineChunkRect(&rect, chunkNumber);
|
executionGroup->determineChunkRect(&rect, chunkNumber);
|
||||||
MemoryBuffer ** inputBuffers = executionGroup->getInputBuffers(chunkNumber);
|
MemoryBuffer ** inputBuffers = executionGroup->getInputBuffersCPU();
|
||||||
MemoryBuffer * outputBuffer = executionGroup->allocateOutputBuffer(chunkNumber, &rect);
|
|
||||||
|
|
||||||
executionGroup->getOutputNodeOperation()->executeRegion(&rect, chunkNumber, inputBuffers);
|
executionGroup->getOutputNodeOperation()->executeRegion(&rect, chunkNumber, inputBuffers);
|
||||||
|
|
||||||
executionGroup->finalizeChunkExecution(chunkNumber, inputBuffers);
|
executionGroup->finalizeChunkExecution(chunkNumber, inputBuffers);
|
||||||
if (outputBuffer != NULL) {
|
|
||||||
outputBuffer->setCreatedState();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,6 @@
|
|||||||
#include "COM_ViewerOperation.h"
|
#include "COM_ViewerOperation.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "BLI_math.h"
|
#include "BLI_math.h"
|
||||||
#include "COM_MemoryManager.h"
|
|
||||||
#include "PIL_time.h"
|
#include "PIL_time.h"
|
||||||
#include "COM_ChunkOrder.h"
|
#include "COM_ChunkOrder.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -362,7 +361,24 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
|
|||||||
delete[] chunkOrder;
|
delete[] chunkOrder;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryBuffer** ExecutionGroup::getInputBuffers(int chunkNumber)
|
MemoryBuffer** ExecutionGroup::getInputBuffersCPU()
|
||||||
|
{
|
||||||
|
vector<MemoryProxy*> 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;
|
rcti rect;
|
||||||
vector<MemoryProxy*> memoryproxies;
|
vector<MemoryProxy*> memoryproxies;
|
||||||
@@ -385,6 +401,8 @@ MemoryBuffer** ExecutionGroup::getInputBuffers(int chunkNumber)
|
|||||||
return memoryBuffers;
|
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)
|
MemoryBuffer *ExecutionGroup::constructConsolidatedMemoryBuffer(MemoryProxy *memoryProxy, rcti *rect)
|
||||||
{
|
{
|
||||||
// find all chunks inside the rect
|
// find all chunks inside the rect
|
||||||
@@ -399,8 +417,7 @@ MemoryBuffer *ExecutionGroup::constructConsolidatedMemoryBuffer(MemoryProxy *mem
|
|||||||
const int maxychunk = ceil((rect->ymax-1)/chunkSizef);
|
const int maxychunk = ceil((rect->ymax-1)/chunkSizef);
|
||||||
|
|
||||||
if (maxxchunk== minxchunk+1 && maxychunk == minychunk+1) {
|
if (maxxchunk== minxchunk+1 && maxychunk == minychunk+1) {
|
||||||
const int chunkNumber = minxchunk+minychunk*numberOfXChunks;
|
MemoryBuffer *result =memoryProxy->getBuffer();
|
||||||
MemoryBuffer *result = MemoryManager::getMemoryBuffer(memoryProxy, chunkNumber);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -420,7 +437,7 @@ MemoryBuffer *ExecutionGroup::constructConsolidatedMemoryBuffer(MemoryProxy *mem
|
|||||||
for (indexx = max(minxchunk, 0); indexx<min((int)this->numberOfXChunks, maxxchunk) ; indexx++) {
|
for (indexx = max(minxchunk, 0); indexx<min((int)this->numberOfXChunks, maxxchunk) ; indexx++) {
|
||||||
for (indexy = max(minychunk, 0); indexy<min((int)this->numberOfYChunks, maxychunk) ; indexy++) {
|
for (indexy = max(minychunk, 0); indexy<min((int)this->numberOfYChunks, maxychunk) ; indexy++) {
|
||||||
int chunkNumber = indexx+indexy*this->numberOfXChunks;
|
int chunkNumber = indexx+indexy*this->numberOfXChunks;
|
||||||
MemoryBuffer *chunkBuffer = MemoryManager::getMemoryBuffer(memoryProxy, chunkNumber);
|
MemoryBuffer *chunkBuffer = memoryProxy->getBuffer();
|
||||||
result->copyContentFrom(chunkBuffer);
|
result->copyContentFrom(chunkBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -432,8 +449,6 @@ void ExecutionGroup::finalizeChunkExecution(int chunkNumber, MemoryBuffer** memo
|
|||||||
{
|
{
|
||||||
if (this->chunkExecutionStates[chunkNumber] == COM_ES_SCHEDULED)
|
if (this->chunkExecutionStates[chunkNumber] == COM_ES_SCHEDULED)
|
||||||
this->chunkExecutionStates[chunkNumber] = COM_ES_EXECUTED;
|
this->chunkExecutionStates[chunkNumber] = COM_ES_EXECUTED;
|
||||||
else
|
|
||||||
throw "Threading inconsistency";
|
|
||||||
|
|
||||||
this->chunksFinished++;
|
this->chunksFinished++;
|
||||||
if (memoryBuffers) {
|
if (memoryBuffers) {
|
||||||
@@ -477,7 +492,7 @@ MemoryBuffer *ExecutionGroup::allocateOutputBuffer(int chunkNumber, rcti *rect)
|
|||||||
NodeOperation * operation = this->getOutputNodeOperation();
|
NodeOperation * operation = this->getOutputNodeOperation();
|
||||||
if (operation->isWriteBufferOperation()) {
|
if (operation->isWriteBufferOperation()) {
|
||||||
WriteBufferOperation *writeOperation = (WriteBufferOperation*)operation;
|
WriteBufferOperation *writeOperation = (WriteBufferOperation*)operation;
|
||||||
outputBuffer = MemoryManager::allocateMemoryBuffer(writeOperation->getMemoryProxy(), chunkNumber, rect);
|
// @todo outputBuffer = MemoryManager::allocateMemoryBuffer(writeOperation->getMemoryProxy(), chunkNumber, rect);
|
||||||
}
|
}
|
||||||
return outputBuffer;
|
return outputBuffer;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -334,7 +334,15 @@ public:
|
|||||||
* @param chunkNumber the chunk to be calculated
|
* @param chunkNumber the chunk to be calculated
|
||||||
* @return MemoryBuffer** the inputbuffers
|
* @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
|
* @brief allocate the outputbuffer of a chunk
|
||||||
|
|||||||
@@ -31,7 +31,6 @@
|
|||||||
#include "COM_NodeBase.h"
|
#include "COM_NodeBase.h"
|
||||||
#include "COM_WorkScheduler.h"
|
#include "COM_WorkScheduler.h"
|
||||||
#include "COM_ReadBufferOperation.h"
|
#include "COM_ReadBufferOperation.h"
|
||||||
#include "COM_MemoryManager.h"
|
|
||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
#include "COM_GroupNode.h"
|
#include "COM_GroupNode.h"
|
||||||
#include "COM_WriteBufferOperation.h"
|
#include "COM_WriteBufferOperation.h"
|
||||||
@@ -114,8 +113,6 @@ void ExecutionSystem::execute()
|
|||||||
order ++;
|
order ++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryManager::initialize();
|
|
||||||
unsigned int index;
|
unsigned int index;
|
||||||
|
|
||||||
for (index = 0 ; index < this->operations.size() ; index ++) {
|
for (index = 0 ; index < this->operations.size() ; index ++) {
|
||||||
@@ -156,7 +153,6 @@ void ExecutionSystem::execute()
|
|||||||
ExecutionGroup * executionGroup = this->groups[index];
|
ExecutionGroup * executionGroup = this->groups[index];
|
||||||
executionGroup->deinitExecution();
|
executionGroup->deinitExecution();
|
||||||
}
|
}
|
||||||
MemoryManager::clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExecutionSystem::addOperation(NodeOperation *operation)
|
void ExecutionSystem::addOperation(NodeOperation *operation)
|
||||||
|
|||||||
@@ -31,7 +31,6 @@
|
|||||||
#include "COM_NodeBase.h"
|
#include "COM_NodeBase.h"
|
||||||
#include "COM_WorkScheduler.h"
|
#include "COM_WorkScheduler.h"
|
||||||
#include "COM_ReadBufferOperation.h"
|
#include "COM_ReadBufferOperation.h"
|
||||||
#include "COM_MemoryManager.h"
|
|
||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
#include "COM_GroupNode.h"
|
#include "COM_GroupNode.h"
|
||||||
#include "COM_WriteBufferOperation.h"
|
#include "COM_WriteBufferOperation.h"
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ MemoryBuffer::MemoryBuffer(MemoryProxy * memoryProxy, unsigned int chunkNumber,
|
|||||||
BLI_init_rcti(&this->rect, rect->xmin, rect->xmax, rect->ymin, rect->ymax);
|
BLI_init_rcti(&this->rect, rect->xmin, rect->xmax, rect->ymin, rect->ymax);
|
||||||
this->memoryProxy = memoryProxy;
|
this->memoryProxy = memoryProxy;
|
||||||
this->chunkNumber = chunkNumber;
|
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->state = COM_MB_ALLOCATED;
|
||||||
this->datatype = COM_DT_COLOR;
|
this->datatype = COM_DT_COLOR;
|
||||||
this->chunkWidth = this->rect.xmax - this->rect.xmin;
|
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);
|
BLI_init_rcti(&this->rect, rect->xmin, rect->xmax, rect->ymin, rect->ymax);
|
||||||
this->memoryProxy = memoryProxy;
|
this->memoryProxy = memoryProxy;
|
||||||
this->chunkNumber = -1;
|
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->state = COM_MB_TEMPORARILY;
|
||||||
this->datatype = COM_DT_COLOR;
|
this->datatype = COM_DT_COLOR;
|
||||||
this->chunkWidth = this->rect.xmax - this->rect.xmin;
|
this->chunkWidth = this->rect.xmax - this->rect.xmin;
|
||||||
@@ -63,12 +63,12 @@ MemoryBuffer::MemoryBuffer(MemoryProxy * memoryProxy, rcti *rect)
|
|||||||
MemoryBuffer *MemoryBuffer::duplicate()
|
MemoryBuffer *MemoryBuffer::duplicate()
|
||||||
{
|
{
|
||||||
MemoryBuffer *result = new MemoryBuffer(this->memoryProxy, &this->rect);
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
void MemoryBuffer::clear()
|
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()
|
float *MemoryBuffer::convertToValueBuffer()
|
||||||
@@ -77,7 +77,7 @@ float *MemoryBuffer::convertToValueBuffer()
|
|||||||
int i;
|
int i;
|
||||||
int offset4;
|
int offset4;
|
||||||
float *result = new float[size];
|
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];
|
result[i] = this->buffer[offset4];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,9 +107,9 @@ void MemoryBuffer::copyContentFrom(MemoryBuffer *otherBuffer)
|
|||||||
|
|
||||||
|
|
||||||
for (otherY = minY ; otherY<maxY ; otherY ++) {
|
for (otherY = minY ; otherY<maxY ; otherY ++) {
|
||||||
otherOffset = ((otherY-otherBuffer->rect.ymin) * otherBuffer->chunkWidth + minX-otherBuffer->rect.xmin)*4;
|
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)*4;
|
offset = ((otherY - this->rect.ymin) * this->chunkWidth + minX-this->rect.xmin)*COM_NUMBER_OF_CHANNELS;
|
||||||
memcpy(&this->buffer[offset], &otherBuffer->buffer[otherOffset], (maxX-minX) * 4*sizeof(float));
|
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) {
|
y>=this->rect.ymin && y < this->rect.ymax) {
|
||||||
int dx = x-this->rect.xmin;
|
int dx = x-this->rect.xmin;
|
||||||
int dy = y-this->rect.ymin;
|
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[0] = this->buffer[offset];
|
||||||
result[1] = this->buffer[offset+1];
|
result[1] = this->buffer[offset+1];
|
||||||
result[2] = this->buffer[offset+2];
|
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 &&
|
if (x>=this->rect.xmin && x < this->rect.xmax &&
|
||||||
y>=this->rect.ymin && y < this->rect.ymax) {
|
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] = color[0];
|
||||||
this->buffer[offset+1] = color[1];
|
this->buffer[offset+1] = color[1];
|
||||||
this->buffer[offset+2] = color[2];
|
this->buffer[offset+2] = color[2];
|
||||||
|
|||||||
@@ -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 <stdio.h>
|
|
||||||
#include "COM_defines.h"
|
|
||||||
|
|
||||||
vector<MemoryBuffer*> 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);
|
|
||||||
}
|
|
||||||
@@ -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.
|
|
||||||
* <pre>
|
|
||||||
* Allocation of the output MemoryBuffer
|
|
||||||
* +----------------------------------------+
|
|
||||||
* | Main device (CPU) |
|
|
||||||
* | +----------------+ +--------------+ |
|
|
||||||
* | | ExecutionGroup | | MemoryBuffer | |
|
|
||||||
* | | | | Chunk a | |
|
|
||||||
* | +----------------+ +--------------+ |
|
|
||||||
* | |
|
|
||||||
* +----------------------------------------+
|
|
||||||
* </pre>
|
|
||||||
* @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].
|
|
||||||
* <pre>
|
|
||||||
* Execute a chunk and store result to the MemoryBuffer
|
|
||||||
* +----------------------------------------+
|
|
||||||
* | Main device (CPU) |
|
|
||||||
* | +----------------+ +--------------+ |
|
|
||||||
* | | ExecutionGroup | | MemoryBuffer | |
|
|
||||||
* | | | | Chunk a | |
|
|
||||||
* | +----------------+ +--------------+ |
|
|
||||||
* | | ^ |
|
|
||||||
* | +----------------+ | |
|
|
||||||
* | | NodeOperation |--------+ |
|
|
||||||
* | | | Write result |
|
|
||||||
* | +----------------+ |
|
|
||||||
* | |
|
|
||||||
* +----------------------------------------+
|
|
||||||
* </pre>
|
|
||||||
* @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.
|
|
||||||
* <pre>
|
|
||||||
* Original MemoryBuffer's Temporarily
|
|
||||||
* +-------+ +-------+ MemoryBuffer
|
|
||||||
* | MB A | | MB B | +-------+-------+
|
|
||||||
* +-------+ +-------+ | MB A | MB B |
|
|
||||||
* ==> +-------+-------+
|
|
||||||
* +-------+ +-------+ | MB C | MB D |
|
|
||||||
* | MB C | | MB D | +-------+-------+
|
|
||||||
* +-------+ +-------+
|
|
||||||
* </pre>
|
|
||||||
* @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
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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 <vector>
|
|
||||||
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
|
|
||||||
@@ -25,15 +25,26 @@
|
|||||||
|
|
||||||
MemoryProxy::MemoryProxy()
|
MemoryProxy::MemoryProxy()
|
||||||
{
|
{
|
||||||
this->state = NULL;
|
|
||||||
this->writeBufferOperation = NULL;
|
this->writeBufferOperation = NULL;
|
||||||
this->executor = NULL;
|
this->executor = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryProxy::~MemoryProxy()
|
void MemoryProxy::allocate(unsigned int width, unsigned int height)
|
||||||
{
|
{
|
||||||
if (this->state) {
|
rcti result;
|
||||||
delete this->state;
|
result.xmin = 0;
|
||||||
this->state = NULL;
|
result.xmax = width;
|
||||||
|
result.ymin = 0;
|
||||||
|
result.ymax = height;
|
||||||
|
|
||||||
|
buffer = new MemoryBuffer(this, &result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryProxy::free()
|
||||||
|
{
|
||||||
|
if (buffer) {
|
||||||
|
delete buffer;
|
||||||
|
buffer = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ class MemoryProxy;
|
|||||||
#ifndef _COM_MemoryProxy_h
|
#ifndef _COM_MemoryProxy_h
|
||||||
#define _COM_MemoryProxy_h
|
#define _COM_MemoryProxy_h
|
||||||
#include "COM_ExecutionGroup.h"
|
#include "COM_ExecutionGroup.h"
|
||||||
#include "COM_MemoryManagerState.h"
|
|
||||||
|
|
||||||
class ExecutionGroup;
|
class ExecutionGroup;
|
||||||
|
|
||||||
@@ -48,12 +47,6 @@ private:
|
|||||||
*/
|
*/
|
||||||
ExecutionGroup *executor;
|
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
|
* @brief datatype of this MemoryProxy
|
||||||
*/
|
*/
|
||||||
@@ -63,9 +56,14 @@ private:
|
|||||||
* @brief channel information of this buffer
|
* @brief channel information of this buffer
|
||||||
*/
|
*/
|
||||||
ChannelInfo channelInfo[COM_NUMBER_OF_CHANNELS];
|
ChannelInfo channelInfo[COM_NUMBER_OF_CHANNELS];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief the allocated memory
|
||||||
|
*/
|
||||||
|
MemoryBuffer* buffer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MemoryProxy();
|
MemoryProxy();
|
||||||
~MemoryProxy();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief set the ExecutionGroup that can be scheduled to calculate a certain chunk.
|
* @brief set the ExecutionGroup that can be scheduled to calculate a certain chunk.
|
||||||
@@ -91,16 +89,19 @@ public:
|
|||||||
WriteBufferOperation *getWriteBufferOperation() {return this->writeBufferOperation;}
|
WriteBufferOperation *getWriteBufferOperation() {return this->writeBufferOperation;}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief set the memorymanager state of this MemoryProxy, this is set from the MemoryManager
|
* @brief allocate memory of size widht x height
|
||||||
* @param state the state to set
|
|
||||||
*/
|
*/
|
||||||
void setState(MemoryManagerState *state) {this->state = state;}
|
void allocate(unsigned int width, unsigned int height);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief get the state of this MemoryProxy
|
* @brief free the allocated memory
|
||||||
* @return MemoryManagerState reference to the state of this MemoryProxy.
|
|
||||||
*/
|
*/
|
||||||
MemoryManagerState *getState() {return this->state;}
|
void free();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief get the allocated memory
|
||||||
|
*/
|
||||||
|
inline MemoryBuffer* getBuffer() {return this->buffer;}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ class NodeOperation;
|
|||||||
#include "COM_SocketReader.h"
|
#include "COM_SocketReader.h"
|
||||||
#include "OCL_opencl.h"
|
#include "OCL_opencl.h"
|
||||||
#include "list"
|
#include "list"
|
||||||
|
#include "BLI_threads.h"
|
||||||
|
|
||||||
class ReadBufferOperation;
|
class ReadBufferOperation;
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ void OpenCLDevice::execute(WorkPackage *work)
|
|||||||
rcti rect;
|
rcti rect;
|
||||||
|
|
||||||
executionGroup->determineChunkRect(&rect, chunkNumber);
|
executionGroup->determineChunkRect(&rect, chunkNumber);
|
||||||
MemoryBuffer ** inputBuffers = executionGroup->getInputBuffers(chunkNumber);
|
MemoryBuffer ** inputBuffers = executionGroup->getInputBuffersOpenCL(chunkNumber);
|
||||||
MemoryBuffer * outputBuffer = executionGroup->allocateOutputBuffer(chunkNumber, &rect);
|
MemoryBuffer * outputBuffer = executionGroup->allocateOutputBuffer(chunkNumber, &rect);
|
||||||
|
|
||||||
executionGroup->getOutputNodeOperation()->executeOpenCLRegion(this->context, this->program, this->queue, &rect, chunkNumber, inputBuffers);
|
executionGroup->getOutputNodeOperation()->executeOpenCLRegion(this->context, this->program, this->queue, &rect, chunkNumber, inputBuffers);
|
||||||
|
|||||||
@@ -22,10 +22,8 @@
|
|||||||
|
|
||||||
#include "COM_WriteBufferOperation.h"
|
#include "COM_WriteBufferOperation.h"
|
||||||
#include "COM_defines.h"
|
#include "COM_defines.h"
|
||||||
#include "COM_MemoryManager.h"
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
/// @TODO: writebuffers don't have an actual data type set.
|
|
||||||
WriteBufferOperation::WriteBufferOperation() :NodeOperation()
|
WriteBufferOperation::WriteBufferOperation() :NodeOperation()
|
||||||
{
|
{
|
||||||
this->addInputSocket(COM_DT_COLOR);
|
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);
|
input->read(color, x, y, sampler, inputBuffers);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteBufferOperation::initExecution()
|
void WriteBufferOperation::initExecution()
|
||||||
{
|
{
|
||||||
this->input = this->getInputOperation(0);
|
this->input = this->getInputOperation(0);
|
||||||
MemoryManager::addMemoryProxy(this->memoryProxy);
|
this->memoryProxy->allocate(this->width, this->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteBufferOperation::deinitExecution()
|
void WriteBufferOperation::deinitExecution()
|
||||||
{
|
{
|
||||||
this->input = NULL;
|
this->input = NULL;
|
||||||
|
this->memoryProxy->free();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WriteBufferOperation::executeRegion(rcti *rect, unsigned int tileNumber, MemoryBuffer** memoryBuffers)
|
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();
|
float *buffer = memoryBuffer->getBuffer();
|
||||||
if (this->input->isComplex()) {
|
if (this->input->isComplex()) {
|
||||||
void *data = this->input->initializeTileData(rect, memoryBuffers);
|
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 y1 = rect->ymin;
|
||||||
int x2 = rect->xmax;
|
int x2 = rect->xmax;
|
||||||
int y2 = rect->ymax;
|
int y2 = rect->ymax;
|
||||||
int offset4 = 0;
|
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
bool breaked = false;
|
bool breaked = false;
|
||||||
for (y = y1 ; y < y2 && (!breaked) ; y++) {
|
for (y = y1 ; y < y2 && (!breaked) ; y++) {
|
||||||
|
int offset4 = (y*memoryBuffer->getWidth()+x1)*COM_NUMBER_OF_CHANNELS;
|
||||||
for (x = x1 ; x < x2; x++) {
|
for (x = x1 ; x < x2; x++) {
|
||||||
input->read(&(buffer[offset4]), x, y, memoryBuffers, data);
|
input->read(&(buffer[offset4]), x, y, memoryBuffers, data);
|
||||||
offset4 +=4;
|
offset4 +=COM_NUMBER_OF_CHANNELS;
|
||||||
|
|
||||||
}
|
}
|
||||||
if (tree->test_break && tree->test_break(tree->tbh)) {
|
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 y1 = rect->ymin;
|
||||||
int x2 = rect->xmax;
|
int x2 = rect->xmax;
|
||||||
int y2 = rect->ymax;
|
int y2 = rect->ymax;
|
||||||
int offset4 = 0;
|
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
bool breaked = false;
|
bool breaked = false;
|
||||||
for (y = y1 ; y < y2 && (!breaked) ; y++) {
|
for (y = y1 ; y < y2 && (!breaked) ; y++) {
|
||||||
|
int offset4 = (y*memoryBuffer->getWidth()+x1)*COM_NUMBER_OF_CHANNELS;
|
||||||
for (x = x1 ; x < x2 ; x++) {
|
for (x = x1 ; x < x2 ; x++) {
|
||||||
input->read(&(buffer[offset4]), x, y, COM_PS_NEAREST, memoryBuffers);
|
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)) {
|
if (tree->test_break && tree->test_break(tree->tbh)) {
|
||||||
breaked = true;
|
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)
|
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();
|
float *outputFloatBuffer = outputMemoryBuffer->getBuffer();
|
||||||
cl_int error;
|
cl_int error;
|
||||||
/*
|
/*
|
||||||
|
|||||||
Reference in New Issue
Block a user