Smoke: Patch #20955 / fix by Damien Plisson (damien78)
* Smoke got it's own thread loop now and can be esc'ed now * Apple OpenMP bug workaround until they fix the GCC (couldn't test this one) * removing some "static" keyword to prevent crashing on frame display * should also fix problems with wavelet.noise crashing (Bug #20710) Fluid: * sleep delay has been reduced to be more responsive * Fluid progress is displayed in percent using the mouse cursor (like smoke)
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user