WIP: Field type inferencing using a constraint solver method #120420

Draft
Lukas Tönne wants to merge 52 commits from LukasTonne/blender:socket-type-inference into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
2 changed files with 47 additions and 1 deletions
Showing only changes of commit 17298bb464 - Show all commits

View File

@ -1081,6 +1081,49 @@ static void solve_field_inferencing_constraints(
*group_output_socket, interface_by_node, result);
inferencing_interface.outputs[group_output_socket->index()] = std::move(field_dependency);
}
/* Perform old propagation method as well to verify the result. */
const bool compare_propagation = true;
if (compare_propagation) {
/* Keep track of the state of all sockets. The index into this array is #SocketRef::id(). */
Array<SocketFieldState> field_state_by_socket_id(tree.all_sockets().size());
propagate_data_requirements_from_right_to_left(
tree, interface_by_node, field_state_by_socket_id);
determine_group_input_states(tree, inferencing_interface, field_state_by_socket_id);
propagate_field_status_from_left_to_right(tree, interface_by_node, field_state_by_socket_id);
determine_group_output_states(
tree, inferencing_interface, interface_by_node, field_state_by_socket_id);
auto log_error = [](const bNodeSocket &socket, StringRef message) {
const std::string socket_address = std::string(socket.owner_node().name) + ":" + socket.name;
std::cout << socket_address << ": " << message << std::endl;
};
std::cout << "Update tree " << tree.id.name << std::endl;
for (const bNodeSocket *socket : tree.all_sockets()) {
const int var_index = socket_vars[socket->index_in_tree()];
const BitSpan state = result[var_index];
const SocketFieldState &old_state = field_state_by_socket_id[socket->index_in_tree()];
if (old_state.is_always_single) {
if (!state[DomainValue::Single] || state[DomainValue::Field]) {
log_error(*socket, "Should only be single value");
}
}
if (!old_state.is_single) {
if (state[DomainValue::Single] || !state[DomainValue::Field]) {
log_error(*socket, "Should only be field");
}
}
if (old_state.requires_single) {
if (!state[DomainValue::Single] || state[DomainValue::Field]) {
log_error(*socket, "Should only be single value");
}
}
if (!state[DomainValue::Single] || !state[DomainValue::Field]) {
log_error(*socket, "Should be both single value and field");
}
}
}
}
template <typename Logger>

View File

@ -84,7 +84,10 @@ static void solve_binary_constraints(const ConstraintSet &constraints,
/* TODO sorting the worklist could have significant impact on performance
* by reducing unnecessary repetition of constraints.
* Using the topological sorting of sockets should make a decent "preconditioner".
* This is similar to what the current R-L/L-R solver does. */
* This is similar to what the current R-L/L-R solver does.
* Nice overview of possible optimizations, depending on the problem to solve:
* https://ics.uci.edu/~kkask/Fall-2018%20CS271/slides/05-constraint-satisfaction.pdf
*/
struct BinaryKey {
VariableIndex source;
VariableIndex target;