Files
test/source/blender/compositor/operations/COM_DenoiseOperation.cc
Aras Pranckevicius f5f7024040 Cleanup: Remove now-unused "tiled" compositor implementation
New ("fullframe") CPU compositor backend is being used now, and all the code
related to "tiled" CPU compositor is just never used anymore. The new backend
is faster, uses less memory, better matches GPU compositor, etc.

TL;DR: 20 thousand lines of code gone.

This commit:
- Removes various bits and pieces related to "tiled" compositor (execution
  groups, one-pixel-at-a-time node processing, read/write buffer operations
  related to node execution groups).
- "GPU" (OpenCL) execution device, that was only used by several nodes of
  the tiled compositor.
  - With that, remove CLEW external library too, since nothing within Blender
    uses OpenCL directly anymore.

Pull Request: https://projects.blender.org/blender/blender/pulls/118819
2024-02-28 16:59:16 +01:00

242 lines
6.4 KiB
C++

/* SPDX-FileCopyrightText: 2019 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "COM_DenoiseOperation.h"
#include "BLI_system.h"
#ifdef WITH_OPENIMAGEDENOISE
# include "BLI_threads.h"
# include <OpenImageDenoise/oidn.hpp>
static pthread_mutex_t oidn_lock = BLI_MUTEX_INITIALIZER;
#endif
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_sse42();
# endif
#else
return false;
#endif
}
#ifdef WITH_OPENIMAGEDENOISE
static bool oidn_progress_monitor_function(void *user_ptr, double /*n*/)
{
const NodeOperation *operation = static_cast<const NodeOperation *>(user_ptr);
return !operation->is_braked();
}
#endif
class DenoiseFilter {
private:
#ifdef WITH_OPENIMAGEDENOISE
oidn::DeviceRef device_;
oidn::FilterRef filter_;
bool initialized_ = false;
#endif
public:
#ifdef WITH_OPENIMAGEDENOISE
~DenoiseFilter()
{
BLI_assert(!initialized_);
}
void init_and_lock_denoiser(NodeOperation *operation, 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(oidn::DeviceType::CPU);
device_.set("setAffinity", false);
device_.commit();
filter_ = device_.newFilter("RT");
filter_.setProgressMonitorFunction(oidn_progress_monitor_function, operation);
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->get_buffer(),
oidn::Format::Float3,
buffer->get_width(),
buffer->get_height(),
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(NodeOperation * /*operation*/, MemoryBuffer * /*output*/) {}
void deinit_and_unlock_denoiser() {}
void set_image(const StringRef /*name*/, MemoryBuffer * /*buffer*/) {}
template<typename T> void set(const StringRef /*option_name*/, T /*value*/) {}
void execute() {}
#endif
};
DenoiseBaseOperation::DenoiseBaseOperation()
{
flags_.can_be_constant = true;
output_rendered_ = false;
}
void DenoiseBaseOperation::get_area_of_interest(const int /*input_idx*/,
const rcti & /*output_area*/,
rcti &r_input_area)
{
r_input_area = this->get_canvas();
}
DenoiseOperation::DenoiseOperation()
{
this->add_input_socket(DataType::Color);
this->add_input_socket(DataType::Vector);
this->add_input_socket(DataType::Color);
this->add_output_socket(DataType::Color);
settings_ = nullptr;
}
static bool are_guiding_passes_noise_free(const 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 (settings_) {
hash_params(int(settings_->hdr), are_guiding_passes_noise_free(settings_));
}
}
void DenoiseOperation::generate_denoise(MemoryBuffer *output,
MemoryBuffer *input_color,
MemoryBuffer *input_normal,
MemoryBuffer *input_albedo,
const NodeDenoise *settings)
{
if (input_color->is_a_single_elem()) {
output->fill(output->get_rect(), input_color->get_elem(0, 0));
return;
}
BLI_assert(COM_is_denoise_supported());
DenoiseFilter filter;
filter.init_and_lock_denoiser(this, output);
filter.set_image("color", input_color);
if (!input_albedo->is_a_single_elem()) {
filter.set_image("albedo", input_albedo);
if (!input_normal->is_a_single_elem()) {
filter.set_image("normal", input_normal);
}
}
BLI_assert(settings);
if (settings) {
filter.set("hdr", settings->hdr);
filter.set("srgb", false);
filter.set("cleanAux", are_guiding_passes_noise_free(settings));
}
filter.execute();
filter.deinit_and_unlock_denoiser();
/* Copy the alpha channel, OpenImageDenoise currently only supports RGB. */
output->copy_from(input_color, input_color->get_rect(), 3, COM_DATA_TYPE_VALUE_CHANNELS, 3);
}
void DenoiseOperation::update_memory_buffer(MemoryBuffer *output,
const rcti & /*area*/,
Span<MemoryBuffer *> inputs)
{
if (!output_rendered_) {
this->generate_denoise(output, inputs[0], inputs[1], inputs[2], settings_);
output_rendered_ = true;
}
}
DenoisePrefilterOperation::DenoisePrefilterOperation(DataType data_type)
{
this->add_input_socket(data_type);
this->add_output_socket(data_type);
image_name_ = "";
}
void DenoisePrefilterOperation::hash_output_params()
{
hash_param(image_name_);
}
void DenoisePrefilterOperation::generate_denoise(MemoryBuffer *output, MemoryBuffer *input)
{
if (input->is_a_single_elem()) {
copy_v4_v4(output->get_elem(0, 0), input->get_elem(0, 0));
return;
}
BLI_assert(COM_is_denoise_supported());
DenoiseFilter filter;
filter.init_and_lock_denoiser(this, output);
filter.set_image(image_name_, input);
filter.execute();
filter.deinit_and_unlock_denoiser();
}
void DenoisePrefilterOperation::update_memory_buffer(MemoryBuffer *output,
const rcti & /*area*/,
Span<MemoryBuffer *> inputs)
{
if (!output_rendered_) {
this->generate_denoise(output, inputs[0]);
output_rendered_ = true;
}
}
} // namespace blender::compositor