33#ifdef WITH_OPENIMAGEDENOISE
34# include <OpenImageDenoise/oidn.hpp>
44 N_(
"No prefiltering, use when guiding passes are noise-free")},
49 N_(
"Denoise image and guiding passes together. Improves quality when guiding passes are "
50 "noisy using least amount of extra processing time.")},
55 N_(
"Prefilter noisy guiding passes before denoising image. Improves quality when guiding "
56 "passes are noisy using extra processing time.")},
57 {0,
nullptr, 0,
nullptr,
nullptr}};
64 N_(
"Use the scene's denoising quality setting")},
70 N_(
"Balanced between performance and quality")},
72 {0,
nullptr, 0,
nullptr,
nullptr}};
76 b.use_custom_socket_order();
77 b.allow_any_socket_order();
79 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
82 b.add_output<
decl::Color>(
"Image").structure_type(StructureType::Dynamic).align_with_previous();
85 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
89 .default_value({0.0f, 0.0f, 0.0f})
93 .structure_type(StructureType::Dynamic);
114#ifdef WITH_OPENIMAGEDENOISE
115# if defined(__APPLE__)
118# elif defined(__aarch64__) || defined(_M_ARM64)
131#ifndef WITH_OPENIMAGEDENOISE
132 layout->
label(
RPT_(
"Disabled. Built without OpenImageDenoise"), ICON_ERROR);
135 layout->
label(
RPT_(
"Disabled. Platform not supported"), ICON_ERROR);
150 return !context->is_canceled();
169#ifdef WITH_OPENIMAGEDENOISE
170 oidn::DeviceRef device = create_oidn_device(this->
context());
171 device.set(
"setAffinity",
false);
174 const int width = input_image.
domain().
size.x;
175 const int height = input_image.
domain().
size.y;
176 const int pixel_stride =
sizeof(
float) * 4;
181 float *input_color =
nullptr;
182 float *output_color =
nullptr;
183 if (this->
context().use_gpu()) {
187 input_color =
static_cast<float *
>(
GPU_texture_read(input_image, data_format, 0));
188 output_color = input_color;
189 temporary_buffers_to_free.
append(input_color);
192 input_color =
const_cast<float *
>(
static_cast<const float *
>(input_image.
cpu_data().
data()));
193 output_color =
static_cast<float *
>(output_image.
cpu_data().
data());
198 oidn::BufferRef input_buffer = create_oidn_buffer(device, input_buffer_span);
200 oidn::BufferRef output_buffer = create_oidn_buffer(device, output_buffer_span);
202 oidn::FilterRef
filter = device.newFilter(
"RT");
203 filter.setImage(
"color", input_buffer, oidn::Format::Float3, width, height, 0, pixel_stride);
204 filter.setImage(
"output", output_buffer, oidn::Format::Float3, width, height, 0, pixel_stride);
207 this->set_filter_quality(
filter);
214 float *albedo =
nullptr;
220 DenoisedAuxiliaryPassType::Albedo,
225 if (this->
context().use_gpu()) {
226 albedo =
static_cast<float *
>(
GPU_texture_read(input_albedo, data_format, 0));
227 temporary_buffers_to_free.
append(albedo);
230 albedo =
static_cast<float *
>(input_albedo.
cpu_data().
data());
235 oidn::BufferRef albedo_buffer = create_oidn_buffer(device, albedo_buffer_span);
238 "albedo", albedo_buffer, oidn::Format::Float3, width, height, 0, pixel_stride);
246 float *normal =
nullptr;
252 DenoisedAuxiliaryPassType::Normal,
257 if (this->
context().use_gpu()) {
258 normal =
static_cast<float *
>(
GPU_texture_read(input_normal, data_format, 0));
259 temporary_buffers_to_free.
append(normal);
262 normal =
static_cast<float *
>(input_normal.
cpu_data().
data());
272 int normal_pixel_stride =
sizeof(
float) * normal_channels_count;
274 const int64_t normal_buffer_size =
int64_t(width) * height * normal_channels_count;
276 oidn::BufferRef normal_buffer = create_oidn_buffer(device, normal_buffer_span);
279 "normal", normal_buffer, oidn::Format::Float3, width, height, 0, normal_pixel_stride);
285 if (output_buffer.getStorage() != oidn::Storage::Host) {
286 output_buffer.read(0, buffer_size *
sizeof(
float), output_color);
289 if (this->
context().use_gpu()) {
302 for (
float *buffer : temporary_buffers_to_free) {
326#ifdef WITH_OPENIMAGEDENOISE
327# if OIDN_VERSION_MAJOR >= 2
328 oidn::Quality get_quality()
334 switch (scene_quality) {
335# if OIDN_VERSION >= 20300
337 return oidn::Quality::Fast;
340 return oidn::Quality::Balanced;
342 return oidn::Quality::High;
345 return oidn::Quality::High;
348 switch (node_quality) {
349# if OIDN_VERSION >= 20300
351 return oidn::Quality::Fast;
354 return oidn::Quality::Balanced;
357 return oidn::Quality::High;
360 return oidn::Quality::High;
364 void set_filter_quality([[maybe_unused]] oidn::FilterRef &
filter)
366# if OIDN_VERSION_MAJOR >= 2
367 oidn::Quality quality = this->get_quality();
368 filter.set(
"quality", quality);
382 const MenuValue menu_value =
input.get_single_value_default(default_menu_value);
390 const MenuValue menu_value =
input.get_single_value_default(default_menu_value);
410 ntype.
ui_description =
"Denoise renders from Cycles and other ray tracing renderers";
413 ntype.
declare = file_ns::cmp_node_denoise_declare;
414 ntype.
draw_buttons = file_ns::node_composit_buts_denoise;
415 ntype.
initfunc = file_ns::node_composit_init_denonise;
#define NODE_CLASS_OP_FILTER
int BLI_cpu_support_sse42(void)
@ CMP_NODE_DENOISE_QUALITY_BALANCED
@ CMP_NODE_DENOISE_QUALITY_FAST
@ CMP_NODE_DENOISE_QUALITY_SCENE
@ CMP_NODE_DENOISE_QUALITY_HIGH
@ CMP_NODE_DENOISE_PREFILTER_FAST
@ CMP_NODE_DENOISE_PREFILTER_NONE
@ CMP_NODE_DENOISE_PREFILTER_ACCURATE
eCompositorDenoiseQaulity
@ SCE_COMPOSITOR_DENOISE_FAST
@ SCE_COMPOSITOR_DENOISE_BALANCED
@ SCE_COMPOSITOR_DENOISE_HIGH
@ GPU_BARRIER_TEXTURE_UPDATE
void GPU_memory_barrier(GPUBarrier barrier)
size_t GPU_texture_component_len(blender::gpu::TextureFormat format)
blender::gpu::TextureFormat GPU_texture_format(const blender::gpu::Texture *texture)
void * GPU_texture_read(blender::gpu::Texture *texture, eGPUDataFormat data_format, int mip_level)
void GPU_texture_update(blender::gpu::Texture *texture, eGPUDataFormat data_format, const void *data)
Read Guarded memory(de)allocation.
#define NOD_REGISTER_NODE(REGISTER_FUNC)
BMesh const char void * data
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
void append(const T &value)
eCompositorDenoiseQaulity get_denoise_quality() const
virtual bool use_gpu() const =0
DenoisedAuxiliaryPassContainer denoised_auxiliary_passes
NodeOperation(Context &context, DNode node)
Result & get_result(StringRef identifier)
Context & context() const
Result & get_input(StringRef identifier) const
void share_data(const Result &source)
T get_single_value_default(const T &default_value) const
void store_pixel(const int2 &texel, const T &pixel_value)
void allocate_texture(const Domain domain, const bool from_pool=true, const std::optional< ResultStorageType > storage_type=std::nullopt)
const Domain & domain() const
T load_pixel(const int2 &texel) const
int64_t channels_count() const
DerivedResources & derived_resources()
bool is_single_value() const
StructureType structure_type
bool should_denoise_auxiliary_passes()
CMPNodeDenoisePrefilter get_prefilter_mode()
bool auxiliary_passes_are_clean()
CMPNodeDenoiseQuality get_quality_mode()
NodeOperation(Context &context, DNode node)
void * MEM_callocN(size_t len, const char *str)
void MEM_freeN(void *vmemh)
void node_register_type(bNodeType &ntype)
void node_type_storage(bNodeType &ntype, std::optional< StringRefNull > storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
void parallel_for(const int2 range, const Function &function)
static NodeOperation * get_compositor_operation(Context &context, DNode node)
static void cmp_node_denoise_declare(NodeDeclarationBuilder &b)
static void node_composit_buts_denoise(uiLayout *layout, bContext *, PointerRNA *)
static bool oidn_progress_monitor_function(void *user_ptr, double)
static bool is_oidn_supported()
static void node_composit_init_denonise(bNodeTree *, bNode *node)
static const EnumPropertyItem quality_items[]
static const EnumPropertyItem prefilter_items[]
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
static void register_node_type_cmp_denoise()
void cmp_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
void node_free_standard_storage(bNode *node)
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
std::string ui_description
NodeGetCompositorOperationFunction get_compositor_operation
void(* initfunc)(bNodeTree *ntree, bNode *node)
const char * enum_name_legacy
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
NodeDeclareFunction declare
void label(blender::StringRef name, int icon)