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