Cycles: Fix wrong order in object flags calculations
[blender.git] / intern / cycles / render / scene.cpp
index 33ebd7a59eff3d932a193b4167cbfa263a9b5232..19d715d834b45cc9ce2ddd164815412571f12849 100644 (file)
@@ -1,40 +1,46 @@
 /*
 /*
- * Copyright 2011, Blender Foundation.
+ * Copyright 2011-2013 Blender Foundation
  *
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * 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
  *
  *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * 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 <stdlib.h>
 
 #include "background.h"
  */
 
 #include <stdlib.h>
 
 #include "background.h"
+#include "bake.h"
 #include "camera.h"
 #include "camera.h"
+#include "curves.h"
 #include "device.h"
 #include "film.h"
 #include "device.h"
 #include "film.h"
-#include "filter.h"
 #include "integrator.h"
 #include "light.h"
 #include "integrator.h"
 #include "light.h"
-#include "shader.h"
 #include "mesh.h"
 #include "object.h"
 #include "mesh.h"
 #include "object.h"
+#include "osl.h"
+#include "particles.h"
 #include "scene.h"
 #include "scene.h"
+#include "shader.h"
 #include "svm.h"
 #include "svm.h"
-#include "osl.h"
+#include "tables.h"
 
 #include "util_foreach.h"
 #include "util_progress.h"
 
 
 #include "util_foreach.h"
 #include "util_progress.h"
 
+#ifdef WITH_CYCLES_DEBUG
+#  include "util_guarded_allocator.h"
+#  include "util_logging.h"
+#endif
+
 CCL_NAMESPACE_BEGIN
 
 Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_)
 CCL_NAMESPACE_BEGIN
 
 Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_)
@@ -44,7 +50,7 @@ Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_)
        memset(&dscene.data, 0, sizeof(dscene.data));
 
        camera = new Camera();
        memset(&dscene.data, 0, sizeof(dscene.data));
 
        camera = new Camera();
-       filter = new Filter();
+       lookup_tables = new LookupTables();
        film = new Film();
        background = new Background();
        light_manager = new LightManager();
        film = new Film();
        background = new Background();
        light_manager = new LightManager();
@@ -52,41 +58,27 @@ Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_)
        object_manager = new ObjectManager();
        integrator = new Integrator();
        image_manager = new ImageManager();
        object_manager = new ObjectManager();
        integrator = new Integrator();
        image_manager = new ImageManager();
-       shader_manager = ShaderManager::create(this);
+       particle_system_manager = new ParticleSystemManager();
+       curve_system_manager = new CurveSystemManager();
+       bake_manager = new BakeManager();
+
+       /* OSL only works on the CPU */
+       if(device_info_.type == DEVICE_CPU)
+               shader_manager = ShaderManager::create(this, params.shadingsystem);
+       else
+               shader_manager = ShaderManager::create(this, SHADINGSYSTEM_SVM);
 
 
-       if (device_info_.type == DEVICE_CPU)
-               image_manager->set_extended_image_limits();
+       /* Extended image limits for CPU and GPUs */
+       image_manager->set_extended_image_limits(device_info_);
 }
 
 Scene::~Scene()
 {
 }
 
 Scene::~Scene()
 {
-       if(device) camera->device_free(device, &dscene);
-       delete camera;
-
-       if(device) filter->device_free(device, &dscene);
-       delete filter;
-
-       if(device) film->device_free(device, &dscene);
-       delete film;
-
-       if(device) background->device_free(device, &dscene);
-       delete background;
-
-       if(device) mesh_manager->device_free(device, &dscene);
-       delete mesh_manager;
-
-       if(device) object_manager->device_free(device, &dscene);
-       delete object_manager;
-
-       if(device) integrator->device_free(device, &dscene);
-       delete integrator;
-
-       if(device) shader_manager->device_free(device, &dscene);
-       delete shader_manager;
-
-       if(device) light_manager->device_free(device, &dscene);
-       delete light_manager;
+       free_memory(true);
+}
 
 
+void Scene::free_memory(bool final)
+{
        foreach(Shader *s, shaders)
                delete s;
        foreach(Mesh *m, meshes)
        foreach(Shader *s, shaders)
                delete s;
        foreach(Mesh *m, meshes)
@@ -95,9 +87,54 @@ Scene::~Scene()
                delete o;
        foreach(Light *l, lights)
                delete l;
                delete o;
        foreach(Light *l, lights)
                delete l;
-
-       if(device) image_manager->device_free(device, &dscene);
-       delete image_manager;
+       foreach(ParticleSystem *p, particle_systems)
+               delete p;
+
+       shaders.clear();
+       meshes.clear();
+       objects.clear();
+       lights.clear();
+       particle_systems.clear();
+
+       if(device) {
+               camera->device_free(device, &dscene);
+               film->device_free(device, &dscene, this);
+               background->device_free(device, &dscene);
+               integrator->device_free(device, &dscene);
+
+               object_manager->device_free(device, &dscene);
+               mesh_manager->device_free(device, &dscene);
+               shader_manager->device_free(device, &dscene, this);
+               light_manager->device_free(device, &dscene);
+
+               particle_system_manager->device_free(device, &dscene);
+               curve_system_manager->device_free(device, &dscene);
+
+               bake_manager->device_free(device, &dscene);
+
+               if(!params.persistent_data || final)
+                       image_manager->device_free(device, &dscene);
+               else
+                       image_manager->device_free_builtin(device, &dscene);
+
+               lookup_tables->device_free(device, &dscene);
+       }
+
+       if(final) {
+               delete lookup_tables;
+               delete camera;
+               delete film;
+               delete background;
+               delete integrator;
+               delete object_manager;
+               delete mesh_manager;
+               delete shader_manager;
+               delete light_manager;
+               delete particle_system_manager;
+               delete curve_system_manager;
+               delete image_manager;
+               delete bake_manager;
+       }
 }
 
 void Scene::device_update(Device *device_, Progress& progress)
 }
 
 void Scene::device_update(Device *device_, Progress& progress)
