[Bf-blender-cvs] [379344b6363] temp-geometry-nodes-expandable-geometry-socket-prototype: support function nodes on arrays
Jacques Lucke
noreply at git.blender.org
Mon Aug 2 15:50:48 CEST 2021
Commit: 379344b6363457e0d793efc6cd4adc8a8d8ecab9
Author: Jacques Lucke
Date: Mon Aug 2 15:04:02 2021 +0200
Branches: temp-geometry-nodes-expandable-geometry-socket-prototype
https://developer.blender.org/rB379344b6363457e0d793efc6cd4adc8a8d8ecab9
support function nodes on arrays
===================================================================
M source/blender/functions/FN_array_cpp_type.hh
M source/blender/functions/FN_generic_pointer.hh
M source/blender/functions/FN_generic_virtual_array.hh
M source/blender/modifiers/intern/MOD_nodes_evaluator.cc
===================================================================
diff --git a/source/blender/functions/FN_array_cpp_type.hh b/source/blender/functions/FN_array_cpp_type.hh
index 181ea543a70..9c1af038814 100644
--- a/source/blender/functions/FN_array_cpp_type.hh
+++ b/source/blender/functions/FN_array_cpp_type.hh
@@ -19,6 +19,7 @@
#include "BLI_array.hh"
#include "FN_cpp_type.hh"
+#include "FN_generic_span.hh"
namespace blender::fn {
@@ -28,6 +29,8 @@ template<typename T> struct ArrayCPPTypeParam {
class ArrayCPPType : public CPPType {
private:
const CPPType &element_type_;
+ GSpan (*get_span_)(const void *value);
+ void (*construct_uninitialized_)(void *r_value, int64_t size);
public:
template<typename ElementT, int64_t InlineBufferCapacity, typename Allocator>
@@ -38,6 +41,36 @@ class ArrayCPPType : public CPPType {
debug_name),
element_type_(CPPType::get<ElementT>())
{
+ using ArrayT = Array<ElementT, InlineBufferCapacity, Allocator>;
+ get_span_ = [](const void *value) {
+ Span<ElementT> span = *(const ArrayT *)value;
+ return GSpan(span);
+ };
+ construct_uninitialized_ = [](void *r_value, const int64_t size) {
+ new (r_value) ArrayT(size, NoInitialization());
+ };
+ }
+
+ int64_t array_size(const void *value) const
+ {
+ return get_span_(value).size();
+ }
+
+ GSpan array_span(const void *value) const
+ {
+ return get_span_(value);
+ }
+
+ GMutableSpan array_span(void *value) const
+ {
+ GSpan span = get_span_(value);
+ return GMutableSpan(span.type(), (void *)span.data(), span.size());
+ }
+
+ GMutableSpan array_construct_uninitialized(void *r_value, const int64_t size) const
+ {
+ construct_uninitialized_(r_value, size);
+ return this->array_span(r_value);
}
};
diff --git a/source/blender/functions/FN_generic_pointer.hh b/source/blender/functions/FN_generic_pointer.hh
index c65c42f26c9..746fd0a916a 100644
--- a/source/blender/functions/FN_generic_pointer.hh
+++ b/source/blender/functions/FN_generic_pointer.hh
@@ -41,7 +41,8 @@ class GMutablePointer {
{
}
- template<typename T> GMutablePointer(T *data) : GMutablePointer(&CPPType::get<T>(), data)
+ template<typename T, typename std::enable_if_t<!std::is_void_v<T>> * = nullptr>
+ GMutablePointer(T *data) : GMutablePointer(&CPPType::get<T>(), data)
{
}
diff --git a/source/blender/functions/FN_generic_virtual_array.hh b/source/blender/functions/FN_generic_virtual_array.hh
index c9398ceb547..30e0df511db 100644
--- a/source/blender/functions/FN_generic_virtual_array.hh
+++ b/source/blender/functions/FN_generic_virtual_array.hh
@@ -588,6 +588,32 @@ template<typename T> class GVMutableArray_For_VMutableArray : public GVMutableAr
}
};
+class GVArray_For_RepeatedGSpan : public GVArray {
+ private:
+ GSpan span_;
+ const void *default_value_;
+
+ public:
+ GVArray_For_RepeatedGSpan(int64_t size, GSpan span, const void *default_value = nullptr)
+ : GVArray(span.type(), size),
+ span_(span),
+ default_value_(default_value ? default_value : span.type().default_value())
+ {
+ }
+
+ private:
+ void get_to_uninitialized_impl(const int64_t index, void *r_value) const override
+ {
+ if (span_.is_empty()) {
+ type_->copy_construct(default_value_, r_value);
+ }
+ else {
+ const int64_t repeated_index = index % span_.size();
+ type_->copy_construct(span_[repeated_index], r_value);
+ }
+ }
+};
+
/* A generic version of VArray_Span. */
class GVArray_GSpan : public GSpan {
private:
diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
index 2157092d639..98c3943cc33 100644
--- a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
+++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
@@ -21,6 +21,7 @@
#include "DEG_depsgraph_query.h"
+#include "FN_array_cpp_type.hh"
#include "FN_generic_value_map.hh"
#include "FN_multi_function.hh"
@@ -32,6 +33,7 @@
namespace blender::modifiers::geometry_nodes {
+using fn::ArrayCPPType;
using fn::CPPType;
using fn::GValueMap;
using nodes::GeoNodeExecParams;
@@ -858,23 +860,45 @@ class GeometryNodesEvaluator {
const MultiFunction &fn,
NodeState &node_state)
{
+ /* Compute output array length. */
+ int output_size = 0;
+ for (const int i : node->inputs().index_range()) {
+ const InputSocketRef &socket_ref = node->input(i);
+ if (!socket_ref.is_available()) {
+ continue;
+ }
+ BLI_assert(!socket_ref.is_multi_input_socket());
+ InputState &input_state = node_state.inputs[i];
+ BLI_assert(input_state.was_ready_for_execution);
+ SingleInputValue &single_value = *input_state.value.single;
+ BLI_assert(single_value.value != nullptr);
+ const ArrayCPPType *array_cpp_type = dynamic_cast<const ArrayCPPType *>(input_state.type);
+ BLI_assert(array_cpp_type != nullptr);
+ const int input_size = array_cpp_type->array_size(single_value.value);
+ output_size = std::max(output_size, input_size);
+ }
+
MFContextBuilder fn_context;
- MFParamsBuilder fn_params{fn, 1};
+ MFParamsBuilder fn_params{fn, output_size};
LinearAllocator<> &allocator = local_allocators_.local();
+ Vector<std::unique_ptr<fn::GVArray>> input_varrays;
+
/* Prepare the inputs for the multi function. */
for (const int i : node->inputs().index_range()) {
const InputSocketRef &socket_ref = node->input(i);
if (!socket_ref.is_available()) {
continue;
}
- BLI_assert(!socket_ref.is_multi_input_socket());
InputState &input_state = node_state.inputs[i];
- BLI_assert(input_state.was_ready_for_execution);
SingleInputValue &single_value = *input_state.value.single;
- BLI_assert(single_value.value != nullptr);
- fn_params.add_readonly_single_input(GPointer{*input_state.type, single_value.value});
+ const ArrayCPPType *array_cpp_type = dynamic_cast<const ArrayCPPType *>(input_state.type);
+ GSpan span = array_cpp_type->array_span(single_value.value);
+ auto varray = std::make_unique<fn::GVArray_For_RepeatedGSpan>(output_size, span);
+ fn_params.add_readonly_single_input(*varray);
+ input_varrays.append(std::move(varray));
}
+
/* Prepare the outputs for the multi function. */
Vector<GMutablePointer> outputs;
for (const int i : node->outputs().index_range()) {
@@ -882,13 +906,16 @@ class GeometryNodesEvaluator {
if (!socket_ref.is_available()) {
continue;
}
- const CPPType &type = *get_socket_cpp_type(socket_ref);
- void *buffer = allocator.allocate(type.size(), type.alignment());
- fn_params.add_uninitialized_single_output(GMutableSpan{type, buffer, 1});
+ const ArrayCPPType *type = dynamic_cast<const ArrayCPPType *>(
+ get_socket_cpp_type(socket_ref));
+ BLI_assert(type != nullptr);
+ void *buffer = allocator.allocate(type->size(), type->alignment());
+ GMutableSpan span = type->array_construct_uninitialized(buffer, output_size);
+ fn_params.add_uninitialized_single_output(span);
outputs.append({type, buffer});
}
- fn.call(IndexRange(1), fn_params, fn_context);
+ fn.call(IndexRange(output_size), fn_params, fn_context);
/* Forward the computed outputs. */
int output_index = 0;
More information about the Bf-blender-cvs
mailing list