diff options
author | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2016-05-07 20:47:37 +0300 |
---|---|---|
committer | Jeroen Bakker <j.bakker@atmind.nl> | 2016-06-08 22:45:40 +0300 |
commit | e0c1dc44880add2fb64b0e0efc2f174576ba2cd1 (patch) | |
tree | 13b5239322ff2803872834fa601451c67e7ca27f /intern | |
parent | bec22ca5263eb801dbc5d086d3315b496d7524cd (diff) |
Code refactor: add generic Cycles node infrastructure.
Differential Revision: https://developer.blender.org/D2016
Diffstat (limited to 'intern')
-rw-r--r-- | intern/cycles/CMakeLists.txt | 1 | ||||
-rw-r--r-- | intern/cycles/app/CMakeLists.txt | 6 | ||||
-rw-r--r-- | intern/cycles/blender/CMakeLists.txt | 1 | ||||
-rw-r--r-- | intern/cycles/bvh/CMakeLists.txt | 1 | ||||
-rw-r--r-- | intern/cycles/device/CMakeLists.txt | 1 | ||||
-rw-r--r-- | intern/cycles/graph/CMakeLists.txt | 22 | ||||
-rw-r--r-- | intern/cycles/graph/node.cpp | 354 | ||||
-rw-r--r-- | intern/cycles/graph/node.h | 90 | ||||
-rw-r--r-- | intern/cycles/graph/node_enum.h | 48 | ||||
-rw-r--r-- | intern/cycles/graph/node_type.cpp | 190 | ||||
-rw-r--r-- | intern/cycles/graph/node_type.h | 252 | ||||
-rw-r--r-- | intern/cycles/kernel/osl/CMakeLists.txt | 1 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm_types.h | 4 | ||||
-rw-r--r-- | intern/cycles/render/CMakeLists.txt | 1 | ||||
-rw-r--r-- | intern/cycles/render/nodes.cpp | 16 | ||||
-rw-r--r-- | intern/cycles/render/svm.cpp | 4 | ||||
-rw-r--r-- | intern/cycles/render/svm.h | 4 | ||||
-rw-r--r-- | intern/cycles/subd/CMakeLists.txt | 3 | ||||
-rw-r--r-- | intern/cycles/util/util_vector.h | 17 |
19 files changed, 998 insertions, 18 deletions
diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt index efc36f0e6b8..3b410b2a1e1 100644 --- a/intern/cycles/CMakeLists.txt +++ b/intern/cycles/CMakeLists.txt @@ -237,6 +237,7 @@ endif() add_subdirectory(bvh) add_subdirectory(device) add_subdirectory(doc) +add_subdirectory(graph) add_subdirectory(kernel) add_subdirectory(render) add_subdirectory(subd) diff --git a/intern/cycles/app/CMakeLists.txt b/intern/cycles/app/CMakeLists.txt index d40a1a14f72..73dbf16a3d3 100644 --- a/intern/cycles/app/CMakeLists.txt +++ b/intern/cycles/app/CMakeLists.txt @@ -1,13 +1,14 @@ set(INC . + ../bvh ../device + ../graph ../kernel ../kernel/svm - ../bvh - ../util ../render ../subd + ../util ) set(INC_SYS ) @@ -20,6 +21,7 @@ set(LIBRARIES cycles_render cycles_bvh cycles_subd + cycles_graph cycles_util ${BLENDER_GL_LIBRARIES} ${CYCLES_APP_GLEW_LIBRARY} diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt index a8cc4907cbf..a79deca53e1 100644 --- a/intern/cycles/blender/CMakeLists.txt +++ b/intern/cycles/blender/CMakeLists.txt @@ -1,5 +1,6 @@ set(INC + ../graph ../render ../device ../kernel diff --git a/intern/cycles/bvh/CMakeLists.txt b/intern/cycles/bvh/CMakeLists.txt index cbbd23fcff8..5729fa6113d 100644 --- a/intern/cycles/bvh/CMakeLists.txt +++ b/intern/cycles/bvh/CMakeLists.txt @@ -1,6 +1,7 @@ set(INC . + ../graph ../kernel ../kernel/svm ../render diff --git a/intern/cycles/device/CMakeLists.txt b/intern/cycles/device/CMakeLists.txt index 2a9ec0c3818..c34677e1b78 100644 --- a/intern/cycles/device/CMakeLists.txt +++ b/intern/cycles/device/CMakeLists.txt @@ -1,6 +1,7 @@ set(INC . + ../graph ../kernel ../kernel/svm ../kernel/osl diff --git a/intern/cycles/graph/CMakeLists.txt b/intern/cycles/graph/CMakeLists.txt new file mode 100644 index 00000000000..401bdb47392 --- /dev/null +++ b/intern/cycles/graph/CMakeLists.txt @@ -0,0 +1,22 @@ + +set(INC + . + ../util +) + +set(SRC + node.cpp + node_type.cpp +) + +set(SRC_HEADERS + node.h + node_enum.h + node_type.h +) + +include_directories(${INC}) +include_directories(SYSTEM ${INC_SYS}) + +add_library(cycles_graph ${SRC} ${SRC_HEADERS}) + diff --git a/intern/cycles/graph/node.cpp b/intern/cycles/graph/node.cpp new file mode 100644 index 00000000000..d9a6bde4fcd --- /dev/null +++ b/intern/cycles/graph/node.cpp @@ -0,0 +1,354 @@ +/* + * Copyright 2011-2016 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "node.h" +#include "node_type.h" + +#include "util_foreach.h" +#include "util_param.h" +#include "util_transform.h" + +CCL_NAMESPACE_BEGIN + +/* Node Type */ + +Node::Node(const NodeType *type_, ustring name_) +: name(name_), type(type_) +{ + assert(type); + + /* assign non-empty name, convenient for debugging */ + if(name.empty()) { + name = type->name; + } + + /* initialize default values */ + typedef unordered_map<ustring, SocketType, ustringHash> map_type; + foreach(const map_type::value_type& it, type->inputs) { + const SocketType& socket = it.second; + const void *src = socket.default_value; + void *dst = ((char*)this) + socket.struct_offset; + memcpy(dst, src, socket.size()); + } +} + +Node::~Node() +{ +} + +template<typename T> +static T& get_socket_value(const Node *node, const SocketType& socket) +{ + return (T&)*(((char*)node) + socket.struct_offset); +} + +static bool is_socket_float3(const SocketType& socket) +{ + return socket.type == SocketType::COLOR || + socket.type == SocketType::POINT || + socket.type == SocketType::VECTOR || + socket.type == SocketType::NORMAL; +} + +static bool is_socket_array_float3(const SocketType& socket) +{ + return socket.type == SocketType::COLOR_ARRAY || + socket.type == SocketType::POINT_ARRAY || + socket.type == SocketType::VECTOR_ARRAY || + socket.type == SocketType::NORMAL_ARRAY; +} + +/* set values */ +void Node::set(const SocketType& input, bool value) +{ + assert(input.type == SocketType::BOOLEAN); + get_socket_value<bool>(this, input) = value; +} + +void Node::set(const SocketType& input, int value) +{ + assert((input.type == SocketType::INT || input.type == SocketType::ENUM)); + get_socket_value<int>(this, input) = value; +} + +void Node::set(const SocketType& input, float value) +{ + assert(input.type == SocketType::FLOAT); + get_socket_value<float>(this, input) = value; +} + +void Node::set(const SocketType& input, float2 value) +{ + assert(input.type == SocketType::FLOAT); + get_socket_value<float2>(this, input) = value; +} + +void Node::set(const SocketType& input, float3 value) +{ + assert(is_socket_float3(input)); + get_socket_value<float3>(this, input) = value; +} + +void Node::set(const SocketType& input, ustring value) +{ + if(input.type == SocketType::STRING) { + get_socket_value<ustring>(this, input) = value; + } + else if(input.type == SocketType::ENUM) { + const NodeEnum& enm = *input.enum_values; + if(enm.exists(value)) { + get_socket_value<int>(this, input) = enm[value]; + } + else { + assert(0); + } + } + else { + assert(0); + } +} + +void Node::set(const SocketType& input, const Transform& value) +{ + assert(input.type == SocketType::TRANSFORM); + get_socket_value<Transform>(this, input) = value; +} + +void Node::set(const SocketType& input, Node *value) +{ + assert(input.type == SocketType::TRANSFORM); + get_socket_value<Node*>(this, input) = value; +} + +/* set array values */ +void Node::set(const SocketType& input, array<bool>& value) +{ + assert(input.type == SocketType::BOOLEAN_ARRAY); + get_socket_value<array<bool> >(this, input).steal_data(value); +} + +void Node::set(const SocketType& input, array<int>& value) +{ + assert(input.type == SocketType::INT_ARRAY); + get_socket_value<array<int> >(this, input).steal_data(value); +} + +void Node::set(const SocketType& input, array<float>& value) +{ + assert(input.type == SocketType::FLOAT_ARRAY); + get_socket_value<array<float> >(this, input).steal_data(value); +} + +void Node::set(const SocketType& input, array<float2>& value) +{ + assert(input.type == SocketType::FLOAT_ARRAY); + get_socket_value<array<float2> >(this, input).steal_data(value); +} + +void Node::set(const SocketType& input, array<float3>& value) +{ + assert(is_socket_array_float3(input)); + get_socket_value<array<float3> >(this, input).steal_data(value); +} + +void Node::set(const SocketType& input, array<ustring>& value) +{ + assert(input.type == SocketType::STRING_ARRAY); + get_socket_value<array<ustring> >(this, input).steal_data(value); +} + +void Node::set(const SocketType& input, array<Transform>& value) +{ + assert(input.type == SocketType::TRANSFORM_ARRAY); + get_socket_value<array<Transform> >(this, input).steal_data(value); +} + +void Node::set(const SocketType& input, array<Node*>& value) +{ + assert(input.type == SocketType::TRANSFORM_ARRAY); + get_socket_value<array<Node*> >(this, input).steal_data(value); +} + +/* get values */ +bool Node::get_bool(const SocketType& input) const +{ + assert(input.type == SocketType::BOOLEAN); + return get_socket_value<bool>(this, input); +} + +int Node::get_int(const SocketType& input) const +{ + assert(input.type == SocketType::INT || input.type == SocketType::ENUM); + return get_socket_value<int>(this, input); +} + +float Node::get_float(const SocketType& input) const +{ + assert(input.type == SocketType::FLOAT); + return get_socket_value<float>(this, input); +} + +float2 Node::get_float2(const SocketType& input) const +{ + assert(input.type == SocketType::FLOAT); + return get_socket_value<float2>(this, input); +} + +float3 Node::get_float3(const SocketType& input) const +{ + assert(is_socket_float3(input)); + return get_socket_value<float3>(this, input); +} + +ustring Node::get_string(const SocketType& input) const +{ + if(input.type == SocketType::STRING) { + return get_socket_value<ustring>(this, input); + } + else if(input.type == SocketType::ENUM) { + const NodeEnum& enm = *input.enum_values; + int intvalue = get_socket_value<int>(this, input); + return (enm.exists(intvalue)) ? enm[intvalue] : ustring(); + } + else { + assert(0); + return ustring(); + } +} + +Transform Node::get_transform(const SocketType& input) const +{ + assert(input.type == SocketType::TRANSFORM); + return get_socket_value<Transform>(this, input); +} + +Node *Node::get_node(const SocketType& input) const +{ + assert(input.type == SocketType::NODE); + return get_socket_value<Node*>(this, input); +} + +/* get array values */ +const array<bool>& Node::get_bool_array(const SocketType& input) const +{ + assert(input.type == SocketType::BOOLEAN_ARRAY); + return get_socket_value<array<bool> >(this, input); +} + +const array<int>& Node::get_int_array(const SocketType& input) const +{ + assert(input.type == SocketType::INT_ARRAY); + return get_socket_value<array<int> >(this, input); +} + +const array<float>& Node::get_float_array(const SocketType& input) const +{ + assert(input.type == SocketType::FLOAT_ARRAY); + return get_socket_value<array<float> >(this, input); +} + +const array<float2>& Node::get_float2_array(const SocketType& input) const +{ + assert(input.type == SocketType::FLOAT_ARRAY); + return get_socket_value<array<float2> >(this, input); +} + +const array<float3>& Node::get_float3_array(const SocketType& input) const +{ + assert(is_socket_array_float3(input)); + return get_socket_value<array<float3> >(this, input); +} + +const array<ustring>& Node::get_string_array(const SocketType& input) const +{ + assert(input.type == SocketType::STRING_ARRAY); + return get_socket_value<array<ustring> >(this, input); +} + +const array<Transform>& Node::get_transform_array(const SocketType& input) const +{ + assert(input.type == SocketType::TRANSFORM_ARRAY); + return get_socket_value<array<Transform> >(this, input); +} + +const array<Node*>& Node::get_node_array(const SocketType& input) const +{ + assert(input.type == SocketType::NODE_ARRAY); + return get_socket_value<array<Node*> >(this, input); +} + +/* default values */ +bool Node::has_default_value(const SocketType& input) const +{ + const void *src = input.default_value; + void *dst = &get_socket_value<char>(this, input); + return memcmp(dst, src, input.size()) == 0; +} + +template<typename T> +static bool is_array_equal(const Node *node, const Node *other, const SocketType& socket) +{ + const array<T>* a = (const array<T>*)(((char*)node) + socket.struct_offset); + const array<T>* b = (const array<T>*)(((char*)other) + socket.struct_offset); + return *a == *b; +} + +/* modified */ +bool Node::modified(const Node& other) +{ + assert(type == other.type); + + typedef unordered_map<ustring, SocketType, ustringHash> map_type; + foreach(const map_type::value_type& it, type->inputs) { + const SocketType& socket = it.second; + + if(socket.is_array()) { + bool equal = true; + + switch(socket.type) + { + case SocketType::BOOLEAN_ARRAY: equal = is_array_equal<bool>(this, &other, socket); break; + case SocketType::FLOAT_ARRAY: equal = is_array_equal<float>(this, &other, socket); break; + case SocketType::INT_ARRAY: equal = is_array_equal<int>(this, &other, socket); break; + case SocketType::COLOR_ARRAY: equal = is_array_equal<float3>(this, &other, socket); break; + case SocketType::VECTOR_ARRAY: equal = is_array_equal<float3>(this, &other, socket); break; + case SocketType::POINT_ARRAY: equal = is_array_equal<float3>(this, &other, socket); break; + case SocketType::NORMAL_ARRAY: equal = is_array_equal<float3>(this, &other, socket); break; + case SocketType::POINT2_ARRAY: equal = is_array_equal<float2>(this, &other, socket); break; + case SocketType::STRING_ARRAY: equal = is_array_equal<ustring>(this, &other, socket); break; + case SocketType::TRANSFORM_ARRAY: equal = is_array_equal<Transform>(this, &other, socket); break; + case SocketType::NODE_ARRAY: equal = is_array_equal<void*>(this, &other, socket); break; + default: assert(0); break; + } + + if(!equal) { + return true; + } + } + else { + const void *a = ((char*)this) + socket.struct_offset; + const void *b = ((char*)&other) + socket.struct_offset; + if(memcmp(a, b, socket.size()) != 0) { + return true; + } + } + } + + return false; +} + +CCL_NAMESPACE_END + diff --git a/intern/cycles/graph/node.h b/intern/cycles/graph/node.h new file mode 100644 index 00000000000..33971fa714a --- /dev/null +++ b/intern/cycles/graph/node.h @@ -0,0 +1,90 @@ +/* + * Copyright 2011-2016 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "node_type.h" + +#include "util_map.h" +#include "util_param.h" +#include "util_vector.h" + +CCL_NAMESPACE_BEGIN + +struct Node; +struct NodeType; +struct Transform; + +/* Node */ + +struct Node +{ + explicit Node(const NodeType *type, ustring name = ustring()); + virtual ~Node(); + + /* set values */ + void set(const SocketType& input, bool value); + void set(const SocketType& input, int value); + void set(const SocketType& input, float value); + void set(const SocketType& input, float2 value); + void set(const SocketType& input, float3 value); + void set(const SocketType& input, ustring value); + void set(const SocketType& input, const Transform& value); + void set(const SocketType& input, Node *value); + + /* set array values. the memory from the input array will taken over + * by the node and the input array will be empty after return */ + void set(const SocketType& input, array<bool>& value); + void set(const SocketType& input, array<int>& value); + void set(const SocketType& input, array<float>& value); + void set(const SocketType& input, array<float2>& value); + void set(const SocketType& input, array<float3>& value); + void set(const SocketType& input, array<ustring>& value); + void set(const SocketType& input, array<Transform>& value); + void set(const SocketType& input, array<Node*>& value); + + /* get values */ + bool get_bool(const SocketType& input) const; + int get_int(const SocketType& input) const; + float get_float(const SocketType& input) const; + float2 get_float2(const SocketType& input) const; + float3 get_float3(const SocketType& input) const; + ustring get_string(const SocketType& input) const; + Transform get_transform(const SocketType& input) const; + Node *get_node(const SocketType& input) const; + + /* get array values */ + const array<bool>& get_bool_array(const SocketType& input) const; + const array<int>& get_int_array(const SocketType& input) const; + const array<float>& get_float_array(const SocketType& input) const; + const array<float2>& get_float2_array(const SocketType& input) const; + const array<float3>& get_float3_array(const SocketType& input) const; + const array<ustring>& get_string_array(const SocketType& input) const; + const array<Transform>& get_transform_array(const SocketType& input) const; + const array<Node*>& get_node_array(const SocketType& input) const; + + /* default values */ + bool has_default_value(const SocketType& input) const; + + /* modified */ + bool modified(const Node& other); + + ustring name; + const NodeType *type; +}; + +CCL_NAMESPACE_END + diff --git a/intern/cycles/graph/node_enum.h b/intern/cycles/graph/node_enum.h new file mode 100644 index 00000000000..2bae531c036 --- /dev/null +++ b/intern/cycles/graph/node_enum.h @@ -0,0 +1,48 @@ +/* + * Copyright 2011-2016 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "util_map.h" +#include "util_param.h" + +CCL_NAMESPACE_BEGIN + +/* Enum + * + * Utility class for enum values. */ + +struct NodeEnum { + bool empty() const { return left.empty(); } + void insert(const char *x, int y) { + left[ustring(x)] = y; + right[y] = ustring(x); + } + + bool exists(ustring x) const { return left.find(x) != left.end(); } + bool exists(int y) const { return right.find(y) != right.end(); } + + int operator[](const char *x) const { return left.find(ustring(x))->second; } + int operator[](ustring x) const { return left.find(x)->second; } + ustring operator[](int y) const { return right.find(y)->second; } + +private: + unordered_map<ustring, int, ustringHash> left; + unordered_map<int, ustring> right; +}; + +CCL_NAMESPACE_END + diff --git a/intern/cycles/graph/node_type.cpp b/intern/cycles/graph/node_type.cpp new file mode 100644 index 00000000000..dc879655d7f --- /dev/null +++ b/intern/cycles/graph/node_type.cpp @@ -0,0 +1,190 @@ +/* + * Copyright 2011-2016 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "node_type.h" +#include "util_foreach.h" +#include "util_transform.h" + +CCL_NAMESPACE_BEGIN + +/* Node Socket Type */ + +size_t SocketType::size() const +{ + return size(type); +} + +bool SocketType::is_array() const +{ + return (type >= BOOLEAN_ARRAY); +} + +size_t SocketType::size(Type type) +{ + switch(type) + { + case UNDEFINED: return 0; + + case BOOLEAN: return sizeof(bool); + case FLOAT: return sizeof(float); + case INT: return sizeof(int); + case COLOR: return sizeof(float3); + case VECTOR: return sizeof(float3); + case POINT: return sizeof(float3); + case NORMAL: return sizeof(float3); + case POINT2: return sizeof(float2); + case CLOSURE: return 0; + case STRING: return sizeof(ustring); + case ENUM: return sizeof(int); + case TRANSFORM: return sizeof(Transform); + case NODE: return sizeof(void*); + + case BOOLEAN_ARRAY: return sizeof(array<bool>); + case FLOAT_ARRAY: return sizeof(array<float>); + case INT_ARRAY: return sizeof(array<int>); + case COLOR_ARRAY: return sizeof(array<float3>); + case VECTOR_ARRAY: return sizeof(array<float3>); + case POINT_ARRAY: return sizeof(array<float3>); + case NORMAL_ARRAY: return sizeof(array<float3>); + case POINT2_ARRAY: return sizeof(array<float2>); + case STRING_ARRAY: return sizeof(array<ustring>); + case TRANSFORM_ARRAY: return sizeof(array<Transform>); + case NODE_ARRAY: return sizeof(array<void*>); + } + + assert(0); + return 0; +} + +size_t SocketType::max_size() +{ + return sizeof(Transform); +} + +void *SocketType::zero_default_value() +{ + static Transform zero_transform = {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}; + return &zero_transform; +} + +ustring SocketType::type_name(Type type) +{ + static ustring names[] = { + ustring("undefined"), + + ustring("boolean"), + ustring("float"), + ustring("int"), + ustring("color"), + ustring("vector"), + ustring("point"), + ustring("normal"), + ustring("point2"), + ustring("closure"), + ustring("string"), + ustring("enum"), + ustring("transform"), + ustring("node"), + + ustring("array_boolean"), + ustring("array_float"), + ustring("array_int"), + ustring("array_color"), + ustring("array_vector"), + ustring("array_point"), + ustring("array_normal"), + ustring("array_point2"), + ustring("array_string"), + ustring("array_transform"), + ustring("array_node")}; + + return names[(int)type]; +} + +/* Node Type */ + +NodeType::NodeType() +{ +} + +NodeType::~NodeType() +{ +} + +void NodeType::register_input(ustring name, ustring ui_name, SocketType::Type type, int struct_offset, + const void *default_value, const NodeEnum *enum_values, + const NodeType **node_type, int flags, int extra_flags) +{ + SocketType socket; + socket.name = name; + socket.ui_name = ui_name; + socket.type = type; + socket.struct_offset = struct_offset; + socket.default_value = default_value; + socket.enum_values = enum_values; + socket.node_type = node_type; + socket.flags = flags | extra_flags; + inputs[name] = socket; +} + +void NodeType::register_output(ustring name, ustring ui_name, SocketType::Type type) +{ + SocketType socket; + socket.name = name; + socket.ui_name = ui_name; + socket.type = type; + socket.struct_offset = 0; + socket.default_value = NULL; + socket.enum_values = NULL; + socket.node_type = NULL; + socket.flags = SocketType::LINKABLE; + outputs[name] = socket; +} + +/* Node Type Registry */ + +unordered_map<ustring, NodeType, ustringHash>& NodeType::types() +{ + static unordered_map<ustring, NodeType, ustringHash> _types; + return _types; +} + +NodeType *NodeType::add(const char *name_, CreateFunc create_) +{ + ustring name(name_); + + if(types().find(name) != types().end()) { + fprintf(stderr, "Node type %s registered twice!\n", name_); + assert(0); + return NULL; + } + + types()[name] = NodeType(); + + NodeType *type = &types()[name]; + type->name = name; + type->create = create_; + return type; +} + +const NodeType *NodeType::find(ustring name) +{ + unordered_map<ustring, NodeType, ustringHash>::iterator it = types().find(name); + return (it == types().end()) ? NULL : &it->second; +} + +CCL_NAMESPACE_END + diff --git a/intern/cycles/graph/node_type.h b/intern/cycles/graph/node_type.h new file mode 100644 index 00000000000..82ddd29da33 --- /dev/null +++ b/intern/cycles/graph/node_type.h @@ -0,0 +1,252 @@ +/* + * Copyright 2011-2016 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "node_enum.h" + +#include "util_map.h" +#include "util_param.h" +#include "util_string.h" + +CCL_NAMESPACE_BEGIN + +struct Node; +struct NodeType; + +/* Socket Type */ + +struct SocketType +{ + enum Type + { + UNDEFINED, + + BOOLEAN, + FLOAT, + INT, + COLOR, + VECTOR, + POINT, + NORMAL, + POINT2, + CLOSURE, + STRING, + ENUM, + TRANSFORM, + NODE, + + BOOLEAN_ARRAY, + FLOAT_ARRAY, + INT_ARRAY, + COLOR_ARRAY, + VECTOR_ARRAY, + POINT_ARRAY, + NORMAL_ARRAY, + POINT2_ARRAY, + STRING_ARRAY, + TRANSFORM_ARRAY, + NODE_ARRAY, + }; + + enum Flags { + LINKABLE = (1 << 0), + ANIMATABLE = (1 << 1), + + SVM_INTERNAL = (1 << 2), + OSL_INTERNAL = (1 << 3), + INTERNAL = (1 << 2) | (1 << 3), + + LINK_TEXTURE_GENERATED = (1 << 4), + LINK_TEXTURE_UV = (1 << 5), + LINK_INCOMING = (1 << 6), + LINK_NORMAL = (1 << 7), + LINK_POSITION = (1 << 8), + LINK_TANGENT = (1 << 9), + DEFAULT_LINK_MASK = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) + }; + + ustring name; + Type type; + int struct_offset; + const void *default_value; + const NodeEnum *enum_values; + const NodeType **node_type; + int flags; + ustring ui_name; + + size_t size() const; + bool is_array() const; + static size_t size(Type type); + static size_t max_size(); + static ustring type_name(Type type); + static void *zero_default_value(); +}; + +/* Node Type */ + +struct NodeType +{ + explicit NodeType(); + ~NodeType(); + + void register_input(ustring name, ustring ui_name, SocketType::Type type, + int struct_offset, const void *default_value, + const NodeEnum *enum_values = NULL, + const NodeType **node_type = NULL, + int flags = 0, int extra_flags = 0); + void register_output(ustring name, ustring ui_name, SocketType::Type type); + + typedef Node *(*CreateFunc)(const NodeType *type); + typedef unordered_map<ustring, SocketType, ustringHash> SocketMap; + + ustring name; + SocketMap inputs; + SocketMap outputs; + CreateFunc create; + + static NodeType *add(const char *name, CreateFunc create); + static const NodeType *find(ustring name); + static unordered_map<ustring, NodeType, ustringHash>& types(); +}; + +/* Node Definition Macros */ + +#define NODE_DECLARE \ +template<typename T> \ +static const NodeType *register_type(); \ +static Node *create(const NodeType *type); \ +static const NodeType *node_type; + +#define NODE_DEFINE(structname) \ +const NodeType *structname::node_type = structname::register_type<structname>(); \ +Node *structname::create(const NodeType*) { return new structname(); } \ +template<typename T> \ +const NodeType *structname::register_type() + +/* Sock Definition Macros */ + +#define SOCKET_OFFSETOF(T, name) (((char *)&(((T *)1)->name)) - (char *)1) +#define SOCKET_SIZEOF(T, name) (sizeof(((T *)1)->name)) +#define SOCKET_DEFINE(name, ui_name, default_value, datatype, TYPE, flags, ...) \ + { \ + static datatype defval = default_value; \ + assert(SOCKET_SIZEOF(T, name) == sizeof(datatype)); \ + type->register_input(ustring(#name), ustring(ui_name), TYPE, SOCKET_OFFSETOF(T, name), &defval, NULL, NULL, flags, ##__VA_ARGS__); \ + } + +#define SOCKET_BOOLEAN(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, bool, SocketType::BOOLEAN, 0, ##__VA_ARGS__) +#define SOCKET_INT(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, int, SocketType::INT, 0, ##__VA_ARGS__) +#define SOCKET_FLOAT(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, float, SocketType::FLOAT, 0, ##__VA_ARGS__) +#define SOCKET_COLOR(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::COLOR, 0, ##__VA_ARGS__) +#define SOCKET_VECTOR(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::VECTOR, 0, ##__VA_ARGS__) +#define SOCKET_POINT(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::POINT, 0, ##__VA_ARGS__) +#define SOCKET_NORMAL(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::NORMAL, 0, ##__VA_ARGS__) +#define SOCKET_POINT2(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, float2, SocketType::POINT2, 0, ##__VA_ARGS__) +#define SOCKET_STRING(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, ustring, SocketType::STRING, 0, ##__VA_ARGS__) +#define SOCKET_TRANSFORM(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, Transform, SocketType::TRANSFORM, 0, ##__VA_ARGS__) +#define SOCKET_ENUM(name, ui_name, values, default_value, ...) \ + { \ + static int defval = default_value; \ + assert(SOCKET_SIZEOF(T, name) == sizeof(int)); \ + type->register_input(ustring(#name), ustring(ui_name), SocketType::ENUM, SOCKET_OFFSETOF(T, name), &defval, &values, NULL, ##__VA_ARGS__); \ + } +#define SOCKET_NODE(name, ui_name, node_type, ...) \ + { \ + static Node *defval = NULL; \ + assert(SOCKET_SIZEOF(T, name) == sizeof(Node*)); \ + type->register_input(ustring(#name), ustring(ui_name), SocketType::NODE, SOCKET_OFFSETOF(T, name), &defval, NULL, node_type, ##__VA_ARGS__); \ + } + +#define SOCKET_BOOLEAN_ARRAY(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, array<bool>, SocketType::BOOLEAN_ARRAY, 0, ##__VA_ARGS__) +#define SOCKET_INT_ARRAY(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, array<int>, SocketType::INT_ARRAY, 0, ##__VA_ARGS__) +#define SOCKET_FLOAT_ARRAY(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, array<float>, SocketType::FLOAT_ARRAY, 0, ##__VA_ARGS__) +#define SOCKET_COLOR_ARRAY(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, array<float3>, SocketType::COLOR_ARRAY, 0, ##__VA_ARGS__) +#define SOCKET_VECTOR_ARRAY(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, array<float3>, SocketType::VECTOR_ARRAY, 0, ##__VA_ARGS__) +#define SOCKET_POINT_ARRAY(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, array<float3>, SocketType::POINT_ARRAY, 0, ##__VA_ARGS__) +#define SOCKET_NORMAL_ARRAY(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, array<float3>, SocketType::NORMAL_ARRAY, 0, ##__VA_ARGS__) +#define SOCKET_POINT2_ARRAY(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, array<float2>, SocketType::POINT2_ARRAY, 0, ##__VA_ARGS__) +#define SOCKET_STRING_ARRAY(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, array<ustring>, SocketType::STRING_ARRAY, 0, ##__VA_ARGS__) +#define SOCKET_TRANSFORM_ARRAY(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, array<Transform>, SocketType::TRANSFORM_ARRAY, 0, ##__VA_ARGS__) +#define SOCKET_NODE_ARRAY(name, ui_name, node_type, ...) \ + { \ + static Node *defval = NULL; \ + assert(SOCKET_SIZEOF(T, name) == sizeof(Node*)); \ + type->register_input(ustring(#name), ustring(ui_name), SocketType::NODE_ARRAY, SOCKET_OFFSETOF(T, name), &defval, NULL, node_type, ##__VA_ARGS__); \ + } + +#define SOCKET_IN_BOOLEAN(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, bool, SocketType::BOOLEAN, SocketType::LINKABLE, ##__VA_ARGS__) +#define SOCKET_IN_INT(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, int, SocketType::INT, SocketType::LINKABLE, ##__VA_ARGS__) +#define SOCKET_IN_FLOAT(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, float, SocketType::FLOAT, SocketType::LINKABLE, ##__VA_ARGS__) +#define SOCKET_IN_COLOR(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::COLOR, SocketType::LINKABLE, ##__VA_ARGS__) +#define SOCKET_IN_VECTOR(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::VECTOR, SocketType::LINKABLE, ##__VA_ARGS__) +#define SOCKET_IN_POINT(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::POINT, SocketType::LINKABLE, ##__VA_ARGS__) +#define SOCKET_IN_NORMAL(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::NORMAL, SocketType::LINKABLE, ##__VA_ARGS__) +#define SOCKET_IN_STRING(name, ui_name, default_value, ...) \ + SOCKET_DEFINE(name, ui_name, default_value, ustring, SocketType::STRING, SocketType::LINKABLE, ##__VA_ARGS__) +#define SOCKET_IN_CLOSURE(name, ui_name, ...) \ + type->register_input(ustring(#name), ustring(ui_name), SocketType::CLOSURE, 0, NULL, NULL, NULL, SocketType::LINKABLE, ##__VA_ARGS__) + +#define SOCKET_OUT_BOOLEAN(name, ui_name) \ + { type->register_output(ustring(#name), ustring(ui_name), SocketType::BOOLEAN); } +#define SOCKET_OUT_INT(name, ui_name) \ + { type->register_output(ustring(#name), ustring(ui_name), SocketType::INT); } +#define SOCKET_OUT_FLOAT(name, ui_name) \ + { type->register_output(ustring(#name), ustring(ui_name), SocketType::FLOAT); } +#define SOCKET_OUT_COLOR(name, ui_name) \ + { type->register_output(ustring(#name), ustring(ui_name), SocketType::COLOR); } +#define SOCKET_OUT_VECTOR(name, ui_name) \ + { type->register_output(ustring(#name), ustring(ui_name), SocketType::VECTOR); } +#define SOCKET_OUT_POINT(name, ui_name) \ + { type->register_output(ustring(#name), ustring(ui_name), SocketType::POINT); } +#define SOCKET_OUT_NORMAL(name, ui_name) \ + { type->register_output(ustring(#name), ustring(ui_name), SocketType::NORMAL); } +#define SOCKET_OUT_CLOSURE(name, ui_name) \ + { type->register_output(ustring(#name), ustring(ui_name), SocketType::CLOSURE); } +#define SOCKET_OUT_STRING(name, ui_name) \ + { type->register_output(ustring(#name), ustring(ui_name), SocketType::STRING); } +#define SOCKET_OUT_ENUM(name, ui_name) \ + { type->register_output(ustring(#name), ustring(ui_name), SocketType::ENUM); } + +CCL_NAMESPACE_END + diff --git a/intern/cycles/kernel/osl/CMakeLists.txt b/intern/cycles/kernel/osl/CMakeLists.txt index b10ec588757..9cf4f2d759a 100644 --- a/intern/cycles/kernel/osl/CMakeLists.txt +++ b/intern/cycles/kernel/osl/CMakeLists.txt @@ -3,6 +3,7 @@ set(INC . .. ../svm + ../../graph ../../render ../../util ../../device diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 21b0cb15a4f..8c69c589ebb 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -51,7 +51,7 @@ CCL_NAMESPACE_BEGIN */ #define NODE_FEATURE_ALL (NODE_FEATURE_VOLUME|NODE_FEATURE_HAIR|NODE_FEATURE_BUMP) -typedef enum NodeType { +typedef enum ShaderNodeType { NODE_END = 0, NODE_CLOSURE_BSDF, NODE_CLOSURE_EMISSION, @@ -127,7 +127,7 @@ typedef enum NodeType { NODE_HAIR_INFO, NODE_UVMAP, NODE_TEX_VOXEL, -} NodeType; +} ShaderNodeType; typedef enum NodeAttributeType { NODE_ATTR_FLOAT = 0, diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt index 38450a9f762..b14da3e63d0 100644 --- a/intern/cycles/render/CMakeLists.txt +++ b/intern/cycles/render/CMakeLists.txt @@ -2,6 +2,7 @@ set(INC . ../device + ../graph ../kernel ../kernel/svm ../kernel/osl diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index b14363d0767..110bbca8576 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -2476,8 +2476,8 @@ void GeometryNode::attributes(Shader *shader, AttributeRequestSet *attributes) void GeometryNode::compile(SVMCompiler& compiler) { ShaderOutput *out; - NodeType geom_node = NODE_GEOMETRY; - NodeType attr_node = NODE_ATTR; + ShaderNodeType geom_node = NODE_GEOMETRY; + ShaderNodeType attr_node = NODE_ATTR; if(bump == SHADER_BUMP_DX) { geom_node = NODE_GEOMETRY_BUMP_DX; @@ -2593,9 +2593,9 @@ void TextureCoordinateNode::attributes(Shader *shader, AttributeRequestSet *attr void TextureCoordinateNode::compile(SVMCompiler& compiler) { ShaderOutput *out; - NodeType texco_node = NODE_TEX_COORD; - NodeType attr_node = NODE_ATTR; - NodeType geom_node = NODE_GEOMETRY; + ShaderNodeType texco_node = NODE_TEX_COORD; + ShaderNodeType attr_node = NODE_ATTR; + ShaderNodeType geom_node = NODE_GEOMETRY; if(bump == SHADER_BUMP_DX) { texco_node = NODE_TEX_COORD_BUMP_DX; @@ -2726,8 +2726,8 @@ void UVMapNode::attributes(Shader *shader, AttributeRequestSet *attributes) void UVMapNode::compile(SVMCompiler& compiler) { ShaderOutput *out = output("UV"); - NodeType texco_node = NODE_TEX_COORD; - NodeType attr_node = NODE_ATTR; + ShaderNodeType texco_node = NODE_TEX_COORD; + ShaderNodeType attr_node = NODE_ATTR; int attr; if(bump == SHADER_BUMP_DX) { @@ -3757,7 +3757,7 @@ void AttributeNode::compile(SVMCompiler& compiler) ShaderOutput *color_out = output("Color"); ShaderOutput *vector_out = output("Vector"); ShaderOutput *fac_out = output("Fac"); - NodeType attr_node = NODE_ATTR; + ShaderNodeType attr_node = NODE_ATTR; AttributeStandard std = Attribute::name_standard(attribute.c_str()); int attr; diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index ab4fe4193db..4c97a5ad792 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -314,12 +314,12 @@ void SVMCompiler::add_node(int a, int b, int c, int d) svm_nodes.push_back(make_int4(a, b, c, d)); } -void SVMCompiler::add_node(NodeType type, int a, int b, int c) +void SVMCompiler::add_node(ShaderNodeType type, int a, int b, int c) { svm_nodes.push_back(make_int4(type, a, b, c)); } -void SVMCompiler::add_node(NodeType type, const float3& f) +void SVMCompiler::add_node(ShaderNodeType type, const float3& f) { svm_nodes.push_back(make_int4(type, __float_as_int(f.x), diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h index c85c866ddbd..dbf1b1de947 100644 --- a/intern/cycles/render/svm.h +++ b/intern/cycles/render/svm.h @@ -103,9 +103,9 @@ public: void stack_clear_offset(ShaderSocketType type, int offset); void stack_link(ShaderInput *input, ShaderOutput *output); - void add_node(NodeType type, int a = 0, int b = 0, int c = 0); + void add_node(ShaderNodeType type, int a = 0, int b = 0, int c = 0); void add_node(int a = 0, int b = 0, int c = 0, int d = 0); - void add_node(NodeType type, const float3& f); + void add_node(ShaderNodeType type, const float3& f); void add_node(const float4& f); uint attribute(ustring name); uint attribute(AttributeStandard std); diff --git a/intern/cycles/subd/CMakeLists.txt b/intern/cycles/subd/CMakeLists.txt index 1ccf80d9457..d1708868fd0 100644 --- a/intern/cycles/subd/CMakeLists.txt +++ b/intern/cycles/subd/CMakeLists.txt @@ -1,10 +1,11 @@ set(INC . - ../util + ../graph ../kernel ../kernel/svm ../render + ../util ) set(INC_SYS diff --git a/intern/cycles/util/util_vector.h b/intern/cycles/util/util_vector.h index 8f833af1844..6f8c3f6f3de 100644 --- a/intern/cycles/util/util_vector.h +++ b/intern/cycles/util/util_vector.h @@ -153,7 +153,7 @@ public: mem_free(data_, capacity_); } - bool operator==(const vector<T>& other) + bool operator==(const array<T>& other) const { if(datasize_ != other.datasize_) { return false; @@ -162,6 +162,21 @@ public: return memcmp(data_, other.data_, datasize_*sizeof(T)) == 0; } + void steal_data(array& from) + { + if(this != &from) { + clear(); + + data_ = from.data_; + datasize_ = from.datasize_; + capacity_ = from.capacity_; + + from.data_ = NULL; + from.datasize_ = 0; + from.capacity_ = 0; + } + } + T* resize(size_t newsize) { if(newsize == 0) { |