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:
@@ -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);
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user