Example #1
0
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;
}
Example #2
0
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;
}
Example #3
0
/* 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);
}
Example #5
0
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;
}
Example #6
0
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);
}
Example #8
0
void NodeOperation::initMutex()
{
  BLI_mutex_init(&this->m_mutex);
}
Example #9
0
ThreadMutex *BLI_mutex_alloc(void)
{
	ThreadMutex *mutex = MEM_callocN(sizeof(ThreadMutex), "ThreadMutex");
	BLI_mutex_init(mutex);
	return mutex;
}
Example #10
0
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;
}