Blender  V2.93
COM_DenoiseOperation.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * Copyright 2019, Blender Foundation.
17  */
18 
19 #include "COM_DenoiseOperation.h"
20 #include "BLI_math.h"
21 #include "BLI_system.h"
22 #ifdef WITH_OPENIMAGEDENOISE
23 # include "BLI_threads.h"
24 # include <OpenImageDenoise/oidn.hpp>
25 static pthread_mutex_t oidn_lock = BLI_MUTEX_INITIALIZER;
26 #endif
27 #include <iostream>
28 
29 namespace blender::compositor {
30 
32 {
37  this->m_settings = nullptr;
38 }
40 {
42  this->m_inputProgramColor = getInputSocketReader(0);
43  this->m_inputProgramNormal = getInputSocketReader(1);
44  this->m_inputProgramAlbedo = getInputSocketReader(2);
45 }
46 
48 {
49  this->m_inputProgramColor = nullptr;
50  this->m_inputProgramNormal = nullptr;
51  this->m_inputProgramAlbedo = nullptr;
53 }
54 
56 {
57  MemoryBuffer *tileColor = (MemoryBuffer *)this->m_inputProgramColor->initializeTileData(rect2);
58  MemoryBuffer *tileNormal = (MemoryBuffer *)this->m_inputProgramNormal->initializeTileData(rect2);
59  MemoryBuffer *tileAlbedo = (MemoryBuffer *)this->m_inputProgramAlbedo->initializeTileData(rect2);
60  rcti rect;
61  rect.xmin = 0;
62  rect.ymin = 0;
63  rect.xmax = getWidth();
64  rect.ymax = getHeight();
66  float *data = result->getBuffer();
67  this->generateDenoise(data, tileColor, tileNormal, tileAlbedo, this->m_settings);
68  return result;
69 }
70 
72  ReadBufferOperation *readOperation,
73  rcti *output)
74 {
75  if (isCached()) {
76  return false;
77  }
78 
79  rcti newInput;
80  newInput.xmax = this->getWidth();
81  newInput.xmin = 0;
82  newInput.ymax = this->getHeight();
83  newInput.ymin = 0;
84  return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
85 }
86 
88  MemoryBuffer *inputTileColor,
89  MemoryBuffer *inputTileNormal,
90  MemoryBuffer *inputTileAlbedo,
91  NodeDenoise *settings)
92 {
93  float *inputBufferColor = inputTileColor->getBuffer();
94  BLI_assert(inputBufferColor);
95  if (!inputBufferColor) {
96  return;
97  }
98 #ifdef WITH_OPENIMAGEDENOISE
99  /* Always supported through Accelerate framework BNNS on macOS. */
100 # ifndef __APPLE__
101  if (BLI_cpu_support_sse41())
102 # endif
103  {
104  /* Since it's memory intensive, it's better to run only one instance of OIDN at a time.
105  * OpenImageDenoise is multithreaded internally and should use all available cores nonetheless.
106  */
107  BLI_mutex_lock(&oidn_lock);
108 
109  oidn::DeviceRef device = oidn::newDevice();
110  device.commit();
111 
112  oidn::FilterRef filter = device.newFilter("RT");
113  filter.setImage("color",
114  inputBufferColor,
115  oidn::Format::Float3,
116  inputTileColor->getWidth(),
117  inputTileColor->getHeight(),
118  0,
119  sizeof(float[4]));
120  if (inputTileNormal && inputTileNormal->getBuffer()) {
121  filter.setImage("normal",
122  inputTileNormal->getBuffer(),
123  oidn::Format::Float3,
124  inputTileNormal->getWidth(),
125  inputTileNormal->getHeight(),
126  0,
127  sizeof(float[3]));
128  }
129  if (inputTileAlbedo && inputTileAlbedo->getBuffer()) {
130  filter.setImage("albedo",
131  inputTileAlbedo->getBuffer(),
132  oidn::Format::Float3,
133  inputTileAlbedo->getWidth(),
134  inputTileAlbedo->getHeight(),
135  0,
136  sizeof(float[4]));
137  }
138  filter.setImage("output",
139  data,
140  oidn::Format::Float3,
141  inputTileColor->getWidth(),
142  inputTileColor->getHeight(),
143  0,
144  sizeof(float[4]));
145 
146  BLI_assert(settings);
147  if (settings) {
148  filter.set("hdr", settings->hdr);
149  filter.set("srgb", false);
150  }
151 
152  filter.commit();
153  filter.execute();
154  BLI_mutex_unlock(&oidn_lock);
155 
156  /* copy the alpha channel, OpenImageDenoise currently only supports RGB */
157  size_t numPixels = inputTileColor->getWidth() * inputTileColor->getHeight();
158  for (size_t i = 0; i < numPixels; i++) {
159  data[i * 4 + 3] = inputBufferColor[i * 4 + 3];
160  }
161  return;
162  }
163 #endif
164  /* If built without OIDN or running on an unsupported CPU, just pass through. */
165  UNUSED_VARS(inputTileAlbedo, inputTileNormal, settings);
166  ::memcpy(data,
167  inputBufferColor,
168  sizeof(float[4]) * inputTileColor->getWidth() * inputTileColor->getHeight());
169 }
170 
171 } // namespace blender::compositor
#define BLI_assert(a)
Definition: BLI_assert.h:58
int BLI_cpu_support_sse41(void)
Definition: system.c:153
#define BLI_MUTEX_INITIALIZER
Definition: BLI_threads.h:84
void BLI_mutex_lock(ThreadMutex *mutex)
Definition: threads.cc:401
void BLI_mutex_unlock(ThreadMutex *mutex)
Definition: threads.cc:406
#define UNUSED_VARS(...)
#define output
bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) override
MemoryBuffer * createMemoryBuffer(rcti *rect) override
void generateDenoise(float *data, MemoryBuffer *inputTileColor, MemoryBuffer *inputTileNormal, MemoryBuffer *inputTileAlbedo, NodeDenoise *settings)
a MemoryBuffer contains access to the data of a chunk
const int getHeight() const
get the height of this MemoryBuffer
const int getWidth() const
get the width of this MemoryBuffer
float * getBuffer()
get the data of this MemoryBuffer
virtual void * initializeTileData(rcti *)
void addInputSocket(DataType datatype, ResizeMode resize_mode=ResizeMode::Center)
void addOutputSocket(DataType datatype)
SocketReader * getInputSocketReader(unsigned int inputSocketindex)
virtual bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
@ Vector
Vector data type.
DO_INLINE void filter(lfVector *V, fmatrix3x3 *S)
int ymin
Definition: DNA_vec_types.h:80
int ymax
Definition: DNA_vec_types.h:80
int xmin
Definition: DNA_vec_types.h:79
int xmax
Definition: DNA_vec_types.h:79