src/raytracer.cc
branchpyrit
changeset 50 14a727b70d07
parent 49 558fde7da82a
child 51 89fec8668768
--- a/src/raytracer.cc	Fri Mar 28 00:53:20 2008 +0100
+++ b/src/raytracer.cc	Fri Mar 28 17:13:21 2008 +0100
@@ -396,39 +396,139 @@
 }
 #endif
 
+void *Raytracer::raytrace_worker(void *d)
+{
+	Raytracer *rt = (Raytracer*)d;
+	Sample *sample;
+	Colour col;
+	Ray ray;
+	for (;;)
+	{
+		cout<<"#worker "<<pthread_self()<<" locking queue"<<endl;
+		pthread_mutex_lock(&rt->sample_queue_mutex);
+		pthread_cond_signal(&rt->worker_ready_cond);
+
+		// if queue is empty, wait for samples
+		while (rt->sample_queue.empty()) {
+			if (rt->sample_queue_end)
+			{
+				cout<<"#worker "<<pthread_self()<<" end of queue, unlocking queue and exiting..."<<endl;
+				pthread_mutex_unlock(&rt->sample_queue_mutex);
+				pthread_exit(NULL);
+			}
+			cout<<"#worker "<<pthread_self()<<" waiting for cond"<<endl;
+			pthread_cond_wait(&rt->sample_queue_cond, &rt->sample_queue_mutex);
+		}
+
+
+		sample = rt->sample_queue.front();
+		rt->sample_queue.pop();
+		cout<<"#worker "<<pthread_self()<<" unlocking queue"<<endl;
+		pthread_mutex_unlock(&rt->sample_queue_mutex);
+
+		// do the work
+		cout<<"#worker "<<pthread_self()<<" locking sampler (camera)"<<endl;
+		pthread_mutex_lock(&rt->sampler_mutex);
+		ray = rt->camera->makeRay(sample);
+		cout<<"#worker "<<pthread_self()<<" unlocking sampler (camera)"<<endl;
+		pthread_mutex_unlock(&rt->sampler_mutex);
+
+		cout<<"#worker "<<pthread_self()<<" ray tracing..."<<endl;
+		col = rt->raytrace(ray, 0, NULL);
+		
+		// save the result
+		cout<<"#worker "<<pthread_self()<<" locking sampler"<<endl;
+		pthread_mutex_lock(&rt->sampler_mutex);
+		rt->sampler->saveSample(sample, col);
+		cout<<"#worker "<<pthread_self()<<" unlocking sampler"<<endl;
+		pthread_mutex_unlock(&rt->sampler_mutex);
+
+		delete sample;
+	}
+}
+
 void Raytracer::render()
 {
 	if (!sampler || !camera || !top)
 		return;
 
+	sample_queue_end = false;
+
 	// create workers
-	// ...
+	dbgmsg(1, "* using %d threads\n", num_threads);
+	pthread_t threads[num_threads];
+	for (int t = 0; t < num_threads; t++)
+	{
+		int rc = pthread_create(&threads[t], NULL, raytrace_worker, (void*)this);
+		if (rc) {
+			dbgmsg(0, "\nE pthread_create unsuccessful, return code was %d\n", rc);
+			exit(1);
+		}
+	}
 
 	sampler->init();
 	int sampnum = 0;
+	cout<<"locking sampler"<<endl;
+	pthread_mutex_lock(&sampler_mutex);
 	while ( (sampnum = sampler->initSampleSet()) > 0 )
 	{
-		Sample *sample, *prev = NULL;
-		while ( (sample = sampler->nextSample(prev)) != NULL )
+		Sample *sample;
+		while ( (sample = sampler->nextSample()) != NULL )
 		{
-			Ray ray = camera->makeRay(sample);
-			//raystack->push(ray);
+			cout<<"unlocking sampler and locking queue"<<endl;
+			pthread_mutex_unlock(&sampler_mutex);
+			pthread_mutex_lock(&sample_queue_mutex);
+			sample_queue.push(sample);
 
-			// in worker:
-			Colour col = raytrace(ray, 0, NULL);
-			sampler->saveSample(sample, col);
+			if (sample_queue.size() > 1000)
+			{
+			    while (sample_queue.size() > 100)
+			    {
+				pthread_cond_signal(&sample_queue_cond);
+				pthread_cond_wait(&worker_ready_cond, &sample_queue_mutex);
+			    }
+			}
 
-			delete prev;
-			prev = sample;
+			cout<<"sending signal and unlocking queue"<<endl;
+			pthread_cond_signal(&sample_queue_cond);
+			pthread_mutex_unlock(&sample_queue_mutex);
+
 			sampnum--;
 			if ((sampnum % 1000) == 0)
 				dbgmsg(2, "\b\b\b\b\b\b\b\b%8d", sampnum);
+
+
+			cout<<"locking sampler"<<endl;
+			pthread_mutex_lock(&sampler_mutex);
 		}
 		dbgmsg(2, "\n");
 	}
+	cout<<"unlocking sampler"<<endl;
+	pthread_mutex_unlock(&sampler_mutex);
 
 	// wait for workers
-	// ...
+	dbgmsg(2, "- waiting for threads to finish\n");
+
+	cout<<"locking queue"<<endl;
+	pthread_mutex_lock(&sample_queue_mutex);
+	sample_queue_end = true;
+	while (!sample_queue.empty())
+	{
+		cout<<"broadcasting signal and unlocking queue"<<endl;
+		pthread_cond_broadcast(&sample_queue_cond);
+		pthread_mutex_unlock(&sample_queue_mutex);
+		cout<<"locking queue"<<endl;
+		pthread_mutex_lock(&sample_queue_mutex);
+	}
+	cout<<"broadcasting signal and unlocking queue"<<endl;
+	pthread_cond_broadcast(&sample_queue_cond);
+	pthread_mutex_unlock(&sample_queue_mutex);
+
+	cout<<"joining threads"<<endl;
+	for (int t = 0; t < num_threads; t++)
+		pthread_join(threads[t], NULL);
+
+	cout<<"done!"<<endl;
 
 #if 0