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:
Diffstat (limited to 'source/blender/compositor/realtime_compositor/intern')
-rw-r--r--source/blender/compositor/realtime_compositor/intern/context.cc6
-rw-r--r--source/blender/compositor/realtime_compositor/intern/evaluator.cc1
-rw-r--r--source/blender/compositor/realtime_compositor/intern/realize_on_domain_operation.cc4
-rw-r--r--source/blender/compositor/realtime_compositor/intern/scheduler.cc96
-rw-r--r--source/blender/compositor/realtime_compositor/intern/static_cache_manager.cc74
5 files changed, 165 insertions, 16 deletions
diff --git a/source/blender/compositor/realtime_compositor/intern/context.cc b/source/blender/compositor/realtime_compositor/intern/context.cc
index 924398f6747..0b123a2c271 100644
--- a/source/blender/compositor/realtime_compositor/intern/context.cc
+++ b/source/blender/compositor/realtime_compositor/intern/context.cc
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "COM_context.hh"
+#include "COM_static_cache_manager.hh"
#include "COM_static_shader_manager.hh"
#include "COM_texture_pool.hh"
@@ -32,4 +33,9 @@ StaticShaderManager &Context::shader_manager()
return shader_manager_;
}
+StaticCacheManager &Context::cache_manager()
+{
+ return cache_manager_;
+}
+
} // namespace blender::realtime_compositor
diff --git a/source/blender/compositor/realtime_compositor/intern/evaluator.cc b/source/blender/compositor/realtime_compositor/intern/evaluator.cc
index 48457bec199..1cd7d4f8951 100644
--- a/source/blender/compositor/realtime_compositor/intern/evaluator.cc
+++ b/source/blender/compositor/realtime_compositor/intern/evaluator.cc
@@ -28,6 +28,7 @@ Evaluator::Evaluator(Context &context, bNodeTree &node_tree)
void Evaluator::evaluate()
{
+ context_.cache_manager().reset();
context_.texture_pool().reset();
if (!is_compiled_) {
diff --git a/source/blender/compositor/realtime_compositor/intern/realize_on_domain_operation.cc b/source/blender/compositor/realtime_compositor/intern/realize_on_domain_operation.cc
index 817293c0fa6..e5c448d0e33 100644
--- a/source/blender/compositor/realtime_compositor/intern/realize_on_domain_operation.cc
+++ b/source/blender/compositor/realtime_compositor/intern/realize_on_domain_operation.cc
@@ -38,8 +38,8 @@ void RealizeOnDomainOperation::execute()
GPU_shader_bind(shader);
/* Transform the input space into the domain space. */
- const float3x3 local_transformation = input.domain().transformation *
- domain_.transformation.inverted();
+ const float3x3 local_transformation = domain_.transformation.inverted() *
+ input.domain().transformation;
/* Set the origin of the transformation to be the center of the domain. */
const float3x3 transformation = float3x3::from_origin_transformation(
diff --git a/source/blender/compositor/realtime_compositor/intern/scheduler.cc b/source/blender/compositor/realtime_compositor/intern/scheduler.cc
index ac5cc55a73f..0d3cce7af39 100644
--- a/source/blender/compositor/realtime_compositor/intern/scheduler.cc
+++ b/source/blender/compositor/realtime_compositor/intern/scheduler.cc
@@ -8,6 +8,7 @@
#include "NOD_derived_node_tree.hh"
+#include "BKE_node.h"
#include "BKE_node_runtime.hh"
#include "COM_scheduler.hh"
@@ -17,36 +18,103 @@ namespace blender::realtime_compositor {
using namespace nodes::derived_node_tree_types;
-/* Compute the output node whose result should be computed. The output node is the node marked as
- * NODE_DO_OUTPUT. If multiple types of output nodes are marked, then the preference will be
- * CMP_NODE_COMPOSITE > CMP_NODE_VIEWER > CMP_NODE_SPLITVIEWER. If no output node exists, a null
- * node will be returned. */
-static DNode compute_output_node(DerivedNodeTree &tree)
+/* Find the active context from the given context and its descendants contexts. The active context
+ * is the one whose node instance key matches the active_viewer_key stored in the root node tree.
+ * The instance key of each context is computed by calling BKE_node_instance_key given the key of
+ * the parent as well as the group node making the context. */
+static const DTreeContext *find_active_context_recursive(const DTreeContext *context,
+ bNodeInstanceKey key)
{
- const bNodeTree &root_tree = tree.root_context().btree();
+ /* The instance key of the given context matches the active viewer instance key, so this is the
+ * active context, return it. */
+ if (key.value == context->derived_tree().root_context().btree().active_viewer_key.value) {
+ return context;
+ }
+
+ /* For each of the group nodes, compute their instance key and contexts and call this function
+ * recursively. */
+ for (const bNode *group_node : context->btree().group_nodes()) {
+ const bNodeInstanceKey child_key = BKE_node_instance_key(key, &context->btree(), group_node);
+ const DTreeContext *child_context = context->child_context(*group_node);
+ const DTreeContext *found_context = find_active_context_recursive(child_context, child_key);
+
+ /* If the found context is null, that means neither the child context nor one of its descendant
+ * contexts is active. */
+ if (!found_context) {
+ continue;
+ }
+
+ /* Otherwise, we have found our active context, return it. */
+ return found_context;
+ }
+
+ /* Neither the given context nor one of its descendant contexts is active, so return null. */
+ return nullptr;
+}
+
+/* Find the active context for the given node tree. The active context represents the node tree
+ * currently being edited. In most cases, that would be the top level node tree itself, but in the
+ * case where the user is editing the node tree of a node group, the active context would be a
+ * representation of the node tree of that node group. Note that the context also stores the group
+ * node that the user selected to edit the node tree, so the context fully represents a particular
+ * instance of the node group. */
+static const DTreeContext *find_active_context(const DerivedNodeTree &tree)
+{
+ /* The root context has an instance key of NODE_INSTANCE_KEY_BASE by definition. */
+ return find_active_context_recursive(&tree.root_context(), NODE_INSTANCE_KEY_BASE);
+}
+
+/* Return the output node which is marked as NODE_DO_OUTPUT. If multiple types of output nodes are
+ * marked, then the preference will be CMP_NODE_COMPOSITE > CMP_NODE_VIEWER > CMP_NODE_SPLITVIEWER.
+ * If no output node exists, a null node will be returned. */
+static DNode find_output_in_context(const DTreeContext *context)
+{
+ const bNodeTree &tree = context->btree();
- for (const bNode *node : root_tree.nodes_by_type("CompositorNodeComposite")) {
+ for (const bNode *node : tree.nodes_by_type("CompositorNodeComposite")) {
if (node->flag & NODE_DO_OUTPUT) {
- return DNode(&tree.root_context(), node);
+ return DNode(context, node);
}
}
- for (const bNode *node : root_tree.nodes_by_type("CompositorNodeViewer")) {
+ for (const bNode *node : tree.nodes_by_type("CompositorNodeViewer")) {
if (node->flag & NODE_DO_OUTPUT) {
- return DNode(&tree.root_context(), node);
+ return DNode(context, node);
}
}
- for (const bNode *node : root_tree.nodes_by_type("CompositorNodeSplitViewer")) {
+ for (const bNode *node : tree.nodes_by_type("CompositorNodeSplitViewer")) {
if (node->flag & NODE_DO_OUTPUT) {
- return DNode(&tree.root_context(), node);
+ return DNode(context, node);
}
}
- /* No output node found, return a null node. */
return DNode();
}
+/* Compute the output node whose result should be computed. This node is the output node that
+ * satisfies the requirements in the find_output_in_context function. First, the active context is
+ * searched for an output node, if non was found, the root context is search. For more information
+ * on what contexts mean here, see the find_active_context function. */
+static DNode compute_output_node(const DerivedNodeTree &tree)
+{
+ const DTreeContext *active_context = find_active_context(tree);
+
+ const DNode node = find_output_in_context(active_context);
+ if (node) {
+ return node;
+ }
+
+ /* If the active context is the root one and no output node was found, we consider this node tree
+ * to have no output node, even if one of the non-active descendants have an output node. */
+ if (active_context->is_root()) {
+ return DNode();
+ }
+
+ /* The active context doesn't have an output node, search in the root context as a fallback. */
+ return find_output_in_context(&tree.root_context());
+}
+
/* A type representing a mapping that associates each node with a heuristic estimation of the
* number of intermediate buffers needed to compute it and all of its dependencies. See the
* compute_number_of_needed_buffers function for more information. */
@@ -225,7 +293,7 @@ static NeededBuffers compute_number_of_needed_buffers(DNode output_node)
* doesn't always guarantee an optimal evaluation order, as the optimal evaluation order is very
* difficult to compute, however, this method works well in most cases. Moreover it assumes that
* all buffers will have roughly the same size, which may not always be the case. */
-Schedule compute_schedule(DerivedNodeTree &tree)
+Schedule compute_schedule(const DerivedNodeTree &tree)
{
Schedule schedule;
diff --git a/source/blender/compositor/realtime_compositor/intern/static_cache_manager.cc b/source/blender/compositor/realtime_compositor/intern/static_cache_manager.cc
new file mode 100644
index 00000000000..da78412a815
--- /dev/null
+++ b/source/blender/compositor/realtime_compositor/intern/static_cache_manager.cc
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <memory>
+
+#include "BLI_math_vec_types.hh"
+
+#include "COM_morphological_distance_feather_weights.hh"
+#include "COM_symmetric_blur_weights.hh"
+#include "COM_symmetric_separable_blur_weights.hh"
+
+#include "COM_static_cache_manager.hh"
+
+namespace blender::realtime_compositor {
+
+/* --------------------------------------------------------------------
+ * Static Cache Manager.
+ */
+
+void StaticCacheManager::reset()
+{
+ /* First, delete all resources that are no longer needed. */
+ symmetric_blur_weights_.remove_if([](auto item) { return !item.value->needed; });
+ symmetric_separable_blur_weights_.remove_if([](auto item) { return !item.value->needed; });
+ morphological_distance_feather_weights_.remove_if([](auto item) { return !item.value->needed; });
+
+ /* Second, reset the needed status of the remaining resources to false to ready them to track
+ * their needed status for the next evaluation. */
+ for (auto &value : symmetric_blur_weights_.values()) {
+ value->needed = false;
+ }
+ for (auto &value : symmetric_separable_blur_weights_.values()) {
+ value->needed = false;
+ }
+ for (auto &value : morphological_distance_feather_weights_.values()) {
+ value->needed = false;
+ }
+}
+
+SymmetricBlurWeights &StaticCacheManager::get_symmetric_blur_weights(int type, float2 radius)
+{
+ const SymmetricBlurWeightsKey key(type, radius);
+
+ auto &weights = *symmetric_blur_weights_.lookup_or_add_cb(
+ key, [&]() { return std::make_unique<SymmetricBlurWeights>(type, radius); });
+
+ weights.needed = true;
+ return weights;
+}
+
+SymmetricSeparableBlurWeights &StaticCacheManager::get_symmetric_separable_blur_weights(
+ int type, float radius)
+{
+ const SymmetricSeparableBlurWeightsKey key(type, radius);
+
+ auto &weights = *symmetric_separable_blur_weights_.lookup_or_add_cb(
+ key, [&]() { return std::make_unique<SymmetricSeparableBlurWeights>(type, radius); });
+
+ weights.needed = true;
+ return weights;
+}
+
+MorphologicalDistanceFeatherWeights &StaticCacheManager::
+ get_morphological_distance_feather_weights(int type, int radius)
+{
+ const MorphologicalDistanceFeatherWeightsKey key(type, radius);
+
+ auto &weights = *morphological_distance_feather_weights_.lookup_or_add_cb(
+ key, [&]() { return std::make_unique<MorphologicalDistanceFeatherWeights>(type, radius); });
+
+ weights.needed = true;
+ return weights;
+}
+
+} // namespace blender::realtime_compositor