[Bf-blender-cvs] [0037411f55e] master: Realtime Compositor: Implement parallel reduction

Omar Emara noreply at git.blender.org
Tue Oct 11 13:24:07 CEST 2022


Commit: 0037411f55ec3da4cfad79575d5531869ae5dc38
Author: Omar Emara
Date:   Tue Oct 11 13:22:52 2022 +0200
Branches: master
https://developer.blender.org/rB0037411f55ec3da4cfad79575d5531869ae5dc38

Realtime Compositor: Implement parallel reduction

This patch implements generic parallel reduction for the realtime
compositor and implements the Levels operation as an example. This patch
also introduces the notion of a "Compositor Algorithm", which is a
reusable operation that can be used to construct other operations.

Differential Revision: https://developer.blender.org/D16184

Reviewed By: Clement Foucault

===================================================================

M	source/blender/compositor/realtime_compositor/CMakeLists.txt
A	source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh
A	source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc
M	source/blender/gpu/CMakeLists.txt
A	source/blender/gpu/shaders/compositor/compositor_parallel_reduction.glsl
A	source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh
M	source/blender/makesdna/DNA_node_types.h
M	source/blender/makesrna/intern/rna_nodetree.c
M	source/blender/nodes/composite/CMakeLists.txt
M	source/blender/nodes/composite/nodes/node_composite_levels.cc

===================================================================

