diff --git a/source/blender/compositor/COM_input_descriptor.hh b/source/blender/compositor/COM_input_descriptor.hh index c08e84cd91f..6e13be7247d 100644 --- a/source/blender/compositor/COM_input_descriptor.hh +++ b/source/blender/compositor/COM_input_descriptor.hh @@ -47,6 +47,9 @@ class InputDescriptor { * result that will be discarded anyways. If false, the input can work with both single and * non-single values. */ bool expects_single_value = false; + /* If true, the input will not be implicitly converted to the type of the input and will be + * passed as is. */ + bool skip_type_conversion = false; }; } // namespace blender::compositor diff --git a/source/blender/compositor/COM_meta_data.hh b/source/blender/compositor/COM_meta_data.hh index 3731f61dbef..49b6164750f 100644 --- a/source/blender/compositor/COM_meta_data.hh +++ b/source/blender/compositor/COM_meta_data.hh @@ -28,10 +28,6 @@ struct CryptomatteMetaData { struct MetaData { /* The result stores non color data, which is not to be color-managed. */ bool is_non_color_data = false; - /* The result stores a 4D vector as opposed to a 3D vector. This is the case for things like - * velocity passes, and we need to mark them as 4D in order to write them to file correctly. This - * field can be ignored for results that are not of type Vector. */ - bool is_4d_vector = false; /* Stores Cryptomatte meta data. This will only be initialized for results that represent * Cryptomatte information. See the CryptomatteMetaData structure for more information. */ CryptomatteMetaData cryptomatte; diff --git a/source/blender/compositor/COM_result.hh b/source/blender/compositor/COM_result.hh index b7d1600665d..d264b294ca6 100644 --- a/source/blender/compositor/COM_result.hh +++ b/source/blender/compositor/COM_result.hh @@ -33,14 +33,12 @@ class DerivedResources; /* Make sure to update the format related static methods in the Result class. */ enum class ResultType : uint8_t { /* The following types are user facing and can be used as inputs and outputs of operations. They - * either represent the base type of the result's image or a single value result. The color type - * represents an RGBA color. And the vector type represents a generic 4-component vector, which - * can encode two 2D vectors, one 3D vector with the last component ignored, or other dimensional - * data. */ + * either represent the base type of the result's image or a single value result. */ Float, Int, Vector, Color, + Float4, /* The following types are for internal use only, not user facing, and can't be used as inputs * and outputs of operations. It follows that they needn't be handled in implicit operations like @@ -482,6 +480,7 @@ BLI_INLINE_METHOD int64_t Result::channels_count() const return 3; case ResultType::Vector: case ResultType::Color: + case ResultType::Float4: return 4; } return 4; diff --git a/source/blender/compositor/algorithms/intern/smaa.cc b/source/blender/compositor/algorithms/intern/smaa.cc index 851a0b5c957..9ca9bf3a2a5 100644 --- a/source/blender/compositor/algorithms/intern/smaa.cc +++ b/source/blender/compositor/algorithms/intern/smaa.cc @@ -1417,6 +1417,7 @@ static float3 get_luminance_coefficients(ResultType type) return luminance_coefficients; } case ResultType::Vector: + case ResultType::Float4: return float3(1.0f, 1.0f, 1.0f); case ResultType::Float: return float3(1.0f, 0.0f, 0.0f); @@ -1588,6 +1589,7 @@ static const char *get_blend_shader_name(ResultType type) switch (type) { case ResultType::Color: case ResultType::Vector: + case ResultType::Float4: return "compositor_smaa_neighborhood_blending_float4"; case ResultType::Float2: return "compositor_smaa_neighborhood_blending_float2"; @@ -1667,6 +1669,9 @@ static void compute_single_value(Result &input, Result &output) case ResultType::Vector: output.set_single_value(input.get_single_value()); break; + case ResultType::Float4: + output.set_single_value(input.get_single_value()); + break; case ResultType::Float2: output.set_single_value(input.get_single_value()); break; diff --git a/source/blender/compositor/algorithms/intern/symmetric_separable_blur.cc b/source/blender/compositor/algorithms/intern/symmetric_separable_blur.cc index b5f9f2e68ee..87e9f20f8b5 100644 --- a/source/blender/compositor/algorithms/intern/symmetric_separable_blur.cc +++ b/source/blender/compositor/algorithms/intern/symmetric_separable_blur.cc @@ -79,6 +79,7 @@ static const char *get_blur_shader(const ResultType type) return "compositor_symmetric_separable_blur_float4"; case ResultType::Float2: case ResultType::Float3: + case ResultType::Float4: case ResultType::Int2: case ResultType::Int: /* Not supported. */ @@ -182,6 +183,7 @@ static Result horizontal_pass_cpu(Context &context, break; case ResultType::Float2: case ResultType::Float3: + case ResultType::Float4: case ResultType::Int2: case ResultType::Int: /* Not supported. */ @@ -280,6 +282,7 @@ static void vertical_pass_cpu(Context &context, break; case ResultType::Float2: case ResultType::Float3: + case ResultType::Float4: case ResultType::Int2: case ResultType::Int: /* Not supported. */ diff --git a/source/blender/compositor/cached_resources/intern/cached_image.cc b/source/blender/compositor/cached_resources/intern/cached_image.cc index f13538ea5f3..862d864cbad 100644 --- a/source/blender/compositor/cached_resources/intern/cached_image.cc +++ b/source/blender/compositor/cached_resources/intern/cached_image.cc @@ -201,6 +201,54 @@ static ImBuf *compute_linear_buffer(ImBuf *image_buffer) return linear_image_buffer; } +/* Returns the appropriate result type for the given image buffer, which represents the pass in the + * given render result with the given image user. The type is determined based on the channels + * count of the buffer, except for when the channels count is 4, because it can either be a color + * or a float4 pass, which is determined by inspecting the channels IDs of the pass. */ +static ResultType get_result_type(const RenderResult *render_result, + const ImageUser &image_user, + const ImBuf *image_buffer) +{ + switch (image_buffer->channels) { + case 1: + return ResultType::Float; + case 2: + return ResultType::Float2; + case 3: + return ResultType::Float3; + case 4: + /* The 4 channel case is ambiguous, it can either be a color or a float4, so we need + * to investigate the pass channel IDs outside of the switch to identify its type. */ + break; + default: + BLI_assert_unreachable(); + return ResultType::Float; + } + + if (!render_result) { + /* Not a multi-layer images, 4-channels are always color images. */ + return ResultType::Color; + } + + const RenderLayer *render_layer = get_render_layer(render_result, image_user); + if (!render_layer) { + /* Not a multi-layer images, 4-channels are always color images. */ + return ResultType::Color; + } + + const RenderPass *render_pass = get_render_pass(render_layer, image_user); + if (!render_pass) { + /* Not a multi-layer images, 4-channels are always color images. */ + return ResultType::Color; + } + + if (StringRef(render_pass->chan_id) == "XYZW") { + return ResultType::Float4; + } + + return ResultType::Color; +} + CachedImage::CachedImage(Context &context, Image *image, ImageUser *image_user, @@ -235,11 +283,7 @@ CachedImage::CachedImage(Context &context, const bool use_half_float = linear_image_buffer->flags & IB_halffloat; this->result.set_precision(use_half_float ? ResultPrecision::Half : ResultPrecision::Full); - /* At the user level, vector images are always treated as color, so there are only two possible - * options, float images and color images. 3-channel images should then be converted to 4-channel - * images below. */ - const bool is_single_channel = linear_image_buffer->channels == 1; - this->result.set_type(is_single_channel ? ResultType::Float : ResultType::Color); + this->result.set_type(get_result_type(render_result, image_user_for_pass, linear_image_buffer)); /* For GPU, we wrap the texture returned by IMB module and free it ourselves in destructor. For * CPU, we allocate the result and copy to it from the image buffer. */ @@ -250,8 +294,7 @@ CachedImage::CachedImage(Context &context, } else { const int2 size = int2(image_buffer->x, image_buffer->y); - const int channels_count = linear_image_buffer->channels; - Result buffer_result(context, Result::float_type(channels_count), ResultPrecision::Full); + Result buffer_result(context, this->result.type(), ResultPrecision::Full); buffer_result.wrap_external(linear_image_buffer->float_buffer.data, size); this->result.allocate_texture(size, false); parallel_for(size, [&](const int2 texel) { @@ -320,10 +363,6 @@ void CachedImage::populate_meta_data(const RenderResult *render_result, } }, false); - - if (StringRef(render_pass->chan_id) == "XYZW") { - this->result.meta_data.is_4d_vector = true; - } } CachedImage::~CachedImage() diff --git a/source/blender/compositor/intern/conversion_operation.cc b/source/blender/compositor/intern/conversion_operation.cc index 01cf75cb4c5..553fb846f49 100644 --- a/source/blender/compositor/intern/conversion_operation.cc +++ b/source/blender/compositor/intern/conversion_operation.cc @@ -67,6 +67,10 @@ SimpleOperation *ConversionOperation::construct_if_needed(Context &context, const Result &input_result, const InputDescriptor &input_descriptor) { + if (input_descriptor.skip_type_conversion) { + return nullptr; + } + const ResultType result_type = input_result.type(); const ResultType expected_type = input_descriptor.type; if (result_type != expected_type) { @@ -86,6 +90,8 @@ const char *ConversionOperation::get_conversion_shader_name() return "compositor_convert_float_to_vector"; case ResultType::Color: return "compositor_convert_float_to_color"; + case ResultType::Float4: + return "compositor_convert_float_to_float4"; case ResultType::Float: /* Same type, no conversion needed. */ break; @@ -104,6 +110,8 @@ const char *ConversionOperation::get_conversion_shader_name() return "compositor_convert_int_to_vector"; case ResultType::Color: return "compositor_convert_int_to_color"; + case ResultType::Float4: + return "compositor_convert_int_to_float4"; case ResultType::Int: /* Same type, no conversion needed. */ break; @@ -122,6 +130,8 @@ const char *ConversionOperation::get_conversion_shader_name() return "compositor_convert_vector_to_int"; case ResultType::Color: return "compositor_convert_vector_to_color"; + case ResultType::Float4: + return "compositor_convert_vector_to_float4"; case ResultType::Vector: /* Same type, no conversion needed. */ break; @@ -140,6 +150,8 @@ const char *ConversionOperation::get_conversion_shader_name() return "compositor_convert_color_to_int"; case ResultType::Vector: return "compositor_convert_color_to_vector"; + case ResultType::Float4: + return "compositor_convert_color_to_float4"; case ResultType::Color: /* Same type, no conversion needed. */ break; @@ -150,6 +162,26 @@ const char *ConversionOperation::get_conversion_shader_name() break; } break; + case ResultType::Float4: + switch (this->get_result().type()) { + case ResultType::Float: + return "compositor_convert_float4_to_float"; + case ResultType::Int: + return "compositor_convert_float4_to_int"; + case ResultType::Vector: + return "compositor_convert_float4_to_vector"; + case ResultType::Color: + return "compositor_convert_float4_to_color"; + case ResultType::Float4: + /* Same type, no conversion needed. */ + break; + case ResultType::Float2: + case ResultType::Float3: + case ResultType::Int2: + /* Types are not user facing, so we needn't implement them. */ + break; + } + break; case ResultType::Float2: case ResultType::Float3: case ResultType::Int2: @@ -175,6 +207,9 @@ void ConversionOperation::execute_single(const Result &input, Result &output) case ResultType::Color: output.set_single_value(float_to_color(input.get_single_value())); return; + case ResultType::Float4: + output.set_single_value(float_to_float4(input.get_single_value())); + return; case ResultType::Float: /* Same type, no conversion needed. */ break; @@ -196,6 +231,9 @@ void ConversionOperation::execute_single(const Result &input, Result &output) case ResultType::Color: output.set_single_value(int_to_color(input.get_single_value())); return; + case ResultType::Float4: + output.set_single_value(int_to_float4(input.get_single_value())); + return; case ResultType::Int: /* Same type, no conversion needed. */ break; @@ -217,6 +255,9 @@ void ConversionOperation::execute_single(const Result &input, Result &output) case ResultType::Color: output.set_single_value(vector_to_color(input.get_single_value())); return; + case ResultType::Float4: + output.set_single_value(vector_to_float4(input.get_single_value())); + return; case ResultType::Vector: /* Same type, no conversion needed. */ break; @@ -238,6 +279,9 @@ void ConversionOperation::execute_single(const Result &input, Result &output) case ResultType::Vector: output.set_single_value(color_to_vector(input.get_single_value())); return; + case ResultType::Float4: + output.set_single_value(color_to_float4(input.get_single_value())); + return; case ResultType::Color: /* Same type, no conversion needed. */ break; @@ -248,6 +292,30 @@ void ConversionOperation::execute_single(const Result &input, Result &output) break; } break; + case ResultType::Float4: + switch (this->get_result().type()) { + case ResultType::Float: + output.set_single_value(float4_to_float(input.get_single_value())); + return; + case ResultType::Int: + output.set_single_value(float4_to_int(input.get_single_value())); + return; + case ResultType::Vector: + output.set_single_value(float4_to_vector(input.get_single_value())); + return; + case ResultType::Color: + output.set_single_value(float4_to_color(input.get_single_value())); + return; + case ResultType::Float4: + /* Same type, no conversion needed. */ + break; + case ResultType::Float2: + case ResultType::Float3: + case ResultType::Int2: + /* Types are not user facing, so we needn't implement them. */ + break; + } + break; case ResultType::Float2: case ResultType::Float3: case ResultType::Int2: @@ -278,6 +346,11 @@ void ConversionOperation::execute_cpu(const Result &input, Result &output) output.store_pixel(texel, float_to_color(input.load_pixel(texel))); }); return; + case ResultType::Float4: + parallel_for(input.domain().size, [&](const int2 texel) { + output.store_pixel(texel, float_to_float4(input.load_pixel(texel))); + }); + return; case ResultType::Float: /* Same type, no conversion needed. */ break; @@ -305,6 +378,11 @@ void ConversionOperation::execute_cpu(const Result &input, Result &output) output.store_pixel(texel, int_to_color(input.load_pixel(texel))); }); return; + case ResultType::Float4: + parallel_for(input.domain().size, [&](const int2 texel) { + output.store_pixel(texel, int_to_float4(input.load_pixel(texel))); + }); + return; case ResultType::Int: /* Same type, no conversion needed. */ break; @@ -332,6 +410,11 @@ void ConversionOperation::execute_cpu(const Result &input, Result &output) output.store_pixel(texel, vector_to_color(input.load_pixel(texel))); }); return; + case ResultType::Float4: + parallel_for(input.domain().size, [&](const int2 texel) { + output.store_pixel(texel, vector_to_float4(input.load_pixel(texel))); + }); + return; case ResultType::Vector: /* Same type, no conversion needed. */ break; @@ -359,6 +442,11 @@ void ConversionOperation::execute_cpu(const Result &input, Result &output) output.store_pixel(texel, color_to_vector(input.load_pixel(texel))); }); return; + case ResultType::Float4: + parallel_for(input.domain().size, [&](const int2 texel) { + output.store_pixel(texel, color_to_float4(input.load_pixel(texel))); + }); + return; case ResultType::Color: /* Same type, no conversion needed. */ break; @@ -369,6 +457,38 @@ void ConversionOperation::execute_cpu(const Result &input, Result &output) break; } break; + case ResultType::Float4: + switch (this->get_result().type()) { + case ResultType::Float: + parallel_for(input.domain().size, [&](const int2 texel) { + output.store_pixel(texel, float4_to_float(input.load_pixel(texel))); + }); + return; + case ResultType::Int: + parallel_for(input.domain().size, [&](const int2 texel) { + output.store_pixel(texel, float4_to_int(input.load_pixel(texel))); + }); + return; + case ResultType::Vector: + parallel_for(input.domain().size, [&](const int2 texel) { + output.store_pixel(texel, float4_to_vector(input.load_pixel(texel))); + }); + return; + case ResultType::Color: + parallel_for(input.domain().size, [&](const int2 texel) { + output.store_pixel(texel, float4_to_color(input.load_pixel(texel))); + }); + return; + case ResultType::Float4: + /* Same type, no conversion needed. */ + break; + case ResultType::Float2: + case ResultType::Float3: + case ResultType::Int2: + /* Types are not user facing, so we needn't implement them. */ + break; + } + break; case ResultType::Float2: case ResultType::Float3: case ResultType::Int2: diff --git a/source/blender/compositor/intern/input_single_value_operation.cc b/source/blender/compositor/intern/input_single_value_operation.cc index 65159786a86..6c555f01979 100644 --- a/source/blender/compositor/intern/input_single_value_operation.cc +++ b/source/blender/compositor/intern/input_single_value_operation.cc @@ -49,6 +49,10 @@ void InputSingleValueOperation::execute() case ResultType::Color: result.set_single_value(float4(bsocket->default_value_typed()->value)); break; + case ResultType::Float4: + result.set_single_value( + float4(float3(bsocket->default_value_typed()->value), 0.0f)); + break; case ResultType::Float2: case ResultType::Float3: case ResultType::Int2: diff --git a/source/blender/compositor/intern/multi_function_procedure_operation.cc b/source/blender/compositor/intern/multi_function_procedure_operation.cc index 4e274f68b63..a2dbeb84c6a 100644 --- a/source/blender/compositor/intern/multi_function_procedure_operation.cc +++ b/source/blender/compositor/intern/multi_function_procedure_operation.cc @@ -62,6 +62,8 @@ static const CPPType &get_cpp_type(ResultType type) case ResultType::Vector: case ResultType::Color: return CPPType::get(); + case ResultType::Float4: + return CPPType::get(); case ResultType::Float2: case ResultType::Float3: case ResultType::Int2: @@ -91,6 +93,9 @@ static void add_single_value_input_parameter(mf::ParamsBuilder ¶meter_builde case ResultType::Vector: parameter_builder.add_readonly_single_input_value(input.get_single_value()); return; + case ResultType::Float4: + parameter_builder.add_readonly_single_input_value(input.get_single_value()); + return; case ResultType::Float2: case ResultType::Float3: case ResultType::Int2: @@ -117,6 +122,9 @@ static void add_single_value_output_parameter(mf::ParamsBuilder ¶meter_build case ResultType::Vector: parameter_builder.add_uninitialized_single_output(&output.get_single_value()); return; + case ResultType::Float4: + parameter_builder.add_uninitialized_single_output(&output.get_single_value()); + return; case ResultType::Float2: case ResultType::Float3: case ResultType::Int2: @@ -143,6 +151,9 @@ static void upload_single_value_output_to_gpu(Result &output) case ResultType::Vector: output.set_single_value(output.get_single_value()); return; + case ResultType::Float4: + output.set_single_value(output.get_single_value()); + return; case ResultType::Float2: case ResultType::Float3: case ResultType::Int2: @@ -378,6 +389,8 @@ static mf::MultiFunction *get_conversion_function(const ResultType variable_type "Float To Vector", float_to_vector, mf::build::exec_presets::AllSpanOrSingle()); static auto float_to_color_function = mf::build::SI1_SO( "Float To Color", float_to_color, mf::build::exec_presets::AllSpanOrSingle()); + static auto float_to_float4_function = mf::build::SI1_SO( + "Float To Float4", float_to_float4, mf::build::exec_presets::AllSpanOrSingle()); static auto int_to_float_function = mf::build::SI1_SO( "Int To Float", int_to_float, mf::build::exec_presets::AllSpanOrSingle()); @@ -385,6 +398,8 @@ static mf::MultiFunction *get_conversion_function(const ResultType variable_type "Int To Vector", int_to_vector, mf::build::exec_presets::AllSpanOrSingle()); static auto int_to_color_function = mf::build::SI1_SO( "Int To Color", int_to_color, mf::build::exec_presets::AllSpanOrSingle()); + static auto int_to_float4_function = mf::build::SI1_SO( + "Int To Float4", int_to_float4, mf::build::exec_presets::AllSpanOrSingle()); static auto vector_to_float_function = mf::build::SI1_SO( "Vector To Float", vector_to_float, mf::build::exec_presets::AllSpanOrSingle()); @@ -392,6 +407,8 @@ static mf::MultiFunction *get_conversion_function(const ResultType variable_type "Vector To Int", vector_to_int, mf::build::exec_presets::AllSpanOrSingle()); static auto vector_to_color_function = mf::build::SI1_SO( "Vector To Color", vector_to_color, mf::build::exec_presets::AllSpanOrSingle()); + static auto vector_to_float4_function = mf::build::SI1_SO( + "Vector To Float4", vector_to_float4, mf::build::exec_presets::AllSpanOrSingle()); static auto color_to_float_function = mf::build::SI1_SO( "Color To Float", color_to_float, mf::build::exec_presets::AllSpanOrSingle()); @@ -399,6 +416,17 @@ static mf::MultiFunction *get_conversion_function(const ResultType variable_type "Color To Int", color_to_int, mf::build::exec_presets::AllSpanOrSingle()); static auto color_to_vector_function = mf::build::SI1_SO( "Color To Vector", color_to_vector, mf::build::exec_presets::AllSpanOrSingle()); + static auto color_to_float4_function = mf::build::SI1_SO( + "Color To Float4", color_to_float4, mf::build::exec_presets::AllSpanOrSingle()); + + static auto float4_to_float_function = mf::build::SI1_SO( + "Float4 To Float", float4_to_float, mf::build::exec_presets::AllSpanOrSingle()); + static auto float4_to_int_function = mf::build::SI1_SO( + "Float4 To Int", float4_to_int, mf::build::exec_presets::AllSpanOrSingle()); + static auto float4_to_vector_function = mf::build::SI1_SO( + "Float4 To Vector", float4_to_vector, mf::build::exec_presets::AllSpanOrSingle()); + static auto float4_to_color_function = mf::build::SI1_SO( + "Float4 To Color", float4_to_color, mf::build::exec_presets::AllSpanOrSingle()); switch (variable_type) { case ResultType::Float: @@ -409,6 +437,8 @@ static mf::MultiFunction *get_conversion_function(const ResultType variable_type return &float_to_vector_function; case ResultType::Color: return &float_to_color_function; + case ResultType::Float4: + return &float_to_float4_function; case ResultType::Float: /* Same type, no conversion needed. */ return nullptr; @@ -427,6 +457,8 @@ static mf::MultiFunction *get_conversion_function(const ResultType variable_type return &int_to_vector_function; case ResultType::Color: return &int_to_color_function; + case ResultType::Float4: + return &int_to_float4_function; case ResultType::Int: /* Same type, no conversion needed. */ return nullptr; @@ -445,6 +477,8 @@ static mf::MultiFunction *get_conversion_function(const ResultType variable_type return &vector_to_int_function; case ResultType::Color: return &vector_to_color_function; + case ResultType::Float4: + return &vector_to_float4_function; case ResultType::Vector: /* Same type, no conversion needed. */ return nullptr; @@ -463,6 +497,8 @@ static mf::MultiFunction *get_conversion_function(const ResultType variable_type return &color_to_int_function; case ResultType::Vector: return &color_to_vector_function; + case ResultType::Float4: + return &color_to_float4_function; case ResultType::Color: /* Same type, no conversion needed. */ return nullptr; @@ -473,6 +509,26 @@ static mf::MultiFunction *get_conversion_function(const ResultType variable_type break; } break; + case ResultType::Float4: + switch (expected_type) { + case ResultType::Float: + return &float4_to_float_function; + case ResultType::Int: + return &float4_to_int_function; + case ResultType::Vector: + return &float4_to_vector_function; + case ResultType::Color: + return &float4_to_color_function; + case ResultType::Float4: + /* Same type, no conversion needed. */ + return nullptr; + case ResultType::Float2: + case ResultType::Float3: + case ResultType::Int2: + /* Types are not user facing, so we needn't implement them. */ + break; + } + break; case ResultType::Float2: case ResultType::Float3: case ResultType::Int2: diff --git a/source/blender/compositor/intern/realize_on_domain_operation.cc b/source/blender/compositor/intern/realize_on_domain_operation.cc index 2f4c2c50c2e..8af9b0905b6 100644 --- a/source/blender/compositor/intern/realize_on_domain_operation.cc +++ b/source/blender/compositor/intern/realize_on_domain_operation.cc @@ -128,12 +128,12 @@ const char *RealizeOnDomainOperation::get_realization_shader_name() { if (this->get_input().get_realization_options().interpolation == Interpolation::Bicubic) { switch (this->get_input().type()) { - case ResultType::Color: - return "compositor_realize_on_domain_bicubic_color"; - case ResultType::Vector: - return "compositor_realize_on_domain_bicubic_vector"; case ResultType::Float: return "compositor_realize_on_domain_bicubic_float"; + case ResultType::Color: + case ResultType::Vector: + case ResultType::Float4: + return "compositor_realize_on_domain_bicubic_float4"; case ResultType::Int: case ResultType::Int2: case ResultType::Float2: @@ -144,12 +144,12 @@ const char *RealizeOnDomainOperation::get_realization_shader_name() } else { switch (this->get_input().type()) { - case ResultType::Color: - return "compositor_realize_on_domain_color"; - case ResultType::Vector: - return "compositor_realize_on_domain_vector"; case ResultType::Float: return "compositor_realize_on_domain_float"; + case ResultType::Color: + case ResultType::Vector: + case ResultType::Float4: + return "compositor_realize_on_domain_float4"; case ResultType::Int: case ResultType::Int2: case ResultType::Float2: diff --git a/source/blender/compositor/intern/reduce_to_single_value_operation.cc b/source/blender/compositor/intern/reduce_to_single_value_operation.cc index a38204d78c3..cb6133200a5 100644 --- a/source/blender/compositor/intern/reduce_to_single_value_operation.cc +++ b/source/blender/compositor/intern/reduce_to_single_value_operation.cc @@ -50,6 +50,9 @@ void ReduceToSingleValueOperation::execute() case ResultType::Vector: result.set_single_value(float4(static_cast(pixel))); break; + case ResultType::Float4: + result.set_single_value(float4(static_cast(pixel))); + break; case ResultType::Float: result.set_single_value(*static_cast(pixel)); break; diff --git a/source/blender/compositor/intern/result.cc b/source/blender/compositor/intern/result.cc index 62e8e5d15a7..30b735922a3 100644 --- a/source/blender/compositor/intern/result.cc +++ b/source/blender/compositor/intern/result.cc @@ -47,6 +47,7 @@ eGPUTextureFormat Result::gpu_texture_format(ResultType type, ResultPrecision pr return GPU_R16F; case ResultType::Vector: case ResultType::Color: + case ResultType::Float4: return GPU_RGBA16F; case ResultType::Float2: return GPU_RG16F; @@ -64,6 +65,7 @@ eGPUTextureFormat Result::gpu_texture_format(ResultType type, ResultPrecision pr return GPU_R32F; case ResultType::Vector: case ResultType::Color: + case ResultType::Float4: return GPU_RGBA32F; case ResultType::Float2: return GPU_RG32F; @@ -233,6 +235,8 @@ const CPPType &Result::get_cpp_type() const return CPPType::get(); case ResultType::Color: return CPPType::get(); + case ResultType::Float4: + return CPPType::get(); case ResultType::Float2: return CPPType::get(); case ResultType::Float3: @@ -285,6 +289,9 @@ void Result::allocate_single_value() case ResultType::Color: this->set_single_value(float4(0.0f)); break; + case ResultType::Float4: + this->set_single_value(float4(0.0f)); + break; case ResultType::Float2: this->set_single_value(float2(0.0f)); break; diff --git a/source/blender/compositor/intern/shader_operation.cc b/source/blender/compositor/intern/shader_operation.cc index cc9ba74b95e..71de90e0341 100644 --- a/source/blender/compositor/intern/shader_operation.cc +++ b/source/blender/compositor/intern/shader_operation.cc @@ -208,6 +208,8 @@ static const char *get_set_function_name(ResultType type) return "set_rgb"; case ResultType::Color: return "set_rgba"; + case ResultType::Float4: + return "set_rgba"; case ResultType::Float2: case ResultType::Float3: case ResultType::Int2: @@ -292,6 +294,8 @@ static const char *get_store_function_name(ResultType type) return "node_compositor_store_output_vector"; case ResultType::Color: return "node_compositor_store_output_color"; + case ResultType::Float4: + return "node_compositor_store_output_float4"; case ResultType::Float2: case ResultType::Float3: case ResultType::Int2: @@ -393,6 +397,8 @@ static const char *glsl_store_expression_from_result_type(ResultType type) return "vec4(vector, 0.0)"; case ResultType::Color: return "color"; + case ResultType::Float4: + return "value"; case ResultType::Float2: case ResultType::Float3: case ResultType::Int2: @@ -410,6 +416,7 @@ static ImageType gpu_image_type_from_result_type(const ResultType type) case ResultType::Float: case ResultType::Vector: case ResultType::Color: + case ResultType::Float4: return ImageType::FLOAT_2D; case ResultType::Int: return ImageType::INT_2D; @@ -431,16 +438,17 @@ void ShaderOperation::generate_code_for_outputs(ShaderCreateInfo &shader_create_ const std::string store_int_function_header = "void store_int(const uint id, float value)"; const std::string store_vector_function_header = "void store_vector(const uint id, vec3 vector)"; const std::string store_color_function_header = "void store_color(const uint id, vec4 color)"; + const std::string store_float4_function_header = "void store_float4(const uint id, vec4 value)"; - /* The store functions are used by the node_compositor_store_output_[float|int|vector|color] - * functions but are only defined later as part of the compute source, so they need to be forward - * declared. - * NOTE(Metal): Metal does not require forward declarations. */ + /* The store functions are used by the node_compositor_store_output_[type] functions but are only + * defined later as part of the compute source, so they need to be forward declared. NOTE(Metal): + * Metal does not require forward declarations. */ if (GPU_backend_get_type() != GPU_BACKEND_METAL) { shader_create_info.typedef_source_generated += store_float_function_header + ";\n"; shader_create_info.typedef_source_generated += store_int_function_header + ";\n"; shader_create_info.typedef_source_generated += store_vector_function_header + ";\n"; shader_create_info.typedef_source_generated += store_color_function_header + ";\n"; + shader_create_info.typedef_source_generated += store_float4_function_header + ";\n"; } /* Each of the store functions is essentially a single switch case on the given ID, so start by @@ -450,11 +458,13 @@ void ShaderOperation::generate_code_for_outputs(ShaderCreateInfo &shader_create_ std::stringstream store_int_function; std::stringstream store_vector_function; std::stringstream store_color_function; + std::stringstream store_float4_function; const std::string store_function_start = "\n{\n switch (id) {\n"; store_float_function << store_float_function_header << store_function_start; store_int_function << store_int_function_header << store_function_start; store_vector_function << store_vector_function_header << store_function_start; store_color_function << store_color_function_header << store_function_start; + store_float4_function << store_float4_function_header << store_function_start; for (StringRefNull output_identifier : output_sockets_to_output_identifiers_map_.values()) { const Result &result = get_result(output_identifier); @@ -489,6 +499,9 @@ void ShaderOperation::generate_code_for_outputs(ShaderCreateInfo &shader_create_ case ResultType::Color: store_color_function << case_code.str(); break; + case ResultType::Float4: + store_float4_function << case_code.str(); + break; case ResultType::Float2: case ResultType::Float3: case ResultType::Int2: @@ -504,11 +517,13 @@ void ShaderOperation::generate_code_for_outputs(ShaderCreateInfo &shader_create_ store_int_function << store_function_end; store_vector_function << store_function_end; store_color_function << store_function_end; + store_float4_function << store_function_end; shader_create_info.compute_source_generated += store_float_function.str() + store_int_function.str() + store_vector_function.str() + - store_color_function.str(); + store_color_function.str() + + store_float4_function.str(); } static const char *glsl_type_from_result_type(ResultType type) @@ -522,6 +537,7 @@ static const char *glsl_type_from_result_type(ResultType type) case ResultType::Vector: return "vec3"; case ResultType::Color: + case ResultType::Float4: return "vec4"; case ResultType::Float2: case ResultType::Float3: @@ -546,6 +562,8 @@ static const char *glsl_swizzle_from_result_type(ResultType type) return "xyz"; case ResultType::Color: return "rgba"; + case ResultType::Float4: + return "xyzw"; case ResultType::Float2: case ResultType::Float3: case ResultType::Int2: diff --git a/source/blender/compositor/intern/utilities.cc b/source/blender/compositor/intern/utilities.cc index 4b587b8634a..09c005add42 100644 --- a/source/blender/compositor/intern/utilities.cc +++ b/source/blender/compositor/intern/utilities.cc @@ -59,6 +59,9 @@ ResultType get_node_socket_result_type(const bNodeSocket *socket) case SOCK_INT: return ResultType::Int; case SOCK_VECTOR: + /* Vector sockets can also be ResultType::Float4 or ResultType::Float2, but the + * developer is expected to define that manually since there is no way to distinguish them + * from the socket. */ return ResultType::Vector; case SOCK_RGBA: return ResultType::Color; diff --git a/source/blender/compositor/shaders/infos/compositor_convert_info.hh b/source/blender/compositor/shaders/infos/compositor_convert_info.hh index b1579e005d0..2a67ea8aead 100644 --- a/source/blender/compositor/shaders/infos/compositor_convert_info.hh +++ b/source/blender/compositor/shaders/infos/compositor_convert_info.hh @@ -45,6 +45,13 @@ DEFINE_VALUE("CONVERT_EXPRESSION(value)", "vec4(float_to_color(value.x))") DO_STATIC_COMPILATION() GPU_SHADER_CREATE_END() +GPU_SHADER_CREATE_INFO(compositor_convert_float_to_float4) +ADDITIONAL_INFO(compositor_convert_float_shared) +IMAGE(0, GPU_RGBA16F, WRITE, FLOAT_2D, output_img) +DEFINE_VALUE("CONVERT_EXPRESSION(value)", "vec4(float_to_float4(value.x))") +DO_STATIC_COMPILATION() +GPU_SHADER_CREATE_END() + /* -------------------------------------------------------------------- * Int to other. */ @@ -70,6 +77,13 @@ DEFINE_VALUE("CONVERT_EXPRESSION(value)", "vec4(int_to_color(value.x))") DO_STATIC_COMPILATION() GPU_SHADER_CREATE_END() +GPU_SHADER_CREATE_INFO(compositor_convert_int_to_float4) +ADDITIONAL_INFO(compositor_convert_int_shared) +IMAGE(0, GPU_RGBA16F, WRITE, FLOAT_2D, output_img) +DEFINE_VALUE("CONVERT_EXPRESSION(value)", "vec4(int_to_float4(value.x))") +DO_STATIC_COMPILATION() +GPU_SHADER_CREATE_END() + /* -------------------------------------------------------------------- * Vector to other. */ @@ -95,6 +109,13 @@ DEFINE_VALUE("CONVERT_EXPRESSION(value)", "vec4(vector_to_color(value))") DO_STATIC_COMPILATION() GPU_SHADER_CREATE_END() +GPU_SHADER_CREATE_INFO(compositor_convert_vector_to_float4) +ADDITIONAL_INFO(compositor_convert_float_shared) +IMAGE(0, GPU_RGBA16F, WRITE, FLOAT_2D, output_img) +DEFINE_VALUE("CONVERT_EXPRESSION(value)", "vec4(vector_to_float4(value))") +DO_STATIC_COMPILATION() +GPU_SHADER_CREATE_END() + /* -------------------------------------------------------------------- * Color to other. */ @@ -124,6 +145,45 @@ DEFINE_VALUE("CONVERT_EXPRESSION(value)", "vec4(color_to_vector(value))") DO_STATIC_COMPILATION() GPU_SHADER_CREATE_END() +GPU_SHADER_CREATE_INFO(compositor_convert_color_to_float4) +ADDITIONAL_INFO(compositor_convert_float_shared) +IMAGE(0, GPU_RGBA16F, WRITE, FLOAT_2D, output_img) +DEFINE_VALUE("CONVERT_EXPRESSION(value)", "vec4(color_to_float4(value))") +DO_STATIC_COMPILATION() +GPU_SHADER_CREATE_END() + +/* -------------------------------------------------------------------- + * Float4 to other. + */ + +GPU_SHADER_CREATE_INFO(compositor_convert_float4_to_float) +ADDITIONAL_INFO(compositor_convert_float_shared) +IMAGE(0, GPU_R16F, WRITE, FLOAT_2D, output_img) +DEFINE_VALUE("CONVERT_EXPRESSION(value)", "vec4(float4_to_float(value), vec3(0.0))") +DO_STATIC_COMPILATION() +GPU_SHADER_CREATE_END() + +GPU_SHADER_CREATE_INFO(compositor_convert_float4_to_int) +ADDITIONAL_INFO(compositor_convert_float_shared) +IMAGE(0, GPU_R16I, WRITE, INT_2D, output_img) +DEFINE_VALUE("CONVERT_EXPRESSION(value)", "ivec4(float4_to_int(value), ivec3(0))") +DO_STATIC_COMPILATION() +GPU_SHADER_CREATE_END() + +GPU_SHADER_CREATE_INFO(compositor_convert_float4_to_vector) +ADDITIONAL_INFO(compositor_convert_float_shared) +IMAGE(0, GPU_RGBA16F, WRITE, FLOAT_2D, output_img) +DEFINE_VALUE("CONVERT_EXPRESSION(value)", "vec4(float4_to_vector(value))") +DO_STATIC_COMPILATION() +GPU_SHADER_CREATE_END() + +GPU_SHADER_CREATE_INFO(compositor_convert_float4_to_color) +ADDITIONAL_INFO(compositor_convert_float_shared) +IMAGE(0, GPU_RGBA16F, WRITE, FLOAT_2D, output_img) +DEFINE_VALUE("CONVERT_EXPRESSION(value)", "vec4(float4_to_color(value))") +DO_STATIC_COMPILATION() +GPU_SHADER_CREATE_END() + /* -------------------------------------------------------------------- * Color to channel. */ diff --git a/source/blender/compositor/shaders/infos/compositor_read_input_info.hh b/source/blender/compositor/shaders/infos/compositor_read_input_info.hh index 0aa1be33ff8..3092497b2ce 100644 --- a/source/blender/compositor/shaders/infos/compositor_read_input_info.hh +++ b/source/blender/compositor/shaders/infos/compositor_read_input_info.hh @@ -18,14 +18,7 @@ DEFINE_VALUE("READ_EXPRESSION(input_color)", "vec4(input_color.r, vec3(0.0))") DO_STATIC_COMPILATION() GPU_SHADER_CREATE_END() -GPU_SHADER_CREATE_INFO(compositor_read_input_vector) -ADDITIONAL_INFO(compositor_read_input_shared) -IMAGE(0, GPU_RGBA16F, WRITE, FLOAT_2D, output_img) -DEFINE_VALUE("READ_EXPRESSION(input_color)", "input_color") -DO_STATIC_COMPILATION() -GPU_SHADER_CREATE_END() - -GPU_SHADER_CREATE_INFO(compositor_read_input_color) +GPU_SHADER_CREATE_INFO(compositor_read_input_float4) ADDITIONAL_INFO(compositor_read_input_shared) IMAGE(0, GPU_RGBA16F, WRITE, FLOAT_2D, output_img) DEFINE_VALUE("READ_EXPRESSION(input_color)", "input_color") diff --git a/source/blender/compositor/shaders/infos/compositor_realize_on_domain_info.hh b/source/blender/compositor/shaders/infos/compositor_realize_on_domain_info.hh index 725ba946b2f..41c09e4f4f4 100644 --- a/source/blender/compositor/shaders/infos/compositor_realize_on_domain_info.hh +++ b/source/blender/compositor/shaders/infos/compositor_realize_on_domain_info.hh @@ -21,13 +21,7 @@ ADDITIONAL_INFO(compositor_realize_on_domain_shared) DEFINE_VALUE("SAMPLER_FUNCTION", "texture_bicubic") GPU_SHADER_CREATE_END() -GPU_SHADER_CREATE_INFO(compositor_realize_on_domain_color) -ADDITIONAL_INFO(compositor_realize_on_domain_standard_shared) -IMAGE(0, GPU_RGBA16F, WRITE, FLOAT_2D, domain_img) -DO_STATIC_COMPILATION() -GPU_SHADER_CREATE_END() - -GPU_SHADER_CREATE_INFO(compositor_realize_on_domain_vector) +GPU_SHADER_CREATE_INFO(compositor_realize_on_domain_float4) ADDITIONAL_INFO(compositor_realize_on_domain_standard_shared) IMAGE(0, GPU_RGBA16F, WRITE, FLOAT_2D, domain_img) DO_STATIC_COMPILATION() @@ -39,13 +33,7 @@ IMAGE(0, GPU_R16F, WRITE, FLOAT_2D, domain_img) DO_STATIC_COMPILATION() GPU_SHADER_CREATE_END() -GPU_SHADER_CREATE_INFO(compositor_realize_on_domain_bicubic_color) -ADDITIONAL_INFO(compositor_realize_on_domain_bicubic_shared) -IMAGE(0, GPU_RGBA16F, WRITE, FLOAT_2D, domain_img) -DO_STATIC_COMPILATION() -GPU_SHADER_CREATE_END() - -GPU_SHADER_CREATE_INFO(compositor_realize_on_domain_bicubic_vector) +GPU_SHADER_CREATE_INFO(compositor_realize_on_domain_bicubic_float4) ADDITIONAL_INFO(compositor_realize_on_domain_bicubic_shared) IMAGE(0, GPU_RGBA16F, WRITE, FLOAT_2D, domain_img) DO_STATIC_COMPILATION() diff --git a/source/blender/compositor/shaders/library/gpu_shader_compositor_store_output.glsl b/source/blender/compositor/shaders/library/gpu_shader_compositor_store_output.glsl index 8fb51156c0e..fc1c4a5e140 100644 --- a/source/blender/compositor/shaders/library/gpu_shader_compositor_store_output.glsl +++ b/source/blender/compositor/shaders/library/gpu_shader_compositor_store_output.glsl @@ -8,7 +8,7 @@ * used to establish an output link that is then used to track the nodes that contribute to the * output of the compositor node tree. * - * The store_[float|vector|color] functions are dynamically generated in + * The store_[type] functions are dynamically generated in * ShaderOperation::generate_code_for_outputs. */ void node_compositor_store_output_float(const float id, float value, out float out_value) @@ -35,3 +35,9 @@ void node_compositor_store_output_color(const float id, vec4 color, out vec4 out store_color(floatBitsToUint(id), color); out_color = color; } + +void node_compositor_store_output_float4(const float id, vec4 value, out vec4 out_value) +{ + store_float4(floatBitsToUint(id), value); + out_value = value; +} diff --git a/source/blender/compositor/shaders/library/gpu_shader_compositor_type_conversion.glsl b/source/blender/compositor/shaders/library/gpu_shader_compositor_type_conversion.glsl index 26f08de08ee..4bbf5a154b7 100644 --- a/source/blender/compositor/shaders/library/gpu_shader_compositor_type_conversion.glsl +++ b/source/blender/compositor/shaders/library/gpu_shader_compositor_type_conversion.glsl @@ -21,6 +21,11 @@ vec4 float_to_color(float value) return vec4(vec3(value), 1.0); } +vec4 float_to_float4(float value) +{ + return vec4(value); +} + /* -------------------------------------------------------------------- * Int to other. */ @@ -40,6 +45,11 @@ vec4 int_to_color(int value) return float_to_color(int_to_float(value)); } +vec4 int_to_float4(int value) +{ + return float_to_float4(int_to_float(value)); +} + /* -------------------------------------------------------------------- * Vector to other. */ @@ -59,6 +69,11 @@ vec4 vector_to_color(vec4 value) return vec4(value.xyz, 1.0); } +vec4 vector_to_float4(vec4 value) +{ + return value; +} + /* -------------------------------------------------------------------- * Color to other. */ @@ -78,6 +93,35 @@ vec4 color_to_vector(vec4 value) return value; } +vec4 color_to_float4(vec4 value) +{ + return value; +} + +/* -------------------------------------------------------------------- + * Float4 to other. + */ + +float float4_to_float(vec4 value) +{ + return dot(value, vec4(1.0)) / 4.0; +} + +int float4_to_int(vec4 value) +{ + return float_to_int(float4_to_float(value)); +} + +vec4 float4_to_vector(vec4 value) +{ + return value; +} + +vec4 float4_to_color(vec4 value) +{ + return value; +} + /* -------------------------------------------------------------------- * GPUMatrial-specific implicit conversion functions. * diff --git a/source/blender/compositor/utilities/COM_utilities_type_conversion.hh b/source/blender/compositor/utilities/COM_utilities_type_conversion.hh index 64cc81ac6bb..9ca3cee846b 100644 --- a/source/blender/compositor/utilities/COM_utilities_type_conversion.hh +++ b/source/blender/compositor/utilities/COM_utilities_type_conversion.hh @@ -30,6 +30,11 @@ inline float4 float_to_color(const float &value) return float4(float3(value), 1.0f); } +inline float4 float_to_float4(const float &value) +{ + return float4(value); +} + /* -------------------------------------------------------------------- * Int to other. */ @@ -49,6 +54,11 @@ inline float4 int_to_color(const int &value) return float_to_color(int_to_float(value)); } +inline float4 int_to_float4(const int &value) +{ + return float_to_float4(int_to_float(value)); +} + /* -------------------------------------------------------------------- * Vector to other. */ @@ -68,6 +78,11 @@ inline float4 vector_to_color(const float4 &value) return float4(value.xyz(), 1.0f); } +inline float4 vector_to_float4(const float4 &value) +{ + return value; +} + /* -------------------------------------------------------------------- * Color to other. */ @@ -87,4 +102,33 @@ inline float4 color_to_vector(const float4 &value) return value; } +inline float4 color_to_float4(const float4 &value) +{ + return value; +} + +/* -------------------------------------------------------------------- + * Float4 to other. + */ + +inline float float4_to_float(const float4 &value) +{ + return math::reduce_add(value) / 4.0f; +} + +inline int float4_to_int(const float4 &value) +{ + return float_to_int(float4_to_float(value)); +} + +inline float4 float4_to_vector(const float4 &value) +{ + return value; +} + +inline float4 float4_to_color(const float4 &value) +{ + return value; +} + } // namespace blender::compositor diff --git a/source/blender/nodes/composite/nodes/node_composite_file_output.cc b/source/blender/nodes/composite/nodes/node_composite_file_output.cc index fa2cffb14bf..7e6cc9b75b9 100644 --- a/source/blender/nodes/composite/nodes/node_composite_file_output.cc +++ b/source/blender/nodes/composite/nodes/node_composite_file_output.cc @@ -513,6 +513,7 @@ class FileOutputOperation : public NodeOperation { descriptor.realization_mode = this->is_multi_layer() ? InputRealizationMode::OperationDomain : InputRealizationMode::Transforms; + descriptor.skip_type_conversion = true; } } @@ -677,12 +678,13 @@ class FileOutputOperation : public NodeOperation { } break; case ResultType::Vector: - if (result.meta_data.is_4d_vector) { - file_output.add_pass(pass_name, view_name, "XYZW", buffer); - } - else { - file_output.add_pass(pass_name, view_name, "XYZ", float4_to_float3_image(size, buffer)); - } + file_output.add_pass(pass_name, view_name, "XYZ", float4_to_float3_image(size, buffer)); + break; + case ResultType::Float3: + file_output.add_pass(pass_name, view_name, "XYZ", buffer); + break; + case ResultType::Float4: + file_output.add_pass(pass_name, view_name, "XYZW", buffer); break; case ResultType::Float: file_output.add_pass(pass_name, view_name, "V", buffer); @@ -715,14 +717,32 @@ class FileOutputOperation : public NodeOperation { float *buffer = static_cast(MEM_malloc_arrayN( size_t(size.x) * size.y, sizeof(float[4]), "File Output Inflated Buffer.")); - const float4 value = result.type() == ResultType::Color ? - result.get_single_value() : - result.get_single_value(); + const float4 value = result.get_single_value(); parallel_for(size, [&](const int2 texel) { copy_v4_v4(buffer + ((int64_t(texel.y) * size.x + texel.x) * 4), value); }); return buffer; } + case ResultType::Float4: { + float *buffer = static_cast(MEM_malloc_arrayN( + size_t(size.x) * size.y, sizeof(float[4]), "File Output Inflated Buffer.")); + + const float4 value = result.get_single_value(); + parallel_for(size, [&](const int2 texel) { + copy_v4_v4(buffer + ((int64_t(texel.y) * size.x + texel.x) * 4), value); + }); + return buffer; + } + case ResultType::Float3: { + float *buffer = static_cast(MEM_malloc_arrayN( + size_t(size.x) * size.y, sizeof(float[3]), "File Output Inflated Buffer.")); + + const float3 value = result.get_single_value(); + parallel_for(size, [&](const int2 texel) { + copy_v3_v3(buffer + ((int64_t(texel.y) * size.x + texel.x) * 3), value); + }); + return buffer; + } default: /* Other types are internal and needn't be handled by operations. */ break; @@ -752,9 +772,15 @@ class FileOutputOperation : public NodeOperation { case ResultType::Color: file_output.add_view(view_name, 4, buffer); break; + case ResultType::Float4: + file_output.add_view(view_name, 4, buffer); + break; case ResultType::Vector: file_output.add_view(view_name, 3, float4_to_float3_image(size, buffer)); break; + case ResultType::Float3: + file_output.add_view(view_name, 3, buffer); + break; case ResultType::Float: file_output.add_view(view_name, 1, buffer); break; diff --git a/source/blender/nodes/composite/nodes/node_composite_image.cc b/source/blender/nodes/composite/nodes/node_composite_image.cc index fc1abaee01e..8d9347d6415 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.cc +++ b/source/blender/nodes/composite/nodes/node_composite_image.cc @@ -472,6 +472,7 @@ class ImageOperation : public NodeOperation { extract_alpha(context(), cached_image, result); } else { + result.set_type(cached_image.type()); result.set_precision(cached_image.precision()); result.wrap_external(cached_image); } @@ -719,6 +720,13 @@ class RenderLayerOperation : public NodeOperation { return; } + /* Vector sockets are 3D by default, so we need to overwrite the type if the pass turned out to + * be 4D. */ + if (result.type() == ResultType::Vector && pass.type() == ResultType::Float4) { + result.set_type(pass.type()); + } + result.set_precision(pass.precision()); + if (this->context().use_gpu()) { this->execute_pass_gpu(pass, result); } @@ -729,8 +737,6 @@ class RenderLayerOperation : public NodeOperation { void execute_pass_gpu(const Result &pass, Result &result) { - result.set_precision(pass.precision()); - GPUShader *shader = this->context().get_shader(this->get_shader_name(pass, result), result.precision()); GPU_shader_bind(shader); @@ -764,11 +770,10 @@ class RenderLayerOperation : public NodeOperation { case ResultType::Float: return "compositor_read_input_float"; case ResultType::Vector: - return "compositor_read_input_vector"; case ResultType::Color: - return "compositor_read_input_color"; + case ResultType::Float4: case ResultType::Float3: - return "compositor_read_input_vector"; + return "compositor_read_input_float4"; default: /* Other types are internal and needn't be handled by operations. */ break; diff --git a/source/blender/nodes/composite/nodes/node_composite_trackpos.cc b/source/blender/nodes/composite/nodes/node_composite_trackpos.cc index 741b28b2772..2de219a6e1f 100644 --- a/source/blender/nodes/composite/nodes/node_composite_trackpos.cc +++ b/source/blender/nodes/composite/nodes/node_composite_trackpos.cc @@ -171,9 +171,11 @@ class TrackPositionOperation : public NodeOperation { const float2 speed_toward_next = current_marker_position - next_marker_position; /* Encode both speeds in a 4D vector. Multiply by the size to get the speed in pixel space. */ - const float4 speed = float4(speed_toward_previous, speed_toward_next) * float4(size, size); + const float4 speed = float4(speed_toward_previous * float2(size), + speed_toward_next * float2(size)); Result &result = get_result("Speed"); + result.set_type(ResultType::Float4); result.allocate_single_value(); result.set_single_value(speed); } @@ -192,6 +194,7 @@ class TrackPositionOperation : public NodeOperation { } if (should_compute_output("Speed")) { Result &result = get_result("Speed"); + result.set_type(ResultType::Float4); result.allocate_single_value(); result.set_single_value(float4(0.0f)); } diff --git a/source/blender/nodes/composite/nodes/node_composite_vec_blur.cc b/source/blender/nodes/composite/nodes/node_composite_vec_blur.cc index ec13a9ea2b2..595af481d88 100644 --- a/source/blender/nodes/composite/nodes/node_composite_vec_blur.cc +++ b/source/blender/nodes/composite/nodes/node_composite_vec_blur.cc @@ -105,7 +105,7 @@ static float2 max_velocity_approximate(const float2 &a, static Result compute_max_tile_velocity_cpu(Context &context, const Result &velocity_image) { if (velocity_image.is_single_value()) { - Result output = context.create_result(ResultType::Vector); + Result output = context.create_result(ResultType::Float4); output.allocate_single_value(); output.set_single_value(velocity_image.get_single_value()); return output; @@ -114,7 +114,7 @@ static Result compute_max_tile_velocity_cpu(Context &context, const Result &velo const int2 tile_size = int2(MOTION_BLUR_TILE_SIZE); const int2 velocity_size = velocity_image.domain().size; const int2 tiles_count = math::divide_ceil(velocity_size, tile_size); - Result output = context.create_result(ResultType::Vector); + Result output = context.create_result(ResultType::Float4); output.allocate_texture(Domain(tiles_count)); parallel_for(tiles_count, [&](const int2 texel) { @@ -197,14 +197,14 @@ static Result dilate_max_velocity_cpu(Context &context, const float shutter_speed) { if (max_tile_velocity.is_single_value()) { - Result output = context.create_result(ResultType::Vector); + Result output = context.create_result(ResultType::Float4); output.allocate_single_value(); output.set_single_value(max_tile_velocity.get_single_value()); return output; } const int2 size = max_tile_velocity.domain().size; - Result output = context.create_result(ResultType::Vector); + Result output = context.create_result(ResultType::Float4); output.allocate_texture(Domain(size)); parallel_for(size, [&](const int2 texel) { output.store_pixel(texel, float4(0.0f)); }); @@ -213,13 +213,14 @@ static Result dilate_max_velocity_cpu(Context &context, for (const int64_t x : IndexRange(size.x)) { const int2 src_tile = int2(x, y); - float4 max_motion = float4(max_tile_velocity.load_pixel(src_tile)) * - float4(float2(shutter_speed), float2(-shutter_speed)); + const float4 max_motion = max_tile_velocity.load_pixel(src_tile); + const float2 max_previous_velocity = max_motion.xy() * shutter_speed; + const float2 max_next_velocity = max_motion.zw() * -shutter_speed; { /* Rectangular area (in tiles) where the motion vector spreads. */ - MotionRect motion_rect = compute_motion_rect(src_tile, max_motion.xy(), size); - MotionLine motion_line = compute_motion_line(src_tile, max_motion.xy()); + MotionRect motion_rect = compute_motion_rect(src_tile, max_previous_velocity, size); + MotionLine motion_line = compute_motion_line(src_tile, max_previous_velocity); /* Do a conservative rasterization of the line of the motion vector line. */ for (int j = 0; j < motion_rect.extent.y; j++) { for (int i = 0; i < motion_rect.extent.x; i++) { @@ -227,9 +228,9 @@ static Result dilate_max_velocity_cpu(Context &context, if (is_inside_motion_line(tile, motion_line)) { const float4 current_max_velocity = output.load_pixel(tile); const float2 new_max_previous_velocity = max_velocity_approximate( - current_max_velocity.xy(), max_motion.xy(), tile, src_tile); + current_max_velocity.xy(), max_previous_velocity, tile, src_tile); const float2 new_max_next_velocity = max_velocity_approximate( - current_max_velocity.zw(), max_motion.zw(), tile, src_tile); + current_max_velocity.zw(), max_next_velocity, tile, src_tile); output.store_pixel(tile, float4(new_max_previous_velocity, new_max_next_velocity)); } } @@ -238,8 +239,8 @@ static Result dilate_max_velocity_cpu(Context &context, { /* Rectangular area (in tiles) where the motion vector spreads. */ - MotionRect motion_rect = compute_motion_rect(src_tile, max_motion.zw(), size); - MotionLine motion_line = compute_motion_line(src_tile, max_motion.zw()); + MotionRect motion_rect = compute_motion_rect(src_tile, max_next_velocity, size); + MotionLine motion_line = compute_motion_line(src_tile, max_next_velocity); /* Do a conservative rasterization of the line of the motion vector line. */ for (int j = 0; j < motion_rect.extent.y; j++) { for (int i = 0; i < motion_rect.extent.x; i++) { @@ -247,9 +248,9 @@ static Result dilate_max_velocity_cpu(Context &context, if (is_inside_motion_line(tile, motion_line)) { const float4 current_max_velocity = output.load_pixel(tile); const float2 new_max_previous_velocity = max_velocity_approximate( - current_max_velocity.xy(), max_motion.xy(), tile, src_tile); + current_max_velocity.xy(), max_previous_velocity, tile, src_tile); const float2 new_max_next_velocity = max_velocity_approximate( - current_max_velocity.zw(), max_motion.zw(), tile, src_tile); + current_max_velocity.zw(), max_next_velocity, tile, src_tile); output.store_pixel(tile, float4(new_max_previous_velocity, new_max_next_velocity)); } } @@ -436,8 +437,9 @@ static void motion_blur_cpu(const Result &input_image, /* Data of the center pixel of the gather (target). */ float center_depth = input_depth.load_pixel(texel); - float4 center_motion = float4(input_velocity.load_pixel(texel)) * - float4(float2(shutter_speed), float2(-shutter_speed)); + float4 center_motion = input_velocity.load_pixel(texel); + float2 center_previous_motion = center_motion.xy() * shutter_speed; + float2 center_next_motion = center_motion.zw() * -shutter_speed; float4 center_color = input_image.load_pixel(texel); /* Randomize tile boundary to avoid ugly discontinuities. Randomize 1/4th of the tile. @@ -460,7 +462,7 @@ static void motion_blur_cpu(const Result &input_image, input_velocity, size, uv, - center_motion.xy(), + center_previous_motion, center_depth, max_motion.xy(), rand, @@ -474,7 +476,7 @@ static void motion_blur_cpu(const Result &input_image, input_velocity, size, uv, - center_motion.zw(), + center_next_motion, center_depth, max_motion.zw(), rand, @@ -510,7 +512,10 @@ static void motion_blur_cpu(const Result &input_image, class VectorBlurOperation : public NodeOperation { public: - using NodeOperation::NodeOperation; + VectorBlurOperation(Context &context, DNode node) : NodeOperation(context, node) + { + this->get_input_descriptor("Speed").type = ResultType::Float4; + } void execute() override { @@ -550,7 +555,7 @@ class VectorBlurOperation : public NodeOperation { Result &input = get_input("Speed"); input.bind_as_texture(shader, "input_tx"); - Result output = context().create_result(ResultType::Vector); + Result output = context().create_result(ResultType::Float4); const int2 tiles_count = math::divide_ceil(input.domain().size, int2(32)); output.allocate_texture(Domain(tiles_count)); output.bind_as_image(shader, "output_img"); diff --git a/source/blender/render/intern/compositor.cc b/source/blender/render/intern/compositor.cc index 42d7edf26e6..0a966839fcf 100644 --- a/source/blender/render/intern/compositor.cc +++ b/source/blender/render/intern/compositor.cc @@ -259,10 +259,8 @@ class Context : public compositor::Context { return compositor::Result(*this); } - const eGPUTextureFormat format = (render_pass->channels == 1) ? GPU_R32F : - (render_pass->channels == 3) ? GPU_RGB32F : - GPU_RGBA32F; - compositor::Result pass = compositor::Result(*this, format); + compositor::Result pass = compositor::Result( + *this, this->result_type_from_pass(render_pass), compositor::ResultPrecision::Full); if (this->use_gpu()) { GPUTexture *pass_texture = RE_pass_ensure_gpu_texture_cache(render, render_pass); @@ -283,6 +281,30 @@ class Context : public compositor::Context { return pass; } + compositor::ResultType result_type_from_pass(const RenderPass *pass) + { + switch (pass->channels) { + case 1: + return compositor::ResultType::Float; + case 2: + return compositor::ResultType::Float2; + case 3: + return compositor::ResultType::Float3; + case 4: + if (StringRef(pass->chan_id) == "XYZW") { + return compositor::ResultType::Float4; + } + else { + return compositor::ResultType::Color; + } + default: + break; + } + + BLI_assert_unreachable(); + return compositor::ResultType::Float; + } + StringRef get_view_name() const override { return input_data_.view_name; @@ -390,23 +412,6 @@ class Context : public compositor::Context { }, false); - RenderLayer *render_layer = RE_GetRenderLayer(render_result, view_layer->name); - if (!render_layer) { - RE_ReleaseResult(render); - return; - } - - RenderPass *render_pass = RE_pass_find_by_name( - render_layer, pass_name, this->get_view_name().data()); - if (!render_pass) { - RE_ReleaseResult(render); - return; - } - - if (StringRef(render_pass->chan_id) == "XYZW") { - meta_data.is_4d_vector = true; - } - RE_ReleaseResult(render); } diff --git a/tests/data b/tests/data index 60777a2f496..42dabf608f1 160000 --- a/tests/data +++ b/tests/data @@ -1 +1 @@ -Subproject commit 60777a2f496ead8f749c62872e9909d9e2b8fabb +Subproject commit 42dabf608f1e756cc9d84ebda0f1fb6bdcbe639f