@@ -108,73 +145,117 @@ void Scene::device_update(Device *device_, Progress& progress)
        /* The order of updates is important, because there's dependencies between
         * the different managers, using data computed by previous managers.
         *
        /* The order of updates is important, because there's dependencies between
         * the different managers, using data computed by previous managers.
         *
-        * - Background generates shader graph compiled by shader manager.
         * - Image manager uploads images used by shaders.
         * - Image manager uploads images used by shaders.
-        * - Camera may be used for adapative subdivison.
+        * - Camera may be used for adaptive subdivision.
         * - Displacement shader must have all shader data available.
         * - Displacement shader must have all shader data available.
-        * - Light manager needs final mesh data to compute emission CDF.
+        * - Light manager needs lookup tables and final mesh data to compute emission CDF.
+        * - Film needs light manager to run for use_light_visibility
+        * - Lookup tables are done a second time to handle film tables
         */
        
        image_manager->set_pack_images(device->info.pack_images);
 
         */
        
        image_manager->set_pack_images(device->info.pack_images);
 
-       progress.set_status("Updating Background");
-       background->device_update(device, &dscene, this);
-
-       if(progress.get_cancel()) return;
-
        progress.set_status("Updating Shaders");
        shader_manager->device_update(device, &dscene, this, progress);
 
        progress.set_status("Updating Shaders");
        shader_manager->device_update(device, &dscene, this, progress);
 
-       if(progress.get_cancel()) return;
+       if(progress.get_cancel() || device->have_error()) return;
 
 
-       progress.set_status("Updating Images");
-       image_manager->device_update(device, &dscene, progress);
+       progress.set_status("Updating Background");
+       background->device_update(device, &dscene, this);
 
 
-       if(progress.get_cancel()) return;
+       if(progress.get_cancel() || device->have_error()) return;
 
        progress.set_status("Updating Camera");
        camera->device_update(device, &dscene, this);
 
 
        progress.set_status("Updating Camera");
        camera->device_update(device, &dscene, this);
 
-       if(progress.get_cancel()) return;
+       if(progress.get_cancel() || device->have_error()) return;
 
        progress.set_status("Updating Objects");
        object_manager->device_update(device, &dscene, this, progress);
 
 
        progress.set_status("Updating Objects");
        object_manager->device_update(device, &dscene, this, progress);
 
-       if(progress.get_cancel()) return;
+       if(progress.get_cancel() || device->have_error()) return;
+
+       progress.set_status("Updating Meshes Flags");
+       mesh_manager->device_update_flags(device, &dscene, this, progress);
+
+       if(progress.get_cancel() || device->have_error()) return;
 
        progress.set_status("Updating Meshes");
        mesh_manager->device_update(device, &dscene, this, progress);
 
 
        progress.set_status("Updating Meshes");
        mesh_manager->device_update(device, &dscene, this, progress);
 
-       if(progress.get_cancel()) return;
+       if(progress.get_cancel() || device->have_error()) return;
+
+       progress.set_status("Updating Objects Flags");
+       object_manager->device_update_flags(device, &dscene, this, progress);
+
+       if(progress.get_cancel() || device->have_error()) return;
+
+       progress.set_status("Updating Images");
+       image_manager->device_update(device, &dscene, progress);
+
+       if(progress.get_cancel() || device->have_error()) return;
+
+       progress.set_status("Updating Camera Volume");
+       camera->device_update_volume(device, &dscene, this);
+
+       if(progress.get_cancel() || device->have_error()) return;
+
+       progress.set_status("Updating Hair Systems");
+       curve_system_manager->device_update(device, &dscene, this, progress);
+
+       if(progress.get_cancel() || device->have_error()) return;
+
+       progress.set_status("Updating Lookup Tables");
+       lookup_tables->device_update(device, &dscene);
+
+       if(progress.get_cancel() || device->have_error()) return;
 
        progress.set_status("Updating Lights");
        light_manager->device_update(device, &dscene, this, progress);
 
 
        progress.set_status("Updating Lights");
        light_manager->device_update(device, &dscene, this, progress);
 
