Possible fix for #9691: blender failing to allocate memory when rendering
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Wed, 7 May 2008 19:25:43 +0000 (19:25 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Wed, 7 May 2008 19:25:43 +0000 (19:25 +0000)
particles on windows, now allocates smaller chunks of memory.

source/blender/blenkernel/intern/particle.c
source/blender/blenloader/intern/readfile.c
source/blender/makesdna/DNA_particle_types.h

index 2aa0d0ad0b89df7fd038ff823727541069fd8cda..fec3da752ff6bdb576b88be4c04649bcf29236dc 100644 (file)
@@ -152,6 +152,49 @@ char *psys_menu_string(Object *ob, int for_sb)
 
        return str;
 }
+
+/* we allocate path cache memory in chunks instead of a big continguous
+ * chunk, windows' memory allocater fails to find big blocks of memory often */
+
+#define PATH_CACHE_BUF_SIZE 1024
+
+static ParticleCacheKey **psys_alloc_path_cache_buffers(ListBase *bufs, int tot, int steps)
+{
+       LinkData *buf;
+       ParticleCacheKey **cache;
+       int i, totkey, totbufkey;
+
+       tot= MAX2(tot, 1);
+       totkey = 0;
+       cache = MEM_callocN(tot*sizeof(void*), "PathCacheArray");
+
+       while(totkey < tot) {
+               totbufkey= MIN2(tot-totkey, PATH_CACHE_BUF_SIZE);
+               buf= MEM_callocN(sizeof(LinkData), "PathCacheLinkData");
+               buf->data= MEM_callocN(sizeof(ParticleCacheKey)*totbufkey*steps, "ParticleCacheKey");
+
+               for(i=0; i<totbufkey; i++)
+                       cache[totkey+i] = ((ParticleCacheKey*)buf->data) + i*steps;
+
+               totkey += totbufkey;
+               BLI_addtail(bufs, buf);
+       }
+
+       return cache;
+}
+
+static void psys_free_path_cache_buffers(ParticleCacheKey **cache, ListBase *bufs)
+{
+       LinkData *buf;
+
+       if(cache)
+               MEM_freeN(cache);
+
+       for(buf= bufs->first; buf; buf=buf->next)
+               MEM_freeN(buf->data);
+       BLI_freelistN(bufs);
+}
+
 /************************************************/
 /*                     Getting stuff                                           */
 /************************************************/
@@ -306,27 +349,16 @@ void free_keyed_keys(ParticleSystem *psys)
 }
 void free_child_path_cache(ParticleSystem *psys)
 {
-       if(psys->childcache){
-               if(psys->childcache[0])
-                       MEM_freeN(psys->childcache[0]);
-
-               MEM_freeN(psys->childcache);
-
-               psys->childcache = NULL;
-               psys->totchildcache = 0;
-       }
+       psys_free_path_cache_buffers(psys->childcache, &psys->childcachebufs);
+       psys->childcache = NULL;
+       psys->totchildcache = 0;
 }
 void psys_free_path_cache(ParticleSystem *psys)
 {
-       if(psys->pathcache){
-               if(psys->pathcache[0])
-                       MEM_freeN(psys->pathcache[0]);
-
-               MEM_freeN(psys->pathcache);
+       psys_free_path_cache_buffers(psys->pathcache, &psys->pathcachebufs);
+       psys->pathcache= NULL;
+       psys->totcached= 0;
 
-               psys->pathcache = NULL;
-               psys->totcached = 0;
-       }
        free_child_path_cache(psys);
 }
 void psys_free_children(ParticleSystem *psys)
