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); |