-       if(progress.get_cancel()) return;
+       if(progress.get_cancel() || device->have_error()) return;
 
 
-       progress.set_status("Updating Filter");
-       filter->device_update(device, &dscene);
+       progress.set_status("Updating Particle Systems");
+       particle_system_manager->device_update(device, &dscene, this, progress);
 
 
-       if(progress.get_cancel()) return;
+       if(progress.get_cancel() || device->have_error()) return;
 
        progress.set_status("Updating Film");
 
        progress.set_status("Updating Film");
-       film->device_update(device, &dscene);
+       film->device_update(device, &dscene, this);
 
 
-       if(progress.get_cancel()) return;
+       if(progress.get_cancel() || device->have_error()) return;
 
        progress.set_status("Updating Integrator");
        integrator->device_update(device, &dscene, this);
 
 
        progress.set_status("Updating Integrator");
        integrator->device_update(device, &dscene, this);
 
-       if(progress.get_cancel()) return;
+       if(progress.get_cancel() || device->have_error()) return;
+
+       progress.set_status("Updating Lookup Tables");
+       lookup_tables->device_update(device, &dscene);
+
+       if(progress.get_cancel() || device->have_error()) return;
+
+       progress.set_status("Updating Baking");
+       bake_manager->device_update(device, &dscene, this, progress);
+
+       if(progress.get_cancel() || device->have_error()) return;
+
+       if(device->have_error() == false) {
+               progress.set_status("Updating Device", "Writing constant memory");
+               device->const_copy_to("__data", &dscene.data, sizeof(dscene.data));
+       }
 
 
-       progress.set_status("Updating Device", "Writing constant memory");
-       device->const_copy_to("__data", &dscene.data, sizeof(dscene.data));
+#ifdef WITH_CYCLES_DEBUG
+       VLOG(1) << "System memory statistics after full device sync:\n"
+               << "  Usage: " << util_guarded_get_mem_used() << "\n"
+               << "  Peak: " << util_guarded_get_mem_peak();
+#endif
 }
 
 }
 
-Scene::MotionType Scene::need_motion()
+Scene::MotionType Scene::need_motion(bool advanced_shading)
 {
        if(integrator->motion_blur)
 {
        if(integrator->motion_blur)
-               return MOTION_BLUR;
+               return (advanced_shading)? MOTION_BLUR: MOTION_NONE;
        else if(Pass::contains(film->passes, PASS_MOTION))
                return MOTION_PASS;
        else
        else if(Pass::contains(film->passes, PASS_MOTION))
                return MOTION_PASS;
        else
@@ -185,8 +266,10 @@ bool Scene::need_global_attribute(AttributeStandard std)
 {
        if(std == ATTR_STD_UV)
                return Pass::contains(film->passes, PASS_UV);
 {
        if(std == ATTR_STD_UV)
                return Pass::contains(film->passes, PASS_UV);
-       if(std == ATTR_STD_MOTION_PRE || ATTR_STD_MOTION_POST)
-               return need_motion() == MOTION_PASS;
+       else if(std == ATTR_STD_MOTION_VERTEX_POSITION)
+               return need_motion() != MOTION_NONE;
+       else if(std == ATTR_STD_MOTION_VERTEX_NORMAL)
+               return need_motion() == MOTION_BLUR;
        
        return false;
 }
        
        return false;
 }
@@ -211,9 +294,35 @@ bool Scene::need_reset()
                || object_manager->need_update
                || mesh_manager->need_update
                || light_manager->need_update
                || object_manager->need_update
                || mesh_manager->need_update
                || light_manager->need_update
-               || filter->need_update
+               || lookup_tables->need_update
                || integrator->need_update
                || integrator->need_update
-               || shader_manager->need_update);
+               || shader_manager->need_update
+               || particle_system_manager->need_update
+               || curve_system_manager->need_update
+               || bake_manager->need_update
+               || film->need_update);
+}
+
+void Scene::reset()
+{
+       shader_manager->reset(this);
+       shader_manager->add_default(this);
+
+       /* ensure all objects are updated */
+       camera->tag_update();
+       film->tag_update(this);
+       background->tag_update(this);
+       integrator->tag_update(this);
+       object_manager->tag_update(this);
+       mesh_manager->tag_update(this);
+       light_manager->tag_update(this);
+       particle_system_manager->tag_update(this);
+       curve_system_manager->tag_update(this);
+}
+
+void Scene::device_free()
+{
+       free_memory(false);
 }
 
 CCL_NAMESPACE_END
 }
 
 CCL_NAMESPACE_END