diff --git a/source/blender/compositor/realtime_compositor/CMakeLists.txt b/source/blender/compositor/realtime_compositor/CMakeLists.txt
index 1f1333332f5..5473a253241 100644
--- a/source/blender/compositor/realtime_compositor/CMakeLists.txt
+++ b/source/blender/compositor/realtime_compositor/CMakeLists.txt
@@ -53,6 +53,10 @@ set(SRC
   COM_static_shader_manager.hh
   COM_texture_pool.hh
   COM_utilities.hh
+
+  algorithms/intern/algorithm_parallel_reduction.cc
+
+  algorithms/COM_algorithm_parallel_reduction.hh
 )
 
 set(LIB
diff --git a/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh b/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh
new file mode 100644
index 00000000000..9d0851eff84
--- /dev/null
+++ b/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#pragma once
+
+#include "BLI_math_vec_types.hh"
+
+#include "GPU_texture.h"
+
+#include "COM_context.hh"
+
+namespace blender::realtime_compositor {
+
+/* --------------------------------------------------------------------
+ * Sum Reductions.
+ */
+
+/* Computes the sum of the red channel of all pixels in the given texture. */
+float sum_red(Context &context, GPUTexture *texture);
+
+/* Computes the sum of the green channel of all pixels in the given texture. */
+float sum_green(Context &context, GPUTexture *texture);
+
+/* Computes the sum of the blue channel of all pixels in the given texture. */
+float sum_blue(Context &context, GPUTexture *texture);
+
+/* Computes the sum of the luminance of all pixels in the given texture, using the given luminance
+ * coefficients to compute the luminance. */
+float sum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients);
+
+/* --------------------------------------------------------------------
+ * Sum Of Squared Difference Reductions.
+ */
+
+/* Computes the sum of the squared difference between the red channel of all pixels in the given
+ * texture and the given subtrahend. This can be used to compute the standard deviation if the
+ * given subtrahend is the mean. */
+float sum_red_squared_difference(Context &context, GPUTexture *texture, float subtrahend);
+
+/* Computes the sum of the squared difference between the green channel of all pixels in the given
+ * texture and the given subtrahend. This can be used to compute the standard deviation if the
+ * given subtrahend is the mean. */
+float sum_green_squared_difference(Context &context, GPUTexture *texture, float subtrahend);
+
+/* Computes the sum of the squared difference between the blue channel of all pixels in the given
+ * texture and the given subtrahend. This can be used to compute the standard deviation if the
+ * given subtrahend is the mean. */
+float sum_blue_squared_difference(Context &context, GPUTexture *texture, float subtrahend);
+
+/* Computes the sum of the squared difference between the luminance of all pixels in the given
+ * texture and the given subtrahend, using the given luminance coefficients to compute the
+ * luminance. This can be used to compute the standard deviation if the given subtrahend is the
+ * mean. */
+float sum_luminance_squared_difference(Context &context,
+                                       GPUTexture *texture,
+                                       float3 luminance_coefficients,
+                                       float subtrahend);
+
+}  // namespace blender::realtime_compositor
diff --git a/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc b/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc
new file mode 100644
index 00000000000..7b571f381c6
--- /dev/null
+++ b/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc
@@ -0,0 +1,203 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "BLI_math_vec_types.hh"
+#include "BLI_math_vector.hh"
+
+#include "MEM_guardedalloc.h"
+
+#include "GPU_compute.h"
+#include "GPU_shader.h"
+#include "GPU_texture.h"
+
+#include "COM_context.hh"
+#include "COM_utilities.hh"
+
+namespace blender::realtime_compositor {
+
+/* Reduces the given texture into a single value and returns it. The return value should be freed
+ * by a call to MEM_freeN. The return value is either a pointer to a float, or a pointer to an
+ * array of floats that represents a vector. This depends on the given format, which should be
+ * compatible with the reduction shader.
+ *
+ * The given reduction shader should be bound when calling the function and the shader is expected
+ * to be derived from the compositor_parallel_reduction.glsl shader, see that file for more
+ * information. Also see the compositor_parallel_reduction_info.hh file for example shader
+ * definitions. */
+static float *parallel_reduction_dispatch(Context &context,
+                                          GPUTexture *texture,
+                                          GPUShader *shader,
+                                          eGPUTextureFormat format)
+{
+  GPU_shader_uniform_1b(shader, "is_initial_reduction", true);
+
+  GPUTexture *texture_to_reduce = texture;
+  int2 size_to_reduce = int2(GPU_texture_width(texture), GPU_texture_height(texture));
+
+  /* Dispatch the reduction shader until the texture reduces to a single pixel. */
+  while (size_to_reduce != int2(1)) {
+    const int2 reduced_size = math::divide_ceil(size_to_reduce, int2(16));
+    GPUTexture *reduced_texture = context.texture_pool().acquire(reduced_size, format);
+
+    GPU_memory_barrier(GPU_BARRIER_TEXTURE_FETCH);
+    const int texture_image_unit = GPU_shader_get_texture_binding(shader, "input_tx");
+    GPU_texture_bind(texture_to_reduce, texture_image_unit);
+
+    const int image_unit = GPU_shader_get_texture_binding(shader, "output_img");
+    GPU_texture_image_bind(reduced_texture, image_unit);
+
+    GPU_compute_dispatch(shader, reduced_size.x, reduced_size.y, 1);
+
+    GPU_texture_image_unbind(reduced_texture);
+    GPU_texture_unbind(texture_to_reduce);
+
+    /* Release the input texture only if it is not the source texture, since the source texture is
+     * not acquired or owned by the function. */
+    if (texture_to_reduce != texture) {
+      context.texture_pool().release(texture_to_reduce);
+    }
+
+    texture_to_reduce = reduced_texture;
+    size_to_reduce = reduced_size;
+
+    GPU_shader_uniform_1b(shader, "is_initial_reduction", false);
+  }
+
+  GPU_memory_barrier(GPU_BARRIER_TEXTURE_UPDATE);
+  float *pixel = static_cast<float *>(GPU_texture_read(texture_to_reduce, GPU_DATA_FLOAT, 0));
+
+  /* Release the final texture only if it is not the source texture, since the source texture is
+   * not acquired or owned by the function. */
+  if (texture_to_reduce != texture) {
+    context.texture_pool().release(texture_to_reduce);
+  }
+
+  return pixel;
+}
+
+/* --------------------------------------------------------------------
+ * Sum Reductions.
+ */
+
+float sum_red(Context &context, GPUTexture *texture)
+{
+  GPUShader *shader = context.shader_manager().get("compositor_sum_red");
+  GPU_shader_bind(shader);
+
+  float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F);
+  const float sum = *reduced_value;
+  MEM_freeN(reduced_value);
+  GPU_shader_unbind();
+
+  return sum;
+}
+
+float sum_green(Context &context, GPUTexture *texture)
+{
+  GPUShader *shader = context.shader_manager().get("compositor_sum_green");
+  GPU_shader_bind(shader);
+
+  float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F);
+  const float sum = *reduced_value;
+  MEM_freeN(reduced_value);
+  GPU_shader_unbind();
+
+  return sum;
+}
+
+float sum_blue(Context &context, GPUTexture *texture)
+{
+  GPUShader *shader = context.shader_manager().get("compositor_sum_blue");
+  GPU_shader_bind(shader);
+
+  float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F);
+  const float sum = *reduced_value;
+  MEM_freeN(reduced_value);
+  GPU_shader_unbind();
+
+  return sum;
+}
+
+float sum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients)
+{
+  GPUShader *shader = context.shader_manager().get("compositor_sum_luminance");
+  GPU_shader_bind(shader);
+
+  GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients);
+
+  float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F);
+  const float sum = *reduced_value;
+  MEM_freeN(reduced_value);
+  GPU_shader_unbind();
+
+  return sum;
+}
+
+/* --------------------------------------------------------------------
+ * Sum Of Squared Difference Reductions.
+ */
+
+float sum_red_squared_difference(Context &context, GPUTexture *texture, float subtrahend)
+{
+  GPUShader *shader = context.shader_manager().get("compositor_sum_red_squared_difference");
+  GPU_shader_bind(shader);
+
+  GPU_shader_uniform_1f(shader, "subtrahend", subtrahend);
+
+  float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F);
+  const float sum = *reduced_value;
+  MEM_freeN(reduced_value);
+  GPU_shader_unbind();
+
+  return sum;
+}
+
+float sum_green_squared_difference(Context &context, GPUTexture *texture, float subtrahend)
+{
+  GPUShader *shader = context.shader_manager().get("compositor_sum_green_squared_difference");
+  GPU_shader_bind(shader);
+
+  GPU_shader_uniform_1f(shader, "subtrahend", subtrahend);
+
+  float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F);
+  const float sum = *reduced_value;
+  MEM_freeN(reduced_value);
+  GPU_shader_unbind();
+
+  return sum;
+}
+
+float sum_blue_squared_difference(Context &context, GPUTexture *texture, float subtrahend)
+{
+  GPUShader *shader = context.shader_manager().get("compositor_sum_blue_squared_difference");
+  GPU_shader_bind(shader);
+
+  GPU_shader_uniform_1f(shader, "subtrahend", subtrahend);
+
+  float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F);
+  const float sum = *reduced_value;
+  MEM_freeN

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list