TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata) { TaskPool *pool = MEM_callocN(sizeof(TaskPool), "TaskPool"); pool->scheduler = scheduler; pool->num = 0; pool->num_threads = 0; pool->currently_running_tasks = 0; pool->do_cancel = false; BLI_mutex_init(&pool->num_mutex); BLI_condition_init(&pool->num_cond); pool->userdata = userdata; BLI_mutex_init(&pool->user_mutex); /* Ensure malloc will go fine from threads, * * This is needed because we could be in main thread here * and malloc could be non-threda safe at this point because * no other jobs are running. */ BLI_begin_threaded_malloc(); return pool; }
static TaskPool *task_pool_create_ex(TaskScheduler *scheduler, void *userdata, const bool is_background) { TaskPool *pool = MEM_mallocN(sizeof(TaskPool), "TaskPool"); #ifndef NDEBUG /* Assert we do not try to create a background pool from some parent task - those only work OK from main thread. */ if (is_background) { const pthread_t thread_id = pthread_self(); int i = scheduler->num_threads; while (i--) { BLI_assert(!pthread_equal(scheduler->threads[i], thread_id)); } } #endif pool->scheduler = scheduler; pool->num = 0; pool->done = 0; pool->num_threads = 0; pool->currently_running_tasks = 0; pool->do_cancel = false; pool->run_in_background = is_background; BLI_mutex_init(&pool->num_mutex); BLI_condition_init(&pool->num_cond); pool->userdata = userdata; BLI_mutex_init(&pool->user_mutex); if (BLI_thread_is_main()) { pool->task_mempool = scheduler->task_mempool; } else { pool->task_mempool = &pool->task_mempool_local; pool->task_mempool_local.num_tasks = 0; } #ifdef DEBUG_STATS pool->mempool_stats = MEM_callocN(sizeof(*pool->mempool_stats) * (scheduler->num_threads + 1), "per-taskpool mempool stats"); #endif /* Ensure malloc will go fine from threads, * * This is needed because we could be in main thread here * and malloc could be non-threda safe at this point because * no other jobs are running. */ BLI_begin_threaded_malloc(); return pool; }
/* presumed to be called when no threads are running */ void IMB_tile_cache_params(int totthread, int maxmem) { int a; /* always one cache for non-threaded access */ totthread++; /* lazy initialize cache */ if(GLOBAL_CACHE.totthread == totthread && GLOBAL_CACHE.maxmem == maxmem) return; imb_tile_cache_exit(); memset(&GLOBAL_CACHE, 0, sizeof(ImGlobalTileCache)); GLOBAL_CACHE.tilehash= BLI_ghash_new(imb_global_tile_hash, imb_global_tile_cmp, "tile_cache_params gh"); GLOBAL_CACHE.memarena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "ImTileCache arena"); BLI_memarena_use_calloc(GLOBAL_CACHE.memarena); GLOBAL_CACHE.maxmem= maxmem*1024*1024; GLOBAL_CACHE.totthread= totthread; for(a=0; a<totthread; a++) imb_thread_cache_init(&GLOBAL_CACHE.thread_cache[a]); BLI_mutex_init(&GLOBAL_CACHE.mutex); }
void COM_execute(RenderData *rd, Scene *scene, bNodeTree *editingtree, int rendering, const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings, const char *viewName) { /* initialize mutex, TODO this mutex init is actually not thread safe and * should be done somewhere as part of blender startup, all the other * initializations can be done lazily */ if (is_compositorMutex_init == false) { BLI_mutex_init(&s_compositorMutex); is_compositorMutex_init = true; } BLI_mutex_lock(&s_compositorMutex); if (editingtree->test_break(editingtree->tbh)) { // during editing multiple calls to this method can be triggered. // make sure one the last one will be doing the work. BLI_mutex_unlock(&s_compositorMutex); return; } /* Make sure node tree has previews. * Don't create previews in advance, this is done when adding preview operations. * Reserved preview size is determined by render output for now. */ float aspect = rd->xsch > 0 ? (float)rd->ysch / (float)rd->xsch : 1.0f; BKE_node_preview_init_tree(editingtree, COM_PREVIEW_SIZE, (int)(COM_PREVIEW_SIZE * aspect), false); /* initialize workscheduler, will check if already done. TODO deinitialize somewhere */ bool use_opencl = (editingtree->flag & NTREE_COM_OPENCL) != 0; WorkScheduler::initialize(use_opencl, BKE_render_num_threads(rd)); /* set progress bar to 0% and status to init compositing */ editingtree->progress(editingtree->prh, 0.0); editingtree->stats_draw(editingtree->sdh, IFACE_("Compositing")); bool twopass = (editingtree->flag & NTREE_TWO_PASS) > 0 && !rendering; /* initialize execution system */ if (twopass) { ExecutionSystem *system = new ExecutionSystem(rd, scene, editingtree, rendering, twopass, viewSettings, displaySettings, viewName); system->execute(); delete system; if (editingtree->test_break(editingtree->tbh)) { // during editing multiple calls to this method can be triggered. // make sure one the last one will be doing the work. BLI_mutex_unlock(&s_compositorMutex); return; } } ExecutionSystem *system = new ExecutionSystem(rd, scene, editingtree, rendering, false, viewSettings, displaySettings, viewName); system->execute(); delete system; BLI_mutex_unlock(&s_compositorMutex); }
void imb_tile_cache_init(void) { memset(&GLOBAL_CACHE, 0, sizeof(ImGlobalTileCache)); BLI_mutex_init(&GLOBAL_CACHE.mutex); /* initialize for one thread, for places that access textures outside of rendering (displace modifier, painting, ..) */ IMB_tile_cache_params(0, 0); GLOBAL_CACHE.initialized = 1; }
TaskScheduler *BLI_task_scheduler_create(int num_threads) { TaskScheduler *scheduler = MEM_callocN(sizeof(TaskScheduler), "TaskScheduler"); /* multiple places can use this task scheduler, sharing the same * threads, so we keep track of the number of users. */ scheduler->do_exit = false; BLI_listbase_clear(&scheduler->queue); BLI_mutex_init(&scheduler->queue_mutex); BLI_condition_init(&scheduler->queue_cond); if (num_threads == 0) { /* automatic number of threads will be main thread + num cores */ num_threads = BLI_system_thread_count(); } /* main thread will also work, so we count it too */ num_threads -= 1; /* Add background-only thread if needed. */ if (num_threads == 0) { scheduler->background_thread_only = true; num_threads = 1; } /* launch threads that will be waiting for work */ if (num_threads > 0) { int i; scheduler->num_threads = num_threads; scheduler->threads = MEM_callocN(sizeof(pthread_t) * num_threads, "TaskScheduler threads"); scheduler->task_threads = MEM_callocN(sizeof(TaskThread) * num_threads, "TaskScheduler task threads"); for (i = 0; i < num_threads; i++) { TaskThread *thread = &scheduler->task_threads[i]; thread->scheduler = scheduler; thread->id = i + 1; if (pthread_create(&scheduler->threads[i], NULL, task_scheduler_thread_run, thread) != 0) { fprintf(stderr, "TaskScheduler failed to launch thread %d/%d\n", i, num_threads); } } scheduler->task_mempool = MEM_callocN(sizeof(*scheduler->task_mempool) * (num_threads + 1), "TaskScheduler task_mempool"); } return scheduler; }
KX_BlenderSceneConverter::KX_BlenderSceneConverter( Main *maggie, KX_KetsjiEngine *engine) :m_maggie(maggie), m_ketsjiEngine(engine), m_alwaysUseExpandFraming(false), m_usemat(false), m_useglslmat(false), m_use_mat_cache(true) { BKE_main_id_tag_all(maggie, LIB_TAG_DOIT, false); /* avoid re-tagging later on */ m_newfilename = ""; m_threadinfo = new ThreadInfo(); m_threadinfo->m_pool = BLI_task_pool_create(engine->GetTaskScheduler(), NULL); BLI_mutex_init(&m_threadinfo->m_mutex); }
void NodeOperation::initMutex() { BLI_mutex_init(&this->m_mutex); }
ThreadMutex *BLI_mutex_alloc(void) { ThreadMutex *mutex = MEM_callocN(sizeof(ThreadMutex), "ThreadMutex"); BLI_mutex_init(mutex); return mutex; }
static bool screen_opengl_render_init(bContext *C, wmOperator *op) { /* new render clears all callbacks */ wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win = CTX_wm_window(C); Scene *scene = CTX_data_scene(C); ScrArea *prevsa = CTX_wm_area(C); ARegion *prevar = CTX_wm_region(C); GPUOffScreen *ofs; OGLRender *oglrender; int sizex, sizey; const int samples = (scene->r.mode & R_OSA) ? scene->r.osa : 0; const bool full_samples = (samples != 0) && (scene->r.scemode & R_FULL_SAMPLE); bool is_view_context = RNA_boolean_get(op->ptr, "view_context"); const bool is_animation = RNA_boolean_get(op->ptr, "animation"); const bool is_sequencer = RNA_boolean_get(op->ptr, "sequencer"); const bool is_write_still = RNA_boolean_get(op->ptr, "write_still"); char err_out[256] = "unknown"; if (G.background) { BKE_report(op->reports, RPT_ERROR, "Cannot use OpenGL render in background mode (no opengl context)"); return false; } /* only one render job at a time */ if (WM_jobs_test(wm, scene, WM_JOB_TYPE_RENDER)) return false; if (is_sequencer) { is_view_context = false; } else { /* ensure we have a 3d view */ if (!ED_view3d_context_activate(C)) { RNA_boolean_set(op->ptr, "view_context", false); is_view_context = false; } if (!is_view_context && scene->camera == NULL) { BKE_report(op->reports, RPT_ERROR, "Scene has no camera"); return false; } } if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) { BKE_report(op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected"); return false; } /* stop all running jobs, except screen one. currently previews frustrate Render */ WM_jobs_kill_all_except(wm, CTX_wm_screen(C)); /* create offscreen buffer */ sizex = (scene->r.size * scene->r.xsch) / 100; sizey = (scene->r.size * scene->r.ysch) / 100; /* corrects render size with actual size, not every card supports non-power-of-two dimensions */ ofs = GPU_offscreen_create(sizex, sizey, full_samples ? 0 : samples, GPU_HDR_NONE, GPU_OFFSCREEN_DEPTH_COMPARE, err_out); if (!ofs) { BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer, %s", err_out); return false; } /* allocate opengl render */ oglrender = MEM_callocN(sizeof(OGLRender), "OGLRender"); op->customdata = oglrender; oglrender->ofs = ofs; oglrender->ofs_samples = samples; oglrender->ofs_full_samples = full_samples; oglrender->sizex = sizex; oglrender->sizey = sizey; oglrender->bmain = CTX_data_main(C); oglrender->scene = scene; oglrender->cfrao = scene->r.cfra; oglrender->write_still = is_write_still && !is_animation; oglrender->is_animation = is_animation; oglrender->views_len = BKE_scene_multiview_num_views_get(&scene->r); oglrender->is_sequencer = is_sequencer; if (is_sequencer) { oglrender->sseq = CTX_wm_space_seq(C); ImBuf **ibufs_arr = MEM_callocN(sizeof(*ibufs_arr) * oglrender->views_len, __func__); oglrender->seq_data.ibufs_arr = ibufs_arr; } oglrender->prevsa = prevsa; oglrender->prevar = prevar; if (is_view_context) { ED_view3d_context_user_region(C, &oglrender->v3d, &oglrender->ar); /* so quad view renders camera */ oglrender->rv3d = oglrender->ar->regiondata; /* MUST be cleared on exit */ oglrender->scene->customdata_mask_modal = ED_view3d_datamask(oglrender->scene, oglrender->v3d); /* apply immediately in case we're rendering from a script, * running notifiers again will overwrite */ oglrender->scene->customdata_mask |= oglrender->scene->customdata_mask_modal; if (oglrender->v3d->fx_settings.fx_flag & (GPU_FX_FLAG_DOF | GPU_FX_FLAG_SSAO)) { oglrender->fx = GPU_fx_compositor_create(); } } /* create render */ oglrender->re = RE_NewRender(scene->id.name); /* create image and image user */ oglrender->ima = BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"); BKE_image_signal(oglrender->ima, NULL, IMA_SIGNAL_FREE); BKE_image_backup_render(oglrender->scene, oglrender->ima, true); oglrender->iuser.scene = scene; oglrender->iuser.ok = 1; /* create render result */ RE_InitState(oglrender->re, NULL, &scene->r, NULL, sizex, sizey, NULL); /* create render views */ screen_opengl_views_setup(oglrender); /* wm vars */ oglrender->wm = wm; oglrender->win = win; oglrender->totvideos = 0; oglrender->mh = NULL; oglrender->movie_ctx_arr = NULL; if (is_animation) { TaskScheduler *task_scheduler = BLI_task_scheduler_get(); if (BKE_imtype_is_movie(scene->r.im_format.imtype)) { task_scheduler = BLI_task_scheduler_create(1); oglrender->task_scheduler = task_scheduler; oglrender->task_pool = BLI_task_pool_create_background(task_scheduler, oglrender); BLI_pool_set_num_threads(oglrender->task_pool, 1); } else { oglrender->task_scheduler = NULL; oglrender->task_pool = BLI_task_pool_create(task_scheduler, oglrender); } oglrender->pool_ok = true; BLI_spin_init(&oglrender->reports_lock); } else { oglrender->task_scheduler = NULL; oglrender->task_pool = NULL; } oglrender->num_scheduled_frames = 0; BLI_mutex_init(&oglrender->task_mutex); BLI_condition_init(&oglrender->task_condition); #ifdef DEBUG_TIME oglrender->time_start = PIL_check_seconds_timer(); #endif return true; }