diff --git a/source/blender/compositor/realtime_compositor/COM_conversion_operation.hh b/source/blender/compositor/realtime_compositor/COM_conversion_operation.hh index 96a6f52afa0..0b432928674 100644 --- a/source/blender/compositor/realtime_compositor/COM_conversion_operation.hh +++ b/source/blender/compositor/realtime_compositor/COM_conversion_operation.hh @@ -13,19 +13,18 @@ namespace blender::realtime_compositor { -/* -------------------------------------------------------------------- */ -/** \name Conversion Operation +/* -------------------------------------------------------------------- + * Conversion Operation * * A simple operation that converts a result from a certain type to another. See the derived - * classes for more details. - * \{ */ - + * classes for more details. */ class ConversionOperation : public SimpleOperation { public: using SimpleOperation::SimpleOperation; /* If the input result is a single value, execute_single is called. Otherwise, the shader - * provided by get_conversion_shader is dispatched. */ + * provided by get_conversion_shader is dispatched for GPU contexts or execute_cpu is called for + * CPU contexts. */ void execute() override; /* Determine if a conversion operation is needed for the input with the given result and @@ -39,119 +38,107 @@ class ConversionOperation : public SimpleOperation { /* Convert the input single value result to the output single value result. */ virtual void execute_single(const Result &input, Result &output) = 0; + /* Convert the input to the appropriate type and write the result to the output on the CPU. */ + virtual void execute_cpu(const Result &input, Result &output) = 0; + /* Get the shader the will be used for conversion. */ virtual GPUShader *get_conversion_shader() const = 0; +}; - /** \} */ - -}; // namespace blender::realtime_compositorclassConversionOperation:publicSimpleOperation - -/* -------------------------------------------------------------------- */ -/** \name Convert Float to Vector Operation +/* -------------------------------------------------------------------- + * Convert Float to Vector Operation * * Takes a float result and outputs a vector result. The first three components of the output are - * filled with the input float, while the fourth component is set to 1. - * \{ */ - + * filled with the input float, while the fourth component is set to 1. */ class ConvertFloatToVectorOperation : public ConversionOperation { public: ConvertFloatToVectorOperation(Context &context); void execute_single(const Result &input, Result &output) override; + void execute_cpu(const Result &input, Result &output) override; + GPUShader *get_conversion_shader() const override; }; -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Convert Float to Color Operation +/* -------------------------------------------------------------------- + * Convert Float to Color Operation * * Takes a float result and outputs a color result. All three color channels of the output are - * filled with the input float and the alpha channel is set to 1. - * \{ */ - + * filled with the input float and the alpha channel is set to 1. */ class ConvertFloatToColorOperation : public ConversionOperation { public: ConvertFloatToColorOperation(Context &context); void execute_single(const Result &input, Result &output) override; + void execute_cpu(const Result &input, Result &output) override; + GPUShader *get_conversion_shader() const override; }; -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Convert Color to Float Operation +/* -------------------------------------------------------------------- + * Convert Color to Float Operation * * Takes a color result and outputs a float result. The output is the average of the three color - * channels, the alpha channel is ignored. - * \{ */ - + * channels, the alpha channel is ignored. */ class ConvertColorToFloatOperation : public ConversionOperation { public: ConvertColorToFloatOperation(Context &context); void execute_single(const Result &input, Result &output) override; + void execute_cpu(const Result &input, Result &output) override; + GPUShader *get_conversion_shader() const override; }; -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Convert Color to Vector Operation +/* -------------------------------------------------------------------- + * Convert Color to Vector Operation * * Takes a color result and outputs a vector result. The output is an exact copy of the input since - * vectors are 4D. - * \{ */ - + * vectors are 4D. */ class ConvertColorToVectorOperation : public ConversionOperation { public: ConvertColorToVectorOperation(Context &context); void execute_single(const Result &input, Result &output) override; + void execute_cpu(const Result &input, Result &output) override; + GPUShader *get_conversion_shader() const override; }; -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Convert Vector to Float Operation +/* -------------------------------------------------------------------- + * Convert Vector to Float Operation * * Takes a vector result and outputs a float result. The output is the average of the three - * components. - * \{ */ - + *components. */ class ConvertVectorToFloatOperation : public ConversionOperation { public: ConvertVectorToFloatOperation(Context &context); void execute_single(const Result &input, Result &output) override; + void execute_cpu(const Result &input, Result &output) override; + GPUShader *get_conversion_shader() const override; }; -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Convert Vector to Color Operation +/* -------------------------------------------------------------------- + * Convert Vector to Color Operation * * Takes a vector result and outputs a color result. The output is a copy of the three vector - * components to the three color channels with the alpha channel set to 1. - * \{ */ - + * components to the three color channels with the alpha channel set to 1. */ class ConvertVectorToColorOperation : public ConversionOperation { public: ConvertVectorToColorOperation(Context &context); void execute_single(const Result &input, Result &output) override; + void execute_cpu(const Result &input, Result &output) override; + GPUShader *get_conversion_shader() const override; }; -/** \} */ - } // namespace blender::realtime_compositor diff --git a/source/blender/compositor/realtime_compositor/intern/conversion_operation.cc b/source/blender/compositor/realtime_compositor/intern/conversion_operation.cc index 882195c2006..d82e2d6a100 100644 --- a/source/blender/compositor/realtime_compositor/intern/conversion_operation.cc +++ b/source/blender/compositor/realtime_compositor/intern/conversion_operation.cc @@ -14,9 +14,9 @@ namespace blender::realtime_compositor { -/* -------------------------------------------------------------------- */ -/** \name Conversion Operation - * \{ */ +/* -------------------------------------------------------------------- + * Conversion Operation + */ void ConversionOperation::execute() { @@ -25,23 +25,27 @@ void ConversionOperation::execute() if (input.is_single_value()) { result.allocate_single_value(); - execute_single(input, result); + this->execute_single(input, result); return; } result.allocate_texture(input.domain()); + if (context().use_gpu()) { + GPUShader *shader = get_conversion_shader(); + GPU_shader_bind(shader); - GPUShader *shader = get_conversion_shader(); - GPU_shader_bind(shader); + input.bind_as_texture(shader, "input_tx"); + result.bind_as_image(shader, "output_img"); - input.bind_as_texture(shader, "input_tx"); - result.bind_as_image(shader, "output_img"); + compute_dispatch_threads_at_least(shader, input.domain().size); - compute_dispatch_threads_at_least(shader, input.domain().size); - - input.unbind_as_texture(); - result.unbind_as_image(); - GPU_shader_unbind(); + input.unbind_as_texture(); + result.unbind_as_image(); + GPU_shader_unbind(); + } + else { + this->execute_cpu(input, result); + } } SimpleOperation *ConversionOperation::construct_if_needed(Context &context, @@ -81,11 +85,9 @@ SimpleOperation *ConversionOperation::construct_if_needed(Context &context, return nullptr; } -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Convert Float to Vector Operation - * \{ */ +/* -------------------------------------------------------------------- + * Convert Float to Vector Operation + */ ConvertFloatToVectorOperation::ConvertFloatToVectorOperation(Context &context) : ConversionOperation(context) @@ -101,16 +103,21 @@ void ConvertFloatToVectorOperation::execute_single(const Result &input, Result & output.set_vector_value(float4(float3(input.get_float_value()), 1.0f)); } +void ConvertFloatToVectorOperation::execute_cpu(const Result &input, Result &output) +{ + parallel_for(input.domain().size, [&](const int2 texel) { + output.store_pixel(texel, float4(float3(input.load_pixel(texel).x), 1.0f)); + }); +} + GPUShader *ConvertFloatToVectorOperation::get_conversion_shader() const { return context().get_shader("compositor_convert_float_to_vector"); } -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Convert Float to Color Operation - * \{ */ +/* -------------------------------------------------------------------- + * Convert Float to Color Operation + */ ConvertFloatToColorOperation::ConvertFloatToColorOperation(Context &context) : ConversionOperation(context) @@ -123,9 +130,14 @@ ConvertFloatToColorOperation::ConvertFloatToColorOperation(Context &context) void ConvertFloatToColorOperation::execute_single(const Result &input, Result &output) { - float4 color = float4(input.get_float_value()); - color[3] = 1.0f; - output.set_color_value(color); + output.set_color_value(float4(float3(input.get_float_value()), 1.0f)); +} + +void ConvertFloatToColorOperation::execute_cpu(const Result &input, Result &output) +{ + parallel_for(input.domain().size, [&](const int2 texel) { + output.store_pixel(texel, float4(float3(input.load_pixel(texel).x), 1.0f)); + }); } GPUShader *ConvertFloatToColorOperation::get_conversion_shader() const @@ -133,11 +145,9 @@ GPUShader *ConvertFloatToColorOperation::get_conversion_shader() const return context().get_shader("compositor_convert_float_to_color"); } -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Convert Color to Float Operation - * \{ */ +/* -------------------------------------------------------------------- + * Convert Color to Float Operation + */ ConvertColorToFloatOperation::ConvertColorToFloatOperation(Context &context) : ConversionOperation(context) @@ -151,7 +161,15 @@ ConvertColorToFloatOperation::ConvertColorToFloatOperation(Context &context) void ConvertColorToFloatOperation::execute_single(const Result &input, Result &output) { float4 color = input.get_color_value(); - output.set_float_value((color[0] + color[1] + color[2]) / 3.0f); + output.set_float_value((color.x + color.y + color.z) / 3.0f); +} + +void ConvertColorToFloatOperation::execute_cpu(const Result &input, Result &output) +{ + parallel_for(input.domain().size, [&](const int2 texel) { + const float4 color = input.load_pixel(texel); + output.store_pixel(texel, float4((color.x + color.y + color.z) / 3.0f)); + }); } GPUShader *ConvertColorToFloatOperation::get_conversion_shader() const @@ -159,11 +177,9 @@ GPUShader *ConvertColorToFloatOperation::get_conversion_shader() const return context().get_shader("compositor_convert_color_to_float"); } -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Convert Color to Vector Operation - * \{ */ +/* -------------------------------------------------------------------- + * Convert Color to Vector Operation + */ ConvertColorToVectorOperation::ConvertColorToVectorOperation(Context &context) : ConversionOperation(context) @@ -180,16 +196,20 @@ void ConvertColorToVectorOperation::execute_single(const Result &input, Result & output.set_vector_value(color); } +void ConvertColorToVectorOperation::execute_cpu(const Result &input, Result &output) +{ + parallel_for(input.domain().size, + [&](const int2 texel) { output.store_pixel(texel, input.load_pixel(texel)); }); +} + GPUShader *ConvertColorToVectorOperation::get_conversion_shader() const { return context().get_shader("compositor_convert_color_to_vector"); } -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Convert Vector to Float Operation - * \{ */ +/* -------------------------------------------------------------------- + * Convert Vector to Float Operation + */ ConvertVectorToFloatOperation::ConvertVectorToFloatOperation(Context &context) : ConversionOperation(context) @@ -206,16 +226,22 @@ void ConvertVectorToFloatOperation::execute_single(const Result &input, Result & output.set_float_value((vector[0] + vector[1] + vector[2]) / 3.0f); } +void ConvertVectorToFloatOperation::execute_cpu(const Result &input, Result &output) +{ + parallel_for(input.domain().size, [&](const int2 texel) { + const float4 vector = input.load_pixel(texel); + output.store_pixel(texel, float4((vector.x + vector.y + vector.z) / 3.0f)); + }); +} + GPUShader *ConvertVectorToFloatOperation::get_conversion_shader() const { return context().get_shader("compositor_convert_vector_to_float"); } -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Convert Vector to Color Operation - * \{ */ +/* -------------------------------------------------------------------- + * Convert Vector to Color Operation + */ ConvertVectorToColorOperation::ConvertVectorToColorOperation(Context &context) : ConversionOperation(context) @@ -231,11 +257,16 @@ void ConvertVectorToColorOperation::execute_single(const Result &input, Result & output.set_color_value(float4(float3(input.get_vector_value()), 1.0f)); } +void ConvertVectorToColorOperation::execute_cpu(const Result &input, Result &output) +{ + parallel_for(input.domain().size, [&](const int2 texel) { + output.store_pixel(texel, float4(input.load_pixel(texel).xyz(), 1.0f)); + }); +} + GPUShader *ConvertVectorToColorOperation::get_conversion_shader() const { return context().get_shader("compositor_convert_vector_to_color"); } -/** \} */ - } // namespace blender::realtime_compositor