- Renderwin still used a thread-unsafe malloc, in the header text print
- Setting clipping flags in vertices for parts required a mutex lock after
all... I thought it would go fine, but noticed on renders with small
amounts of faces that sometimes faces disappear from a render.
(was doing movie credits, so all faces are visible! Otherwise it would
have hardly been noticable...)
if(ima->ok==0) return NULL;
if(ima->ibuf==NULL) {
if(ima->ok==0) return NULL;
if(ima->ibuf==NULL) {
+ BLI_lock_thread(LOCK_MALLOC);
load_image(ima, IB_rect, G.sce, rd->cfra); /* G.sce is current .blend path */
load_image(ima, IB_rect, G.sce, rd->cfra); /* G.sce is current .blend path */
+ BLI_unlock_thread(LOCK_MALLOC);
if(ima->ibuf==NULL) {
ima->ok= 0;
return NULL;
if(ima->ibuf==NULL) {
ima->ok= 0;
return NULL;
#ifndef BLI_THREADS_H
#define BLI_THREADS_H
#ifndef BLI_THREADS_H
#define BLI_THREADS_H
+/* default lock is to protect MEM_ module calls, one custom lock available now. van be extended */
+#define LOCK_MALLOC 0
+#define LOCK_CUSTOM1 1
+
void BLI_init_threads (ListBase *threadbase, void *(*do_thread)(void *), int tot);
int BLI_available_threads(ListBase *threadbase);
void BLI_init_threads (ListBase *threadbase, void *(*do_thread)(void *), int tot);
int BLI_available_threads(ListBase *threadbase);
void BLI_remove_thread (ListBase *threadbase, void *callerdata);
void BLI_end_threads (ListBase *threadbase);
void BLI_remove_thread (ListBase *threadbase, void *callerdata);
void BLI_end_threads (ListBase *threadbase);
-void BLI_lock_thread (void);
-void BLI_unlock_thread (void);
+void BLI_lock_thread (int type);
+void BLI_unlock_thread (int type);
/* threadsafe version of MEM_malloc and friends */
void *MEM_mallocT(int len, char *name);
/* threadsafe version of MEM_malloc and friends */
void *MEM_mallocT(int len, char *name);
************************************************ */
static pthread_mutex_t _malloc_lock = PTHREAD_MUTEX_INITIALIZER;
************************************************ */
static pthread_mutex_t _malloc_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t _custom1_lock = PTHREAD_MUTEX_INITIALIZER;
/* just a max for security reasons */
#define RE_MAX_THREAD 8
/* just a max for security reasons */
#define RE_MAX_THREAD 8
-void BLI_lock_thread(void)
+void BLI_lock_thread(int type)
- pthread_mutex_lock(&_malloc_lock);
+ if(type==LOCK_MALLOC)
+ pthread_mutex_lock(&_malloc_lock);
+ else
+ pthread_mutex_lock(&_custom1_lock);
-void BLI_unlock_thread(void)
+void BLI_unlock_thread(int type)
- pthread_mutex_unlock(&_malloc_lock);
+ if(type==LOCK_MALLOC)
+ pthread_mutex_unlock(&_malloc_lock);
+ else
+ pthread_mutex_unlock(&_custom1_lock);
env->ima= tex->ima;
if(env->ima && env->ima->ok) {
// Now thread safe
env->ima= tex->ima;
if(env->ima && env->ima->ok) {
// Now thread safe
+ BLI_lock_thread(LOCK_MALLOC);
if(env->ima->ibuf==NULL) ima_ibuf_is_nul(tex, tex->ima);
if(env->ima->ok && env->ok==0) envmap_split_ima(env);
if(env->ima->ibuf==NULL) ima_ibuf_is_nul(tex, tex->ima);
if(env->ima->ok && env->ok==0) envmap_split_ima(env);
+ BLI_unlock_thread(LOCK_MALLOC);
+ BLI_lock_thread(LOCK_MALLOC);
if(ima->ibuf==NULL) ima_ibuf_is_nul(tex, ima);
if(ima->ibuf==NULL) ima_ibuf_is_nul(tex, ima);
+ BLI_unlock_thread(LOCK_MALLOC);
+ BLI_lock_thread(LOCK_MALLOC);
if(ima->ibuf==NULL) ima_ibuf_is_nul(tex, ima);
if(ima->ibuf==NULL) ima_ibuf_is_nul(tex, ima);
+ BLI_unlock_thread(LOCK_MALLOC);
}
if (ima->ok) {
if(tex->imaflag & TEX_MIPMAP) {
if(ima->mipmap[0]==NULL) {
}
if (ima->ok) {
if(tex->imaflag & TEX_MIPMAP) {
if(ima->mipmap[0]==NULL) {
+ BLI_lock_thread(LOCK_MALLOC);
if(ima->mipmap[0]==NULL) makemipmap(tex, ima);
if(ima->mipmap[0]==NULL) makemipmap(tex, ima);
+ BLI_unlock_thread(LOCK_MALLOC);
/* supports up to 4 threads this way */
clipclear= ~(15 << 4*(pa->thread & 3));
/* supports up to 4 threads this way */
clipclear= ~(15 << 4*(pa->thread & 3));
+ /* extra security to prevent access to same data */
+ BLI_lock_thread(LOCK_CUSTOM1);
+
for(v=0; v<R.totvert; v++) {
for(v=0; v<R.totvert; v++) {
- if((v & 255)==0) ver= RE_findOrAddVert(&R, v);
+ if((v & 255)==0)
+ ver= RE_findOrAddVert(&R, v);
else ver++;
wco= ver->ho[3];
else ver++;
wco= ver->ho[3];
+
+ BLI_unlock_thread(LOCK_CUSTOM1);
}
void zbuffer_solid(RenderPart *pa, unsigned int lay, short layflag)
}
void zbuffer_solid(RenderPart *pa, unsigned int lay, short layflag)
#include <limits.h>
#include "BLI_blenlib.h"
#include <limits.h>
#include "BLI_blenlib.h"
+#include "BLI_threads.h"
#include "MEM_guardedalloc.h"
#include "MEM_guardedalloc.h"
/* space for info text */
#define RW_HEADERY 18
/* space for info text */
#define RW_HEADERY 18
+/* header print for window */
+#define RW_MAXTEXT 512
+
typedef struct {
Window *win;
typedef struct {
Window *win;
rw->flags= 0;
rw->zoomofs[0]= rw->zoomofs[1]= 0;
rw->info_text= NULL;
rw->flags= 0;
rw->zoomofs[0]= rw->zoomofs[1]= 0;
rw->info_text= NULL;
- rw->render_text= rw->render_text_spare= NULL;
+ rw->render_text= MEM_callocN(RW_MAXTEXT, "rendertext");
+ rw->render_text_spare= MEM_callocN(RW_MAXTEXT, "rendertext spare");
rw->lmouse[0]= rw->lmouse[1]= 0;
rw->mbut[0]= rw->mbut[1]= rw->mbut[2]= 0;
rw->lmouse[0]= rw->lmouse[1]= 0;
rw->mbut[0]= rw->mbut[1]= rw->mbut[2]= 0;
/* copy imgw-imgh to a temporal 32 bits rect */
if(img_w<1 || img_h<1) return;
/* copy imgw-imgh to a temporal 32 bits rect */
if(img_w<1 || img_h<1) return;
- rc= rect32= MEM_mallocN(img_w*img_h*sizeof(int), "temp 32 bits");
+ /* happens during threaded render... */
+ rc= rect32= MEM_mallocT(img_w*img_h*sizeof(int), "temp 32 bits");
for(y=0; y<img_h; y++) {
rf= rectf;
for(y=0; y<img_h; y++) {
rf= rectf;
glaDrawPixelsSafe(fx, fy, img_w, img_h, img_w, GL_RGBA, GL_UNSIGNED_BYTE, rect32);
glaDrawPixelsSafe(fx, fy, img_w, img_h, img_w, GL_RGBA, GL_UNSIGNED_BYTE, rect32);
}
/* XXX, this is not good, we do this without any regard to state
}
/* XXX, this is not good, we do this without any regard to state
extern char info_time_str[32]; // header_info.c
extern unsigned long mem_in_use, mmap_in_use;
static float megs_used_memory, mmap_used_memory;
extern char info_time_str[32]; // header_info.c
extern unsigned long mem_in_use, mmap_in_use;
static float megs_used_memory, mmap_used_memory;
- char str[300], *spos= str;
+ char *spos= render_win->render_text;
megs_used_memory= (mem_in_use-mmap_in_use)/(1024.0*1024.0);
mmap_used_memory= (mmap_in_use)/(1024.0*1024.0);
megs_used_memory= (mem_in_use-mmap_in_use)/(1024.0*1024.0);
mmap_used_memory= (mmap_in_use)/(1024.0*1024.0);
if(rs->infostr)
spos+= sprintf(spos, " | %s", rs->infostr);
if(rs->infostr)
spos+= sprintf(spos, " | %s", rs->infostr);
- if(render_win->render_text) MEM_freeN(render_win->render_text);
- render_win->render_text= BLI_strdup(str);
+ /* very weak... but 512 characters is quite safe... we cannot malloc during thread render */
+ if(spos >= render_win->render_text+RW_MAXTEXT)
+ printf("WARNING! renderwin text beyond limit \n");
+
#ifdef __APPLE__
#else
glDrawBuffer(GL_FRONT);
#ifdef __APPLE__
#else
glDrawBuffer(GL_FRONT);
/* temporal render debug printing, needed for testing orange renders atm... will be gone soon (or option) */
if(G.rt==7 && rs->convertdone) {
/* temporal render debug printing, needed for testing orange renders atm... will be gone soon (or option) */
if(G.rt==7 && rs->convertdone) {
spos= str;
spos+= sprintf(spos, "Fra:%d Mem:%.2fM (%.2fM)", G.scene->r.cfra, megs_used_memory, mmap_used_memory);
spos= str;
spos+= sprintf(spos, "Fra:%d Mem:%.2fM (%.2fM)", G.scene->r.cfra, megs_used_memory, mmap_used_memory);
window_set_title(render_win->win, renderwin_get_title(1));
}
window_set_title(render_win->win, renderwin_get_title(1));
}
- if(render_win->render_text_spare) MEM_freeN(render_win->render_text_spare);
- render_win->render_text_spare= render_win->render_text;
- render_win->render_text= NULL;
+ BLI_strncpy(render_win->render_text_spare, render_win->render_text, RW_MAXTEXT);
if(render_win->rectspare) MEM_freeN(render_win->rectspare);
render_win->rectspare= NULL;
if(render_win->rectspare) MEM_freeN(render_win->rectspare);
render_win->rectspare= NULL;