Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOmar Emara <mail@OmarEmara.dev>2022-08-10 10:14:22 +0300
committerOmar Emara <mail@OmarEmara.dev>2022-08-10 10:14:22 +0300
commit624b0ac656e4876c8518adb479be94e581c46bb8 (patch)
treecd5cd314498cab0ca367d33ce41f768de1af378e /source/blender/compositor/realtime_compositor/intern/utilities.cc
parent169216684a7dd9fff065bad2c0bad60578f9412f (diff)
Realtime Compositor: Add evaluator and engine
This patch adds the core realtime compositor evaluator as well as a compositor draw engine powered by the evaluator that operates in the viewport. The realtime compositor is a new GPU accelerated compositor that will be used to power the viewport compositor imminently as well as the existing compositor in the future. This patch only adds the evaluator and engine as an experimental feature, the implementation of the nodes themselves will be committed separately. See T99210. Differential Revision: https://developer.blender.org/D15206 Reviewed By: Clement Foucault
Diffstat (limited to 'source/blender/compositor/realtime_compositor/intern/utilities.cc')
-rw-r--r--source/blender/compositor/realtime_compositor/intern/utilities.cc134
1 files changed, 134 insertions, 0 deletions
diff --git a/source/blender/compositor/realtime_compositor/intern/utilities.cc b/source/blender/compositor/realtime_compositor/intern/utilities.cc
new file mode 100644
index 00000000000..169ba70e9eb
--- /dev/null
+++ b/source/blender/compositor/realtime_compositor/intern/utilities.cc
@@ -0,0 +1,134 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "BLI_assert.h"
+#include "BLI_function_ref.hh"
+#include "BLI_math_vec_types.hh"
+#include "BLI_math_vector.hh"
+#include "BLI_utildefines.h"
+
+#include "DNA_node_types.h"
+
+#include "NOD_derived_node_tree.hh"
+#include "NOD_node_declaration.hh"
+
+#include "GPU_compute.h"
+#include "GPU_shader.h"
+
+#include "COM_operation.hh"
+#include "COM_result.hh"
+#include "COM_utilities.hh"
+
+namespace blender::realtime_compositor {
+
+using namespace nodes::derived_node_tree_types;
+using TargetSocketPathInfo = DOutputSocket::TargetSocketPathInfo;
+
+DSocket get_input_origin_socket(DInputSocket input)
+{
+ /* The input is unlinked. Return the socket itself. */
+ if (input->logically_linked_sockets().is_empty()) {
+ return input;
+ }
+
+ /* Only a single origin socket is guaranteed to exist. */
+ DSocket socket;
+ input.foreach_origin_socket([&](const DSocket origin) { socket = origin; });
+ return socket;
+}
+
+DOutputSocket get_output_linked_to_input(DInputSocket input)
+{
+ /* Get the origin socket of this input, which will be an output socket if the input is linked
+ * to an output. */
+ const DSocket origin = get_input_origin_socket(input);
+
+ /* If the origin socket is an input, that means the input is unlinked, so return a null output
+ * socket. */
+ if (origin->is_input()) {
+ return DOutputSocket();
+ }
+
+ /* Now that we know the origin is an output, return a derived output from it. */
+ return DOutputSocket(origin);
+}
+
+ResultType get_node_socket_result_type(const SocketRef *socket)
+{
+ switch (socket->bsocket()->type) {
+ case SOCK_FLOAT:
+ return ResultType::Float;
+ case SOCK_VECTOR:
+ return ResultType::Vector;
+ case SOCK_RGBA:
+ return ResultType::Color;
+ default:
+ BLI_assert_unreachable();
+ return ResultType::Float;
+ }
+}
+
+bool is_output_linked_to_node_conditioned(DOutputSocket output, FunctionRef<bool(DNode)> condition)
+{
+ bool condition_satisfied = false;
+ output.foreach_target_socket(
+ [&](DInputSocket target, const TargetSocketPathInfo &UNUSED(path_info)) {
+ if (condition(target.node())) {
+ condition_satisfied = true;
+ return;
+ }
+ });
+ return condition_satisfied;
+}
+
+int number_of_inputs_linked_to_output_conditioned(DOutputSocket output,
+ FunctionRef<bool(DInputSocket)> condition)
+{
+ int count = 0;
+ output.foreach_target_socket(
+ [&](DInputSocket target, const TargetSocketPathInfo &UNUSED(path_info)) {
+ if (condition(target)) {
+ count++;
+ }
+ });
+ return count;
+}
+
+bool is_shader_node(DNode node)
+{
+ return node->typeinfo()->get_compositor_shader_node;
+}
+
+bool is_node_supported(DNode node)
+{
+ return node->typeinfo()->get_compositor_operation ||
+ node->typeinfo()->get_compositor_shader_node;
+}
+
+InputDescriptor input_descriptor_from_input_socket(const InputSocketRef *socket)
+{
+ using namespace nodes;
+ InputDescriptor input_descriptor;
+ input_descriptor.type = get_node_socket_result_type(socket);
+ const NodeDeclaration *node_declaration = socket->node().declaration();
+ /* Not every node have a declaration, in which case, we assume the default values for the rest of
+ * the properties. */
+ if (!node_declaration) {
+ return input_descriptor;
+ }
+ const SocketDeclarationPtr &socket_declaration = node_declaration->inputs()[socket->index()];
+ input_descriptor.domain_priority = socket_declaration->compositor_domain_priority();
+ input_descriptor.expects_single_value = socket_declaration->compositor_expects_single_value();
+ return input_descriptor;
+}
+
+void compute_dispatch_threads_at_least(GPUShader *shader, int2 threads_range, int2 local_size)
+{
+ /* If the threads range is divisible by the local size, dispatch the number of needed groups,
+ * which is their division. If it is not divisible, then dispatch an extra group to cover the
+ * remaining invocations, which means the actual threads range of the dispatch will be a bit
+ * larger than the given one. */
+ const int2 groups_to_dispatch = math::divide_ceil(threads_range, local_size);
+ GPU_compute_dispatch(shader, groups_to_dispatch.x, groups_to_dispatch.y, 1);
+}
+
+} // namespace blender::realtime_compositor