Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/render/scene.cpp')
-rw-r--r--intern/cycles/render/scene.cpp66
1 files changed, 40 insertions, 26 deletions
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index d3dfe1c5be6..c4e7d2c79d6 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);
@@ -179,7 +203,7 @@ void Scene::free_memory(bool final)
bake_manager->device_free(device, &dscene);
- if (!params.persistent_data || final)
+ if (final)
image_manager->device_free(device);
else
image_manager->device_free_builtin(device);
@@ -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;
@@ -504,9 +523,6 @@ bool Scene::update(Progress &progress, bool &kernel_switch_needed)
{
/* update scene */
if (need_update()) {
- /* Updated used shader tag so we know which features are need for the kernel. */
- shader_manager->update_shaders_used(this);
-
/* Update max_closures. */
KernelIntegrator *kintegrator = &dscene.data.integrator;
if (params.background) {
@@ -526,9 +542,6 @@ bool Scene::update(Progress &progress, bool &kernel_switch_needed)
DeviceKernelStatus kernel_switch_status = device->get_active_kernel_switch_state();
kernel_switch_needed = kernel_switch_status == DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE ||
kernel_switch_status == DEVICE_KERNEL_FEATURE_KERNEL_INVALID;
- if (kernel_switch_status == DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL) {
- progress.set_kernel_status("Compiling render kernels");
- }
if (new_kernels_needed || kernel_switch_needed) {
progress.set_kernel_status("Compiling render kernels");
device->wait_for_availability(loaded_kernel_features);
@@ -566,9 +579,6 @@ bool Scene::load_kernels(Progress &progress, bool lock_scene)
return false;
}
- progress.add_skip_time(timer, false);
- VLOG(1) << "Total time spent loading kernels: " << time_dt() - timer.get_start();
-
kernels_loaded = true;
loaded_kernel_features = requested_features;
return true;
@@ -587,7 +597,7 @@ int Scene::get_max_closure_count()
int max_closures = 0;
for (int i = 0; i < shaders.size(); i++) {
Shader *shader = shaders[i];
- if (shader->used) {
+ if (shader->reference_count()) {
int num_closures = shader->graph->get_num_closures();
max_closures = max(max_closures, num_closures);
}
@@ -748,9 +758,10 @@ template<> void Scene::delete_node_impl(ParticleSystem *node)
particle_system_manager->tag_update(this);
}
-template<> void Scene::delete_node_impl(Shader * /*node*/)
+template<> void Scene::delete_node_impl(Shader *shader)
{
/* don't delete unused shaders, not supported */
+ shader->clear_reference_count();
}
template<> void Scene::delete_node_impl(Procedural *node)
@@ -817,9 +828,12 @@ template<> void Scene::delete_nodes(const set<ParticleSystem *> &nodes, const No
particle_system_manager->tag_update(this);
}
-template<> void Scene::delete_nodes(const set<Shader *> & /*nodes*/, const NodeOwner * /*owner*/)
+template<> void Scene::delete_nodes(const set<Shader *> &nodes, const NodeOwner * /*owner*/)
{
/* don't delete unused shaders, not supported */
+ for (Shader *shader : nodes) {
+ shader->clear_reference_count();
+ }
}
template<> void Scene::delete_nodes(const set<Procedural *> &nodes, const NodeOwner *owner)