[Bf-blender-cvs] [d5707b9] object_nodes: Moved the block definition from codegen to the node graph optimization.
Lukas Tönne
noreply at git.blender.org
Tue Jan 12 12:38:28 CET 2016
Commit: d5707b9a05a6017bb006c8a8fad8e1de60a2644f
Author: Lukas Tönne
Date: Sat Jan 9 14:07:58 2016 +0100
Branches: object_nodes
https://developer.blender.org/rBd5707b9a05a6017bb006c8a8fad8e1de60a2644f
Moved the block definition from codegen to the node graph optimization.
This now involves making actual copies of nodes, so that each block has
a unique instance of each node and ambiguity is avoided.
===================================================================
M source/blender/blenvm/compile/bvm_codegen.h
M source/blender/blenvm/compile/bvm_nodegraph.cc
M source/blender/blenvm/compile/bvm_nodegraph.h
===================================================================
diff --git a/source/blender/blenvm/compile/bvm_codegen.h b/source/blender/blenvm/compile/bvm_codegen.h
index f7737ef..a24a7c9 100644
--- a/source/blender/blenvm/compile/bvm_codegen.h
+++ b/source/blender/blenvm/compile/bvm_codegen.h
@@ -57,8 +57,7 @@ struct NodeIndexCmp {
};
typedef std::set<const NodeInstance *, NodeIndexCmp> OrderedNodeSet;
-typedef std::set<ConstInputKey> InputSet;
-typedef std::set<ConstOutputKey> OutputSet;
+
typedef std::map<ConstInputKey, StackIndex> InputIndexMap;
typedef std::map<ConstOutputKey, StackIndex> OutputIndexMap;
typedef std::map<ConstOutputKey, StackIndex> OutputIndexMap;
diff --git a/source/blender/blenvm/compile/bvm_nodegraph.cc b/source/blender/blenvm/compile/bvm_nodegraph.cc
index 5df6e8e..b2de181 100644
--- a/source/blender/blenvm/compile/bvm_nodegraph.cc
+++ b/source/blender/blenvm/compile/bvm_nodegraph.cc
@@ -389,6 +389,11 @@ OutputKey InputKey::link() const
return OutputKey();
}
+void InputKey::link_set(const OutputKey &from) const
+{
+ node->link_set(socket->name, from);
+}
+
const Value *InputKey::value() const
{
return node->input_value(socket->name);
@@ -416,6 +421,20 @@ NodeInstance::NodeInstance(const NodeType *type, const string &name) :
{
}
+NodeInstance::NodeInstance(const NodeInstance *other, const string &name) :
+ type(other->type), name(name), index(0)
+{
+ for (InputMap::const_iterator it = other->inputs.begin(); it != other->inputs.end(); ++it) {
+ const string &input_name = it->first;
+ const InputInstance &other_input = it->second;
+
+ InputInstance &input = inputs[input_name];
+ if (other_input.value)
+ input.value = other_input.value->copy();
+ /* note: links have to be copied externally based on a node map */
+ }
+}
+
NodeInstance::~NodeInstance()
{
/* value instances are managed by the node */
@@ -491,6 +510,19 @@ OutputKey NodeInstance::link(int index) const
return socket ? link(socket->name) : OutputKey(NULL, "");
}
+bool NodeInstance::link_set(const string &name, const OutputKey &from)
+{
+ const NodeInput *socket = type->find_input(name);
+ InputInstance &input = inputs[name];
+
+ if (socket->typedesc.assignable(from.socket->typedesc)) {
+ input.link = from;
+ return true;
+ }
+ else
+ return false;
+}
+
const Value *NodeInstance::input_value(const string &name) const
{
InputMap::const_iterator it = inputs.find(name);
@@ -516,19 +548,6 @@ bool NodeInstance::input_value_set(const string &name, Value *value)
return true;
}
-bool NodeInstance::link_set(const string &name, const OutputKey &from)
-{
- const NodeInput *socket = type->find_input(name);
- InputInstance &input = inputs[name];
-
- if (socket->typedesc.assignable(from.socket->typedesc)) {
- input.link = from;
- return true;
- }
- else
- return false;
-}
-
/* ------------------------------------------------------------------------- */
NodeGraph::NodeTypeMap NodeGraph::node_types;
@@ -591,6 +610,24 @@ NodeInstance *NodeGraph::get_node(const string &name)
return (it != nodes.end())? it->second : NULL;
}
+static void make_unique_name(string &name, const NodeGraph::NodeInstanceMap &nodes)
+{
+ if (nodes.find(name) == nodes.end())
+ return;
+ else {
+ string new_name;
+ int suffix = 1;
+ do {
+ ++suffix;
+ std::stringstream ss;
+ ss << name << suffix;
+ new_name = ss.str();
+ } while (nodes.find(new_name) != nodes.end());
+
+ name = new_name;
+ }
+}
+
NodeInstance *NodeGraph::add_node(const string &type, const string &name)
{
const NodeType *nodetype = find_node_type(type);
@@ -602,17 +639,14 @@ NodeInstance *NodeGraph::add_node(const string &type, const string &name)
ss << nodetype->name();
final = ss.str();
}
- if (nodes.find(final) != nodes.end()) {
- std::stringstream ss;
- ss << "_" << nodes.size();
- final = ss.str();
- }
+ make_unique_name(final, nodes);
NodeInstance *node = new NodeInstance(nodetype, final);
std::pair<NodeInstanceMap::iterator, bool> result =
nodes.insert(NodeInstanceMapPair(final, node));
+ BLI_assert(result.second);
- return (result.second)? result.first->second : NULL;
+ return result.first->second;
}
const NodeGraph::Input *NodeGraph::get_input(int index) const
@@ -747,9 +781,6 @@ OutputKey NodeGraph::add_argument_node(const TypeDesc &typedesc)
return OutputKey(node, "value");
}
-/* ------------------------------------------------------------------------- */
-/* Optimization */
-
void NodeGraph::remove_all_nodes()
{
for (NodeInstanceMap::iterator it = nodes.begin(); it != nodes.end(); ++it) {
@@ -758,6 +789,36 @@ void NodeGraph::remove_all_nodes()
nodes.clear();
}
+NodeInstance *NodeGraph::copy_node(const NodeInstance *node, NodeMap &node_map)
+{
+ string name = node->name;
+ make_unique_name(name, nodes);
+ NodeInstance *cnode = new NodeInstance(node, name);
+ std::pair<NodeInstanceMap::iterator, bool> result =
+ nodes.insert(NodeInstanceMapPair(cnode->name, cnode));
+ BLI_assert(result.second);
+
+ node_map[node] = cnode;
+ for (NodeInstance::InputMap::const_iterator it = node->inputs.begin(); it != node->inputs.end(); ++it) {
+ const string &input_name = it->first;
+ const NodeInstance::InputInstance &input = it->second;
+
+ if (input.link) {
+ NodeInstance *clink_node;
+ if (node_map.find(input.link.node) != node_map.end())
+ clink_node = node_map.at(input.link.node);
+ else
+ clink_node = input.link.node;
+ cnode->inputs[input_name].link = OutputKey(clink_node, input.link.socket);
+ }
+ }
+
+ return cnode;
+}
+
+/* ------------------------------------------------------------------------- */
+/* Optimization */
+
OutputKey NodeGraph::find_root(const OutputKey &key)
{
OutputKey root = key;
@@ -805,8 +866,6 @@ void NodeGraph::skip_pass_nodes()
}
}
-typedef std::set<NodeInstance *> NodeSet;
-
static void used_nodes_append(NodeInstance *node, NodeSet &used_nodes)
{
if (used_nodes.find(node) != used_nodes.end())
@@ -853,6 +912,143 @@ void NodeGraph::remove_unused_nodes()
}
}
+void NodeGraph::get_local_args(const NodeInstance *node, OutputSet &local_args) const
+{
+ if (!node->type->is_kernel_node())
+ return;
+
+ for (int i = 0; i < node->num_outputs(); ++i) {
+ const NodeOutput *output = node->type->find_output(i);
+
+ if (output->value_type == OUTPUT_LOCAL) {
+ const Input *graph_input = get_input(output->name);
+ assert(graph_input);
+
+ if (graph_input->key) {
+ local_args.insert(graph_input->key);
+ }
+ }
+ }
+}
+
+static bool is_arg_node(const NodeInstance *node, const OutputSet &args)
+{
+ for (int i = 0; i < node->num_outputs(); ++i) {
+ ConstOutputKey output = node->output(i);
+ if (args.find(output) != args.end())
+ return true;
+ }
+ return false;
+}
+
+bool NodeGraph::add_block_node(NodeInstance *node, const OutputSet &block_args,
+ NodeBlock &block, NodeMap &block_map)
+{
+ bool is_block_node = false; /* determines if the node is part of the block */
+
+ is_block_node |= is_arg_node(node, block_args);
+
+ OutputSet local_args;
+ get_local_args(node, local_args);
+
+ for (int i = 0; i < node->num_inputs(); ++i) {
+ InputKey input = node->input(i);
+ if (input.is_constant()) {
+ if (!block.parent)
+ is_block_node |= true;
+ }
+ else if (input.is_expression()) {
+ if (!block.parent)
+ is_block_node |= blockify_expression(input, block_args, local_args, block, block_map);
+ }
+ else {
+ OutputKey output = input.link();
+ if (output) {
+ is_block_node |= add_block_node(output.node, block_args, block, block_map);
+ }
+ }
+ }
+
+ if (is_block_node) {
+ NodeInstance *block_node = (block.parent) ? copy_node(node, block_map) : node;
+ block.nodes.insert(block_node);
+ return true;
+ }
+ else
+ return false;
+}
+
+bool NodeGraph::blockify_expression(const InputKey &input, const OutputSet &block_args, const OutputSet &local_args,
+ NodeBlock &block, NodeMap &block_map)
+{
+ OutputKey link_key = input.link();
+ if (!link_key)
+ return false;
+ NodeInstance *link_node = link_key.node;
+
+ bool is_block_node = false;
+
+ /* generate a local block for the input expression */
+ blocks.push_back(NodeBlock(&block));
+ NodeBlock &expr_block = blocks.back();
+ NodeMap expr_block_map;
+
+ add_block_node(link_node, local_args, expr_block, expr_block_map);
+ if (expr_block.nodes.empty()) {
+ /* use the input directly if no expression nodes are generated (no local arg dependencies) */
+ is_block_node |= add_block_node(link_node, block_args, block, block_map);
+ }
+ else {
+ /* remap the input link */
+ input.link_set(OutputKey(expr_block_map.at(link_node), link_key.socket));
+ }
+
+ /* find node inputs in the expression block that use values outside of it,
+ * which means these must be included in the parent block
+ */
+ for (NodeSet::iterator it = expr_block.nodes.begin(); it != expr_block.nodes.end(); ++it) {
+ NodeInstance *node = *it;
+ for (int i = 0; i < node->num_inputs(); ++i) {
+ InputKey expr_input = node->input(i);
+ NodeInstance *link_node = expr_input.link().node;
+ if (link_node && expr_block.nodes.find(link_node) == expr_block.nodes.end())
+ is_block_node |= add_block_node(link_node, block_args, block, block_map);
+ }
+ }
+
+ return is_block_node;
+}
+
+void NodeGraph::blockify_nodes()
+{
+ OutputSet main_args;
+ for (InputList::const_iterator it = inputs.begin(); it != inputs.end(); ++it) {
+ const Input &input = *it;
+ if (input.key)
+ main_args.insert(input.key);
+ }
+
+ blocks.push_back(NodeBlock(NULL));
+ NodeBlock &main = blocks.back();
+ /* for main block the node map is empty */
+ NodeMap main_map;
+
+ for (OutputList::const_iterator it = outputs.begin(); it != outputs.end(); ++it) {
+ const Output &output = *it;
+ if (output.key)
+ add_block_node(output.key.node, main_args, main, main_map);
+ }
+
+ /* input argument nodes must always be included in main,
+ * to provide reliable storage for caller arguments
+ */
+ for (InputList::const_iterator it = inputs.begin(); it != inputs.end(); ++it) {
+ const Input &input = *it;
+ if (input.key)
+ add_block_node(input.key.node, main_args, main, main_map);
+ }
+}
+
static void assign_node_index(NodeInsta
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list