src/raytracer.cc
branchpyrit
changeset 55 f6d75ae82c88
parent 54 dbe3c7a4e0f0
child 56 d4481fc43952
equal deleted inserted replaced
54:dbe3c7a4e0f0 55:f6d75ae82c88
   393 }
   393 }
   394 #endif
   394 #endif
   395 
   395 
   396 void *Raytracer::raytrace_worker(void *d)
   396 void *Raytracer::raytrace_worker(void *d)
   397 {
   397 {
   398 	static const int my_queue_size = 32;
   398 	static const int my_queue_size = 256;
   399 	Raytracer *rt = (Raytracer*)d;
   399 	Raytracer *rt = (Raytracer*)d;
   400 	Sample my_queue[my_queue_size];
   400 	Sample my_queue[my_queue_size];
   401 	Colour my_colours[my_queue_size];
   401 	Colour my_colours[my_queue_size];
   402 	int my_count;
   402 	int my_count;
   403 	Ray ray;
   403 	Ray ray;
   404 	for (;;)
   404 	for (;;)
   405 	{
   405 	{
   406 		pthread_mutex_lock(&rt->sample_queue_mutex);
   406 		pthread_mutex_lock(&rt->sample_queue_mutex);
   407 		pthread_cond_signal(&rt->worker_ready_cond);
       
   408 
       
   409 		while (rt->sample_queue_count == 0)
   407 		while (rt->sample_queue_count == 0)
   410 		{
   408 		{
   411 			if (rt->end_of_samples)
   409 			if (rt->end_of_samples)
   412 			{
   410 			{
   413 				dbgmsg(4, "T thread [%d] exiting\n", pthread_self());
   411 				dbgmsg(4, "T thread [%d] exiting\n", pthread_self());
   422 		else
   420 		else
   423 			my_count = rt->sample_queue_count;
   421 			my_count = rt->sample_queue_count;
   424 		rt->sample_queue_count -= my_count;
   422 		rt->sample_queue_count -= my_count;
   425 
   423 
   426 		// copy samples to local queue
   424 		// copy samples to local queue
   427 		if (rt->sample_queue_pos+my_count >= rt->sample_queue_size)
   425 		if (rt->sample_queue_pos + my_count >= rt->sample_queue_size)
   428 		{
   426 		{
   429 			memcpy(my_queue, rt->sample_queue+rt->sample_queue_pos,
   427 			register int c = rt->sample_queue_size - rt->sample_queue_pos;
   430 				(rt->sample_queue_size - rt->sample_queue_pos)*sizeof(Sample));
   428 			memcpy(my_queue, rt->sample_queue + rt->sample_queue_pos, c*sizeof(Sample));
   431 			my_count -= rt->sample_queue_size - rt->sample_queue_pos;
   429 			memcpy(my_queue + c, rt->sample_queue, (my_count - c)*sizeof(Sample));
   432 			rt->sample_queue_pos = 0;
   430 			rt->sample_queue_pos = my_count - c;
   433 		}
   431 		}
   434 		memcpy(my_queue, rt->sample_queue+rt->sample_queue_pos,
   432 		else
   435 			my_count*sizeof(Sample));
   433 		{
   436 
   434 			memcpy(my_queue, rt->sample_queue + rt->sample_queue_pos,
       
   435 				my_count*sizeof(Sample));
       
   436 			rt->sample_queue_pos += my_count;
       
   437 		}
       
   438 		if (rt->sample_queue_count <= my_queue_size*2)
       
   439 			pthread_cond_signal(&rt->worker_ready_cond);
   437 		pthread_mutex_unlock(&rt->sample_queue_mutex);
   440 		pthread_mutex_unlock(&rt->sample_queue_mutex);
   438 
   441 
   439 		// do the work
   442 		// do the work
   440 		for (int i = 0; i < my_count; i++)
   443 		for (int i = 0; i < my_count; i++)
   441 		{
   444 		{
   454 void Raytracer::render()
   457 void Raytracer::render()
   455 {
   458 {
   456 	if (!sampler || !camera || !top)
   459 	if (!sampler || !camera || !top)
   457 		return;
   460 		return;
   458 
   461 
   459 	static const int sample_queue_size = 2000;
   462 	static const int my_count_max = 256;
   460 	sample_queue = new Sample [sample_queue_size+1];
   463 	sample_queue_size = my_count_max*2*num_threads;
       
   464 	sample_queue = new Sample [sample_queue_size];
   461 	sample_queue_pos = 0;
   465 	sample_queue_pos = 0;
   462 	sample_queue_count = 0;
   466 	sample_queue_count = 0;
   463 	end_of_samples = false;
   467 	end_of_samples = false;
   464 	static const int my_count_max = 512;
   468 	int my_count, my_pos = 0;
   465 	int  my_count, my_pos = 0;
       
   466 	int sampnum = 0, sampdone;
   469 	int sampnum = 0, sampdone;
   467 	bool more_samples;
   470 	bool more_samples;
       
   471 
       
   472 	sampler->init();
   468 
   473 
   469 	// create workers
   474 	// create workers
   470 	dbgmsg(1, "* running %d threads\n", num_threads);
   475 	dbgmsg(1, "* running %d threads\n", num_threads);
   471 	pthread_t threads[num_threads];
   476 	pthread_t threads[num_threads];
   472 	for (int t = 0; t < num_threads; t++)
   477 	for (int t = 0; t < num_threads; t++)
   480 
   485 
   481 	dbgmsg(1, "* raytracing...\n");
   486 	dbgmsg(1, "* raytracing...\n");
   482 	dbgmsg(2, "-  0%% done");
   487 	dbgmsg(2, "-  0%% done");
   483 
   488 
   484 	pthread_mutex_lock(&sampler_mutex);
   489 	pthread_mutex_lock(&sampler_mutex);
   485 	sampler->init();
       
   486 	while ( (sampnum = sampler->initSampleSet()) > 0 )
   490 	while ( (sampnum = sampler->initSampleSet()) > 0 )
   487 	{
   491 	{
   488 		sampdone = 0;
   492 		sampdone = 0;
   489 		for (;;)
   493 		for (;;)
   490 		{
   494 		{
   491 			my_count = 0;
   495 			my_count = 0;
   492 			while ( more_samples = sampler->nextSample(&sample_queue[my_pos++]) )
   496 			while ( more_samples = sampler->nextSample(&sample_queue[my_pos++]) )
   493 			{
   497 			{
   494 				my_count++;
   498 				my_count++;
       
   499 				if (my_pos >= sample_queue_size)
       
   500 					my_pos = 0;
   495 				if (my_count >= my_count_max)
   501 				if (my_count >= my_count_max)
   496 					break;
   502 					break;
   497 				if (my_pos >= sample_queue_size)
   503 			}
   498 					my_pos = 0;
   504 			if (!more_samples && !my_count)
   499 			}
       
   500 			if (!more_samples)
       
   501 				break;
   505 				break;
   502 
   506 
   503 			pthread_mutex_unlock(&sampler_mutex);
   507 			pthread_mutex_unlock(&sampler_mutex);
   504 			pthread_mutex_lock(&sample_queue_mutex);
   508 			pthread_mutex_lock(&sample_queue_mutex);
   505 			sample_queue_count += my_count;
   509 			sample_queue_count += my_count;
   506 
   510 
   507 			// wait for workers if there is enough samples ready on queue
   511 			// wait for workers if there is enough samples ready on queue
   508 			while (sample_queue_count > my_count_max)
   512 			while (sample_queue_count > (2*num_threads-1)*my_count_max)
   509 			{
       
   510 				pthread_cond_signal(&sample_queue_cond);
       
   511 				pthread_cond_wait(&worker_ready_cond, &sample_queue_mutex);
   513 				pthread_cond_wait(&worker_ready_cond, &sample_queue_mutex);
   512 			}
   514 
       
   515 			pthread_cond_signal(&sample_queue_cond);
       
   516 			pthread_mutex_unlock(&sample_queue_mutex);
   513 
   517 
   514 			sampdone += my_count;
   518 			sampdone += my_count;
   515 			dbgmsg(2, "\b\b\b\b\b\b\b\b%2d%% done", (sampdone - sample_queue_count)*100/sampnum);
   519 			dbgmsg(2, "\b\b\b\b\b\b\b\b%2d%% done", (sampdone - sample_queue_count)*100/sampnum);
   516 
   520 
   517 			pthread_cond_signal(&sample_queue_cond);
       
   518 			pthread_mutex_unlock(&sample_queue_mutex);
       
   519 			pthread_mutex_lock(&sampler_mutex);
   521 			pthread_mutex_lock(&sampler_mutex);
   520 		}
   522 		}
   521 		dbgmsg(2, "\b\b\b\b\b\b\b\b100%% done\n");
   523 		dbgmsg(2, "\b\b\b\b\b\b\b\b100%% done\n");
   522 	}
   524 	}
   523 	pthread_mutex_unlock(&sampler_mutex);
   525 	pthread_mutex_unlock(&sampler_mutex);