[Bf-blender-cvs] [89826e0a0d8] master: Alembic: integrate cache file into the dependency graph

Brecht Van Lommel noreply at git.blender.org
Wed May 1 16:02:54 CEST 2019


Commit: 89826e0a0d8ac55881569e021c487ac5541c6612
Author: Brecht Van Lommel
Date:   Thu Apr 4 15:07:37 2019 +0200
Branches: master
https://developer.blender.org/rB89826e0a0d8ac55881569e021c487ac5541c6612

Alembic: integrate cache file into the dependency graph

* The cache file datablock is now evaluated as part of the dependency graph,
  creating/freeing the Alembic file handle matching the current frame.
  Modifiers and constraints depend on this evaluation.
* Cache file handles and readers now only exist on COW datablocks, never the
  original ones.
* Object data paths are flushed back to the original for the user interface.
* The cache file keeps a list of all readers associated with its handle, and
  automatically frees them when the handle is freed. This kind of sharing of
  data across datablocks is weak but we have no better mechanism for it.

Fix T62720: Alembic sequences not working and crashing

Differential Revision: https://developer.blender.org/D4774

===================================================================

M	source/blender/alembic/intern/abc_object.cc
M	source/blender/alembic/intern/alembic_capi.cc
M	source/blender/blenkernel/BKE_cachefile.h
M	source/blender/blenkernel/intern/cachefile.c
M	source/blender/blenkernel/intern/constraint.c
M	source/blender/blenkernel/intern/scene.c
M	source/blender/blenloader/intern/readfile.c
M	source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
M	source/blender/depsgraph/intern/builder/deg_builder_relations.cc
M	source/blender/editors/interface/interface_templates.c
M	source/blender/editors/io/io_cache.c
M	source/blender/makesdna/DNA_cachefile_types.h
M	source/blender/makesdna/DNA_constraint_types.h
M	source/blender/makesdna/DNA_modifier_types.h
M	source/blender/makesrna/intern/rna_cachefile.c
M	source/blender/makesrna/intern/rna_constraint.c
M	source/blender/makesrna/intern/rna_modifier.c
M	source/blender/modifiers/intern/MOD_meshsequencecache.c

===================================================================

diff --git a/source/blender/alembic/intern/abc_object.cc b/source/blender/alembic/intern/abc_object.cc
index 36daa50e095..e437273c1be 100644
--- a/source/blender/alembic/intern/abc_object.cc
+++ b/source/blender/alembic/intern/abc_object.cc
@@ -364,9 +364,6 @@ void AbcObjectReader::addCacheModifier()
   id_us_plus(&mcmd->cache_file->id);
 
   BLI_strncpy(mcmd->object_path, m_iobject.getFullName().c_str(), FILE_MAX);
-
-  mcmd->reader = reinterpret_cast<CacheReader *>(this);
-  this->incref();
 }
 
 chrono_t AbcObjectReader::minTime() const
diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc
index 3ff3fbe2001..b502692d0e5 100644
--- a/source/blender/alembic/intern/alembic_capi.cc
+++ b/source/blender/alembic/intern/alembic_capi.cc
@@ -627,6 +627,7 @@ struct ImportJobData {
   char filename[1024];
   ImportSettings settings;
 
+  ArchiveReader *archive;
   std::vector<AbcObjectReader *> readers;
 
   short *stop;
@@ -672,9 +673,9 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa
 
   cache_file->is_sequence = data->settings.is_sequence;
   cache_file->scale = data->settings.scale;
-  cache_file->handle = handle_from_archive(archive);
-  BLI_strncpy(cache_file->filepath, data->filename, 1024);
+  STRNCPY(cache_file->filepath, data->filename);
 
+  data->archive = archive;
   data->settings.cache_file = cache_file;
 
   *data->do_update = true;
@@ -855,6 +856,7 @@ static void import_endjob(void *user_data)
 static void import_freejob(void *user_data)
 {
   ImportJobData *data = static_cast<ImportJobData *>(user_data);
+  delete data->archive;
   delete data;
 }
 
@@ -886,6 +888,7 @@ bool ABC_import(bContext *C,
   job->settings.validate_meshes = validate_meshes;
   job->error_code = ABC_NO_ERROR;
   job->was_cancelled = false;
+  job->archive = NULL;
 
   G.is_break = false;
 
diff --git a/source/blender/blenkernel/BKE_cachefile.h b/source/blender/blenkernel/BKE_cachefile.h
index b991ac24284..257975e3c17 100644
--- a/source/blender/blenkernel/BKE_cachefile.h
+++ b/source/blender/blenkernel/BKE_cachefile.h
@@ -29,8 +29,10 @@ extern "C" {
 #endif
 
 struct CacheFile;
+struct CacheReader;
 struct Depsgraph;
 struct Main;
+struct Object;
 struct Scene;
 
 void BKE_cachefiles_init(void);
@@ -52,24 +54,27 @@ void BKE_cachefile_make_local(struct Main *bmain,
                               struct CacheFile *cache_file,
                               const bool lib_local);
 
-void BKE_cachefile_reload(const struct Main *bmain, struct CacheFile *cache_file);
+void BKE_cachefile_reload(struct Depsgraph *depsgraph, struct CacheFile *cache_file);
 
-void BKE_cachefile_ensure_handle(const struct Main *bmain, struct CacheFile *cache_file);
-
-void BKE_cachefile_update_frame(struct Main *bmain,
-                                struct Depsgraph *depsgraph,
-                                struct Scene *scene,
-                                const float ctime,
-                                const float fps);
+void BKE_cachefile_eval(struct Main *bmain,
+                        struct Depsgraph *depsgraph,
+                        struct CacheFile *cache_file);
 
 bool BKE_cachefile_filepath_get(const struct Main *bmain,
+                                const struct Depsgraph *depsgrah,
                                 const struct CacheFile *cache_file,
-                                float frame,
                                 char r_filename[1024]);
 
-float BKE_cachefile_time_offset(struct CacheFile *cache_file, const float time, const float fps);
+float BKE_cachefile_time_offset(const struct CacheFile *cache_file,
+                                const float time,
+                                const float fps);
 
-void BKE_cachefile_clean(struct Main *bmain, struct CacheFile *cache_file);
+/* Modifiers and constraints open and free readers through these. */
+void BKE_cachefile_reader_open(struct CacheFile *cache_file,
+                               struct CacheReader **reader,
+                               struct Object *object,
+                               const char *object_path);
+void BKE_cachefile_reader_free(struct CacheFile *cache_file, struct CacheReader **reader);
 
 #ifdef __cplusplus
 }
diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c
index e4fc4706e66..a60b840344c 100644
--- a/source/blender/blenkernel/intern/cachefile.c
+++ b/source/blender/blenkernel/intern/cachefile.c
@@ -21,18 +21,21 @@
  * \ingroup bke
  */
 
+#include <string.h>
+
 #include "DNA_anim_types.h"
 #include "DNA_cachefile_types.h"
 #include "DNA_constraint_types.h"
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
 
+#include "BLI_utildefines.h"
 #include "BLI_fileops.h"
+#include "BLI_ghash.h"
 #include "BLI_listbase.h"
 #include "BLI_path_util.h"
 #include "BLI_string.h"
 #include "BLI_threads.h"
-#include "BLI_utildefines.h"
 
 #include "BKE_animsys.h"
 #include "BKE_cachefile.h"
@@ -41,10 +44,13 @@
 #include "BKE_modifier.h"
 #include "BKE_scene.h"
 
+#include "DEG_depsgraph_query.h"
+
 #ifdef WITH_ALEMBIC
 #  include "ABC_alembic.h"
 #endif
 
+/* TODO: make this per cache file to avoid global locks. */
 static SpinLock spin;
 
 void BKE_cachefiles_init(void)
@@ -57,6 +63,94 @@ void BKE_cachefiles_exit(void)
   BLI_spin_end(&spin);
 }
 
+void BKE_cachefile_reader_open(CacheFile *cache_file,
+                               struct CacheReader **reader,
+                               Object *object,
+                               const char *object_path)
+{
+#ifdef WITH_ALEMBIC
+  BLI_assert(cache_file->id.tag & LIB_TAG_COPIED_ON_WRITE);
+
+  if (cache_file->handle == NULL) {
+    return;
+  }
+
+  /* Open Alembic cache reader. */
+  *reader = CacheReader_open_alembic_object(cache_file->handle, *reader, object, object_path);
+
+  /* Multiple modifiers and constraints can call this function concurrently. */
+  BLI_spin_lock(&spin);
+  if (*reader) {
+    /* Register in set so we can free it when the cache file changes. */
+    if (cache_file->handle_readers == NULL) {
+      cache_file->handle_readers = BLI_gset_ptr_new("CacheFile.handle_readers");
+    }
+    BLI_gset_reinsert(cache_file->handle_readers, reader, NULL);
+  }
+  else if (cache_file->handle_readers) {
+    /* Remove in case CacheReader_open_alembic_object free the existing reader. */
+    BLI_gset_remove(cache_file->handle_readers, reader, NULL);
+  }
+  BLI_spin_unlock(&spin);
+#else
+  UNUSED_VARS(reader, object, object_path);
+#endif
+}
+
+void BKE_cachefile_reader_free(CacheFile *cache_file, struct CacheReader **reader)
+{
+#ifdef WITH_ALEMBIC
+  BLI_assert(cache_file->id.tag & LIB_TAG_COPIED_ON_WRITE);
+
+  if (*reader != NULL) {
+    CacheReader_free(*reader);
+    *reader = NULL;
+
+    /* Multiple modifiers and constraints can call this function concurrently. */
+    BLI_spin_lock(&spin);
+    if (cache_file->handle_readers) {
+      BLI_gset_remove(cache_file->handle_readers, reader, NULL);
+    }
+    BLI_spin_unlock(&spin);
+  }
+#else
+  UNUSED_VARS(cache_file, reader);
+#endif
+}
+
+static void cachefile_handle_free(CacheFile *cache_file)
+{
+#ifdef WITH_ALEMBIC
+  /* Free readers in all modifiers and constraints that use the handle, before
+   * we free the handle itself. */
+  BLI_spin_lock(&spin);
+  if (cache_file->handle_readers) {
+    GSetIterator gs_iter;
+    GSET_ITER (gs_iter, cache_file->handle_readers) {
+      struct CacheReader **reader = BLI_gsetIterator_getKey(&gs_iter);
+      if (*reader != NULL) {
+        CacheReader_free(*reader);
+        *reader = NULL;
+      }
+    }
+
+    BLI_gset_free(cache_file->handle_readers, NULL);
+    cache_file->handle_readers = NULL;
+  }
+  BLI_spin_unlock(&spin);
+
+  /* Free handle. */
+  if (cache_file->handle) {
+    ABC_free_handle(cache_file->handle);
+    cache_file->handle = NULL;
+  }
+
+  cache_file->handle_filepath[0] = '\0';
+#else
+  UNUSED_VARS(cache_file);
+#endif
+}
+
 void *BKE_cachefile_add(Main *bmain, const char *name)
 {
   CacheFile *cache_file = BKE_libblock_alloc(bmain, ID_CF, name, 0);
@@ -68,37 +162,23 @@ void *BKE_cachefile_add(Main *bmain, const char *name)
 
 void BKE_cachefile_init(CacheFile *cache_file)
 {
-  cache_file->handle = NULL;
   cache_file->filepath[0] = '\0';
   cache_file->override_frame = false;
   cache_file->frame = 0.0f;
   cache_file->is_sequence = false;
   cache_file->scale = 1.0f;
-  cache_file->handle_mutex = BLI_mutex_alloc();
   BLI_listbase_clear(&cache_file->object_paths);
+
+  cache_file->handle = NULL;
+  cache_file->handle_filepath[0] = '\0';
+  cache_file->handle_readers = NULL;
 }
 
 /** Free (or release) any data used by this cachefile (does not free the cachefile itself). */
 void BKE_cachefile_free(CacheFile *cache_file)
 {
   BKE_animdata_free((ID *)cache_file, false);
-
-  if (cache_file->id.tag & LIB_TAG_NO_MAIN) {
-    /* CoW/no-main copies reuse the existing ArchiveReader and mutex */
-    return;
-  }
-
-  if (cache_file->handle) {
-#ifdef WITH_ALEMBIC
-    ABC_free_handle(cache_file->handle);
-#endif
-    cache_file->handle = NULL;
-  }
-  if (cache_file->handle_mutex) {
-    BLI_mutex_free(cache_file->handle_mutex);
-    cache_file->handle_mutex = NULL;
-  }
-
+  cachefile_handle_free(cache_file);
   BLI_freelistN(&cache_file->object_paths);
 }
 
@@ -117,13 +197,8 @@ void BKE_cachefile_copy_data(Main *UNUSED(bmain),
                              const CacheFile *UNUSED(cache_file_src),
                              const int UNUSED(flag))
 {
-  if (cache_file_dst->id.tag & LIB_TAG_NO_MAIN) {
-    /* CoW/no-main copies reuse the existing ArchiveReader and mutex */
-    return;
-  }
-
   cache_file_dst->handle = NULL;
-  cache_file_dst->handle_mutex = NULL;
+  cache_file_dst->handle_readers = NULL;
   BLI_duplicatelist(&cache_file_dst->object_paths, &cache_file_dst->object_paths);
 }
 
@@ -139,72 +214,51 @@ void BKE_cachefile_make_local(Main *bmain, CacheFile *cache_file, const bool lib
   BKE_id_make_local_generic(bmain, &cache_file->id, true, lib_local);
 }
 
-void BKE_cachefile_reload(const Main *bmain, CacheFile *cache_file)
+void BKE_cachefile_reload(Depsgraph *depsgraph, CacheFile *cache_file)
 {
-  char fi

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list