Fix #33405: preview render getting stuck in a particular .blend file, ObjectKey
[blender.git] / intern / cycles / render / scene.cpp
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18
19 #include <stdlib.h>
20
21 #include "background.h"
22 #include "camera.h"
23 #include "device.h"
24 #include "film.h"
25 #include "filter.h"
26 #include "integrator.h"
27 #include "light.h"
28 #include "shader.h"
29 #include "mesh.h"
30 #include "object.h"
31 #include "particles.h"
32 #include "scene.h"
33 #include "svm.h"
34 #include "osl.h"
35
36 #include "util_foreach.h"
37 #include "util_progress.h"
38
39 CCL_NAMESPACE_BEGIN
40
41 Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_)
42 : params(params_)
43 {
44         device = NULL;
45         memset(&dscene.data, 0, sizeof(dscene.data));
46
47         camera = new Camera();
48         filter = new Filter();
49         film = new Film();
50         background = new Background();
51         light_manager = new LightManager();
52         mesh_manager = new MeshManager();
53         object_manager = new ObjectManager();
54         integrator = new Integrator();
55         image_manager = new ImageManager();
56         particle_system_manager = new ParticleSystemManager();
57
58         /* OSL only works on the CPU */
59         if(device_info_.type == DEVICE_CPU)
60                 shader_manager = ShaderManager::create(this, params.shadingsystem);
61         else
62                 shader_manager = ShaderManager::create(this, SceneParams::SVM);
63
64         if (device_info_.type == DEVICE_CPU)
65                 image_manager->set_extended_image_limits();
66 }
67
68 Scene::~Scene()
69 {
70         free_memory(true);
71 }
72
73 void Scene::free_memory(bool final)
74 {
75         foreach(Shader *s, shaders)
76                 delete s;
77         foreach(Mesh *m, meshes)
78                 delete m;
79         foreach(Object *o, objects)
80                 delete o;
81         foreach(Light *l, lights)
82                 delete l;
83         foreach(ParticleSystem *p, particle_systems)
84                 delete p;
85
86         if(device) {
87                 camera->device_free(device, &dscene);
88                 filter->device_free(device, &dscene);
89                 film->device_free(device, &dscene);
90                 background->device_free(device, &dscene);
91                 integrator->device_free(device, &dscene);
92
93                 object_manager->device_free(device, &dscene);
94                 mesh_manager->device_free(device, &dscene);
95                 shader_manager->device_free(device, &dscene);
96                 light_manager->device_free(device, &dscene);
97
98                 particle_system_manager->device_free(device, &dscene);
99
100                 if(!params.persistent_images || final)
101                         image_manager->device_free(device, &dscene);
102         }
103
104         if(final) {
105                 delete filter;
106                 delete camera;
107                 delete film;
108                 delete background;
109                 delete integrator;
110                 delete object_manager;
111                 delete mesh_manager;
112                 delete shader_manager;
113                 delete light_manager;
114                 delete particle_system_manager;
115                 delete image_manager;
116         }
117         else {
118                 shaders.clear();
119                 meshes.clear();
120                 objects.clear();
121                 lights.clear();
122                 particle_systems.clear();
123         }
124 }
125
126 void Scene::device_update(Device *device_, Progress& progress)
127 {
128         if(!device)
129                 device = device_;
130         
131         /* The order of updates is important, because there's dependencies between
132          * the different managers, using data computed by previous managers.
133          *
134          * - Background generates shader graph compiled by shader manager.
135          * - Image manager uploads images used by shaders.
136          * - Camera may be used for adapative subdivison.
137          * - Displacement shader must have all shader data available.
138          * - Light manager needs final mesh data to compute emission CDF.
139          */
140         
141         image_manager->set_pack_images(device->info.pack_images);
142
143         progress.set_status("Updating Background");
144         background->device_update(device, &dscene, this);
145
146         if(progress.get_cancel()) return;
147
148         progress.set_status("Updating Shaders");
149         shader_manager->device_update(device, &dscene, this, progress);
150
151         if(progress.get_cancel()) return;
152
153         progress.set_status("Updating Images");
154         image_manager->device_update(device, &dscene, progress);
155
156         if(progress.get_cancel()) return;
157
158         progress.set_status("Updating Camera");
159         camera->device_update(device, &dscene, this);
160
161         if(progress.get_cancel()) return;
162
163         progress.set_status("Updating Objects");
164         object_manager->device_update(device, &dscene, this, progress);
165
166         if(progress.get_cancel()) return;
167
168         progress.set_status("Updating Meshes");
169         mesh_manager->device_update(device, &dscene, this, progress);
170
171         if(progress.get_cancel()) return;
172
173         progress.set_status("Updating Lights");
174         light_manager->device_update(device, &dscene, this, progress);
175
176         if(progress.get_cancel()) return;
177
178         progress.set_status("Updating Particle Systems");
179         particle_system_manager->device_update(device, &dscene, this, progress);
180
181         if(progress.get_cancel()) return;
182
183         progress.set_status("Updating Filter");
184         filter->device_update(device, &dscene);
185
186         if(progress.get_cancel()) return;
187
188         progress.set_status("Updating Film");
189         film->device_update(device, &dscene);
190
191         if(progress.get_cancel()) return;
192
193         progress.set_status("Updating Integrator");
194         integrator->device_update(device, &dscene, this);
195
196         if(progress.get_cancel()) return;
197
198         progress.set_status("Updating Device", "Writing constant memory");
199         device->const_copy_to("__data", &dscene.data, sizeof(dscene.data));
200 }
201
202 Scene::MotionType Scene::need_motion(bool advanced_shading)
203 {
204         if(integrator->motion_blur)
205                 return (advanced_shading)? MOTION_BLUR: MOTION_NONE;
206         else if(Pass::contains(film->passes, PASS_MOTION))
207                 return MOTION_PASS;
208         else
209                 return MOTION_NONE;
210 }
211
212 bool Scene::need_global_attribute(AttributeStandard std)
213 {
214         if(std == ATTR_STD_UV)
215                 return Pass::contains(film->passes, PASS_UV);
216         if(std == ATTR_STD_MOTION_PRE || ATTR_STD_MOTION_POST)
217                 return need_motion() == MOTION_PASS;
218         
219         return false;
220 }
221
222 void Scene::need_global_attributes(AttributeRequestSet& attributes)
223 {
224         for(int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++)
225                 if(need_global_attribute((AttributeStandard)std))
226                         attributes.add((AttributeStandard)std);
227 }
228
229 bool Scene::need_update()
230 {
231         return (need_reset() || film->need_update);
232 }
233
234 bool Scene::need_reset()
235 {
236         return (background->need_update
237                 || image_manager->need_update
238                 || camera->need_update
239                 || object_manager->need_update
240                 || mesh_manager->need_update
241                 || light_manager->need_update
242                 || filter->need_update
243                 || integrator->need_update
244                 || shader_manager->need_update
245                 || particle_system_manager->need_update);
246 }
247
248 void Scene::reset()
249 {
250         shader_manager->add_default(this);
251
252         /* ensure all objects are updated */
253         camera->tag_update();
254         filter->tag_update(this);
255         film->tag_update(this);
256         background->tag_update(this);
257         integrator->tag_update(this);
258 }
259
260 void Scene::device_free()
261 {
262         free_memory(false);
263 }
264
265 CCL_NAMESPACE_END
266