[Bf-blender-cvs] [063b52b7f28] temp-compositor-fixes: Compositor: Add OIDN prefiltering option to Denoise node
Manuel Castilla
noreply at git.blender.org
Sun Sep 19 20:40:54 CEST 2021
Commit: 063b52b7f283a191b72dd48a3dadfeeea5cf42e1
Author: Manuel Castilla
Date: Sun Sep 19 20:12:53 2021 +0200
Branches: temp-compositor-fixes
https://developer.blender.org/rB063b52b7f283a191b72dd48a3dadfeeea5cf42e1
Compositor: Add OIDN prefiltering option to Denoise node
It's equivalent to the OpenImageDenoise prefiltering option in Cycles.
See D12043.
Prefilter modes:
- None: No prefiltering, use when guiding passes are noise-free.
- Fast: Denoise image and guiding passes together. Improves quality when
guiding passes are noisy using least amount of extra processing time.
- Accurate: Prefilter noisy guiding passes before denoising image.
Improves quality when guiding passes are noisy using extra
processing time.
Reviewed By: #compositing, jbakker, sergey
Differential Revision: https://developer.blender.org/D12342
===================================================================
M source/blender/compositor/nodes/COM_DenoiseNode.cc
M source/blender/compositor/operations/COM_DenoiseOperation.cc
M source/blender/compositor/operations/COM_DenoiseOperation.h
M source/blender/editors/space_node/drawnode.cc
M source/blender/makesdna/DNA_node_types.h
M source/blender/makesrna/intern/rna_nodetree.c
M source/blender/nodes/composite/nodes/node_composite_denoise.c
===================================================================
diff --git a/source/blender/compositor/nodes/COM_DenoiseNode.cc b/source/blender/compositor/nodes/COM_DenoiseNode.cc
index e58a9c7ba9a..cc9328414ef 100644
--- a/source/blender/compositor/nodes/COM_DenoiseNode.cc
+++ b/source/blender/compositor/nodes/COM_DenoiseNode.cc
@@ -31,6 +31,12 @@ DenoiseNode::DenoiseNode(bNode *editorNode) : Node(editorNode)
void DenoiseNode::convertToOperations(NodeConverter &converter,
const CompositorContext & /*context*/) const
{
+ if (!COM_is_denoise_supported()) {
+ converter.mapOutputSocket(getOutputSocket(0),
+ converter.addInputProxy(getInputSocket(0), false));
+ return;
+ }
+
bNode *node = this->getbNode();
NodeDenoise *denoise = (NodeDenoise *)node->storage;
@@ -39,8 +45,28 @@ void DenoiseNode::convertToOperations(NodeConverter &converter,
operation->setDenoiseSettings(denoise);
converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0));
- converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1));
- converter.mapInputSocket(getInputSocket(2), operation->getInputSocket(2));
+ if (denoise && denoise->prefilter == CMP_NODE_DENOISE_PREFILTER_ACCURATE) {
+ {
+ DenoisePrefilterOperation *normal_prefilter = new DenoisePrefilterOperation(
+ DataType::Vector);
+ normal_prefilter->set_image_name("normal");
+ converter.addOperation(normal_prefilter);
+ converter.mapInputSocket(getInputSocket(1), normal_prefilter->getInputSocket(0));
+ converter.addLink(normal_prefilter->getOutputSocket(), operation->getInputSocket(1));
+ }
+ {
+ DenoisePrefilterOperation *albedo_prefilter = new DenoisePrefilterOperation(DataType::Color);
+ albedo_prefilter->set_image_name("albedo");
+ converter.addOperation(albedo_prefilter);
+ converter.mapInputSocket(getInputSocket(2), albedo_prefilter->getInputSocket(0));
+ converter.addLink(albedo_prefilter->getOutputSocket(), operation->getInputSocket(2));
+ }
+ }
+ else {
+ converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1));
+ converter.mapInputSocket(getInputSocket(2), operation->getInputSocket(2));
+ }
+
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket(0));
}
diff --git a/source/blender/compositor/operations/COM_DenoiseOperation.cc b/source/blender/compositor/operations/COM_DenoiseOperation.cc
index e7f2d5a740a..0c660e0b723 100644
--- a/source/blender/compositor/operations/COM_DenoiseOperation.cc
+++ b/source/blender/compositor/operations/COM_DenoiseOperation.cc
@@ -28,6 +28,137 @@ static pthread_mutex_t oidn_lock = BLI_MUTEX_INITIALIZER;
namespace blender::compositor {
+bool COM_is_denoise_supported()
+{
+#ifdef WITH_OPENIMAGEDENOISE
+ /* Always supported through Accelerate framework BNNS on macOS. */
+# ifdef __APPLE__
+ return true;
+# else
+ return BLI_cpu_support_sse41();
+# endif
+
+#else
+ return false;
+#endif
+}
+
+class DenoiseFilter {
+ private:
+#ifdef WITH_OPENIMAGEDENOISE
+ oidn::DeviceRef device;
+ oidn::FilterRef filter;
+#endif
+ bool initialized_ = false;
+
+ public:
+ ~DenoiseFilter()
+ {
+ BLI_assert(!initialized_);
+ }
+
+#ifdef WITH_OPENIMAGEDENOISE
+ void init_and_lock_denoiser(MemoryBuffer *output)
+ {
+ /* Since it's memory intensive, it's better to run only one instance of OIDN at a time.
+ * OpenImageDenoise is multithreaded internally and should use all available cores
+ * nonetheless. */
+ BLI_mutex_lock(&oidn_lock);
+
+ device = oidn::newDevice();
+ device.commit();
+ filter = device.newFilter("RT");
+ initialized_ = true;
+ set_image("output", output);
+ }
+
+ void deinit_and_unlock_denoiser()
+ {
+ BLI_mutex_unlock(&oidn_lock);
+ initialized_ = false;
+ }
+
+ void set_image(const StringRef name, MemoryBuffer *buffer)
+ {
+ BLI_assert(initialized_);
+ BLI_assert(!buffer->is_a_single_elem());
+ filter.setImage(name.data(),
+ buffer->getBuffer(),
+ oidn::Format::Float3,
+ buffer->getWidth(),
+ buffer->getHeight(),
+ 0,
+ buffer->get_elem_bytes_len());
+ }
+
+ template<typename T> void set(const StringRef option_name, T value)
+ {
+ BLI_assert(initialized_);
+ filter.set(option_name.data(), value);
+ }
+
+ void execute()
+ {
+ BLI_assert(initialized_);
+ filter.commit();
+ filter.execute();
+ }
+
+#else
+ void init_and_lock_denoiser(MemoryBuffer *UNUSED(output))
+ {
+ }
+
+ void deinit_and_unlock_denoiser()
+ {
+ }
+
+ void set_image(const StringRef UNUSED(name), MemoryBuffer *UNUSED(buffer))
+ {
+ }
+
+ template<typename T> void set(const StringRef UNUSED(option_name), T UNUSED(value))
+ {
+ }
+
+ void execute()
+ {
+ }
+#endif
+};
+
+DenoiseBaseOperation::DenoiseBaseOperation()
+{
+ flags.is_fullframe_operation = true;
+ output_rendered_ = false;
+}
+
+bool DenoiseBaseOperation::determineDependingAreaOfInterest(rcti * /*input*/,
+ ReadBufferOperation *readOperation,
+ rcti *output)
+{
+ if (isCached()) {
+ return false;
+ }
+
+ rcti newInput;
+ newInput.xmax = this->getWidth();
+ newInput.xmin = 0;
+ newInput.ymax = this->getHeight();
+ newInput.ymin = 0;
+ return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
+}
+
+void DenoiseBaseOperation::get_area_of_interest(const int UNUSED(input_idx),
+ const rcti &UNUSED(output_area),
+ rcti &r_input_area)
+{
+ r_input_area.xmin = 0;
+ r_input_area.xmax = this->getWidth();
+ r_input_area.ymin = 0;
+ r_input_area.ymax = this->getHeight();
+}
+
DenoiseOperation::DenoiseOperation()
{
this->addInputSocket(DataType::Color);
@@ -35,8 +166,6 @@ DenoiseOperation::DenoiseOperation()
this->addInputSocket(DataType::Color);
this->addOutputSocket(DataType::Color);
this->m_settings = nullptr;
- flags.is_fullframe_operation = true;
- output_rendered_ = false;
}
void DenoiseOperation::initExecution()
{
@@ -54,6 +183,25 @@ void DenoiseOperation::deinitExecution()
SingleThreadedOperation::deinitExecution();
}
+static bool are_guiding_passes_noise_free(NodeDenoise *settings)
+{
+ switch (settings->prefilter) {
+ case CMP_NODE_DENOISE_PREFILTER_NONE:
+ case CMP_NODE_DENOISE_PREFILTER_ACCURATE: /* Prefiltered with #DenoisePrefilterOperation. */
+ return true;
+ case CMP_NODE_DENOISE_PREFILTER_FAST:
+ default:
+ return false;
+ }
+}
+
+void DenoiseOperation::hash_output_params()
+{
+ if (m_settings) {
+ hash_params((int)m_settings->hdr, are_guiding_passes_noise_free(m_settings));
+ }
+}
+
MemoryBuffer *DenoiseOperation::createMemoryBuffer(rcti *rect2)
{
MemoryBuffer *tileColor = (MemoryBuffer *)this->m_inputProgramColor->initializeTileData(rect2);
@@ -69,22 +217,6 @@ MemoryBuffer *DenoiseOperation::createMemoryBuffer(rcti *rect2)
return result;
}
-bool DenoiseOperation::determineDependingAreaOfInterest(rcti * /*input*/,
- ReadBufferOperation *readOperation,
- rcti *output)
-{
- if (isCached()) {
- return false;
- }
-
- rcti newInput;
- newInput.xmax = this->getWidth();
- newInput.xmin = 0;
- newInput.ymax = this->getHeight();
- newInput.ymin = 0;
- return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
-}
-
void DenoiseOperation::generateDenoise(MemoryBuffer *output,
MemoryBuffer *input_color,
MemoryBuffer *input_normal,
@@ -96,104 +228,46 @@ void DenoiseOperation::generateDenoise(MemoryBuffer *output,
return;
}
-#ifdef WITH_OPENIMAGEDENOISE
- /* Always supported through Accelerate framework BNNS on macOS. */
-# ifndef __APPLE__
- if (BLI_cpu_support_sse41())
-# endif
- {
- /* OpenImageDenoise needs full buffers. */
- MemoryBuffer *buf_color = input_color->is_a_single_elem() ? input_color->inflate() :
- input_color;
- MemoryBuffer *buf_normal = input_normal && input_normal->is_a_single_elem() ?
- input_normal->inflate() :
- input_normal;
- MemoryBuffer *buf_albedo = input_albedo && input_albedo->is_a_single_elem() ?
- input_albedo->inflate() :
- input_albedo;
+ BLI_assert(COM_is_denoise_supported());
+ /* OpenImageDenoise needs full buffers. */
+ MemoryBuffer *buf_color = input_color->is_a_single_elem() ? input_color->inflate() : input_color;
+ MemoryBuffer *buf_normal = input_normal && input_normal->is_a_single_elem() ?
+ input_normal->inflate() :
+ input_normal;
+ MemoryBuffer *buf_albedo = input_albedo && input_albedo->is_a_single_elem() ?
+ input_albedo->inflate() :
+ input_albedo;
- /* Since it's memory intensive, it's better to run only one instance of OIDN at a time.
- * OpenImageDenoise is multithreaded internally and should use all available cores nonetheless.
- */
- BLI_mutex_lock(&oidn_lock);
+ DenoiseFilter filter;
+ filter.init_and_lock_denoiser(output);
- oidn::DeviceRef device = oidn::newDevice();
- device.commit();
+ filter.set_image("color", buf_color);
+ filter.set_image("normal", buf_normal);
+ filter.set_image("albedo", buf_albedo);
- oidn::FilterRef filter = device.newFilter("RT");
- filter.setImage("color",
- buf_color->getBuffer(),
- oidn::Format::Float3,
- buf_color->getWidth(),
- buf_color->getHeight(),
- 0,
- sizeof(float[4]));
- if (buf_normal && buf_normal->getBuffer()) {
- filter
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list