Code refactor: add generic Cycles node infrastructure.

Differential Revision: https://developer.blender.org/D2016
This commit is contained in:
Brecht Van Lommel
2016-05-07 19:47:37 +02:00
parent 841d008b98
commit ec51175f1f
20 changed files with 1000 additions and 18 deletions

View File

@@ -487,6 +487,7 @@ function(SETUP_BLENDER_SORTED_LIBS)
if(WITH_CYCLES)
list(APPEND BLENDER_LINK_LIBS
cycles_render
cycles_graph
cycles_bvh
cycles_device
cycles_kernel
@@ -600,6 +601,7 @@ function(SETUP_BLENDER_SORTED_LIBS)
bf_intern_dualcon
bf_intern_cycles
cycles_render
cycles_graph
cycles_bvh
cycles_device
cycles_kernel

View File

@@ -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)

View File

@@ -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}

View File

@@ -1,5 +1,6 @@
set(INC
../graph
../render
../device
../kernel

View File

@@ -1,6 +1,7 @@
set(INC
.
../graph
../kernel
../kernel/svm
../render

View File

@@ -1,6 +1,7 @@
set(INC
.
../graph
../kernel
../kernel/svm
../kernel/osl

View File

@@ -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})

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -3,6 +3,7 @@ set(INC
.
..
../svm
../../graph
../../render
../../util
../../device

View File

@@ -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,

View File

@@ -2,6 +2,7 @@
set(INC
.
../device
../graph
../kernel
../kernel/svm
../kernel/osl

View File

@@ -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;

View File

@@ -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),

View File

@@ -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);

View File

@@ -1,10 +1,11 @@
set(INC
.
../util
../graph
../kernel
../kernel/svm
../render
../util
)
set(INC_SYS

View File

@@ -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) {