diff options
-rw-r--r-- | intern/smoke/intern/WAVELET_NOISE.h | 46 | ||||
-rw-r--r-- | source/blender/blenkernel/CMakeLists.txt | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/SConscript | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/Makefile | 5 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/pointcache.c | 105 | ||||
-rw-r--r-- | source/blender/editors/physics/physics_fluid.c | 20 |
6 files changed, 153 insertions, 31 deletions
diff --git a/intern/smoke/intern/WAVELET_NOISE.h b/intern/smoke/intern/WAVELET_NOISE.h index 4c2e7514af7..7056b1db5be 100644 --- a/intern/smoke/intern/WAVELET_NOISE.h +++ b/intern/smoke/intern/WAVELET_NOISE.h @@ -42,6 +42,10 @@ #include <MERSENNETWISTER.h> +// Tile file header, update revision upon any change done to the noise generator +static const char tilefile_headerstring[] = "Noise Tile File rev. "; +static const char tilefile_revision[] = "001"; + #define NOISE_TILE_SIZE 128 static const int noiseTileSize = NOISE_TILE_SIZE; @@ -94,7 +98,7 @@ static void downsampleNeumann(const float *from, float *to, int n, int stride) { // if these values are not local incorrect results are generated float downCoeffs[32] = { DOWNCOEFFS }; - static const float *const aCoCenter= &downCoeffs[16]; + const float *const aCoCenter= &downCoeffs[16]; for (int i = 0; i < n / 2; i++) { to[i * stride] = 0; for (int k = 2 * i - 16; k < 2 * i + 16; k++) { @@ -212,6 +216,12 @@ static void upsampleZNeumann(float* to, const float* from, int sx, int sy, int s static bool loadTile(float* const noiseTileData, std::string filename) { FILE* file; + char headerbuffer[64]; + size_t headerlen; + size_t bread; + int endiantest = 1; + char endianness; + file = fopen(filename.c_str(), "rb"); if (file == NULL) { @@ -219,11 +229,28 @@ static bool loadTile(float* const noiseTileData, std::string filename) return false; } + //Check header + headerlen = strlen(tilefile_headerstring) + strlen(tilefile_revision) + 2; + bread = fread((void*)headerbuffer, 1, headerlen, file); + if (*((unsigned char*)&endiantest) == 1) + endianness = 'L'; + else + endianness = 'B'; + if ((bread != headerlen) + || (strncmp(headerbuffer, tilefile_headerstring, strlen(tilefile_headerstring))) + || (strncmp(headerbuffer+ strlen(tilefile_headerstring), tilefile_revision, strlen(tilefile_revision))) + || (headerbuffer[headerlen-2] != endianness) + || (headerbuffer[headerlen-1] != (char)((char)sizeof(long)+'0'))) + { + printf("loadTile : Noise tile '%s' was generated on an incompatible platform.\n",filename.c_str()); + return false; + } + // dimensions size_t gridSize = noiseTileSize * noiseTileSize * noiseTileSize; // noiseTileData memory is managed by caller - size_t bread = fread((void*)noiseTileData, sizeof(float), gridSize, file); + bread = fread((void*)noiseTileData, sizeof(float), gridSize, file); fclose(file); printf("Noise tile file '%s' loaded.\n", filename.c_str()); @@ -241,12 +268,27 @@ static void saveTile(float* const noiseTileData, std::string filename) { FILE* file; file = fopen(filename.c_str(), "wb"); + int endiantest=1; + char longsize; if (file == NULL) { printf("saveTile: Noise tile '%s' could not be saved.\n", filename.c_str()); return; } + //Write file header + fwrite(tilefile_headerstring, strlen(tilefile_headerstring), 1, file); + fwrite(tilefile_revision, strlen(tilefile_revision), 1, file); + //Endianness + if (*((unsigned char*)&endiantest) == 1) + fwrite("L", 1, 1, file); //Little endian + else + fwrite("B",1,1,file); //Big endian + //32/64bit + longsize = (char)sizeof(long)+'0'; + fwrite(&longsize, 1, 1, file); + + fwrite((void*)noiseTileData, sizeof(float), noiseTileSize * noiseTileSize * noiseTileSize, file); fclose(file); diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index b1cbd16512e..68bc7c5bf15 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -73,6 +73,10 @@ ELSE(WITH_PYTHON) ADD_DEFINITIONS(-DDISABLE_PYTHON) ENDIF(WITH_PYTHON) +IF(WITH_OPENMP) + ADD_DEFINITIONS(-DPARALLEL=1) +ENDIF(WITH_OPENMP) + IF(NOT WITH_ELBEEM) ADD_DEFINITIONS(-DDISABLE_ELBEEM) ENDIF(NOT WITH_ELBEEM) diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index 508ed58165f..37a63be6389 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -55,6 +55,10 @@ if env['WITH_BF_QUICKTIME']: if env['WITH_BF_BULLET']: defs.append('USE_BULLET') +if env['OURPLATFORM'] == 'darwin': + if env['WITH_BF_OPENMP']: + defs.append('PARALLEL=1') + if env['BF_NO_ELBEEM']: defs.append('DISABLE_ELBEEM') diff --git a/source/blender/blenkernel/intern/Makefile b/source/blender/blenkernel/intern/Makefile index 95c82d31890..70e1a785787 100644 --- a/source/blender/blenkernel/intern/Makefile +++ b/source/blender/blenkernel/intern/Makefile @@ -129,3 +129,8 @@ ifeq ($(WITH_QUICKTIME), true) CPPFLAGS += -DWITH_QUICKTIME endif +ifeq ($(OS), darwin) + ifeq ($(WITH_BF_OPENMP), true) + CPPFLAGS += -DPARALLEL=1 + endif +endif diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 9bdc700c313..71cea63b0bc 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -42,7 +42,13 @@ #include "DNA_smoke_types.h" #include "BLI_blenlib.h" +#include "BLI_threads.h" +#include "PIL_time.h" + +#include "WM_api.h" + +#include "BKE_blender.h" #include "BKE_cloth.h" #include "BKE_depsgraph.h" #include "BKE_global.h" @@ -58,8 +64,6 @@ #include "BKE_utildefines.h" #include "BIK_api.h" -#include "BLI_blenlib.h" - /* both in intern */ #include "smoke_API.h" @@ -84,6 +88,13 @@ #include "BLI_winstuff.h" #endif +#if defined(__APPLE__) && (PARALLEL == 1) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 2) +/* ************** libgomp (Apple gcc 4.2.1) TLS bug workaround *************** */ +#include <pthread.h> +extern pthread_key_t gomp_tls_key; +static void *thread_tls_data; +#endif + #define PTCACHE_DATA_FROM(data, type, from) if(data[type]) { memcpy(data[type], from, ptcache_data_size[type]); } #define PTCACHE_DATA_TO(data, type, index, to) if(data[type]) { memcpy(to, (char*)data[type] + (index ? index * ptcache_data_size[type] : 0), ptcache_data_size[type]); } @@ -2247,6 +2258,32 @@ void BKE_ptcache_quick_cache_all(Scene *scene) BKE_ptcache_make_cache(&baker); } +/* Simulation thread, no need for interlocks as data written in both threads + are only unitary integers (I/O assumed to be atomic for them) */ +typedef struct { + int break_operation; + int thread_ended; + int endframe; + int step; + int *cfra_ptr; + Scene *scene; +} ptcache_make_cache_data; + +static void *ptcache_make_cache_thread(void *ptr) { + ptcache_make_cache_data *data = (ptcache_make_cache_data*)ptr; + +#if defined(__APPLE__) && (PARALLEL == 1) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 2) + // Workaround for Apple gcc 4.2.1 omp vs background thread bug + pthread_setspecific (gomp_tls_key, thread_tls_data); +#endif + + for(; (*data->cfra_ptr <= data->endframe) && !data->break_operation; *data->cfra_ptr+=data->step) + scene_update_for_newframe(data->scene, data->scene->lay); + + data->thread_ended = TRUE; + return NULL; +} + /* if bake is not given run simulations to current frame */ void BKE_ptcache_make_cache(PTCacheBaker* baker) { @@ -2258,10 +2295,16 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) float frameleno = scene->r.framelen; int cfrao = CFRA; int startframe = MAXFRAME; - int endframe = baker->anim_init ? scene->r.sfra : CFRA; int bake = baker->bake; int render = baker->render; - int step = baker->quick_step; + ListBase threads; + ptcache_make_cache_data thread_data; + int progress, old_progress; + + thread_data.endframe = baker->anim_init ? scene->r.sfra : CFRA; + thread_data.step = baker->quick_step; + thread_data.cfra_ptr = &CFRA; + thread_data.scene = baker->scene; G.afbreek = 0; @@ -2299,11 +2342,11 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) startframe = MAX2(cache->last_exact, cache->startframe); if(bake) { - endframe = cache->endframe; + thread_data.endframe = cache->endframe; cache->flag |= PTCACHE_BAKING; } else { - endframe = MIN2(endframe, cache->endframe); + thread_data.endframe = MIN2(thread_data.endframe, cache->endframe); } cache->flag &= ~PTCACHE_BAKED; @@ -2335,7 +2378,7 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) cache->flag |= PTCACHE_BAKING; if(bake) - endframe = MAX2(endframe, cache->endframe); + thread_data.endframe = MAX2(thread_data.endframe, cache->endframe); } cache->flag &= ~PTCACHE_BAKED; @@ -2345,30 +2388,45 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) BLI_freelistN(&pidlist); } - CFRA= startframe; + CFRA = startframe; scene->r.framelen = 1.0; - - for(; CFRA <= endframe; CFRA+=step) { - int prog; + thread_data.break_operation = FALSE; + thread_data.thread_ended = FALSE; + old_progress = -1; + +#if defined(__APPLE__) && (PARALLEL == 1) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 2) + // Workaround for Apple gcc 4.2.1 omp vs background thread bug + thread_tls_data = pthread_getspecific(gomp_tls_key); +#endif + BLI_init_threads(&threads, ptcache_make_cache_thread, 1); + BLI_insert_thread(&threads, (void*)&thread_data); + + while (thread_data.thread_ended == FALSE) { if(bake) - prog = (int)(100.0f * (float)(CFRA - startframe)/(float)(endframe-startframe)); + progress = (int)(100.0f * (float)(CFRA - startframe)/(float)(thread_data.endframe-startframe)); else - prog = CFRA; + progress = CFRA; /* NOTE: baking should not redraw whole ui as this slows things down */ - if(baker->progressbar) - baker->progressbar(baker->progresscontext, prog); + if ((baker->progressbar) && (progress != old_progress)) { + baker->progressbar(baker->progresscontext, progress); + old_progress = progress; + } - scene_update_for_newframe(scene, scene->lay); + /* Delay to lessen CPU load from UI thread */ + PIL_sleep_ms(200); /* NOTE: breaking baking should leave calculated frames in cache, not clear it */ - if(baker->break_test && baker->break_test(baker->break_data)) - break; + if(blender_test_break() && !thread_data.break_operation) { + thread_data.break_operation = TRUE; + if (baker->progressend) + baker->progressend(baker->progresscontext); + WM_cursor_wait(1); + } } - if (baker->progressend) - baker->progressend(baker->progresscontext); + BLI_end_threads(&threads); /* clear baking flag */ if(pid) { @@ -2391,7 +2449,7 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) cache = pid->cache; - if(step > 1) + if(thread_data.step > 1) cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED); else cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED); @@ -2413,6 +2471,11 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) if(bake) /* already on cfra unless baking */ scene_update_for_newframe(scene, scene->lay); + if (thread_data.break_operation) + WM_cursor_wait(0); + else if (baker->progressend) + baker->progressend(baker->progresscontext); + /* TODO: call redraw all windows somehow */ } /* Helpers */ diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index eec971e777e..b1a3a3be28d 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -109,9 +109,9 @@ static void *thread_tls_data; /* XXX */ /* from header info.c */ static int start_progress_bar(void) {return 0;}; -static void end_progress_bar(void) {}; +static void end_progress_bar(wmWindow *win) {WM_cursor_restore(win);}; static void waitcursor(int val) {}; -static int progress_bar(float done, char *busy_info) {return 0;} +static int progress_bar(wmWindow *win, float done, char *busy_info) { WM_timecursor(win,done*100); return 0;} static int pupmenu() {return 0;} /* XXX */ @@ -1060,7 +1060,7 @@ int fluidsimBake(bContext *C, ReportList *reports, Object *ob) { int done = 0; float noFramesf = (float)noFrames; - float percentdone = 0.0; + float percentdone = 0.0, oldpercentdone = -1.0; int lastRedraw = -1; g_break= 0; @@ -1075,11 +1075,15 @@ int fluidsimBake(bContext *C, ReportList *reports, Object *ob) // lukep we add progress bar as an interim mesure percentdone = globalBakeFrame / noFramesf; - sprintf(busy_mess, "baking fluids %d / %d |||", globalBakeFrame, (int) noFramesf); - progress_bar(percentdone, busy_mess ); + if (percentdone != oldpercentdone) { + sprintf(busy_mess, "baking fluids %d / %d |||", globalBakeFrame, (int) noFramesf); + percentdone = percentdone < 0.0 ? 0.0:percentdone; + progress_bar(CTX_wm_window(C), percentdone, busy_mess ); + oldpercentdone = percentdone; + } - // longer delay to prevent frequent redrawing - PIL_sleep_ms(2000); + //XXX no more need for longer delay to prevent frequent redrawing + PIL_sleep_ms(200); BLI_lock_thread(LOCK_CUSTOM1); if(globalBakeState != 0) done = 1; // 1=ok, <0=error/abort @@ -1121,7 +1125,7 @@ int fluidsimBake(bContext *C, ReportList *reports, Object *ob) #endif } // redraw } - end_progress_bar(); + end_progress_bar(CTX_wm_window(C)); } BLI_end_threads(&threads); } // El'Beem API init, thread creation |