Code refactor: move more memory allocation logic into device API.
[blender.git] / intern / cycles / render / scene.cpp
index 4a42b2c9e3510c0cc5d219b5ca387cbb36cee22c..260a325206c847dc2fd72cc0bc738a87a41a546b 100644 (file)
  * 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
+ * limitations under the License.
  */
 
 #include <stdlib.h>
 
-#include "background.h"
-#include "bake.h"
-#include "camera.h"
-#include "curves.h"
-#include "device.h"
-#include "film.h"
-#include "integrator.h"
-#include "light.h"
-#include "mesh.h"
-#include "object.h"
-#include "osl.h"
-#include "particles.h"
-#include "scene.h"
-#include "shader.h"
-#include "svm.h"
-#include "tables.h"
-
-#include "util_foreach.h"
-#include "util_progress.h"
+#include "render/background.h"
+#include "render/bake.h"
+#include "render/camera.h"
+#include "render/curves.h"
+#include "device/device.h"
+#include "render/film.h"
+#include "render/integrator.h"
+#include "render/light.h"
+#include "render/mesh.h"
+#include "render/object.h"
+#include "render/osl.h"
+#include "render/particles.h"
+#include "render/scene.h"
+#include "render/shader.h"
+#include "render/svm.h"
+#include "render/tables.h"
+
+#include "util/util_foreach.h"
+#include "util/util_guarded_allocator.h"
+#include "util/util_logging.h"
+#include "util/util_progress.h"
 
 CCL_NAMESPACE_BEGIN
 
-Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_)
-: params(params_)
+DeviceScene::DeviceScene(Device *device)
+: bvh_nodes(device, "__bvh_nodes", MEM_TEXTURE),
+  bvh_leaf_nodes(device, "__bvh_leaf_nodes", MEM_TEXTURE),
+  object_node(device, "__object_node", MEM_TEXTURE),
+  prim_tri_index(device, "__prim_tri_index", MEM_TEXTURE),
+  prim_tri_verts(device, "__prim_tri_verts", MEM_TEXTURE),
+  prim_type(device, "__prim_type", MEM_TEXTURE),
+  prim_visibility(device, "__prim_visibility", MEM_TEXTURE),
+  prim_index(device, "__prim_index", MEM_TEXTURE),
+  prim_object(device, "__prim_object", MEM_TEXTURE),
+  prim_time(device, "__prim_time", MEM_TEXTURE),
+  tri_shader(device, "__tri_shader", MEM_TEXTURE),
+  tri_vnormal(device, "__tri_vnormal", MEM_TEXTURE),
+  tri_vindex(device, "__tri_vindex", MEM_TEXTURE),
+  tri_patch(device, "__tri_patch", MEM_TEXTURE),
+  tri_patch_uv(device, "__tri_patch_uv", MEM_TEXTURE),
+  curves(device, "__curves", MEM_TEXTURE),
+  curve_keys(device, "__curve_keys", MEM_TEXTURE),
+  patches(device, "__patches", MEM_TEXTURE),
+  objects(device, "__objects", MEM_TEXTURE),
+  objects_vector(device, "__objects_vector", MEM_TEXTURE),
+  attributes_map(device, "__attributes_map", MEM_TEXTURE),
+  attributes_float(device, "__attributes_float", MEM_TEXTURE),
+  attributes_float3(device, "__attributes_float3", MEM_TEXTURE),
+  attributes_uchar4(device, "__attributes_uchar4", MEM_TEXTURE),
+  light_distribution(device, "__light_distribution", MEM_TEXTURE),
+  light_data(device, "__light_data", MEM_TEXTURE),
+  light_background_marginal_cdf(device, "__light_background_marginal_cdf", MEM_TEXTURE),
+  light_background_conditional_cdf(device, "__light_background_conditional_cdf", MEM_TEXTURE),
+  particles(device, "__particles", MEM_TEXTURE),
+  svm_nodes(device, "__svm_nodes", MEM_TEXTURE),
+  shader_flag(device, "__shader_flag", MEM_TEXTURE),
+  object_flag(device, "__object_flag", MEM_TEXTURE),
+  lookup_table(device, "__lookup_table", MEM_TEXTURE),
+  sobol_directions(device, "__sobol_directions", MEM_TEXTURE)
+{
+       memset(&data, 0, sizeof(data));
+}
+
+Scene::Scene(const SceneParams& params_, Device *device)
+: device(device), dscene(device), params(params_)
 {
-       device = NULL;
        memset(&dscene.data, 0, sizeof(dscene.data));
 
        camera = new Camera();
@@ -52,19 +92,16 @@ Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_)
        mesh_manager = new MeshManager();
        object_manager = new ObjectManager();
        integrator = new Integrator();
-       image_manager = new ImageManager();
+       image_manager = new ImageManager(device->info);
        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)
+       if(device->info.has_osl)
                shader_manager = ShaderManager::create(this, params.shadingsystem);
        else
