diff options
author | Janne Karhu <jhkarh@gmail.com> | 2010-09-27 13:58:37 +0400 |
---|---|---|
committer | Janne Karhu <jhkarh@gmail.com> | 2010-09-27 13:58:37 +0400 |
commit | afa4b855caa874d32d0cd0e02524846da58628c1 (patch) | |
tree | e9f7da1bb430aa309ddf32672802d559e1c3e578 /source | |
parent | 03c65a0c01cd463f87bc9ccafebb3e10a7db5527 (diff) |
Fixed: Showing pointcached frames in the timeline was terribly slow when using disk cache.
* The existence of cached frames was checked each frame causing hundreds of disk operations per frame update.
* Pointcache now keeps an updated array of the cached frames for fast "frame exists in cache" queries.
* This fix also speeds up some other pointcache operations nicely.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/intern/pointcache.c | 92 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 1 | ||||
-rw-r--r-- | source/blender/editors/space_time/space_time.c | 15 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_object_force.h | 2 |
4 files changed, 106 insertions, 4 deletions
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 741580048cf..f503858a70f 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -1876,6 +1876,9 @@ int BKE_ptcache_write_cache(PTCacheID *pid, int cfra) else cache->flag |= PTCACHE_FRAMES_SKIPPED; } + + if(cache->cached_frames) + cache->cached_frames[cfra] = 1; if(pf) ptcache_file_close(pf); @@ -1893,6 +1896,9 @@ int BKE_ptcache_write_cache(PTCacheID *pid, int cfra) void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) { int len; /* store the length of the string */ + int i; + int sta = pid->cache->startframe; + int end = pid->cache->endframe; /* mode is same as fopen's modes */ DIR *dir; @@ -1936,6 +1942,8 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) pid->cache->last_exact = MIN2(pid->cache->startframe, 0); BLI_join_dirfile(path_full, path, de->d_name); BLI_delete(path_full, 0, 0); + if(pid->cache->cached_frames) for(i=0; i<end-sta+1; i++) + pid->cache->cached_frames[i] = 0; } else { /* read the number of the file */ int frame, len2 = (int)strlen(de->d_name); @@ -1950,6 +1958,8 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) BLI_join_dirfile(path_full, path, de->d_name); BLI_delete(path_full, 0, 0); + if(frame >=sta && frame <= end) + pid->cache->cached_frames[frame-sta] = 0; } } } @@ -1970,11 +1980,16 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) for(; pm; pm=pm->next) ptcache_free_data(pm); BLI_freelistN(&pid->cache->mem_cache); + + if(pid->cache->cached_frames) for(i=0; i<end-sta+1; i++) + pid->cache->cached_frames[i] = 0; } else { while(pm) { if((mode==PTCACHE_CLEAR_BEFORE && pm->frame < cfra) || (mode==PTCACHE_CLEAR_AFTER && pm->frame > cfra) ) { link = pm; + if(pm->frame >=sta && pm->frame <= end) + pid->cache->cached_frames[pm->frame-sta] = 0; ptcache_free_data(pm); pm = pm->next; BLI_freelinkN(&pid->cache->mem_cache, link); @@ -2004,6 +2019,8 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) } } } + if(pid->cache->cached_frames && cfra>=sta && cfra<=end) + pid->cache->cached_frames[cfra-sta] = 0; break; } @@ -2014,6 +2031,12 @@ int BKE_ptcache_id_exist(PTCacheID *pid, int cfra) { if(!pid->cache) return 0; + + if(cfra<pid->cache->startframe || cfra > pid->cache->endframe) + return 0; + + if(pid->cache->cached_frames && pid->cache->cached_frames[cfra-pid->cache->startframe]==0) + return 0; if(pid->cache->flag & PTCACHE_DISK_CACHE) { char filename[MAX_PTCACHE_FILE]; @@ -2073,6 +2096,73 @@ void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startfra *endframe += (int)(offset+0.5f); } } + + /* verify cached_frames array is up to date */ + if(cache->cached_frames) { + if(MEM_allocN_len(cache->cached_frames) != sizeof(char) * (cache->endframe-cache->startframe+1)) { + MEM_freeN(cache->cached_frames); + cache->cached_frames = NULL; + } + } + + if(cache->cached_frames==NULL) { + int sta=cache->startframe; + int end=cache->endframe; + int i=0; + + cache->cached_frames = MEM_callocN(sizeof(char) * (cache->endframe-cache->startframe+1), "cached frames array"); + + if(pid->cache->flag & PTCACHE_DISK_CACHE) { + /* mode is same as fopen's modes */ + DIR *dir; + struct dirent *de; + char path[MAX_PTCACHE_PATH]; + char filename[MAX_PTCACHE_FILE]; + char ext[MAX_PTCACHE_PATH]; + int len; /* store the length of the string */ + + ptcache_path(pid, path); + + len = BKE_ptcache_id_filename(pid, filename, (int)cfra, 0, 0); /* no path */ + + dir = opendir(path); + if (dir==NULL) + return; + + snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, pid->stack_index); + + while ((de = readdir(dir)) != NULL) { + if (strstr(de->d_name, ext)) { /* do we have the right extension?*/ + if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */ + /* read the number of the file */ + int frame, len2 = (int)strlen(de->d_name); + char num[7]; + + if (len2 > 15) { /* could crash if trying to copy a string out of this range*/ + BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num)); + frame = atoi(num); + + if(frame >= sta && frame <= end) + cache->cached_frames[frame-sta] = 1; + } + } + } + } + closedir(dir); + } + else { + PTCacheMem *pm= pid->cache->mem_cache.first; + PTCacheMem *link= NULL; + + pm= pid->cache->mem_cache.first; + + while(pm) { + if(pm->frame >= sta && pm->frame <= end) + cache->cached_frames[pm->frame-sta] = 1; + pm = pm->next; + } + } + } } int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) @@ -2293,6 +2383,8 @@ void BKE_ptcache_free(PointCache *cache) BKE_ptcache_free_mem(&cache->mem_cache); if(cache->edit && cache->free_edit) cache->free_edit(cache->edit); + if(cache->cached_frames) + MEM_freeN(cache->cached_frames); MEM_freeN(cache); } void BKE_ptcache_free_list(ListBase *ptcaches) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index fc700c8db8b..bccbc451427 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2937,6 +2937,7 @@ static void direct_link_pointcache(FileData *fd, PointCache *cache) cache->simframe= 0; cache->edit= NULL; cache->free_edit= NULL; + cache->cached_frames= NULL; } static void direct_link_pointcache_list(FileData *fd, ListBase *ptcaches, PointCache **ocache) diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c index de9c063f069..bbdd6891199 100644 --- a/source/blender/editors/space_time/space_time.c +++ b/source/blender/editors/space_time/space_time.c @@ -181,6 +181,7 @@ static void time_cache_refresh(const bContext *C, SpaceTime *stime, ARegion *ar) SpaceTimeCache *stc; float *fp, *array; int i, len; + int sta, end; switch(pid->type) { case PTCACHE_TYPE_SOFTBODY: @@ -197,6 +198,11 @@ static void time_cache_refresh(const bContext *C, SpaceTime *stime, ARegion *ar) if (!(stime->cache_display & TIME_CACHE_SMOKE)) continue; break; } + + BKE_ptcache_id_time(pid, CTX_data_scene(C), 0, &sta, &end, NULL); + + if(pid->cache->cached_frames==NULL) + continue; stc= MEM_callocN(sizeof(SpaceTimeCache), "spacetimecache"); @@ -208,14 +214,15 @@ static void time_cache_refresh(const bContext *C, SpaceTime *stime, ARegion *ar) stc->flag |= PTCACHE_DISK_CACHE; /* first allocate with maximum number of frames needed */ - BKE_ptcache_id_time(pid, CTX_data_scene(C), 0, &stc->startframe, &stc->endframe, NULL); - len = (stc->endframe - stc->startframe + 1)*4; + stc->startframe = sta; + stc->endframe = end; + len = (end - sta + 1)*4; fp = array = MEM_callocN(len*2*sizeof(float), "temporary timeline cache array"); /* fill the vertex array with a quad for each cached frame */ - for (i=stc->startframe; i<=stc->endframe; i++) { + for (i=sta; i<=end; i++) { - if (BKE_ptcache_id_exist(pid, i)) { + if (pid->cache->cached_frames[i-sta]) { fp[0] = (float)i; fp[1] = 0.0; fp+=2; diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h index 63a6b8fbe4a..d07db66cb0f 100644 --- a/source/blender/makesdna/DNA_object_force.h +++ b/source/blender/makesdna/DNA_object_force.h @@ -167,6 +167,8 @@ typedef struct PointCache { char prev_name[64]; char info[64]; char path[240]; /* file path */ + char *cached_frames; /* array of length endframe-startframe+1 with flags to indicate cached frames */ + /* can be later used for other per frame flags too if needed */ struct ListBase mem_cache; struct PTCacheEdit *edit; |