From 5a964664d6cf54deb3d5590f8581683f865af747 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dietrich?= Date: Sun, 2 May 2021 02:23:34 +0200 Subject: Cycles: add reference counting to Nodes This adds a reference count to Nodes which is incremented or decremented whenever they are added to or removed from a socket, which will help us track used Nodes throughout the scene graph generically without having to add an explicit count or flag on specific Node types. This is especially useful to track Nodes defined through Procedurals out of Cycles' control. This also modifies the order in which nodes are deleted to ensure that upon deletion, a Node does not attempt to decrement the reference count of another Node which was already freed or deleted. This is not currently used, but will be in the next commit. Reviewed By: brecht Differential Revision: https://developer.blender.org/D10965 --- intern/cycles/render/scene.cpp | 45 ++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 13 deletions(-) (limited to 'intern/cycles/render/scene.cpp') diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index 38e8d9145dc..dca545fa56c 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -143,21 +143,27 @@ void Scene::free_memory(bool final) delete bvh; bvh = NULL; - foreach (Shader *s, shaders) - delete s; - /* delete procedurals before other types as they may hold pointers to those types */ + /* The order of deletion is important to make sure data is freed based on possible dependencies + * as the Nodes' reference counts are decremented in the destructors: + * + * - Procedurals can create and hold pointers to any other types. + * - Objects can hold pointers to Geometries and ParticleSystems + * - Lights and Geometries can hold pointers to Shaders. + * + * Similarly, we first delete all nodes and their associated device data, and then the managers + * and their associated device data. + */ foreach (Procedural *p, procedurals) delete p; - foreach (Geometry *g, geometry) - delete g; foreach (Object *o, objects) delete o; - foreach (Light *l, lights) - delete l; + foreach (Geometry *g, geometry) + delete g; foreach (ParticleSystem *p, particle_systems) delete p; + foreach (Light *l, lights) + delete l; - shaders.clear(); geometry.clear(); objects.clear(); lights.clear(); @@ -169,7 +175,25 @@ void Scene::free_memory(bool final) film->device_free(device, &dscene, this); background->device_free(device, &dscene); integrator->device_free(device, &dscene, true); + } + + if (final) { + delete camera; + delete dicing_camera; + delete film; + delete background; + delete integrator; + } + + /* Delete Shaders after every other nodes to ensure that we do not try to decrement the reference + * count on some dangling pointer. */ + foreach (Shader *s, shaders) + delete s; + shaders.clear(); + + /* Now that all nodes have been deleted, we can safely delete managers and device data. */ + if (device) { object_manager->device_free(device, &dscene, true); geometry_manager->device_free(device, &dscene, true); shader_manager->device_free(device, &dscene, this); @@ -189,11 +213,6 @@ void Scene::free_memory(bool final) if (final) { delete lookup_tables; - delete camera; - delete dicing_camera; - delete film; - delete background; - delete integrator; delete object_manager; delete geometry_manager; delete shader_manager; -- cgit v1.2.3