diff options
Diffstat (limited to 'intern/cycles/render')
-rw-r--r-- | intern/cycles/render/graph.cpp | 32 | ||||
-rw-r--r-- | intern/cycles/render/graph.h | 30 | ||||
-rw-r--r-- | intern/cycles/render/nodes.cpp | 49 | ||||
-rw-r--r-- | intern/cycles/render/nodes.h | 12 | ||||
-rw-r--r-- | intern/cycles/render/osl.cpp | 5 | ||||
-rw-r--r-- | intern/cycles/render/osl.h | 3 | ||||
-rw-r--r-- | intern/cycles/render/particles.cpp | 8 | ||||
-rw-r--r-- | intern/cycles/render/particles.h | 6 | ||||
-rw-r--r-- | intern/cycles/render/scene.cpp | 134 | ||||
-rw-r--r-- | intern/cycles/render/scene.h | 72 | ||||
-rw-r--r-- | intern/cycles/render/shader.cpp | 21 |
11 files changed, 297 insertions, 75 deletions
diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index 1b138455515..684fe6a82c4 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -221,7 +221,7 @@ ShaderGraph::ShaderGraph() finalized = false; simplified = false; num_node_ids = 0; - add(new OutputNode()); + add(create_node<OutputNode>()); } ShaderGraph::~ShaderGraph() @@ -272,7 +272,7 @@ void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to) ShaderInput *convert_in; if (to->type() == SocketType::CLOSURE) { - EmissionNode *emission = new EmissionNode(); + EmissionNode *emission = create_node<EmissionNode>(); emission->color = make_float3(1.0f, 1.0f, 1.0f); emission->strength = 1.0f; convert = add(emission); @@ -285,7 +285,7 @@ void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to) } } else { - convert = add(new ConvertNode(from->type(), to->type(), true)); + convert = add(create_node<ConvertNode>(from->type(), to->type(), true)); convert_in = convert->inputs[0]; } @@ -416,7 +416,7 @@ void ShaderGraph::find_dependencies(ShaderNodeSet &dependencies, ShaderInput *in void ShaderGraph::clear_nodes() { foreach (ShaderNode *node, nodes) { - delete node; + delete_node(node); } nodes.clear(); } @@ -428,7 +428,7 @@ void ShaderGraph::copy_nodes(ShaderNodeSet &nodes, ShaderNodeMap &nnodemap) /* copy nodes */ foreach (ShaderNode *node, nodes) { - ShaderNode *nnode = node->clone(); + ShaderNode *nnode = node->clone(this); nnodemap[node] = nnode; /* create new inputs and outputs to recreate links and ensure @@ -523,7 +523,7 @@ void ShaderGraph::remove_proxy_nodes() if (!removed[node->id]) newnodes.push_back(node); else - delete node; + delete_node(node); } nodes = newnodes; @@ -821,7 +821,7 @@ void ShaderGraph::clean(Scene *scene) if (visited[node->id]) newnodes.push_back(node); else - delete node; + delete_node(node); } nodes = newnodes; @@ -848,43 +848,43 @@ void ShaderGraph::default_inputs(bool do_osl) if (!input->link && (!(input->flags() & SocketType::OSL_INTERNAL) || do_osl)) { if (input->flags() & SocketType::LINK_TEXTURE_GENERATED) { if (!texco) - texco = new TextureCoordinateNode(); + texco = create_node<TextureCoordinateNode>(); connect(texco->output("Generated"), input); } if (input->flags() & SocketType::LINK_TEXTURE_NORMAL) { if (!texco) - texco = new TextureCoordinateNode(); + texco = create_node<TextureCoordinateNode>(); connect(texco->output("Normal"), input); } else if (input->flags() & SocketType::LINK_TEXTURE_UV) { if (!texco) - texco = new TextureCoordinateNode(); + texco = create_node<TextureCoordinateNode>(); connect(texco->output("UV"), input); } else if (input->flags() & SocketType::LINK_INCOMING) { if (!geom) - geom = new GeometryNode(); + geom = create_node<GeometryNode>(); connect(geom->output("Incoming"), input); } else if (input->flags() & SocketType::LINK_NORMAL) { if (!geom) - geom = new GeometryNode(); + geom = create_node<GeometryNode>(); connect(geom->output("Normal"), input); } else if (input->flags() & SocketType::LINK_POSITION) { if (!geom) - geom = new GeometryNode(); + geom = create_node<GeometryNode>(); connect(geom->output("Position"), input); } else if (input->flags() & SocketType::LINK_TANGENT) { if (!geom) - geom = new GeometryNode(); + geom = create_node<GeometryNode>(); connect(geom->output("Tangent"), input); } @@ -1064,7 +1064,7 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight if (fin) { /* mix closure: add node to mix closure weights */ - MixClosureWeightNode *mix_node = new MixClosureWeightNode(); + MixClosureWeightNode *mix_node = create_node<MixClosureWeightNode>(); add(mix_node); ShaderInput *fac_in = mix_node->input("Fac"); ShaderInput *weight_in = mix_node->input("Weight"); @@ -1101,7 +1101,7 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight /* already has a weight connected to it? add weights */ float weight_value = node->get_float(weight_in->socket_type); if (weight_in->link || weight_value != 0.0f) { - MathNode *math_node = new MathNode(); + MathNode *math_node = create_node<MathNode>(); add(math_node); if (weight_in->link) diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h index febd7a76f03..f6ee708b3f8 100644 --- a/intern/cycles/render/graph.h +++ b/intern/cycles/render/graph.h @@ -159,7 +159,7 @@ class ShaderNode : public Node { ShaderInput *input(ustring name); ShaderOutput *output(ustring name); - virtual ShaderNode *clone() const = 0; + virtual ShaderNode *clone(ShaderGraph *graph) const = 0; virtual void attributes(Shader *shader, AttributeRequestSet *attributes); virtual void compile(SVMCompiler &compiler) = 0; virtual void compile(OSLCompiler &compiler) = 0; @@ -275,9 +275,9 @@ class ShaderNode : public Node { #define SHADER_NODE_CLASS(type) \ NODE_DECLARE \ type(); \ - virtual ShaderNode *clone() const \ + virtual ShaderNode *clone(ShaderGraph *graph) const \ { \ - return new type(*this); \ + return graph->create_node<type>(*this); \ } \ virtual void compile(SVMCompiler &compiler); \ virtual void compile(OSLCompiler &compiler); @@ -289,9 +289,9 @@ class ShaderNode : public Node { virtual void compile(OSLCompiler &compiler); #define SHADER_NODE_BASE_CLASS(type) \ - virtual ShaderNode *clone() const \ + virtual ShaderNode *clone(ShaderGraph *graph) const \ { \ - return new type(*this); \ + return graph->create_node<type>(*this); \ } \ virtual void compile(SVMCompiler &compiler); \ virtual void compile(OSLCompiler &compiler); @@ -312,7 +312,7 @@ typedef map<ShaderNode *, ShaderNode *, ShaderNodeIDComparator> ShaderNodeMap; * Shader graph of nodes. Also does graph manipulations for default inputs, * bump mapping from displacement, and possibly other things in the future. */ -class ShaderGraph { +class ShaderGraph : public NodeOwner { public: list<ShaderNode *> nodes; size_t num_node_ids; @@ -345,6 +345,24 @@ class ShaderGraph { void dump_graph(const char *filename); + /* This function is used to create a node of a specified type instead of + * calling 'new', and sets the graph as the owner of the node. + */ + template<typename T, typename... Args> T *create_node(Args &&... args) + { + T *node = new T(args...); + node->set_owner(this); + return node; + } + + /* This function is used to delete a node created and owned by the graph. + */ + template<typename T> void delete_node(T *node) + { + assert(node->get_owner() == this); + delete node; + } + protected: typedef pair<ShaderNode *const, ShaderNode *> NodePair; diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index f62d64a7eb3..de32ce53ad7 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -262,9 +262,9 @@ ImageTextureNode::ImageTextureNode() : ImageSlotTextureNode(node_type) tiles.push_back(1001); } -ShaderNode *ImageTextureNode::clone() const +ShaderNode *ImageTextureNode::clone(ShaderGraph *graph) const { - ImageTextureNode *node = new ImageTextureNode(*this); + ImageTextureNode *node = graph->create_node<ImageTextureNode>(*this); node->handle = handle; return node; } @@ -525,9 +525,9 @@ EnvironmentTextureNode::EnvironmentTextureNode() : ImageSlotTextureNode(node_typ animated = false; } -ShaderNode *EnvironmentTextureNode::clone() const +ShaderNode *EnvironmentTextureNode::clone(ShaderGraph *graph) const { - EnvironmentTextureNode *node = new EnvironmentTextureNode(*this); + EnvironmentTextureNode *node = graph->create_node<EnvironmentTextureNode>(*this); node->handle = handle; return node; } @@ -1234,9 +1234,9 @@ IESLightNode::IESLightNode() : TextureNode(node_type) slot = -1; } -ShaderNode *IESLightNode::clone() const +ShaderNode *IESLightNode::clone(ShaderGraph *graph) const { - IESLightNode *node = new IESLightNode(*this); + IESLightNode *node = graph->create_node<IESLightNode>(*this); node->light_manager = NULL; node->slot = -1; @@ -1782,12 +1782,12 @@ PointDensityTextureNode::~PointDensityTextureNode() { } -ShaderNode *PointDensityTextureNode::clone() const +ShaderNode *PointDensityTextureNode::clone(ShaderGraph *graph) const { /* Increase image user count for new node. We need to ensure to not call * add_image again, to work around access of freed data on the Blender * side. A better solution should be found to avoid this. */ - PointDensityTextureNode *node = new PointDensityTextureNode(*this); + PointDensityTextureNode *node = graph->create_node<PointDensityTextureNode>(*this); node->handle = handle; /* TODO: not needed? */ return node; } @@ -2783,8 +2783,8 @@ void PrincipledBsdfNode::expand(ShaderGraph *graph) ShaderInput *emission_in = input("Emission"); if (emission_in->link || emission != make_float3(0.0f, 0.0f, 0.0f)) { /* Create add closure and emission. */ - AddClosureNode *add = new AddClosureNode(); - EmissionNode *emission_node = new EmissionNode(); + AddClosureNode *add = graph->create_node<AddClosureNode>(); + EmissionNode *emission_node = graph->create_node<EmissionNode>(); ShaderOutput *new_out = add->output("Closure"); graph->add(add); @@ -2802,8 +2802,8 @@ void PrincipledBsdfNode::expand(ShaderGraph *graph) ShaderInput *alpha_in = input("Alpha"); if (alpha_in->link || alpha != 1.0f) { /* Create mix and transparent BSDF for alpha transparency. */ - MixClosureNode *mix = new MixClosureNode(); - TransparentBsdfNode *transparent = new TransparentBsdfNode(); + MixClosureNode *mix = graph->create_node<MixClosureNode>(); + TransparentBsdfNode *transparent = graph->create_node<TransparentBsdfNode>(); graph->add(mix); graph->add(transparent); @@ -4475,7 +4475,7 @@ void VolumeInfoNode::expand(ShaderGraph *graph) { ShaderOutput *color_out = output("Color"); if (!color_out->links.empty()) { - AttributeNode *attr = new AttributeNode(); + AttributeNode *attr = graph->create_node<AttributeNode>(); attr->attribute = "color"; graph->add(attr); graph->relink(color_out, attr->output("Color")); @@ -4483,7 +4483,7 @@ void VolumeInfoNode::expand(ShaderGraph *graph) ShaderOutput *density_out = output("Density"); if (!density_out->links.empty()) { - AttributeNode *attr = new AttributeNode(); + AttributeNode *attr = graph->create_node<AttributeNode>(); attr->attribute = "density"; graph->add(attr); graph->relink(density_out, attr->output("Fac")); @@ -4491,7 +4491,7 @@ void VolumeInfoNode::expand(ShaderGraph *graph) ShaderOutput *flame_out = output("Flame"); if (!flame_out->links.empty()) { - AttributeNode *attr = new AttributeNode(); + AttributeNode *attr = graph->create_node<AttributeNode>(); attr->attribute = "flame"; graph->add(attr); graph->relink(flame_out, attr->output("Fac")); @@ -4499,7 +4499,7 @@ void VolumeInfoNode::expand(ShaderGraph *graph) ShaderOutput *temperature_out = output("Temperature"); if (!temperature_out->links.empty()) { - AttributeNode *attr = new AttributeNode(); + AttributeNode *attr = graph->create_node<AttributeNode>(); attr->attribute = "temperature"; graph->add(attr); graph->relink(temperature_out, attr->output("Fac")); @@ -5768,7 +5768,7 @@ void MapRangeNode::expand(ShaderGraph *graph) if (clamp) { ShaderOutput *result_out = output("Result"); if (!result_out->links.empty()) { - ClampNode *clamp_node = new ClampNode(); + ClampNode *clamp_node = graph->create_node<ClampNode>(); clamp_node->type = NODE_CLAMP_RANGE; graph->add(clamp_node); graph->relink(result_out, clamp_node->output("Result")); @@ -6009,7 +6009,7 @@ void MathNode::expand(ShaderGraph *graph) if (use_clamp) { ShaderOutput *result_out = output("Value"); if (!result_out->links.empty()) { - ClampNode *clamp_node = new ClampNode(); + ClampNode *clamp_node = graph->create_node<ClampNode>(); clamp_node->type = NODE_CLAMP_MINMAX; clamp_node->min = 0.0f; clamp_node->max = 1.0f; @@ -6337,7 +6337,7 @@ void BumpNode::constant_fold(const ConstantFolder &folder) if (height_in->link == NULL) { if (normal_in->link == NULL) { - GeometryNode *geom = new GeometryNode(); + GeometryNode *geom = folder.graph->create_node<GeometryNode>(); folder.graph->add(geom); folder.bypass(geom->output("Normal")); } @@ -6620,12 +6620,12 @@ OSLNode::~OSLNode() delete type; } -ShaderNode *OSLNode::clone() const +ShaderNode *OSLNode::clone(ShaderGraph *graph) const { - return OSLNode::create(this->inputs.size(), this); + return OSLNode::create(graph, this->inputs.size(), this); } -OSLNode *OSLNode::create(size_t num_inputs, const OSLNode *from) +OSLNode *OSLNode::create(ShaderGraph *graph, size_t num_inputs, const OSLNode *from) { /* allocate space for the node itself and parameters, aligned to 16 bytes * assuming that's the most parameter types need */ @@ -6636,7 +6636,9 @@ OSLNode *OSLNode::create(size_t num_inputs, const OSLNode *from) memset(node_memory, 0, node_size + inputs_size); if (!from) { - return new (node_memory) OSLNode(); + OSLNode *node = new (node_memory) OSLNode(); + node->set_owner(graph); + return node; } else { /* copy input default values and node type for cloning */ @@ -6644,6 +6646,7 @@ OSLNode *OSLNode::create(size_t num_inputs, const OSLNode *from) OSLNode *node = new (node_memory) OSLNode(*from); node->type = new NodeType(*(from->type)); + node->set_owner(from->owner); return node; } } diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index c21bcacb3ce..59e00231c2c 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -92,7 +92,7 @@ class ImageSlotTextureNode : public TextureNode { class ImageTextureNode : public ImageSlotTextureNode { public: SHADER_NODE_NO_CLONE_CLASS(ImageTextureNode) - ShaderNode *clone() const; + ShaderNode *clone(ShaderGraph *graph) const; void attributes(Shader *shader, AttributeRequestSet *attributes); bool has_attribute_dependency() { @@ -126,7 +126,7 @@ class ImageTextureNode : public ImageSlotTextureNode { class EnvironmentTextureNode : public ImageSlotTextureNode { public: SHADER_NODE_NO_CLONE_CLASS(EnvironmentTextureNode) - ShaderNode *clone() const; + ShaderNode *clone(ShaderGraph *graph) const; void attributes(Shader *shader, AttributeRequestSet *attributes); bool has_attribute_dependency() { @@ -364,7 +364,7 @@ class PointDensityTextureNode : public ShaderNode { } ~PointDensityTextureNode(); - ShaderNode *clone() const; + ShaderNode *clone(ShaderGraph *graph) const; void attributes(Shader *shader, AttributeRequestSet *attributes); bool has_attribute_dependency() { @@ -400,7 +400,7 @@ class IESLightNode : public TextureNode { SHADER_NODE_NO_CLONE_CLASS(IESLightNode) ~IESLightNode(); - ShaderNode *clone() const; + ShaderNode *clone(ShaderGraph *graph) const; virtual int get_group() { return NODE_GROUP_LEVEL_2; @@ -1501,10 +1501,10 @@ class SetNormalNode : public ShaderNode { class OSLNode : public ShaderNode { public: - static OSLNode *create(size_t num_inputs, const OSLNode *from = NULL); + static OSLNode *create(ShaderGraph *graph, size_t num_inputs, const OSLNode *from = NULL); ~OSLNode(); - ShaderNode *clone() const; + ShaderNode *clone(ShaderGraph *graph) const; char *input_default_value(); void add_input(ustring name, SocketType::Type type); diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index 5c62ae73e47..1c54dc2d531 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -439,7 +439,8 @@ const char *OSLShaderManager::shader_load_bytecode(const string &hash, const str /* This is a static function to avoid RTTI link errors with only this * file being compiled without RTTI to match OSL and LLVM libraries. */ -OSLNode *OSLShaderManager::osl_node(ShaderManager *manager, +OSLNode *OSLShaderManager::osl_node(ShaderGraph *graph, + ShaderManager *manager, const std::string &filepath, const std::string &bytecode_hash, const std::string &bytecode) @@ -482,7 +483,7 @@ OSLNode *OSLShaderManager::osl_node(ShaderManager *manager, } /* create node */ - OSLNode *node = OSLNode::create(num_inputs); + OSLNode *node = OSLNode::create(graph, num_inputs); /* add new sockets from parameters */ set<void *> used_sockets; diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h index 4dd9f6630f2..ea2d0ca492c 100644 --- a/intern/cycles/render/osl.h +++ b/intern/cycles/render/osl.h @@ -93,7 +93,8 @@ class OSLShaderManager : public ShaderManager { OSLShaderInfo *shader_loaded_info(const string &hash); /* create OSL node using OSLQuery */ - static OSLNode *osl_node(ShaderManager *manager, + static OSLNode *osl_node(ShaderGraph *graph, + ShaderManager *manager, const std::string &filepath, const std::string &bytecode_hash = "", const std::string &bytecode = ""); diff --git a/intern/cycles/render/particles.cpp b/intern/cycles/render/particles.cpp index ec9276eff86..494f5929df2 100644 --- a/intern/cycles/render/particles.cpp +++ b/intern/cycles/render/particles.cpp @@ -29,7 +29,13 @@ CCL_NAMESPACE_BEGIN /* Particle System */ -ParticleSystem::ParticleSystem() +NODE_DEFINE(ParticleSystem) +{ + NodeType *type = NodeType::add("particle_system", create); + return type; +} + +ParticleSystem::ParticleSystem() : Node(node_type) { } diff --git a/intern/cycles/render/particles.h b/intern/cycles/render/particles.h index 65663c31c37..0b0408184fe 100644 --- a/intern/cycles/render/particles.h +++ b/intern/cycles/render/particles.h @@ -20,6 +20,8 @@ #include "util/util_array.h" #include "util/util_types.h" +#include "graph/node.h" + CCL_NAMESPACE_BEGIN class Device; @@ -40,8 +42,10 @@ struct Particle { float3 angular_velocity; }; -class ParticleSystem { +class ParticleSystem : public Node { public: + NODE_DECLARE + ParticleSystem(); ~ParticleSystem(); diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index a8a5b50e6a2..8f863b5d15f 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -33,6 +33,7 @@ #include "render/shader.h" #include "render/svm.h" #include "render/tables.h" +#include "render/volume.h" #include "util/util_foreach.h" #include "util/util_guarded_allocator.h" @@ -98,15 +99,15 @@ Scene::Scene(const SceneParams ¶ms_, Device *device) { memset((void *)&dscene.data, 0, sizeof(dscene.data)); - camera = new Camera(); - dicing_camera = new Camera(); + camera = create_node<Camera>(); + dicing_camera = create_node<Camera>(); lookup_tables = new LookupTables(); - film = new Film(); - background = new Background(); + film = create_node<Film>(); + background = create_node<Background>(); light_manager = new LightManager(); geometry_manager = new GeometryManager(); object_manager = new ObjectManager(); - integrator = new Integrator(); + integrator = create_node<Integrator>(); image_manager = new ImageManager(device->info); particle_system_manager = new ParticleSystemManager(); bake_manager = new BakeManager(); @@ -560,4 +561,127 @@ int Scene::get_max_closure_count() return max_closure_global; } +template<> Light *Scene::create_node<Light>() +{ + Light *node = new Light(); + node->set_owner(this); + lights.push_back(node); + light_manager->tag_update(this); + return node; +} + +template<> Mesh *Scene::create_node<Mesh>() +{ + Mesh *node = new Mesh(); + node->set_owner(this); + geometry.push_back(node); + geometry_manager->tag_update(this); + return node; +} + +template<> Hair *Scene::create_node<Hair>() +{ + Hair *node = new Hair(); + node->set_owner(this); + geometry.push_back(node); + geometry_manager->tag_update(this); + return node; +} + +template<> Volume *Scene::create_node<Volume>() +{ + Volume *node = new Volume(); + node->set_owner(this); + geometry.push_back(node); + geometry_manager->tag_update(this); + return node; +} + +template<> Object *Scene::create_node<Object>() +{ + Object *node = new Object(); + node->set_owner(this); + objects.push_back(node); + object_manager->tag_update(this); + return node; +} + +template<> ParticleSystem *Scene::create_node<ParticleSystem>() +{ + ParticleSystem *node = new ParticleSystem(); + node->set_owner(this); + particle_systems.push_back(node); + particle_system_manager->tag_update(this); + return node; +} + +template<> Shader *Scene::create_node<Shader>() +{ + Shader *node = new Shader(); + node->set_owner(this); + shaders.push_back(node); + shader_manager->need_update = true; + return node; +} + +template<typename T> void delete_node_from_array(vector<T> &nodes, T node) +{ + for (size_t i = 0; i < nodes.size(); ++i) { + if (nodes[i] == node) { + std::swap(nodes[i], nodes[nodes.size() - 1]); + break; + } + } + + nodes.resize(nodes.size() - 1); + delete node; +} + +template<> void Scene::delete_node_impl(Light *node) +{ + delete_node_from_array(lights, node); + light_manager->tag_update(this); +} + +template<> void Scene::delete_node_impl(Mesh *node) +{ + delete_node_from_array(geometry, static_cast<Geometry *>(node)); + geometry_manager->tag_update(this); +} + +template<> void Scene::delete_node_impl(Hair *node) +{ + delete_node_from_array(geometry, static_cast<Geometry *>(node)); + geometry_manager->tag_update(this); +} + +template<> void Scene::delete_node_impl(Volume *node) +{ + delete_node_from_array(geometry, static_cast<Geometry *>(node)); + geometry_manager->tag_update(this); +} + +template<> void Scene::delete_node_impl(Geometry *node) +{ + delete_node_from_array(geometry, node); + geometry_manager->tag_update(this); +} + +template<> void Scene::delete_node_impl(Object *node) +{ + delete_node_from_array(objects, node); + object_manager->tag_update(this); +} + +template<> void Scene::delete_node_impl(ParticleSystem *node) +{ + delete_node_from_array(particle_systems, node); + particle_system_manager->tag_update(this); +} + +template<> void Scene::delete_node_impl(Shader * /*node*/) +{ + /* don't delete unused shaders, not supported */ +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index 25b6b2ef0e4..0e32a70952b 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -59,6 +59,7 @@ class Progress; class BakeManager; class BakeData; class RenderStats; +class Volume; /* Scene Device Data */ @@ -212,7 +213,7 @@ class SceneParams { /* Scene */ -class Scene { +class Scene : public NodeOwner { public: /* Optional name. Is used for logging and reporting. */ string name; @@ -281,6 +282,40 @@ class Scene { bool update(Progress &progress, bool &kernel_switch_needed); + /* This function is used to create a node of a specified type instead of + * calling 'new', and sets the scene as the owner of the node. + * The function has overloads that will also add the created node to the right + * node array (e.g. Scene::geometry for Geometry nodes) and tag the appropriate + * manager for an update. + */ + template<typename T, typename... Args> T *create_node(Args &&... args) + { + T *node = new T(args...); + node->set_owner(this); + return node; + } + + /* This function is used to delete a node from the scene instead of calling 'delete' + * and manually removing the node from the data array. It also tags the + * appropriate manager for an update, if any, and checks that the scene is indeed + * the owner of the node. Calling this function on a node not owned by the scene + * will likely cause a crash which we want in order to detect such cases. + */ + template<typename T> void delete_node(T *node) + { + assert(node->get_owner() == this); + delete_node_impl(node); + } + + /* Same as above, but specify the actual owner. + */ + template<typename T> void delete_node(T *node, const NodeOwner *owner) + { + assert(node->get_owner() == owner); + delete_node_impl(node); + (void)owner; + } + protected: /* Check if some heavy data worth logging was updated. * Mainly used to suppress extra annoying logging. @@ -303,8 +338,43 @@ class Scene { /* Get maximum number of closures to be used in kernel. */ int get_max_closure_count(); + + template<typename T> void delete_node_impl(T *node) + { + delete node; + } }; +template<> Light *Scene::create_node<Light>(); + +template<> Mesh *Scene::create_node<Mesh>(); + +template<> Object *Scene::create_node<Object>(); + +template<> Hair *Scene::create_node<Hair>(); + +template<> Volume *Scene::create_node<Volume>(); + +template<> ParticleSystem *Scene::create_node<ParticleSystem>(); + +template<> Shader *Scene::create_node<Shader>(); + +template<> void Scene::delete_node_impl(Light *node); + +template<> void Scene::delete_node_impl(Mesh *node); + +template<> void Scene::delete_node_impl(Volume *node); + +template<> void Scene::delete_node_impl(Hair *node); + +template<> void Scene::delete_node_impl(Geometry *node); + +template<> void Scene::delete_node_impl(Object *node); + +template<> void Scene::delete_node_impl(ParticleSystem *node); + +template<> void Scene::delete_node_impl(Shader *node); + CCL_NAMESPACE_END #endif /* __SCENE_H__ */ diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index 1120d909e98..135d0dc962b 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -624,16 +624,15 @@ void ShaderManager::add_default(Scene *scene) { ShaderGraph *graph = new ShaderGraph(); - DiffuseBsdfNode *diffuse = new DiffuseBsdfNode(); + DiffuseBsdfNode *diffuse = graph->create_node<DiffuseBsdfNode>(); diffuse->color = make_float3(0.8f, 0.8f, 0.8f); graph->add(diffuse); graph->connect(diffuse->output("BSDF"), graph->output()->input("Surface")); - Shader *shader = new Shader(); + Shader *shader = scene->create_node<Shader>(); shader->name = "default_surface"; shader->set_graph(graph); - scene->shaders.push_back(shader); scene->default_surface = shader; shader->tag_update(scene); } @@ -642,15 +641,14 @@ void ShaderManager::add_default(Scene *scene) { ShaderGraph *graph = new ShaderGraph(); - PrincipledVolumeNode *principled = new PrincipledVolumeNode(); + PrincipledVolumeNode *principled = graph->create_node<PrincipledVolumeNode>(); graph->add(principled); graph->connect(principled->output("Volume"), graph->output()->input("Volume")); - Shader *shader = new Shader(); + Shader *shader = scene->create_node<Shader>(); shader->name = "default_volume"; shader->set_graph(graph); - scene->shaders.push_back(shader); scene->default_volume = shader; shader->tag_update(scene); } @@ -659,17 +657,16 @@ void ShaderManager::add_default(Scene *scene) { ShaderGraph *graph = new ShaderGraph(); - EmissionNode *emission = new EmissionNode(); + EmissionNode *emission = graph->create_node<EmissionNode>(); emission->color = make_float3(0.8f, 0.8f, 0.8f); emission->strength = 0.0f; graph->add(emission); graph->connect(emission->output("Emission"), graph->output()->input("Surface")); - Shader *shader = new Shader(); + Shader *shader = scene->create_node<Shader>(); shader->name = "default_light"; shader->set_graph(graph); - scene->shaders.push_back(shader); scene->default_light = shader; shader->tag_update(scene); } @@ -678,10 +675,9 @@ void ShaderManager::add_default(Scene *scene) { ShaderGraph *graph = new ShaderGraph(); - Shader *shader = new Shader(); + Shader *shader = scene->create_node<Shader>(); shader->name = "default_background"; shader->set_graph(graph); - scene->shaders.push_back(shader); scene->default_background = shader; shader->tag_update(scene); } @@ -690,10 +686,9 @@ void ShaderManager::add_default(Scene *scene) { ShaderGraph *graph = new ShaderGraph(); - Shader *shader = new Shader(); + Shader *shader = scene->create_node<Shader>(); shader->name = "default_empty"; shader->set_graph(graph); - scene->shaders.push_back(shader); scene->default_empty = shader; shader->tag_update(scene); } |