-               shader_manager = ShaderManager::create(this, SceneParams::SVM);
-
-       if (device_info_.type == DEVICE_CPU)
-               image_manager->set_extended_image_limits();
+               shader_manager = ShaderManager::create(this, SHADINGSYSTEM_SVM);
 }
 
 Scene::~Scene()
@@ -92,7 +129,7 @@ void Scene::free_memory(bool final)
        particle_systems.clear();
 
        if(device) {
-               camera->device_free(device, &dscene);
+               camera->device_free(device, &dscene, this);
                film->device_free(device, &dscene, this);
                background->device_free(device, &dscene);
                integrator->device_free(device, &dscene);
@@ -108,7 +145,9 @@ void Scene::free_memory(bool final)
                bake_manager->device_free(device, &dscene);
 
                if(!params.persistent_data || final)
-                       image_manager->device_free(device, &dscene);
+                       image_manager->device_free(device);
+               else
+                       image_manager->device_free_builtin(device);
 
                lookup_tables->device_free(device, &dscene);
        }
@@ -134,92 +173,120 @@ void Scene::device_update(Device *device_, Progress& progress)
 {
        if(!device)
                device = device_;
-       
+
+       bool print_stats = need_data_update();
+
        /* The order of updates is important, because there's dependencies between
         * the different managers, using data computed by previous managers.
         *
         * - 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.
         * - 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);
 
        progress.set_status("Updating Shaders");
        shader_manager->device_update(device, &dscene, this, progress);
 
-       if(progress.get_cancel()) return;
-
-       progress.set_status("Updating Images");
-       image_manager->device_update(device, &dscene, progress);
-
-       if(progress.get_cancel()) return;
+       if(progress.get_cancel() || device->have_error()) return;
 
        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);
 
-       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 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");
+       mesh_manager->device_update(device, &dscene, this, progress);
+
+       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, this, 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()) 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()) return;
-
-       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 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 Particle Systems");
        particle_system_manager->device_update(device, &dscene, this, progress);
 
-       if(progress.get_cancel()) return;
-
-       progress.set_status("Updating Film");
-       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);
 
-       if(progress.get_cancel()) return;
+       if(progress.get_cancel() || device->have_error()) return;
+
+       progress.set_status("Updating Film");
+       film->device_update(device, &dscene, this);
+
+       if(progress.get_cancel() || device->have_error()) return;
 
        progress.set_status("Updating Lookup Tables");
        lookup_tables->device_update(device, &dscene);
 
-       if(progress.get_cancel()) return;
+       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()) return;
+       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));
+       }
+
+       if(print_stats) {
+               size_t mem_used = util_guarded_get_mem_used();
+               size_t mem_peak = util_guarded_get_mem_peak();
 
-       progress.set_status("Updating Device", "Writing constant memory");
-       device->const_copy_to("__data", &dscene.data, sizeof(dscene.data));
+               VLOG(1) << "System memory statistics after full device sync:\n"
+                       << "  Usage: " << string_human_readable_number(mem_used)
+                       << " (" << string_human_readable_size(mem_used) << ")\n"
+                       << "  Peak: " << string_human_readable_number(mem_peak)
+                       << " (" << string_human_readable_size(mem_peak) << ")";
+       }
 }
 
 Scene::MotionType Scene::need_motion(bool advanced_shading)
@@ -232,13 +299,21 @@ Scene::MotionType Scene::need_motion(bool advanced_shading)
                return MOTION_NONE;
 }
 
+float Scene::motion_shutter_time()
+{
+       if(need_motion() == Scene::MOTION_PASS)
+               return 2.0f;
+       else
+               return camera->shuttertime;
+}
+
 bool Scene::need_global_attribute(AttributeStandard std)
 {
        if(std == ATTR_STD_UV)
                return Pass::contains(film->passes, PASS_UV);
-       if(std == ATTR_STD_MOTION_VERTEX_POSITION)
+       else if(std == ATTR_STD_MOTION_VERTEX_POSITION)
                return need_motion() != MOTION_NONE;
-       if(std == ATTR_STD_MOTION_VERTEX_NORMAL)
+       else if(std == ATTR_STD_MOTION_VERTEX_NORMAL)
                return need_motion() == MOTION_BLUR;
        
        return false;
@@ -256,11 +331,10 @@ bool Scene::need_update()
        return (need_reset() || film->need_update);
 }
 
-bool Scene::need_reset()
+bool Scene::need_data_update()
 {
        return (background->need_update
                || image_manager->need_update
-               || camera->need_update
                || object_manager->need_update
                || mesh_manager->need_update
                || light_manager->need_update
@@ -269,7 +343,13 @@ bool Scene::need_reset()
                || shader_manager->need_update
                || particle_system_manager->need_update
                || curve_system_manager->need_update
-               || bake_manager->need_update);
+               || bake_manager->need_update
+               || film->need_update);
+}
+
+bool Scene::need_reset()
+{
+       return need_data_update() || camera->need_update;
 }
 
 void Scene::reset()
@@ -282,6 +362,11 @@ void Scene::reset()
        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()