Merge branch 'blender-v3.0-release'

This commit is contained in:
Jacques Lucke 2021-11-03 10:54:53 +01:00
commit bdf6665e3a
4 changed files with 141 additions and 84 deletions

View File

@ -921,6 +921,10 @@ static Mesh *modifier_modify_mesh_and_geometry_set(ModifierData *md,
/* Release the mesh from the geometry set again. */
if (geometry_set.has<MeshComponent>()) {
MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
if (mesh_component.get_for_read() != input_mesh) {
/* Make sure the mesh component actually owns the mesh before taking over ownership. */
mesh_component.ensure_owns_direct_data();
}
mesh_output = mesh_component.release();
}

View File

@ -568,15 +568,15 @@ class GeometryNodesEvaluator {
}
/* Count the number of potential users for this socket. */
socket.foreach_target_socket(
[&, this](const DInputSocket target_socket) {
[&, this](const DInputSocket target_socket,
const DOutputSocket::TargetSocketPathInfo &UNUSED(path_info)) {
const DNode target_node = target_socket.node();
if (!this->node_states_.contains_as(target_node)) {
/* The target node is not computed because it is not computed to the output. */
return;
}
output_state.potential_users += 1;
},
{});
});
if (output_state.potential_users == 0) {
/* If it does not have any potential users, it is unused. It might become required again in
* `schedule_initial_nodes`. */
@ -1257,43 +1257,61 @@ class GeometryNodesEvaluator {
{
BLI_assert(value_to_forward.get() != nullptr);
Vector<DSocket> sockets_to_log_to;
sockets_to_log_to.append(from_socket);
Vector<DInputSocket> to_sockets;
auto handle_target_socket_fn = [&, this](const DInputSocket to_socket) {
if (this->should_forward_to_socket(to_socket)) {
to_sockets.append(to_socket);
}
};
auto handle_skipped_socket_fn = [&](const DSocket socket) {
sockets_to_log_to.append(socket);
};
from_socket.foreach_target_socket(handle_target_socket_fn, handle_skipped_socket_fn);
LinearAllocator<> &allocator = local_allocators_.local();
const CPPType &from_type = *value_to_forward.type();
Vector<DInputSocket> to_sockets_same_type;
for (const DInputSocket &to_socket : to_sockets) {
const CPPType &to_type = *get_socket_cpp_type(to_socket);
if (from_type == to_type) {
/* All target sockets that do not need a conversion will be handled afterwards. */
to_sockets_same_type.append(to_socket);
/* Multi input socket values are logged once all values are available. */
if (!to_socket->is_multi_input_socket()) {
sockets_to_log_to.append(to_socket);
}
continue;
}
this->forward_to_socket_with_different_type(
allocator, value_to_forward, from_socket, to_socket, to_type);
}
this->log_socket_value(sockets_to_log_to, value_to_forward);
Vector<DSocket> log_original_value_sockets;
Vector<DInputSocket> forward_original_value_sockets;
log_original_value_sockets.append(from_socket);
from_socket.foreach_target_socket(
[&](const DInputSocket to_socket, const DOutputSocket::TargetSocketPathInfo &path_info) {
if (!this->should_forward_to_socket(to_socket)) {
return;
}
BLI_assert(to_socket == path_info.sockets.last());
GMutablePointer current_value = value_to_forward;
for (const DSocket &next_socket : path_info.sockets) {
const DNode next_node = next_socket.node();
const bool is_last_socket = to_socket == next_socket;
const bool do_conversion_if_necessary = is_last_socket ||
next_node->is_group_output_node() ||
(next_node->is_group_node() &&
!next_node->is_muted());
if (do_conversion_if_necessary) {
const CPPType &next_type = *get_socket_cpp_type(next_socket);
if (*current_value.type() != next_type) {
void *buffer = allocator.allocate(next_type.size(), next_type.alignment());
this->convert_value(*current_value.type(), next_type, current_value.get(), buffer);
if (current_value.get() != value_to_forward.get()) {
current_value.destruct();
}
current_value = {next_type, buffer};
}
}
if (current_value.get() == value_to_forward.get()) {
/* Log the original value at the current socket. */
log_original_value_sockets.append(next_socket);
}
else {
/* Multi-input sockets are logged when all values are available. */
if (!(next_socket->is_input() && next_socket->as_input().is_multi_input_socket())) {
/* Log the converted value at the socket. */
this->log_socket_value({next_socket}, current_value);
}
}
}
if (current_value.get() == value_to_forward.get()) {
/* The value has not been converted, so forward the original value. */
forward_original_value_sockets.append(to_socket);
}
else {
/* The value has been converted. */
this->add_value_to_input_socket(to_socket, from_socket, current_value);
}
});
this->log_socket_value(log_original_value_sockets, value_to_forward);
this->forward_to_sockets_with_same_type(
allocator, to_sockets_same_type, value_to_forward, from_socket);
allocator, forward_original_value_sockets, value_to_forward, from_socket);
}
bool should_forward_to_socket(const DInputSocket socket)
@ -1312,27 +1330,6 @@ class GeometryNodesEvaluator {
return target_input_state.usage != ValueUsage::Unused;
}
void forward_to_socket_with_different_type(LinearAllocator<> &allocator,
const GPointer value_to_forward,
const DOutputSocket from_socket,
const DInputSocket to_socket,
const CPPType &to_type)
{
const CPPType &from_type = *value_to_forward.type();
/* Allocate a buffer for the converted value. */
void *buffer = allocator.allocate(to_type.size(), to_type.alignment());
GMutablePointer value{to_type, buffer};
this->convert_value(from_type, to_type, value_to_forward.get(), buffer);
/* Multi input socket values are logged once all values are available. */
if (!to_socket->is_multi_input_socket()) {
this->log_socket_value({to_socket}, value);
}
this->add_value_to_input_socket(to_socket, from_socket, value);
}
void forward_to_sockets_with_same_type(LinearAllocator<> &allocator,
Span<DInputSocket> to_sockets,
GMutablePointer value_to_forward,

View File

@ -158,8 +158,19 @@ class DOutputSocket : public DSocket {
DInputSocket get_corresponding_group_node_input() const;
DInputSocket get_active_corresponding_group_output_socket() const;
void foreach_target_socket(FunctionRef<void(DInputSocket)> target_fn,
FunctionRef<void(DSocket)> skipped_fn) const;
struct TargetSocketPathInfo {
/** All sockets on the path from the current to the final target sockets, excluding `this`. */
Vector<DSocket, 16> sockets;
};
using ForeachTargetSocketFn =
FunctionRef<void(DInputSocket, const TargetSocketPathInfo &path_info)>;
void foreach_target_socket(ForeachTargetSocketFn target_fn) const;
private:
void foreach_target_socket(ForeachTargetSocketFn target_fn,
TargetSocketPathInfo &path_info) const;
};
class DerivedNodeTree {

View File

@ -231,45 +231,90 @@ void DInputSocket::foreach_origin_socket(FunctionRef<void(DSocket)> origin_fn) c
/* Calls `target_fn` for every "real" target socket. "Real" means that reroutes, muted nodes
* and node groups are handled by this function. Target sockets are on the nodes that use the value
* from this socket. The `skipped_fn` function is called for sockets that have been skipped during
* the search for target sockets (e.g. reroutes). */
void DOutputSocket::foreach_target_socket(FunctionRef<void(DInputSocket)> target_fn,
FunctionRef<void(DSocket)> skipped_fn) const
* from this socket. */
void DOutputSocket::foreach_target_socket(ForeachTargetSocketFn target_fn) const
{
for (const SocketRef *skipped_socket : socket_ref_->logically_linked_skipped_sockets()) {
skipped_fn.call_safe({context_, skipped_socket});
}
for (const InputSocketRef *linked_socket : socket_ref_->as_output().logically_linked_sockets()) {
const NodeRef &linked_node = linked_socket->node();
DInputSocket linked_dsocket{context_, linked_socket};
TargetSocketPathInfo path_info;
this->foreach_target_socket(target_fn, path_info);
}
if (linked_node.is_group_output_node()) {
void DOutputSocket::foreach_target_socket(ForeachTargetSocketFn target_fn,
TargetSocketPathInfo &path_info) const
{
for (const LinkRef *link : socket_ref_->as_output().directly_linked_links()) {
if (link->is_muted()) {
continue;
}
const DInputSocket &linked_socket{context_, &link->to()};
if (!linked_socket->is_available()) {
continue;
}
const DNode linked_node = linked_socket.node();
if (linked_node->is_reroute_node()) {
const DInputSocket reroute_input = linked_socket;
const DOutputSocket reroute_output = linked_node.output(0);
path_info.sockets.append(reroute_input);
path_info.sockets.append(reroute_output);
reroute_output.foreach_target_socket(target_fn, path_info);
path_info.sockets.pop_last();
path_info.sockets.pop_last();
}
else if (linked_node->is_muted()) {
for (const InternalLinkRef *internal_link : linked_node->internal_links()) {
if (&internal_link->from() != linked_socket.socket_ref()) {
continue;
}
/* The internal link only forwards the first incoming link. */
if (linked_socket->is_multi_input_socket()) {
if (linked_socket->directly_linked_links()[0] == link) {
continue;
}
}
const DInputSocket mute_input = linked_socket;
const DOutputSocket mute_output{context_, &internal_link->to()};
path_info.sockets.append(mute_input);
path_info.sockets.append(mute_output);
mute_output.foreach_target_socket(target_fn, path_info);
path_info.sockets.pop_last();
path_info.sockets.pop_last();
break;
}
}
else if (linked_node->is_group_output_node()) {
if (context_->is_root()) {
/* This is a group output in the root node group. */
target_fn(linked_dsocket);
path_info.sockets.append(linked_socket);
target_fn(linked_socket, path_info);
path_info.sockets.pop_last();
}
else {
/* Follow the links going out of the group node in the parent node group. */
DOutputSocket socket_in_parent_group =
linked_dsocket.get_corresponding_group_node_output();
skipped_fn.call_safe(linked_dsocket);
skipped_fn.call_safe(socket_in_parent_group);
socket_in_parent_group.foreach_target_socket(target_fn, skipped_fn);
const DOutputSocket socket_in_parent_group =
linked_socket.get_corresponding_group_node_output();
path_info.sockets.append(linked_socket);
path_info.sockets.append(socket_in_parent_group);
socket_in_parent_group.foreach_target_socket(target_fn, path_info);
path_info.sockets.pop_last();
path_info.sockets.pop_last();
}
}
else if (linked_node.is_group_node()) {
else if (linked_node->is_group_node()) {
/* Follow the links within the nested node group. */
Vector<DOutputSocket> sockets_in_group =
linked_dsocket.get_corresponding_group_input_sockets();
skipped_fn.call_safe(linked_dsocket);
for (DOutputSocket socket_in_group : sockets_in_group) {
skipped_fn.call_safe(socket_in_group);
socket_in_group.foreach_target_socket(target_fn, skipped_fn);
path_info.sockets.append(linked_socket);
const Vector<DOutputSocket> sockets_in_group =
linked_socket.get_corresponding_group_input_sockets();
for (const DOutputSocket &socket_in_group : sockets_in_group) {
path_info.sockets.append(socket_in_group);
socket_in_group.foreach_target_socket(target_fn, path_info);
path_info.sockets.pop_last();
}
path_info.sockets.pop_last();
}
else {
/* The normal case: just use the linked input socket as target. */
target_fn(linked_dsocket);
path_info.sockets.append(linked_socket);
target_fn(linked_socket, path_info);
path_info.sockets.pop_last();
}
}
}