Refactor: Compositor: Reduce boilerplate in conversion code

This patch refactors GPU implicit conversion code by generating the name
of the shaders on the fly using fmt. This reduces boilerplate and makes
it easier to add new types.
This commit is contained in:
Omar Emara
2025-03-13 11:38:12 +02:00
parent 42e7a950cd
commit cbd01d2a6f
4 changed files with 33 additions and 109 deletions

View File

@@ -145,6 +145,7 @@ set(SRC
set(LIB
PRIVATE bf::blenkernel
PRIVATE bf::blentranslation
PRIVATE bf::extern::fmtlib
PRIVATE bf::functions
PRIVATE bf::gpu
PRIVATE bf::imbuf

View File

@@ -187,6 +187,9 @@ class Result {
/* Returns the CPP type corresponding to the given result type. */
static const CPPType &cpp_type(const ResultType type);
/* Returns a string representation of the given result type. */
static const char *type_name(const ResultType type);
/* Implicit conversion to the internal GPU texture. */
operator GPUTexture *() const;

View File

@@ -2,6 +2,8 @@
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include <fmt/format.h>
#include "BLI_math_vector_types.hh"
#include "BLI_utildefines.h"
@@ -38,7 +40,10 @@ void ConversionOperation::execute()
result.allocate_texture(input.domain());
if (this->context().use_gpu()) {
GPUShader *shader = this->context().get_shader(this->get_conversion_shader_name());
const std::string shader_name = fmt::format("compositor_convert_{}_to_{}",
Result::type_name(this->get_input().type()),
Result::type_name(this->get_result().type()));
GPUShader *shader = this->context().get_shader(shader_name.c_str());
GPU_shader_bind(shader);
if (this->get_input().type() == ResultType::Color &&
@@ -79,114 +84,6 @@ SimpleOperation *ConversionOperation::construct_if_needed(Context &context,
return nullptr;
}
const char *ConversionOperation::get_conversion_shader_name()
{
switch (this->get_input().type()) {
case ResultType::Float:
switch (this->get_result().type()) {
case ResultType::Int:
return "compositor_convert_float_to_int";
case ResultType::Float3:
return "compositor_convert_float_to_float3";
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;
case ResultType::Float2:
case ResultType::Int2:
/* Types are not user facing, so we needn't implement them. */
break;
}
break;
case ResultType::Int:
switch (this->get_result().type()) {
case ResultType::Float:
return "compositor_convert_int_to_float";
case ResultType::Float3:
return "compositor_convert_int_to_float3";
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;
case ResultType::Float2:
case ResultType::Int2:
/* Types are not user facing, so we needn't implement them. */
break;
}
break;
case ResultType::Float3:
switch (this->get_result().type()) {
case ResultType::Float:
return "compositor_convert_float3_to_float";
case ResultType::Int:
return "compositor_convert_float3_to_int";
case ResultType::Color:
return "compositor_convert_float3_to_color";
case ResultType::Float4:
return "compositor_convert_float3_to_float4";
case ResultType::Float3:
/* Same type, no conversion needed. */
break;
case ResultType::Float2:
case ResultType::Int2:
/* Types are not user facing, so we needn't implement them. */
break;
}
break;
case ResultType::Color:
switch (this->get_result().type()) {
case ResultType::Float:
return "compositor_convert_color_to_float";
case ResultType::Int:
return "compositor_convert_color_to_int";
case ResultType::Float3:
return "compositor_convert_color_to_float3";
case ResultType::Float4:
return "compositor_convert_color_to_float4";
case ResultType::Color:
/* Same type, no conversion needed. */
break;
case ResultType::Float2:
case ResultType::Int2:
/* Types are not user facing, so we needn't implement them. */
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::Float3:
return "compositor_convert_float4_to_float3";
case ResultType::Color:
return "compositor_convert_float4_to_color";
case ResultType::Float4:
/* Same type, no conversion needed. */
break;
case ResultType::Float2:
case ResultType::Int2:
/* Types are not user facing, so we needn't implement them. */
break;
}
break;
case ResultType::Float2:
case ResultType::Int2:
/* Types are not user facing, so we needn't implement them. */
break;
}
BLI_assert_unreachable();
return nullptr;
}
void ConversionOperation::execute_single(const Result &input, Result &output)
{
switch (this->get_input().type()) {

View File

@@ -244,6 +244,29 @@ const CPPType &Result::cpp_type(const ResultType type)
return CPPType::get<float>();
}
const char *Result::type_name(const ResultType type)
{
switch (type) {
case ResultType::Float:
return "float";
case ResultType::Float2:
return "float2";
case ResultType::Float3:
return "float3";
case ResultType::Float4:
return "float4";
case ResultType::Color:
return "color";
case ResultType::Int2:
return "int2";
case ResultType::Int:
return "int";
}
BLI_assert_unreachable();
return "";
}
Result::operator GPUTexture *() const
{
return this->gpu_texture();