Compositor: Implement type conversion in new CPU compositor

This patch implements implicit conversion operations for the new CPU
compositor.
This commit is contained in:
Omar Emara
2024-08-22 11:15:57 +03:00
parent 1b23a8983d
commit 9b903d4c6f
2 changed files with 119 additions and 101 deletions

View File

@@ -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

View File

@@ -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