src/raytracer.cc
branchpyrit
changeset 54 dbe3c7a4e0f0
parent 53 228cb8bfdd54
child 55 f6d75ae82c88
equal deleted inserted replaced
53:228cb8bfdd54 54:dbe3c7a4e0f0
   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 	Raytracer *rt = (Raytracer*)d;
   399 	Raytracer *rt = (Raytracer*)d;
   399 	Sample my_queue[80];
   400 	Sample my_queue[my_queue_size];
   400 	Colour my_colours[80];
   401 	Colour my_colours[my_queue_size];
   401 	int my_count;
   402 	int my_count;
   402 	Ray ray;
   403 	Ray ray;
   403 	for (;;)
   404 	for (;;)
   404 	{
   405 	{
   405 		pthread_mutex_lock(&rt->sample_queue_mutex);
   406 		pthread_mutex_lock(&rt->sample_queue_mutex);
   406 		pthread_cond_signal(&rt->worker_ready_cond);
   407 		pthread_cond_signal(&rt->worker_ready_cond);
   407 
   408 
   408 		while (rt->sample_queue_count == 0)
   409 		while (rt->sample_queue_count == 0)
   409 		{
   410 		{
   410 			if (rt->sample_queue_end)
   411 			if (rt->end_of_samples)
   411 			{
   412 			{
   412 				dbgmsg(4, "T thread [%d] exiting\n", pthread_self());
   413 				dbgmsg(4, "T thread [%d] exiting\n", pthread_self());
   413 				pthread_mutex_unlock(&rt->sample_queue_mutex);
   414 				pthread_mutex_unlock(&rt->sample_queue_mutex);
   414 				pthread_exit(NULL);
   415 				pthread_exit(NULL);
   415 			}
   416 			}
   416 			pthread_cond_wait(&rt->sample_queue_cond, &rt->sample_queue_mutex);
   417 			pthread_cond_wait(&rt->sample_queue_cond, &rt->sample_queue_mutex);
   417 		}
   418 		}
   418 
   419 
   419 		if (rt->sample_queue_count >= 80)
   420 		if (rt->sample_queue_count >= my_queue_size)
   420 			my_count = 80;
   421 			my_count = my_queue_size;
   421 		else
   422 		else
   422 			my_count = rt->sample_queue_count;
   423 			my_count = rt->sample_queue_count;
   423 		rt->sample_queue_count -= my_count;
   424 		rt->sample_queue_count -= my_count;
   424 
   425 
   425 		for (int i = 0; i < my_count; i++)
   426 		// copy samples to local queue
   426 		{
   427 		if (rt->sample_queue_pos+my_count >= rt->sample_queue_size)
   427 			my_queue[i] = rt->sample_queue[rt->sample_queue_pos++];
   428 		{
   428 			if (rt->sample_queue_pos > rt->sample_queue_max)
   429 			memcpy(my_queue, rt->sample_queue+rt->sample_queue_pos,
   429 				rt->sample_queue_pos = 0;
   430 				(rt->sample_queue_size - rt->sample_queue_pos)*sizeof(Sample));
   430 		}
   431 			my_count -= rt->sample_queue_size - rt->sample_queue_pos;
       
   432 			rt->sample_queue_pos = 0;
       
   433 		}
       
   434 		memcpy(my_queue, rt->sample_queue+rt->sample_queue_pos,
       
   435 			my_count*sizeof(Sample));
   431 
   436 
   432 		pthread_mutex_unlock(&rt->sample_queue_mutex);
   437 		pthread_mutex_unlock(&rt->sample_queue_mutex);
   433 
   438 
   434 		// do the work
   439 		// do the work
   435 		for (int i = 0; i < my_count; i++)
   440 		for (int i = 0; i < my_count; i++)
   449 void Raytracer::render()
   454 void Raytracer::render()
   450 {
   455 {
   451 	if (!sampler || !camera || !top)
   456 	if (!sampler || !camera || !top)
   452 		return;
   457 		return;
   453 
   458 
   454 	sample_queue_end = false;
   459 	static const int sample_queue_size = 2000;
   455 	sample_queue_max = 2000;
   460 	sample_queue = new Sample [sample_queue_size+1];
   456 	sample_queue = new Sample [sample_queue_max+1];
       
   457 	sample_queue_pos = 0;
   461 	sample_queue_pos = 0;
   458 	sample_queue_count = 0;
   462 	sample_queue_count = 0;
       
   463 	end_of_samples = false;
       
   464 	static const int my_count_max = 512;
       
   465 	int  my_count, my_pos = 0;
       
   466 	int sampnum = 0, sampdone;
       
   467 	bool more_samples;
   459 
   468 
   460 	// create workers
   469 	// create workers
   461 	dbgmsg(1, "* running %d threads\n", num_threads);
   470 	dbgmsg(1, "* running %d threads\n", num_threads);
   462 	pthread_t threads[num_threads];
   471 	pthread_t threads[num_threads];
   463 	for (int t = 0; t < num_threads; t++)
   472 	for (int t = 0; t < num_threads; t++)
   470 	}
   479 	}
   471 
   480 
   472 	dbgmsg(1, "* raytracing...\n");
   481 	dbgmsg(1, "* raytracing...\n");
   473 	dbgmsg(2, "-  0%% done");
   482 	dbgmsg(2, "-  0%% done");
   474 
   483 
       
   484 	pthread_mutex_lock(&sampler_mutex);
   475 	sampler->init();
   485 	sampler->init();
   476 	int sampnum = 0, sampdone;
       
   477 	int my_pos = 0, my_count;
       
   478 	bool more_samples;
       
   479 
       
   480 	pthread_mutex_lock(&sampler_mutex);
       
   481 	while ( (sampnum = sampler->initSampleSet()) > 0 )
   486 	while ( (sampnum = sampler->initSampleSet()) > 0 )
   482 	{
   487 	{
   483 		sampdone = 0;
   488 		sampdone = 0;
   484 		for (;;)
   489 		for (;;)
   485 		{
   490 		{
   486 			my_count = 0;
   491 			my_count = 0;
   487 			while ( more_samples = sampler->nextSample(&sample_queue[my_pos++]) )
   492 			while ( more_samples = sampler->nextSample(&sample_queue[my_pos++]) )
   488 			{
   493 			{
   489 				my_count++;
   494 				my_count++;
   490 				if (my_count >= 1000)
   495 				if (my_count >= my_count_max)
   491 					break;
   496 					break;
   492 				if (my_pos > sample_queue_max)
   497 				if (my_pos >= sample_queue_size)
   493 					my_pos = 0;
   498 					my_pos = 0;
   494 			}
   499 			}
   495 			if (!more_samples)
   500 			if (!more_samples)
   496 				break;
   501 				break;
   497 
   502 
   498 			pthread_mutex_unlock(&sampler_mutex);
   503 			pthread_mutex_unlock(&sampler_mutex);
   499 			pthread_mutex_lock(&sample_queue_mutex);
   504 			pthread_mutex_lock(&sample_queue_mutex);
   500 			sample_queue_count += my_count;
   505 			sample_queue_count += my_count;
   501 
   506 
   502 			// wait for workers if there is enough samples ready on queue
   507 			// wait for workers if there is enough samples ready on queue
   503 			while (sample_queue_count > 1000)
   508 			while (sample_queue_count > my_count_max)
   504 			{
   509 			{
   505 				pthread_cond_signal(&sample_queue_cond);
   510 				pthread_cond_signal(&sample_queue_cond);
   506 				pthread_cond_wait(&worker_ready_cond, &sample_queue_mutex);
   511 				pthread_cond_wait(&worker_ready_cond, &sample_queue_mutex);
   507 			}
   512 			}
   508 
   513 
   519 
   524 
   520 	// wait for workers
   525 	// wait for workers
   521 	dbgmsg(2, "- waiting for threads to finish\n");
   526 	dbgmsg(2, "- waiting for threads to finish\n");
   522 
   527 
   523 	pthread_mutex_lock(&sample_queue_mutex);
   528 	pthread_mutex_lock(&sample_queue_mutex);
   524 	sample_queue_end = true;
   529 	end_of_samples = true;
   525 	while (sample_queue_count)
   530 	while (sample_queue_count)
   526 	{
   531 	{
   527 		pthread_cond_broadcast(&sample_queue_cond);
   532 		pthread_cond_broadcast(&sample_queue_cond);
   528 		pthread_mutex_unlock(&sample_queue_mutex);
   533 		pthread_mutex_unlock(&sample_queue_mutex);
   529 		pthread_mutex_lock(&sample_queue_mutex);
   534 		pthread_mutex_lock(&sample_queue_mutex);