Fix #122587: File Output node can only save one size

The File Output node forces all inputs to have the same size, which
should only be the case for multilayer files. This is a regression in
931c188ce5. To fix this, we allow inputs to have any size, except for
multilayer files, which are realized on the automatic operation domain
of the operation.

Pull Request: https://projects.blender.org/blender/blender/pulls/122824
This commit is contained in:
Omar Emara
2024-06-07 17:34:14 +02:00
committed by Omar Emara
parent d66e3f899a
commit 79da892126
3 changed files with 31 additions and 17 deletions

View File

@@ -57,8 +57,12 @@ FileOutputOperation::FileOutputOperation(const CompositorContext *context,
Vector<FileOutputInput> inputs)
: context_(context), node_data_(node_data), file_output_inputs_(inputs)
{
/* Inputs for multi-layer files need to be the same size, while they can be different for
* individual file outputs. */
const ResizeMode resize_mode = this->is_multi_layer() ? ResizeMode::Center : ResizeMode::None;
for (const FileOutputInput &input : inputs) {
add_input_socket(input.data_type);
add_input_socket(input.data_type, resize_mode);
}
this->set_canvas_input_index(RESOLUTION_INPUT_ANY);
}
@@ -71,13 +75,14 @@ void FileOutputOperation::init_execution()
if (!input.image_input) {
continue;
}
input.output_buffer = initialize_buffer(get_width(), get_height(), input.data_type);
input.output_buffer = initialize_buffer(
input.image_input->get_width(), input.image_input->get_height(), input.data_type);
}
}
void FileOutputOperation::update_memory_buffer_partial(MemoryBuffer * /*output*/,
const rcti &area,
Span<MemoryBuffer *> inputs)
void FileOutputOperation::update_memory_buffer(MemoryBuffer * /*output*/,
const rcti & /*area*/,
Span<MemoryBuffer *> inputs)
{
for (int i = 0; i < file_output_inputs_.size(); i++) {
const FileOutputInput &input = file_output_inputs_[i];
@@ -86,8 +91,9 @@ void FileOutputOperation::update_memory_buffer_partial(MemoryBuffer * /*output*/
}
int channels_count = get_channels_count(input.data_type);
MemoryBuffer output_buf(input.output_buffer, channels_count, get_width(), get_height());
output_buf.copy_from(inputs[i], area, 0, inputs[i]->get_num_channels(), 0);
MemoryBuffer output_buf(
input.output_buffer, channels_count, inputs[i]->get_width(), inputs[i]->get_height());
output_buf.copy_from(inputs[i], inputs[i]->get_rect(), 0, inputs[i]->get_num_channels(), 0);
}
}
@@ -139,7 +145,6 @@ void FileOutputOperation::deinit_execution()
void FileOutputOperation::execute_single_layer()
{
const int2 size = int2(get_width(), get_height());
for (const FileOutputInput &input : file_output_inputs_) {
/* We only write images, not single values. */
if (!input.image_input || input.image_input->get_flags().is_constant_operation) {
@@ -170,6 +175,7 @@ void FileOutputOperation::execute_single_layer()
char image_path[FILE_MAX];
get_single_layer_image_path(base_path, format, image_path);
const int2 size = int2(input.image_input->get_width(), input.image_input->get_height());
realtime_compositor::FileOutput &file_output = context_->get_render_context()->get_file_output(
image_path, format, size, input.data->save_as_render);
@@ -195,7 +201,7 @@ void FileOutputOperation::execute_single_layer_multi_view_exr(const FileOutputIn
const char *path_view = has_views ? "" : context_->get_view_name();
get_multi_layer_exr_image_path(base_path, path_view, image_path);
const int2 size = int2(get_width(), get_height());
const int2 size = int2(input.image_input->get_width(), input.image_input->get_height());
realtime_compositor::FileOutput &file_output = context_->get_render_context()->get_file_output(
image_path, format, size, false);

View File

@@ -9,7 +9,7 @@
#include "DNA_node_types.h"
#include "COM_CompositorContext.h"
#include "COM_MultiThreadedOperation.h"
#include "COM_NodeOperation.h"
struct StampData;
@@ -29,7 +29,7 @@ struct FileOutputInput {
SocketReader *image_input = nullptr;
};
class FileOutputOperation : public MultiThreadedOperation {
class FileOutputOperation : public NodeOperation {
private:
const CompositorContext *context_;
const NodeImageMultiFile *node_data_;
@@ -51,9 +51,9 @@ class FileOutputOperation : public MultiThreadedOperation {
return eCompositorPriority::Low;
}
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
void update_memory_buffer(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
private:
void execute_single_layer();

View File

@@ -482,7 +482,15 @@ using namespace blender::realtime_compositor;
class FileOutputOperation : public NodeOperation {
public:
using NodeOperation::NodeOperation;
FileOutputOperation(Context &context, DNode node) : NodeOperation(context, node)
{
for (const bNodeSocket *input : node->input_sockets()) {
InputDescriptor &descriptor = this->get_input_descriptor(input->identifier);
/* Inputs for multi-layer files need to be the same size, while they can be different for
* individual file outputs. */
descriptor.realization_options.realize_on_operation_domain = this->is_multi_layer();
}
}
void execute() override
{
@@ -500,7 +508,6 @@ class FileOutputOperation : public NodeOperation {
void execute_single_layer()
{
const int2 size = compute_domain().size;
for (const bNodeSocket *input : this->node()->input_sockets()) {
const Result &result = get_input(input->identifier);
/* We only write images, not single values. */
@@ -528,6 +535,7 @@ class FileOutputOperation : public NodeOperation {
char image_path[FILE_MAX];
get_single_layer_image_path(base_path, format, image_path);
const int2 size = result.domain().size;
FileOutput &file_output = context().render_context()->get_file_output(
image_path, format, size, socket.save_as_render);
@@ -551,7 +559,7 @@ class FileOutputOperation : public NodeOperation {
const char *path_view = has_views ? "" : context().get_view_name().data();
get_multi_layer_exr_image_path(base_path, path_view, image_path);
const int2 size = compute_domain().size;
const int2 size = result.domain().size;
FileOutput &file_output = context().render_context()->get_file_output(
image_path, format, size, false);