diff options
author | Jeroen Bakker <j.bakker@atmind.nl> | 2015-01-19 20:13:26 +0300 |
---|---|---|
committer | Jeroen Bakker <j.bakker@atmind.nl> | 2015-01-19 20:17:50 +0300 |
commit | 35d3b6316b21ad9ae7eb96a7a541c4051eae3441 (patch) | |
tree | dd4eea63f9229d87041e2f5a5679d05f1360afea /source/blender/compositor/intern | |
parent | a8fa291b8c539da7669463ef622d5c61ee9c90e7 (diff) |
D627: Memory usage optimization for the compositor.
The compostor used a fixed size of 4 floats to hold pixel data. this
patch will select size of a pixel based on its type.
It uses 1 float for Value, 3 float for vector and 4 floats for color
data types.
When benchmarking on shots (opening shot of caminandes) we get a
reduction of memory of 30% and a tiny speedup as less data
transformations needs to take place (but these are negligable.
More information of the patch can be found on
https://developer.blender.org/D627 and
http://wiki.blender.org/index.php/Dev:Ref/Proposals/Compositor2014_p1.1_TD
Developers: jbakker & mdewanchand
Thanks for Sergey for his indept review.
Diffstat (limited to 'source/blender/compositor/intern')
11 files changed, 195 insertions, 269 deletions
diff --git a/source/blender/compositor/intern/COM_ChannelInfo.cpp b/source/blender/compositor/intern/COM_ChannelInfo.cpp deleted file mode 100644 index 557075cdc80..00000000000 --- a/source/blender/compositor/intern/COM_ChannelInfo.cpp +++ /dev/null @@ -1,35 +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_ChannelInfo.h" -#include "COM_defines.h" -#include <stdio.h> - -/** - * @brief create new ChannelInfo instance and sets the defaults. - */ -ChannelInfo::ChannelInfo() -{ - this->m_number = 0; - this->m_premultiplied = true; - this->m_type = COM_CT_UNUSED; -} diff --git a/source/blender/compositor/intern/COM_ChannelInfo.h b/source/blender/compositor/intern/COM_ChannelInfo.h deleted file mode 100644 index ec78e7e1cb1..00000000000 --- a/source/blender/compositor/intern/COM_ChannelInfo.h +++ /dev/null @@ -1,121 +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_ChannelInfo_h -#define _COM_ChannelInfo_h - -#include <vector> -#include "BKE_text.h" -#include <string> -#include "DNA_node_types.h" -#include "BLI_rect.h" - -using namespace std; - -/** - * @brief List of possible channel types - * @ingroup Model - */ -typedef enum ChannelType { - COM_CT_ColorComponent /** @brief this channel is contains color information. Specific used is determined by channelnumber, and in the future color space */, - COM_CT_Alpha /** @brief this channel is contains transparency value */, - COM_CT_Value /** @brief this channel is contains a value */, - COM_CT_X /** @brief this channel is contains a X value */, - COM_CT_Y /** @brief this channel is contains a Y value */, - COM_CT_Z /** @brief this channel is contains a Z value */, - COM_CT_W /** @brief this channel is contains a W value */, - COM_CT_UNUSED /** @brief this channel is unused */ -} ChannelType; - -/** - * @brief ChannelInfo holds information about a channel. - * - * Channels are transported from node to node via a NodeLink. - * ChannelInfo holds specific setting of these channels in order that the to-node of the link - * Can handle specific logic per channel setting. - * - * @note currently this is not used, but a future place to implement color spacing and other things. - * @ingroup Model - */ -class ChannelInfo { -private: - /** - * @brief the channel number, in the link. [0-3] - */ - int m_number; - - /** - * @brief type of channel - */ - ChannelType m_type; - - /** - * @brieg Is this value in this channel premultiplied with its alpha - * @note only valid if type = ColorComponent; - */ - bool m_premultiplied; - -// /** -// * Color space of this value. -// * only valid when type = ColorComponent; -// */ -// string colorspacename; - -public: - /** - * @brief creates a new ChannelInfo and set default values - */ - ChannelInfo(); - - /** - * @brief set the index of this channel in the NodeLink - */ - void setNumber(const int number) { this->m_number = number; } - - /** - * @brief get the index of this channel in the NodeLink - */ - const int getNumber() const { return this->m_number; } - - /** - * @brief set the type of channel - */ - void setType(const ChannelType type) { this->m_type = type; } - - /** - * @brief get the type of channel - */ - const ChannelType getType() const { return this->m_type; } - - /** - * @brief set the premultiplicatioin of this channel - */ - void setPremultiplied(const bool premultiplied) { this->m_premultiplied = premultiplied; } - - /** - * @brief is this channel premultiplied - */ - const bool isPremultiplied() const { return this->m_premultiplied; } -}; - - -#endif diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cpp b/source/blender/compositor/intern/COM_ExecutionSystem.cpp index 7c08188db90..0667271f4b1 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystem.cpp +++ b/source/blender/compositor/intern/COM_ExecutionSystem.cpp @@ -137,11 +137,15 @@ void ExecutionSystem::execute() } unsigned int index; + // First allocale all write buffer for (index = 0; index < this->m_operations.size(); index++) { NodeOperation *operation = this->m_operations[index]; - operation->setbNodeTree(this->m_context.getbNodeTree()); - operation->initExecution(); + if (operation->isWriteBufferOperation()) { + operation->setbNodeTree(this->m_context.getbNodeTree()); + operation->initExecution(); + } } + // Connect read buffers to their write buffers for (index = 0; index < this->m_operations.size(); index++) { NodeOperation *operation = this->m_operations[index]; if (operation->isReadBufferOperation()) { @@ -149,6 +153,14 @@ void ExecutionSystem::execute() readOperation->updateMemoryBuffer(); } } + // initialize other operations + for (index = 0; index < this->m_operations.size(); index++) { + NodeOperation *operation = this->m_operations[index]; + if (!operation->isWriteBufferOperation()) { + operation->setbNodeTree(this->m_context.getbNodeTree()); + operation->initExecution(); + } + } for (index = 0; index < this->m_groups.size(); index++) { ExecutionGroup *executionGroup = this->m_groups[index]; executionGroup->setChunksize(this->m_context.getChunksize()); diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.cpp b/source/blender/compositor/intern/COM_MemoryBuffer.cpp index c59ecced93c..58767960cc8 100644 --- a/source/blender/compositor/intern/COM_MemoryBuffer.cpp +++ b/source/blender/compositor/intern/COM_MemoryBuffer.cpp @@ -27,6 +27,18 @@ using std::min; using std::max; +static unsigned int determine_num_channels(DataType datatype) { + switch (datatype) { + case COM_DT_VALUE: + return COM_NUM_CHANNELS_VALUE; + case COM_DT_VECTOR: + return COM_NUM_CHANNELS_VECTOR; + case COM_DT_COLOR: + default: + return COM_NUM_CHANNELS_COLOR; + } +} + unsigned int MemoryBuffer::determineBufferSize() { return getWidth() * getHeight(); @@ -34,61 +46,62 @@ unsigned int MemoryBuffer::determineBufferSize() int MemoryBuffer::getWidth() const { - return this->m_rect.xmax - this->m_rect.xmin; + return this->m_width; } int MemoryBuffer::getHeight() const { - return this->m_rect.ymax - this->m_rect.ymin; + return this->m_height; } MemoryBuffer::MemoryBuffer(MemoryProxy *memoryProxy, unsigned int chunkNumber, rcti *rect) { BLI_rcti_init(&this->m_rect, rect->xmin, rect->xmax, rect->ymin, rect->ymax); + this->m_width = BLI_rcti_size_x(&this->m_rect); + this->m_height = BLI_rcti_size_y(&this->m_rect); this->m_memoryProxy = memoryProxy; this->m_chunkNumber = chunkNumber; - this->m_buffer = (float *)MEM_mallocN_aligned(sizeof(float) * determineBufferSize() * COM_NUMBER_OF_CHANNELS, 16, "COM_MemoryBuffer"); + this->m_num_channels = determine_num_channels(memoryProxy->getDataType()); + this->m_buffer = (float *)MEM_mallocN_aligned(sizeof(float) * determineBufferSize() * this->m_num_channels, 16, "COM_MemoryBuffer"); this->m_state = COM_MB_ALLOCATED; - this->m_datatype = COM_DT_COLOR; - this->m_chunkWidth = this->m_rect.xmax - this->m_rect.xmin; + this->m_datatype = memoryProxy->getDataType();; } MemoryBuffer::MemoryBuffer(MemoryProxy *memoryProxy, rcti *rect) { BLI_rcti_init(&this->m_rect, rect->xmin, rect->xmax, rect->ymin, rect->ymax); + this->m_width = BLI_rcti_size_x(&this->m_rect); + this->m_height = BLI_rcti_size_y(&this->m_rect); this->m_memoryProxy = memoryProxy; this->m_chunkNumber = -1; - this->m_buffer = (float *)MEM_mallocN_aligned(sizeof(float) * determineBufferSize() * COM_NUMBER_OF_CHANNELS, 16, "COM_MemoryBuffer"); + this->m_num_channels = determine_num_channels(memoryProxy->getDataType()); + this->m_buffer = (float *)MEM_mallocN_aligned(sizeof(float) * determineBufferSize() * this->m_num_channels, 16, "COM_MemoryBuffer"); + this->m_state = COM_MB_TEMPORARILY; + this->m_datatype = memoryProxy->getDataType(); +} +MemoryBuffer::MemoryBuffer(DataType dataType, rcti *rect) +{ + BLI_rcti_init(&this->m_rect, rect->xmin, rect->xmax, rect->ymin, rect->ymax); + this->m_width = BLI_rcti_size_x(&this->m_rect); + this->m_height = BLI_rcti_size_y(&this->m_rect); + this->m_height = this->m_rect.ymax - this->m_rect.ymin; + this->m_memoryProxy = NULL; + this->m_chunkNumber = -1; + this->m_num_channels = determine_num_channels(dataType); + this->m_buffer = (float *)MEM_mallocN_aligned(sizeof(float) * determineBufferSize() * this->m_num_channels, 16, "COM_MemoryBuffer"); this->m_state = COM_MB_TEMPORARILY; - this->m_datatype = COM_DT_COLOR; - this->m_chunkWidth = this->m_rect.xmax - this->m_rect.xmin; + this->m_datatype = dataType; } MemoryBuffer *MemoryBuffer::duplicate() { MemoryBuffer *result = new MemoryBuffer(this->m_memoryProxy, &this->m_rect); - memcpy(result->m_buffer, this->m_buffer, this->determineBufferSize() * COM_NUMBER_OF_CHANNELS * sizeof(float)); + memcpy(result->m_buffer, this->m_buffer, this->determineBufferSize() * this->m_num_channels * sizeof(float)); return result; } void MemoryBuffer::clear() { - memset(this->m_buffer, 0, this->determineBufferSize() * COM_NUMBER_OF_CHANNELS * sizeof(float)); + memset(this->m_buffer, 0, this->determineBufferSize() * this->m_num_channels * sizeof(float)); } -float *MemoryBuffer::convertToValueBuffer() -{ - const unsigned int size = this->determineBufferSize(); - unsigned int i; - - float *result = (float *)MEM_mallocN(sizeof(float) * size, __func__); - - const float *fp_src = this->m_buffer; - float *fp_dst = result; - - for (i = 0; i < size; i++, fp_dst++, fp_src += COM_NUMBER_OF_CHANNELS) { - *fp_dst = *fp_src; - } - - return result; -} float MemoryBuffer::getMaximumValue() { @@ -98,7 +111,7 @@ float MemoryBuffer::getMaximumValue() const float *fp_src = this->m_buffer; - for (i = 0; i < size; i++, fp_src += COM_NUMBER_OF_CHANNELS) { + for (i = 0; i < size; i++, fp_src += this->m_num_channels) { float value = *fp_src; if (value > result) { result = value; @@ -116,7 +129,7 @@ float MemoryBuffer::getMaximumValue(rcti *rect) BLI_rcti_isect(rect, &this->m_rect, &rect_clamp); if (!BLI_rcti_is_empty(&rect_clamp)) { - MemoryBuffer *temp = new MemoryBuffer(NULL, &rect_clamp); + MemoryBuffer *temp = new MemoryBuffer(this->m_datatype, &rect_clamp); temp->copyContentFrom(this); float result = temp->getMaximumValue(); delete temp; @@ -152,9 +165,9 @@ void MemoryBuffer::copyContentFrom(MemoryBuffer *otherBuffer) for (otherY = minY; otherY < maxY; otherY++) { - otherOffset = ((otherY - otherBuffer->m_rect.ymin) * otherBuffer->m_chunkWidth + minX - otherBuffer->m_rect.xmin) * COM_NUMBER_OF_CHANNELS; - offset = ((otherY - this->m_rect.ymin) * this->m_chunkWidth + minX - this->m_rect.xmin) * COM_NUMBER_OF_CHANNELS; - memcpy(&this->m_buffer[offset], &otherBuffer->m_buffer[otherOffset], (maxX - minX) * COM_NUMBER_OF_CHANNELS * sizeof(float)); + otherOffset = ((otherY - otherBuffer->m_rect.ymin) * otherBuffer->m_width + minX - otherBuffer->m_rect.xmin) * this->m_num_channels; + offset = ((otherY - this->m_rect.ymin) * this->m_width + minX - this->m_rect.xmin) * this->m_num_channels; + memcpy(&this->m_buffer[offset], &otherBuffer->m_buffer[otherOffset], (maxX - minX) * this->m_num_channels * sizeof(float)); } } @@ -163,9 +176,8 @@ void MemoryBuffer::writePixel(int x, int y, const float color[4]) if (x >= this->m_rect.xmin && x < this->m_rect.xmax && y >= this->m_rect.ymin && y < this->m_rect.ymax) { - const int offset = (this->m_chunkWidth * (y - this->m_rect.ymin) + x - this->m_rect.xmin) * COM_NUMBER_OF_CHANNELS; - copy_v4_v4(&this->m_buffer[offset], color); - } + const int offset = (this->m_width * (y - this->m_rect.ymin) + x - this->m_rect.xmin) * this->m_num_channels; + memcpy(&this->m_buffer[offset], color, sizeof(float)*this->m_num_channels); } } void MemoryBuffer::addPixel(int x, int y, const float color[4]) @@ -173,8 +185,12 @@ void MemoryBuffer::addPixel(int x, int y, const float color[4]) if (x >= this->m_rect.xmin && x < this->m_rect.xmax && y >= this->m_rect.ymin && y < this->m_rect.ymax) { - const int offset = (this->m_chunkWidth * (y - this->m_rect.ymin) + x - this->m_rect.xmin) * COM_NUMBER_OF_CHANNELS; - add_v4_v4(&this->m_buffer[offset], color); + const int offset = (this->m_width * (y - this->m_rect.ymin) + x - this->m_rect.xmin) * this->m_num_channels; + float *dst = &this->m_buffer[offset]; + const float *src = color; + for (int i = 0; i < this->m_num_channels ; i++, dst++, src++) { + *dst += *src; + } } } @@ -208,8 +224,9 @@ static void read_ewa_pixel_sampled(void *userdata, int x, int y, float result[4] } } -void MemoryBuffer::readEWA(float result[4], const float uv[2], const float derivatives[2][2], PixelSampler sampler) +void MemoryBuffer::readEWA(float *result, const float uv[2], const float derivatives[2][2], PixelSampler sampler) { + BLI_assert(this->m_datatype==COM_DT_COLOR); ReadEWAData data; data.buffer = this; data.sampler = sampler; diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.h b/source/blender/compositor/intern/COM_MemoryBuffer.h index d6ef9cd673e..70b4dec2bed 100644 --- a/source/blender/compositor/intern/COM_MemoryBuffer.h +++ b/source/blender/compositor/intern/COM_MemoryBuffer.h @@ -83,11 +83,6 @@ private: unsigned int m_chunkNumber; /** - * @brief width of the chunk - */ - unsigned int m_chunkWidth; - - /** * @brief state of the buffer */ MemoryBufferState m_state; @@ -97,6 +92,15 @@ private: */ float *m_buffer; + /** + * @brief the number of channels of a single value in the buffer. + * For value buffers this is 1, vector 3 and color 4 + */ + unsigned int m_num_channels; + + int m_width; + int m_height; + public: /** * @brief construct new MemoryBuffer for a chunk @@ -107,7 +111,12 @@ public: * @brief construct new temporarily MemoryBuffer for an area */ MemoryBuffer(MemoryProxy *memoryProxy, rcti *rect); - + + /** + * @brief construct new temporarily MemoryBuffer for an area + */ + MemoryBuffer(DataType datatype, rcti *rect); + /** * @brief destructor */ @@ -117,7 +126,9 @@ public: * @brief read the ChunkNumber of this MemoryBuffer */ unsigned int getChunkNumber() { return this->m_chunkNumber; } - + + unsigned int get_num_channels() { return this->m_num_channels; } + /** * @brief get the data of this MemoryBuffer * @note buffer should already be available in memory @@ -134,8 +145,8 @@ public: inline void wrap_pixel(int &x, int &y, MemoryBufferExtend extend_x, MemoryBufferExtend extend_y) { - int w = m_rect.xmax - m_rect.xmin; - int h = m_rect.ymax - m_rect.ymin; + int w = this->m_width; + int h = this->m_height; x = x - m_rect.xmin; y = y - m_rect.ymin; @@ -164,7 +175,39 @@ public: } } - inline void read(float result[4], int x, int y, + inline void wrap_pixel(float &x, float &y, MemoryBufferExtend extend_x, MemoryBufferExtend extend_y) + { + float w = (float)this->m_width; + float h = (float)this->m_height; + x = x - m_rect.xmin; + y = y - m_rect.ymin; + + switch (extend_x) { + case COM_MB_CLIP: + break; + case COM_MB_EXTEND: + if (x < 0) x = 0.0f; + if (x >= w) x = w; + break; + case COM_MB_REPEAT: + x = fmodf(x, w); + break; + } + + switch (extend_y) { + case COM_MB_CLIP: + break; + case COM_MB_EXTEND: + if (y < 0) y = 0.0f; + if (y >= h) y = h; + break; + case COM_MB_REPEAT: + y = fmodf(y, h); + break; + } + } + + inline void read(float *result, int x, int y, MemoryBufferExtend extend_x = COM_MB_CLIP, MemoryBufferExtend extend_y = COM_MB_CLIP) { @@ -172,81 +215,54 @@ public: bool clip_y = (extend_y == COM_MB_CLIP && (y < m_rect.ymin || y >= m_rect.ymax)); if (clip_x || clip_y) { /* clip result outside rect is zero */ - zero_v4(result); + memset(result, 0, this->m_num_channels*sizeof(float)); } else { - wrap_pixel(x, y, extend_x, extend_y); - const int offset = (this->m_chunkWidth * y + x) * COM_NUMBER_OF_CHANNELS; - copy_v4_v4(result, &this->m_buffer[offset]); + int u = x; + int v = y; + this->wrap_pixel(u, v, extend_x, extend_y); + const int offset = (this->m_width * y + x) * this->m_num_channels; + float* buffer = &this->m_buffer[offset]; + memcpy(result, buffer, sizeof(float)*this->m_num_channels); } } - inline void readNoCheck(float result[4], int x, int y, + inline void readNoCheck(float *result, int x, int y, MemoryBufferExtend extend_x = COM_MB_CLIP, MemoryBufferExtend extend_y = COM_MB_CLIP) { - wrap_pixel(x, y, extend_x, extend_y); - const int offset = (this->m_chunkWidth * y + x) * COM_NUMBER_OF_CHANNELS; + int u = x; + int v = y; - BLI_assert(offset >= 0); - BLI_assert(offset < this->determineBufferSize() * COM_NUMBER_OF_CHANNELS); - BLI_assert(!(extend_x == COM_MB_CLIP && (x < m_rect.xmin || x >= m_rect.xmax)) && - !(extend_y == COM_MB_CLIP && (y < m_rect.ymin || y >= m_rect.ymax))); + this->wrap_pixel(u, v, extend_x, extend_y); + const int offset = (this->m_width * v + u) * this->m_num_channels; + BLI_assert(offset >= 0); + BLI_assert(offset < this->determineBufferSize() * this->m_num_channels); + BLI_assert(!(extend_x == COM_MB_CLIP && (u < m_rect.xmin || u >= m_rect.xmax)) && + !(extend_y == COM_MB_CLIP && (v < m_rect.ymin || v >= m_rect.ymax))); #if 0 /* always true */ BLI_assert((int)(MEM_allocN_len(this->m_buffer) / sizeof(*this->m_buffer)) == (int)(this->determineBufferSize() * COM_NUMBER_OF_CHANNELS)); #endif - - copy_v4_v4(result, &this->m_buffer[offset]); + float* buffer = &this->m_buffer[offset]; + memcpy(result, buffer, sizeof(float)*this->m_num_channels); } void writePixel(int x, int y, const float color[4]); void addPixel(int x, int y, const float color[4]); - inline void readBilinear(float result[4], float x, float y, + inline void readBilinear(float *result, float x, float y, MemoryBufferExtend extend_x = COM_MB_CLIP, MemoryBufferExtend extend_y = COM_MB_CLIP) { - int x1 = floor(x); - int y1 = floor(y); - int x2 = x1 + 1; - int y2 = y1 + 1; - wrap_pixel(x1, y1, extend_x, extend_y); - wrap_pixel(x2, y2, extend_x, extend_y); - - float valuex = x - x1; - float valuey = y - y1; - float mvaluex = 1.0f - valuex; - float mvaluey = 1.0f - valuey; - - float color1[4]; - float color2[4]; - float color3[4]; - float color4[4]; - - read(color1, x1, y1); - read(color2, x1, y2); - read(color3, x2, y1); - read(color4, x2, y2); - - color1[0] = color1[0] * mvaluey + color2[0] * valuey; - color1[1] = color1[1] * mvaluey + color2[1] * valuey; - color1[2] = color1[2] * mvaluey + color2[2] * valuey; - color1[3] = color1[3] * mvaluey + color2[3] * valuey; - - color3[0] = color3[0] * mvaluey + color4[0] * valuey; - color3[1] = color3[1] * mvaluey + color4[1] * valuey; - color3[2] = color3[2] * mvaluey + color4[2] * valuey; - color3[3] = color3[3] * mvaluey + color4[3] * valuey; - - result[0] = color1[0] * mvaluex + color3[0] * valuex; - result[1] = color1[1] * mvaluex + color3[1] * valuex; - result[2] = color1[2] * mvaluex + color3[2] * valuex; - result[3] = color1[3] * mvaluex + color3[3] * valuex; + float u = x; + float v = y; + this->wrap_pixel(u, v, extend_x, extend_y); + BLI_bilinear_interpolation_fl(this->m_buffer, result, this->m_width, this->m_height, this->m_num_channels, u, v); } - void readEWA(float result[4], const float uv[2], const float derivatives[2][2], PixelSampler sampler); + void readEWA(float *result, const float uv[2], const float derivatives[2][2], PixelSampler sampler); /** * @brief is this MemoryBuffer a temporarily buffer (based on an area, not on a chunk) @@ -284,7 +300,6 @@ public: MemoryBuffer *duplicate(); - float *convertToValueBuffer(); float getMaximumValue(); float getMaximumValue(rcti *rect); private: diff --git a/source/blender/compositor/intern/COM_MemoryProxy.cpp b/source/blender/compositor/intern/COM_MemoryProxy.cpp index 90ca0baea06..1df3e59db62 100644 --- a/source/blender/compositor/intern/COM_MemoryProxy.cpp +++ b/source/blender/compositor/intern/COM_MemoryProxy.cpp @@ -23,10 +23,11 @@ #include "COM_MemoryProxy.h" -MemoryProxy::MemoryProxy() +MemoryProxy::MemoryProxy(DataType datatype) { this->m_writeBufferOperation = NULL; this->m_executor = NULL; + this->m_datatype = datatype; } void MemoryProxy::allocate(unsigned int width, unsigned int height) diff --git a/source/blender/compositor/intern/COM_MemoryProxy.h b/source/blender/compositor/intern/COM_MemoryProxy.h index 233b035a2d7..b332852088b 100644 --- a/source/blender/compositor/intern/COM_MemoryProxy.h +++ b/source/blender/compositor/intern/COM_MemoryProxy.h @@ -63,8 +63,13 @@ private: */ MemoryBuffer *m_buffer; + /** + * @brief datatype of this MemoryProxy + */ + DataType m_datatype; + public: - MemoryProxy(); + MemoryProxy(DataType type); /** * @brief set the ExecutionGroup that can be scheduled to calculate a certain chunk. @@ -104,6 +109,8 @@ public: */ inline MemoryBuffer *getBuffer() { return this->m_buffer; } + inline DataType getDataType() { return this->m_datatype; } + #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("COM:MemoryProxy") #endif diff --git a/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp index fb5bc8fcd9b..74c05c3e62e 100644 --- a/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp +++ b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp @@ -476,7 +476,7 @@ void NodeOperationBuilder::add_input_buffers(NodeOperation *operation, NodeOpera /* check of other end already has write operation, otherwise add a new one */ WriteBufferOperation *writeoperation = find_attached_write_buffer_operation(output); if (!writeoperation) { - writeoperation = new WriteBufferOperation(); + writeoperation = new WriteBufferOperation(output->getDataType()); writeoperation->setbNodeTree(m_context->getbNodeTree()); addOperation(writeoperation); @@ -486,7 +486,7 @@ void NodeOperationBuilder::add_input_buffers(NodeOperation *operation, NodeOpera } /* add readbuffer op for the input */ - ReadBufferOperation *readoperation = new ReadBufferOperation(); + ReadBufferOperation *readoperation = new ReadBufferOperation(output->getDataType()); readoperation->setMemoryProxy(writeoperation->getMemoryProxy()); this->addOperation(readoperation); @@ -519,7 +519,7 @@ void NodeOperationBuilder::add_output_buffers(NodeOperation *operation, NodeOper /* if no write buffer operation exists yet, create a new one */ if (!writeOperation) { - writeOperation = new WriteBufferOperation(); + writeOperation = new WriteBufferOperation(operation->getOutputSocket()->getDataType()); writeOperation->setbNodeTree(m_context->getbNodeTree()); addOperation(writeOperation); @@ -534,7 +534,7 @@ void NodeOperationBuilder::add_output_buffers(NodeOperation *operation, NodeOper if (&target->getOperation() == writeOperation) continue; /* skip existing write op links */ - ReadBufferOperation *readoperation = new ReadBufferOperation(); + ReadBufferOperation *readoperation = new ReadBufferOperation(operation->getOutputSocket()->getDataType()); readoperation->setMemoryProxy(writeOperation->getMemoryProxy()); addOperation(readoperation); diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.cpp b/source/blender/compositor/intern/COM_OpenCLDevice.cpp index c5b663d2aef..7fc4fd38abd 100644 --- a/source/blender/compositor/intern/COM_OpenCLDevice.cpp +++ b/source/blender/compositor/intern/COM_OpenCLDevice.cpp @@ -24,6 +24,18 @@ #include "COM_WorkScheduler.h" typedef enum COM_VendorID {NVIDIA = 0x10DE, AMD = 0x1002} COM_VendorID; +const cl_image_format IMAGE_FORMAT_COLOR = { + CL_RGBA, + CL_FLOAT +}; +const cl_image_format IMAGE_FORMAT_VECTOR = { + CL_RGB, + CL_FLOAT +}; +const cl_image_format IMAGE_FORMAT_VALUE = { + CL_R, + CL_FLOAT +}; OpenCLDevice::OpenCLDevice(cl_context context, cl_device_id device, cl_program program, cl_int vendorId) { @@ -72,6 +84,21 @@ cl_mem OpenCLDevice::COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel, return COM_clAttachMemoryBufferToKernelParameter(kernel, parameterIndex, offsetIndex, cleanup, inputMemoryBuffers, (ReadBufferOperation *)reader); } +const cl_image_format* OpenCLDevice::determineImageFormat(MemoryBuffer *memoryBuffer) +{ + const cl_image_format *imageFormat; + int num_channels = memoryBuffer->get_num_channels(); + if (num_channels == 1) { + imageFormat = &IMAGE_FORMAT_VALUE; + } else if (num_channels == 3) { + imageFormat = &IMAGE_FORMAT_VECTOR; + } else { + imageFormat = &IMAGE_FORMAT_COLOR; + } + + return imageFormat; +} + cl_mem OpenCLDevice::COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel, int parameterIndex, int offsetIndex, list<cl_mem> *cleanup, MemoryBuffer **inputMemoryBuffers, ReadBufferOperation *reader) @@ -80,12 +107,9 @@ cl_mem OpenCLDevice::COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel, MemoryBuffer *result = reader->getInputMemoryBuffer(inputMemoryBuffers); - const cl_image_format imageFormat = { - CL_RGBA, - CL_FLOAT - }; + const cl_image_format *imageFormat = determineImageFormat(result); - cl_mem clBuffer = clCreateImage2D(this->m_context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, &imageFormat, result->getWidth(), + cl_mem clBuffer = clCreateImage2D(this->m_context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, imageFormat, result->getWidth(), result->getHeight(), 0, result->getBuffer(), &error); if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.h b/source/blender/compositor/intern/COM_OpenCLDevice.h index 94df2f2b44c..f8a8841ef47 100644 --- a/source/blender/compositor/intern/COM_OpenCLDevice.h +++ b/source/blender/compositor/intern/COM_OpenCLDevice.h @@ -94,6 +94,12 @@ public: */ void execute(WorkPackage *work); + /** + * @brief determine an image format + * @param memorybuffer + */ + static const cl_image_format* determineImageFormat(MemoryBuffer *memoryBuffer); + cl_context getContext() { return this->m_context; } cl_command_queue getQueue() { return this->m_queue; } diff --git a/source/blender/compositor/intern/COM_WorkScheduler.cpp b/source/blender/compositor/intern/COM_WorkScheduler.cpp index e1016731c7f..8445dee5ae4 100644 --- a/source/blender/compositor/intern/COM_WorkScheduler.cpp +++ b/source/blender/compositor/intern/COM_WorkScheduler.cpp @@ -196,7 +196,7 @@ void WorkScheduler::schedule(ExecutionGroup *group, int chunkNumber) BLI_thread_queue_push(g_cpuqueue, package); } #else - BLI_thread_queue_push(cpuqueue, package); + BLI_thread_queue_push(g_cpuqueue, package); #endif #endif } |