@@ -2257,10 +2289,9 @@ void psys_cache_child_paths(Object *ob, ParticleSystem *psys, float cfra, int ed
        ParticleSettings *part = psys->part;
        ParticleThread *pthreads;
        ParticleThreadContext *ctx;
-       ParticleCacheKey **cache, *tcache;
+       ParticleCacheKey **cache;
        ListBase threads;
        int i, totchild, totparent, totthread;
-       unsigned long totchildstep;
 
        pthreads= psys_threads_create(ob, psys);
 
@@ -2279,13 +2310,7 @@ void psys_cache_child_paths(Object *ob, ParticleSystem *psys, float cfra, int ed
        else {
                /* clear out old and create new empty path cache */
                free_child_path_cache(psys);
-
-               cache = psys->childcache = MEM_callocN(totchild*sizeof(void *), "Child path cache array");
-               totchildstep= totchild*(ctx->steps + 1);
-               tcache = MEM_callocN(totchildstep*sizeof(ParticleCacheKey), "Child path cache");
-               for(i=0; i<totchild; i++)
-                       cache[i] = tcache + i * (ctx->steps + 1);
-
+               psys->childcache= psys_alloc_path_cache_buffers(&psys->childcachebufs, totchild, ctx->steps+1);
                psys->totchildcache = totchild;
        }
 
@@ -2372,12 +2397,8 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda
        else {
                /* clear out old and create new empty path cache */
                psys_free_path_cache(psys);
-
-               /* allocate cache array for fast access and set pointers to contiguous mem block */
-               cache = psys->pathcache = MEM_callocN(MAX2(1, totpart) * sizeof(void *), "Path cache array");
-               cache[0] = MEM_callocN(totpart * (steps + 1) * sizeof(ParticleCacheKey), "Path cache");
-               for(i=1; i<totpart; i++)
-                       cache[i] = cache[0] + i * (steps + 1);
+               cache= psys_alloc_path_cache_buffers(&psys->pathcachebufs, totpart, steps+1);
+               psys->pathcache= cache;
        }
 
        if(edit==NULL && psys->soft && psys->softflag & OB_SB_ENABLE)
index 24606bd822fe30ea1546d04b535f79d5a5677df3..8d315ba37e132973942a3263fc9a3ee5119536ac 100644 (file)
@@ -2615,6 +2615,8 @@ static void direct_link_particlesystems(FileData *fd, ListBase *particles)
                psys->edit = 0;
                psys->pathcache = 0;
                psys->childcache = 0;
+               psys->pathcachebufs.first = psys->pathcachebufs.last = 0;
+               psys->childcachebufs.first = psys->childcachebufs.last = 0;
                psys->reactevents.first = psys->reactevents.last = 0;
 
                psys->pointcache= newdataadr(fd, psys->pointcache);
index 8122cdd9cc7b898932249147c89ad7d2f07a9a8e..e5f781a3365da253dc21371f57c8e5f6ce3ad801 100644 (file)
@@ -171,24 +171,24 @@ typedef struct ParticleSettings {
 typedef struct ParticleSystem{
        struct ParticleSystem *next, *prev;
 
-       ParticleSettings *part;
+       ParticleSettings *part;                                 /* particle settings */
 
-       ParticleData *particles;
+       ParticleData *particles;                                /* (parent) particles */
+       ChildParticle *child;                                   /* child particles */
 
-       ChildParticle *child;
+       struct ParticleEdit *edit;                              /* particle editmode (runtime) */
 
-       struct ParticleEdit *edit;
+       struct ParticleCacheKey **pathcache;    /* path cache (runtime) */
+       struct ParticleCacheKey **childcache;   /* child cache (runtime) */
+       ListBase pathcachebufs, childcachebufs; /* buffers for the above */
 
-       struct ParticleCacheKey **pathcache;
-       struct ParticleCacheKey **childcache;
-
-       struct SoftBody *soft;
+       struct SoftBody *soft;                                  /* hair softbody */
 
        struct Object *target_ob;
        struct Object *keyed_ob;
        struct Object *lattice;
 
-       struct ListBase effectors, reactevents;
+       struct ListBase effectors, reactevents; /* runtime */
        
        float imat[4][4];       /* used for duplicators */
        float cfra;
@@ -196,10 +196,10 @@ typedef struct ParticleSystem{
        int flag, totpart, totchild, totcached, totchildcache, rt;
        short recalc, target_psys, keyed_psys, totkeyed, softflag, bakespace;
 
-       char bb_uvname[3][32];
+       char bb_uvname[3][32];                                  /* billboard uv name */
 
        /* if you change these remember to update array lengths to PSYS_TOT_VG! */
-       short vgroup[11], vg_neg, rt3[2];
+       short vgroup[11], vg_neg, rt3[2];               /* vertex groups */
 
        /* temporary storage during render */
        void *renderdata;