This is used as base class for the compute contexts for group and evaluate closure nodes. Furthermore, in the future this can be used for the compute context that is passed into field evaluation. Pull Request: https://projects.blender.org/blender/blender/pulls/139377
95 lines
4.4 KiB
C++
95 lines
4.4 KiB
C++
/* SPDX-FileCopyrightText: 2025 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
#pragma once
|
|
|
|
#include "BKE_compute_context_cache_fwd.hh"
|
|
#include "BKE_compute_contexts.hh"
|
|
|
|
#include "BLI_linear_allocator.hh"
|
|
#include "BLI_map.hh"
|
|
#include "BLI_vector.hh"
|
|
|
|
namespace blender::bke {
|
|
|
|
/**
|
|
* When traversing the computation of a node tree (like in `socket_usage_inference.cc` or
|
|
* `partial_eval.cc`) one often enters and exists the same compute contexts. The cache implemented
|
|
* here avoids re-creating the same compute contexts over and over again. While requiring less
|
|
* memory and having potentially better performance, it can also be used to ensure that the same
|
|
* compute context will always have the same pointer, even if it's created in two different places.
|
|
*
|
|
* Constructing compute contexts through this cache can also be a bit more convenient.
|
|
*/
|
|
class ComputeContextCache {
|
|
/** Allocator used to allocate the compute contexts. */
|
|
LinearAllocator<> allocator_;
|
|
/** The allocated computed contexts that need to be destructed in the end. */
|
|
Vector<destruct_ptr<ComputeContext>> cache_;
|
|
|
|
Map<std::pair<const ComputeContext *, int>, const ModifierComputeContext *>
|
|
modifier_contexts_cache_;
|
|
Map<const ComputeContext *, const OperatorComputeContext *> operator_contexts_cache_;
|
|
Map<std::pair<const ComputeContext *, int32_t>, const GroupNodeComputeContext *>
|
|
group_node_contexts_cache_;
|
|
Map<std::pair<const ComputeContext *, int32_t>, const SimulationZoneComputeContext *>
|
|
simulation_zone_contexts_cache_;
|
|
Map<std::pair<const ComputeContext *, std::pair<int32_t, int>>, const RepeatZoneComputeContext *>
|
|
repeat_zone_contexts_cache_;
|
|
Map<std::pair<const ComputeContext *, std::pair<int32_t, int>>,
|
|
const ForeachGeometryElementZoneComputeContext *>
|
|
foreach_geometry_element_zone_contexts_cache_;
|
|
Map<std::pair<const ComputeContext *, int32_t>, const EvaluateClosureComputeContext *>
|
|
evaluate_closure_contexts_cache_;
|
|
|
|
public:
|
|
const ModifierComputeContext &for_modifier(const ComputeContext *parent,
|
|
const NodesModifierData &nmd);
|
|
const ModifierComputeContext &for_modifier(const ComputeContext *parent, int modifier_uid);
|
|
|
|
const OperatorComputeContext &for_operator(const ComputeContext *parent);
|
|
const OperatorComputeContext &for_operator(const ComputeContext *parent, const bNodeTree &tree);
|
|
|
|
const GroupNodeComputeContext &for_group_node(const ComputeContext *parent,
|
|
int32_t node_id,
|
|
const bNodeTree *tree = nullptr);
|
|
|
|
const SimulationZoneComputeContext &for_simulation_zone(const ComputeContext *parent,
|
|
int output_node_id);
|
|
const SimulationZoneComputeContext &for_simulation_zone(const ComputeContext *parent,
|
|
const bNode &output_node);
|
|
|
|
const RepeatZoneComputeContext &for_repeat_zone(const ComputeContext *parent,
|
|
int32_t output_node_id,
|
|
int iteration);
|
|
const RepeatZoneComputeContext &for_repeat_zone(const ComputeContext *parent,
|
|
const bNode &output_node,
|
|
int iteration);
|
|
|
|
const ForeachGeometryElementZoneComputeContext &for_foreach_geometry_element_zone(
|
|
const ComputeContext *parent, int32_t output_node_id, int index);
|
|
const ForeachGeometryElementZoneComputeContext &for_foreach_geometry_element_zone(
|
|
const ComputeContext *parent, const bNode &output_node, int index);
|
|
|
|
const EvaluateClosureComputeContext &for_evaluate_closure(
|
|
const ComputeContext *parent,
|
|
int32_t node_id,
|
|
const bNodeTree *tree = nullptr,
|
|
const std::optional<nodes::ClosureSourceLocation> &closure_source_location = std::nullopt);
|
|
|
|
/**
|
|
* A fallback that does not use caching and can be used for any compute context.
|
|
* More constructors like the ones above can be added as they become necessary.
|
|
*/
|
|
template<typename T, typename... Args> const T &for_any_uncached(Args &&...args)
|
|
{
|
|
destruct_ptr<T> compute_context = allocator_.construct<T>(std::forward<Args>(args)...);
|
|
const T &result = *compute_context;
|
|
cache_.append(std::move(compute_context));
|
|
return result;
|
|
}
|
|
};
|
|
|
|
} // namespace blender::bke
|