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:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2019-04-04 16:07:37 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2019-05-01 17:02:27 +0300
commit89826e0a0d8ac55881569e021c487ac5541c6612 (patch)
treec80797e8c804d43fc84a8e91396a8a86cf3a79b7 /source/blender
parenta72a831570822190f782e6bbecfd57b45dc2e872 (diff)
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
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/alembic/intern/abc_object.cc3
-rw-r--r--source/blender/alembic/intern/alembic_capi.cc7
-rw-r--r--source/blender/blenkernel/BKE_cachefile.h27
-rw-r--r--source/blender/blenkernel/intern/cachefile.c247
-rw-r--r--source/blender/blenkernel/intern/constraint.c24
-rw-r--r--source/blender/blenkernel/intern/scene.c9
-rw-r--r--source/blender/blenloader/intern/readfile.c5
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc8
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc11
-rw-r--r--source/blender/editors/interface/interface_templates.c5
-rw-r--r--source/blender/editors/io/io_cache.c14
-rw-r--r--source/blender/makesdna/DNA_cachefile_types.h12
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h5
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h5
-rw-r--r--source/blender/makesrna/intern/rna_cachefile.c38
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c18
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c15
-rw-r--r--source/blender/modifiers/intern/MOD_meshsequencecache.c28
18 files changed, 229 insertions, 252 deletions
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 filepath[FILE_MAX];
-
- BLI_strncpy(filepath, cache_file->filepath, sizeof(filepath));
- BLI_path_abs(filepath, ID_BLEND_PATH(bmain, &cache_file->id));
-
-#ifdef WITH_ALEMBIC
- if (cache_file->handle) {
- ABC_free_handle(cache_file->handle);
+ /* To force reload, free the handle and tag depsgraph to load it again. */
+ CacheFile *cache_file_eval = (CacheFile *)DEG_get_evaluated_id(depsgraph, &cache_file->id);
+ if (cache_file_eval) {
+ cachefile_handle_free(cache_file_eval);
}
- cache_file->handle = ABC_create_handle(filepath, &cache_file->object_paths);
-#endif
+ DEG_id_tag_update(&cache_file->id, ID_RECALC_COPY_ON_WRITE);
}
-void BKE_cachefile_ensure_handle(const Main *bmain, CacheFile *cache_file)
+void BKE_cachefile_eval(Main *bmain, Depsgraph *depsgraph, CacheFile *cache_file)
{
- BLI_spin_lock(&spin);
- if (cache_file->handle_mutex == NULL) {
- cache_file->handle_mutex = BLI_mutex_alloc();
- }
- BLI_spin_unlock(&spin);
-
- BLI_mutex_lock(cache_file->handle_mutex);
+ BLI_assert(cache_file->id.tag & LIB_TAG_COPIED_ON_WRITE);
- if (cache_file->handle == NULL) {
- /* Assigning to a CoW copy is a bad idea; assign to the original instead. */
- BLI_assert((cache_file->id.tag & LIB_TAG_COPIED_ON_WRITE) == 0);
- BKE_cachefile_reload(bmain, cache_file);
+ /* Compute filepath. */
+ char filepath[FILE_MAX];
+ if (!BKE_cachefile_filepath_get(bmain, depsgraph, cache_file, filepath)) {
+ return;
}
- BLI_mutex_unlock(cache_file->handle_mutex);
-}
-
-void BKE_cachefile_update_frame(
- Main *bmain, struct Depsgraph *depsgraph, Scene *scene, const float ctime, const float fps)
-{
- CacheFile *cache_file;
- char filename[FILE_MAX];
-
- for (cache_file = bmain->cachefiles.first; cache_file; cache_file = cache_file->id.next) {
- /* TODO: dependency graph should be updated to do drivers on cachefile.
- * Execute drivers only, as animation has already been done. */
- BKE_animsys_evaluate_animdata(
- depsgraph, scene, &cache_file->id, cache_file->adt, ctime, ADT_RECALC_DRIVERS);
-
- if (!cache_file->is_sequence) {
- continue;
- }
+ /* Test if filepath change or if we can keep the existing handle. */
+ if (STREQ(cache_file->handle_filepath, filepath)) {
+ return;
+ }
- const float time = BKE_cachefile_time_offset(cache_file, ctime, fps);
+ cachefile_handle_free(cache_file);
+ BLI_freelistN(&cache_file->object_paths);
- if (BKE_cachefile_filepath_get(bmain, cache_file, time, filename)) {
- BKE_cachefile_clean(bmain, cache_file);
#ifdef WITH_ALEMBIC
- ABC_free_handle(cache_file->handle);
- cache_file->handle = ABC_create_handle(filename, NULL);
+ cache_file->handle = ABC_create_handle(filepath, &cache_file->object_paths);
+ BLI_strncpy(cache_file->handle_filepath, filepath, FILE_MAX);
#endif
- }
+
+ if (DEG_is_active(depsgraph)) {
+ /* Flush object paths back to original datablock for UI. */
+ CacheFile *cache_file_orig = (CacheFile *)DEG_get_original_id(&cache_file->id);
+ BLI_freelistN(&cache_file_orig->object_paths);
+ BLI_duplicatelist(&cache_file_orig->object_paths, &cache_file->object_paths);
}
}
bool BKE_cachefile_filepath_get(const Main *bmain,
+ const Depsgraph *depsgraph,
const CacheFile *cache_file,
- float frame,
char r_filepath[FILE_MAX])
{
BLI_strncpy(r_filepath, cache_file->filepath, FILE_MAX);
@@ -214,6 +268,11 @@ bool BKE_cachefile_filepath_get(const Main *bmain,
int frame_len;
if (cache_file->is_sequence && BLI_path_frame_get(r_filepath, &fframe, &frame_len)) {
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ const float ctime = BKE_scene_frame_get(scene);
+ const float fps = (((double)scene->r.frs_sec) / (double)scene->r.frs_sec_base);
+ const float frame = BKE_cachefile_time_offset(cache_file, ctime, fps);
+
char ext[32];
BLI_path_frame_strip(r_filepath, ext);
BLI_path_frame(r_filepath, frame, frame_len);
@@ -226,47 +285,9 @@ bool BKE_cachefile_filepath_get(const Main *bmain,
return true;
}
-float BKE_cachefile_time_offset(CacheFile *cache_file, const float time, const float fps)
+float BKE_cachefile_time_offset(const CacheFile *cache_file, const float time, const float fps)
{
const float time_offset = cache_file->frame_offset / fps;
const float frame = (cache_file->override_frame ? cache_file->frame : time);
return cache_file->is_sequence ? frame : frame / fps - time_offset;
}
-
-/* TODO(kevin): replace this with some depsgraph mechanism, or something similar. */
-void BKE_cachefile_clean(struct Main *bmain, CacheFile *cache_file)
-{
- for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
- ModifierData *md = modifiers_findByType(ob, eModifierType_MeshSequenceCache);
-
- if (md) {
- MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md;
-
- if (cache_file == mcmd->cache_file) {
-#ifdef WITH_ALEMBIC
- if (mcmd->reader != NULL) {
- CacheReader_free(mcmd->reader);
- }
-#endif
- mcmd->reader = NULL;
- }
- }
-
- for (bConstraint *con = ob->constraints.first; con; con = con->next) {
- if (con->type != CONSTRAINT_TYPE_TRANSFORM_CACHE) {
- continue;
- }
-
- bTransformCacheConstraint *data = con->data;
-
- if (cache_file == data->cache_file) {
-#ifdef WITH_ALEMBIC
- if (data->reader != NULL) {
- CacheReader_free(data->reader);
- }
-#endif
- data->reader = NULL;
- }
- }
- }
-}
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index a475a16dd57..0e29f165992 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -4835,13 +4835,9 @@ static void transformcache_evaluate(bConstraint *con, bConstraintOb *cob, ListBa
const float frame = DEG_get_ctime(cob->depsgraph);
const float time = BKE_cachefile_time_offset(cache_file, frame, FPS);
- /* Must always load ABC handle on original. */
- CacheFile *cache_file_orig = (CacheFile *)DEG_get_original_id(&cache_file->id);
- BKE_cachefile_ensure_handle(G.main, cache_file_orig);
-
- if (!data->reader) {
- data->reader = CacheReader_open_alembic_object(
- cache_file_orig->handle, data->reader, cob->ob, data->object_path);
+ if (!data->reader || !STREQ(data->reader_object_path, data->object_path)) {
+ STRNCPY(data->reader_object_path, data->object_path);
+ BKE_cachefile_reader_open(cache_file, &data->reader, cob->ob, data->object_path);
}
ABC_get_transform(data->reader, cob->matrix, time, cache_file->scale);
@@ -4859,12 +4855,8 @@ static void transformcache_copy(bConstraint *con, bConstraint *srccon)
BLI_strncpy(dst->object_path, src->object_path, sizeof(dst->object_path));
dst->cache_file = src->cache_file;
-
-#ifdef WITH_ALEMBIC
- if (dst->reader) {
- CacheReader_incref(dst->reader);
- }
-#endif
+ dst->reader = NULL;
+ dst->reader_object_path[0] = '\0';
}
static void transformcache_free(bConstraint *con)
@@ -4872,10 +4864,8 @@ static void transformcache_free(bConstraint *con)
bTransformCacheConstraint *data = con->data;
if (data->reader) {
-#ifdef WITH_ALEMBIC
- CacheReader_free(data->reader);
-#endif
- data->reader = NULL;
+ BKE_cachefile_reader_free(data->cache_file, &data->reader);
+ data->reader_object_path[0] = '\0';
}
}
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index e0bf62402d2..58b36aed24f 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -1565,15 +1565,6 @@ void BKE_scene_graph_update_for_newframe(Depsgraph *depsgraph, Main *bmain)
BKE_image_editors_update_frame(bmain, scene->r.cfra);
BKE_sound_set_cfra(scene->r.cfra);
DEG_graph_relations_update(depsgraph, bmain, scene, view_layer);
- /* Update animated cache files for modifiers.
- *
- * TODO(sergey): Make this a depsgraph node?
- */
- BKE_cachefile_update_frame(bmain,
- depsgraph,
- scene,
- ctime,
- (((double)scene->r.frs_sec) / (double)scene->r.frs_sec_base));
#ifdef POSE_ANIMATION_WORKAROUND
scene_armature_depsgraph_workaround(bmain, depsgraph);
#endif
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 55f02b45854..bf96cc9fa8e 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -3305,7 +3305,8 @@ static void direct_link_cachefile(FileData *fd, CacheFile *cache_file)
{
BLI_listbase_clear(&cache_file->object_paths);
cache_file->handle = NULL;
- cache_file->handle_mutex = NULL;
+ cache_file->handle_filepath[0] = '\0';
+ cache_file->handle_readers = NULL;
/* relink animdata */
cache_file->adt = newdataadr(fd, cache_file->adt);
@@ -3739,6 +3740,7 @@ static void direct_link_constraints(FileData *fd, ListBase *lb)
case CONSTRAINT_TYPE_TRANSFORM_CACHE: {
bTransformCacheConstraint *data = con->data;
data->reader = NULL;
+ data->reader_object_path[0] = '\0';
}
}
}
@@ -5745,6 +5747,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
else if (md->type == eModifierType_MeshSequenceCache) {
MeshSeqCacheModifierData *msmcd = (MeshSeqCacheModifierData *)md;
msmcd->reader = NULL;
+ msmcd->reader_object_path[0] = '\0';
}
else if (md->type == eModifierType_SurfaceDeform) {
SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index 87bbcef7f01..b6822a89093 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -65,6 +65,7 @@ extern "C" {
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_animsys.h"
+#include "BKE_cachefile.h"
#include "BKE_collection.h"
#include "BKE_constraint.h"
#include "BKE_curve.h"
@@ -1469,11 +1470,16 @@ void DepsgraphNodeBuilder::build_cachefile(CacheFile *cache_file)
return;
}
ID *cache_file_id = &cache_file->id;
+ add_id_node(cache_file_id);
+ CacheFile *cache_file_cow = get_cow_datablock(cache_file);
/* Animation, */
build_animdata(cache_file_id);
build_parameters(cache_file_id);
/* Cache evaluation itself. */
- add_operation_node(cache_file_id, NodeType::CACHE, OperationCode::FILE_CACHE_UPDATE);
+ add_operation_node(cache_file_id,
+ NodeType::CACHE,
+ OperationCode::FILE_CACHE_UPDATE,
+ function_bind(BKE_cachefile_eval, bmain_, _1, cache_file_cow));
}
void DepsgraphNodeBuilder::build_mask(Mask *mask)
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index 147d82c5999..d3fd16d889f 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -2222,6 +2222,14 @@ void DepsgraphRelationBuilder::build_cachefile(CacheFile *cache_file)
ComponentKey datablock_key(&cache_file->id, NodeType::CACHE);
add_relation(animation_key, datablock_key, "Datablock Animation");
}
+
+ /* Cache file updates */
+ if (cache_file->is_sequence) {
+ OperationKey cache_update_key(
+ &cache_file->id, NodeType::CACHE, OperationCode::FILE_CACHE_UPDATE);
+ TimeSourceKey time_src_key;
+ add_relation(time_src_key, cache_update_key, "TimeSrc -> Cache File Eval");
+ }
}
void DepsgraphRelationBuilder::build_mask(Mask *mask)
@@ -2329,7 +2337,8 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDNode *id_node)
continue;
}
int rel_flag = (RELATION_FLAG_NO_FLUSH | RELATION_FLAG_GODMODE);
- if (id_type == ID_ME && comp_node->type == NodeType::GEOMETRY) {
+ if ((id_type == ID_ME && comp_node->type == NodeType::GEOMETRY) ||
+ (id_type == ID_CF && comp_node->type == NodeType::CACHE)) {
rel_flag &= ~RELATION_FLAG_NO_FLUSH;
}
/* Notes on exceptions:
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index f656e917c44..e96141eaa05 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -6711,17 +6711,18 @@ void uiTemplateCacheFile(uiLayout *layout, bContext *C, PointerRNA *ptr, const c
uiItemR(row, &fileptr, "override_frame", 0, "Override Frame", ICON_NONE);
row = uiLayoutRow(layout, false);
- uiLayoutSetEnabled(row, RNA_boolean_get(&fileptr, "override_frame"));
+ uiLayoutSetActive(row, RNA_boolean_get(&fileptr, "override_frame"));
uiItemR(row, &fileptr, "frame", 0, "Frame", ICON_NONE);
row = uiLayoutRow(layout, false);
uiItemR(row, &fileptr, "frame_offset", 0, "Frame Offset", ICON_NONE);
+ uiLayoutSetActive(row, !RNA_boolean_get(&fileptr, "is_sequence"));
row = uiLayoutRow(layout, false);
uiItemL(row, IFACE_("Manual Transform:"), ICON_NONE);
row = uiLayoutRow(layout, false);
- uiLayoutSetEnabled(row, (sbuts->mainb == BCONTEXT_CONSTRAINT));
+ uiLayoutSetActive(row, (sbuts->mainb == BCONTEXT_CONSTRAINT));
uiItemR(row, &fileptr, "scale", 0, "Scale", ICON_NONE);
/* TODO: unused for now, so no need to expose. */
diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c
index 6358c2c1370..3dd3b20bda3 100644
--- a/source/blender/editors/io/io_cache.c
+++ b/source/blender/editors/io/io_cache.c
@@ -38,6 +38,8 @@
#include "RNA_access.h"
+#include "DEG_depsgraph.h"
+
#include "UI_interface.h"
#include "WM_api.h"
@@ -93,7 +95,7 @@ static int cachefile_open_exec(bContext *C, wmOperator *op)
CacheFile *cache_file = BKE_libblock_alloc(bmain, ID_CF, BLI_path_basename(filename), 0);
BLI_strncpy(cache_file->filepath, filename, FILE_MAX);
- BKE_cachefile_reload(bmain, cache_file);
+ DEG_id_tag_update(&cache_file->id, ID_RECALC_COPY_ON_WRITE);
/* Will be set when running invoke, not exec directly. */
if (op->customdata != NULL) {
@@ -137,7 +139,7 @@ void CACHEFILE_OT_open(wmOperatorType *ot)
/* ***************************** Reload Operator **************************** */
-static int cachefile_reload_exec(bContext *C, wmOperator *op)
+static int cachefile_reload_exec(bContext *C, wmOperator *UNUSED(op))
{
CacheFile *cache_file = CTX_data_edit_cachefile(C);
@@ -145,14 +147,10 @@ static int cachefile_reload_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- Main *bmain = CTX_data_main(C);
-
- BLI_freelistN(&cache_file->object_paths);
- BKE_cachefile_reload(bmain, cache_file);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ BKE_cachefile_reload(depsgraph, cache_file);
return OPERATOR_FINISHED;
-
- UNUSED_VARS(op);
}
void CACHEFILE_OT_reload(wmOperatorType *ot)
diff --git a/source/blender/makesdna/DNA_cachefile_types.h b/source/blender/makesdna/DNA_cachefile_types.h
index e5f77f70720..bc57202367c 100644
--- a/source/blender/makesdna/DNA_cachefile_types.h
+++ b/source/blender/makesdna/DNA_cachefile_types.h
@@ -30,10 +30,12 @@
extern "C" {
#endif
+struct GSet;
+
/* CacheFile::flag */
enum {
CACHEFILE_DS_EXPAND = (1 << 0),
- CACHEFILE_DIRTY = (1 << 1),
+ CACHEFILE_UNUSED_0 = (1 << 1),
};
/* CacheFile::draw_flag */
@@ -53,9 +55,6 @@ typedef struct CacheFile {
ID id;
struct AnimData *adt;
- struct AbcArchiveHandle *handle;
- void *handle_mutex;
-
/** Paths of the objects inside of the Alembic archive referenced by this CacheFile. */
ListBase object_paths;
@@ -78,6 +77,11 @@ typedef struct CacheFile {
short draw_flag;
char _pad[4];
+
+ /* Runtime */
+ struct AbcArchiveHandle *handle;
+ char handle_filepath[1024];
+ struct GSet *handle_readers;
} CacheFile;
#ifdef __cplusplus
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index 3ca61400e2e..f839f22ec9f 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -593,9 +593,12 @@ typedef struct bObjectSolverConstraint {
/* Transform matrix cache constraint */
typedef struct bTransformCacheConstraint {
struct CacheFile *cache_file;
- struct CacheReader *reader;
/** FILE_MAX. */
char object_path[1024];
+
+ /* Runtime. */
+ struct CacheReader *reader;
+ char reader_object_path[1024];
} bTransformCacheConstraint;
/* ------------------------------------------ */
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 1b85fb26c0e..6a524e03b6e 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -1852,12 +1852,15 @@ typedef struct MeshSeqCacheModifierData {
ModifierData modifier;
struct CacheFile *cache_file;
- struct CacheReader *reader;
/** 1024 = FILE_MAX. */
char object_path[1024];
char read_flag;
char _pad[7];
+
+ /* Runtime. */
+ struct CacheReader *reader;
+ char reader_object_path[1024];
} MeshSeqCacheModifierData;
/* MeshSeqCacheModifierData.read_flag */
diff --git a/source/blender/makesrna/intern/rna_cachefile.c b/source/blender/makesrna/intern/rna_cachefile.c
index fb61be69ee6..189a4a7de86 100644
--- a/source/blender/makesrna/intern/rna_cachefile.c
+++ b/source/blender/makesrna/intern/rna_cachefile.c
@@ -45,29 +45,12 @@
# include "../../../alembic/ABC_alembic.h"
# endif
-static void rna_CacheFile_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_CacheFile_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
CacheFile *cache_file = (CacheFile *)ptr->data;
- DEG_id_tag_update(&cache_file->id, 0);
+ DEG_id_tag_update(&cache_file->id, ID_RECALC_COPY_ON_WRITE);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
-
- UNUSED_VARS(bmain, scene);
-}
-
-static void rna_CacheFile_update_handle(Main *bmain, Scene *scene, PointerRNA *ptr)
-{
- CacheFile *cache_file = ptr->data;
-
- if ((cache_file->flag & CACHEFILE_DIRTY) != 0) {
- BKE_cachefile_clean(bmain, cache_file);
- BLI_freelistN(&cache_file->object_paths);
- cache_file->flag &= ~CACHEFILE_DIRTY;
- }
-
- BKE_cachefile_reload(bmain, cache_file);
-
- rna_CacheFile_update(bmain, scene, ptr);
}
static void rna_CacheFile_object_paths_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
@@ -76,20 +59,6 @@ static void rna_CacheFile_object_paths_begin(CollectionPropertyIterator *iter, P
rna_iterator_listbase_begin(iter, &cache_file->object_paths, NULL);
}
-static void rna_CacheFile_filename_set(PointerRNA *ptr, const char *value)
-{
- CacheFile *cache_file = ptr->data;
-
- if (STREQ(cache_file->filepath, value)) {
- return;
- }
-
- /* Different file is opened, close all readers. */
- cache_file->flag |= CACHEFILE_DIRTY;
-
- BLI_strncpy(cache_file->filepath, value, sizeof(cache_file->filepath));
-}
-
#else
/* cachefile.object_paths */
@@ -122,9 +91,8 @@ static void rna_def_cachefile(BlenderRNA *brna)
RNA_def_struct_ui_icon(srna, ICON_FILE);
PropertyRNA *prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
- RNA_def_property_string_funcs(prop, NULL, NULL, "rna_CacheFile_filename_set");
RNA_def_property_ui_text(prop, "File Path", "Path to external displacements file");
- RNA_def_property_update(prop, 0, "rna_CacheFile_update_handle");
+ RNA_def_property_update(prop, 0, "rna_CacheFile_update");
prop = RNA_def_property(srna, "is_sequence", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_ui_text(
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index 44445181402..c1c235d497b 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -729,22 +729,6 @@ static void rna_Constraint_objectSolver_camera_set(PointerRNA *ptr, PointerRNA v
}
}
-static void rna_Constraint_transformCache_object_path_update(Main *bmain,
- Scene *scene,
- PointerRNA *ptr)
-{
-# ifdef WITH_ALEMBIC
- bConstraint *con = (bConstraint *)ptr->data;
- bTransformCacheConstraint *data = (bTransformCacheConstraint *)con->data;
- Object *ob = (Object *)ptr->id.data;
-
- data->reader = CacheReader_open_alembic_object(
- data->cache_file->handle, data->reader, ob, data->object_path);
-# endif
-
- rna_Constraint_update(bmain, scene, ptr);
-}
-
#else
static const EnumPropertyItem constraint_distance_items[] = {
@@ -2902,7 +2886,7 @@ static void rna_def_constraint_transform_cache(BlenderRNA *brna)
prop,
"Object Path",
"Path to the object in the Alembic archive used to lookup the transform matrix");
- RNA_def_property_update(prop, 0, "rna_Constraint_transformCache_object_path_update");
+ RNA_def_property_update(prop, 0, "rna_Constraint_update");
}
/* base struct for constraints */
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 8a63bf1a619..4f304f97cac 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -1300,19 +1300,6 @@ static bool rna_SurfaceDeformModifier_is_bound_get(PointerRNA *ptr)
return (((SurfaceDeformModifierData *)ptr->data)->verts != NULL);
}
-static void rna_MeshSequenceCache_object_path_update(Main *bmain, Scene *scene, PointerRNA *ptr)
-{
-# ifdef WITH_ALEMBIC
- MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)ptr->data;
- Object *ob = (Object *)ptr->id.data;
-
- mcmd->reader = CacheReader_open_alembic_object(
- mcmd->cache_file->handle, mcmd->reader, ob, mcmd->object_path);
-# endif
-
- rna_Modifier_update(bmain, scene, ptr);
-}
-
static bool rna_ParticleInstanceModifier_particle_system_poll(PointerRNA *ptr,
const PointerRNA value)
{
@@ -5107,7 +5094,7 @@ static void rna_def_modifier_meshseqcache(BlenderRNA *brna)
prop,
"Object Path",
"Path to the object in the Alembic archive used to lookup geometric data");
- RNA_def_property_update(prop, 0, "rna_MeshSequenceCache_object_path_update");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
static const EnumPropertyItem read_flag_items[] = {
{MOD_MESHSEQ_READ_VERT, "VERT", 0, "Vertex", ""},
diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c
index 7710082150b..760830ffb24 100644
--- a/source/blender/modifiers/intern/MOD_meshsequencecache.c
+++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c
@@ -18,6 +18,11 @@
* \ingroup modifiers
*/
+#include <string.h>
+
+#include "BLI_utildefines.h"
+#include "BLI_string.h"
+
#include "DNA_cachefile_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -47,6 +52,9 @@ static void initData(ModifierData *md)
mcmd->cache_file = NULL;
mcmd->object_path[0] = '\0';
mcmd->read_flag = MOD_MESHSEQ_READ_ALL;
+
+ mcmd->reader = NULL;
+ mcmd->reader_object_path[0] = '\0';
}
static void copyData(const ModifierData *md, ModifierData *target, const int flag)
@@ -59,6 +67,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla
modifier_copyData_generic(md, target, flag);
tmcmd->reader = NULL;
+ tmcmd->reader_object_path[0] = '\0';
}
static void freeData(ModifierData *md)
@@ -66,10 +75,8 @@ static void freeData(ModifierData *md)
MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md;
if (mcmd->reader) {
-#ifdef WITH_ALEMBIC
- CacheReader_free(mcmd->reader);
-#endif
- mcmd->reader = NULL;
+ mcmd->reader_object_path[0] = '\0';
+ BKE_cachefile_reader_free(mcmd->cache_file, &mcmd->reader);
}
}
@@ -93,17 +100,14 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
Mesh *org_mesh = mesh;
Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
+ CacheFile *cache_file = mcmd->cache_file;
const float frame = DEG_get_ctime(ctx->depsgraph);
- const float time = BKE_cachefile_time_offset(mcmd->cache_file, frame, FPS);
+ const float time = BKE_cachefile_time_offset(cache_file, frame, FPS);
const char *err_str = NULL;
- CacheFile *cache_file = (CacheFile *)DEG_get_original_id(&mcmd->cache_file->id);
-
- BKE_cachefile_ensure_handle(G.main, cache_file);
-
- if (!mcmd->reader) {
- mcmd->reader = CacheReader_open_alembic_object(
- cache_file->handle, NULL, ctx->object, mcmd->object_path);
+ if (!mcmd->reader || !STREQ(mcmd->reader_object_path, mcmd->object_path)) {
+ STRNCPY(mcmd->reader_object_path, mcmd->object_path);
+ BKE_cachefile_reader_open(cache_file, &mcmd->reader, ctx->object, mcmd->object_path);
if (!mcmd->reader) {
modifier_setError(md, "Could not create Alembic reader for file %s", cache_file->filepath);
return mesh;