diff options
Diffstat (limited to 'src/modules/ray')
-rw-r--r-- | src/modules/ray/Makefile.am | 2 | ||||
-rw-r--r-- | src/modules/ray/ray.c | 1 | ||||
-rw-r--r-- | src/modules/ray/ray_scene.c | 17 | ||||
-rw-r--r-- | src/modules/ray/ray_scene.h | 2 | ||||
-rw-r--r-- | src/modules/ray/ray_threads.c | 111 | ||||
-rw-r--r-- | src/modules/ray/ray_threads.h | 30 |
6 files changed, 1 insertions, 162 deletions
diff --git a/src/modules/ray/Makefile.am b/src/modules/ray/Makefile.am index 7acfdd8..957b6d1 100644 --- a/src/modules/ray/Makefile.am +++ b/src/modules/ray/Makefile.am @@ -1,4 +1,4 @@ noinst_LIBRARIES = libray.a -libray_a_SOURCES = ray_3f.h ray.c ray_camera.c ray_camera.h ray_color.h ray_euler.c ray_euler.h ray.h ray_light_emitter.h ray_object.c ray_object.h ray_object_light.h ray_object_plane.h ray_object_point.h ray_object_sphere.h ray_object_type.h ray_ray.h ray_scene.c ray_scene.h ray_surface.h ray_threads.c ray_threads.h +libray_a_SOURCES = ray_3f.h ray.c ray_camera.c ray_camera.h ray_color.h ray_euler.c ray_euler.h ray.h ray_light_emitter.h ray_object.c ray_object.h ray_object_light.h ray_object_plane.h ray_object_point.h ray_object_sphere.h ray_object_type.h ray_ray.h ray_scene.c ray_scene.h ray_surface.h libray_a_CFLAGS = @ROTOTILLER_CFLAGS@ -ffast-math libray_a_CPPFLAGS = @ROTOTILLER_CFLAGS@ -I@top_srcdir@/src diff --git a/src/modules/ray/ray.c b/src/modules/ray/ray.c index 9847bd9..e79bfaf 100644 --- a/src/modules/ray/ray.c +++ b/src/modules/ray/ray.c @@ -9,7 +9,6 @@ #include "ray_camera.h" #include "ray_object.h" #include "ray_scene.h" -#include "ray_threads.h" /* Copyright (C) 2016-2017 Vito Caputo <vcaputo@pengaru.com> */ diff --git a/src/modules/ray/ray_scene.c b/src/modules/ray/ray_scene.c index b4cddad..e2c7f2c 100644 --- a/src/modules/ray/ray_scene.c +++ b/src/modules/ray/ray_scene.c @@ -8,7 +8,6 @@ #include "ray_object.h" #include "ray_ray.h" #include "ray_scene.h" -#include "ray_threads.h" #define MAX_RECURSION_DEPTH 5 @@ -168,19 +167,3 @@ void ray_scene_render_fragment(ray_scene_t *scene, ray_camera_t *camera, fb_frag buf += stride; } while (ray_camera_frame_y_step(&frame)); } - -/* we expect fragments[threads->n_threads + 1], or fragments[1] when threads == NULL */ -void ray_scene_render_fragments(ray_scene_t *scene, ray_camera_t *camera, ray_threads_t *threads, fb_fragment_t *fragments) -{ - unsigned n_threads = threads ? threads->n_threads + 1 : 1; - unsigned i; - - for (i = 1; i < n_threads; i++) - ray_thread_fragment_submit(&threads->threads[i - 1], scene, camera, &fragments[i]); - - /* always render the zero fragment in-line */ - ray_scene_render_fragment(scene, camera, &fragments[0]); - - for (i = 1; i < n_threads; i++) - ray_thread_wait_idle(&threads->threads[i - 1]); -} diff --git a/src/modules/ray/ray_scene.h b/src/modules/ray/ray_scene.h index e9781c6..9a31d80 100644 --- a/src/modules/ray/ray_scene.h +++ b/src/modules/ray/ray_scene.h @@ -6,7 +6,6 @@ #include "ray_camera.h" #include "ray_color.h" #include "ray_ray.h" -#include "ray_threads.h" typedef union ray_object_t ray_object_t; @@ -21,7 +20,6 @@ typedef struct ray_scene_t { float ambient_brightness; } ray_scene_t; -void ray_scene_render_fragments(ray_scene_t *scene, ray_camera_t *camera, ray_threads_t *threads, fb_fragment_t *fragments); void ray_scene_render_fragment(ray_scene_t *scene, ray_camera_t *camera, fb_fragment_t *fragment); #endif diff --git a/src/modules/ray/ray_threads.c b/src/modules/ray/ray_threads.c deleted file mode 100644 index 2369687..0000000 --- a/src/modules/ray/ray_threads.c +++ /dev/null @@ -1,111 +0,0 @@ -#include <pthread.h> -#include <stdlib.h> - -#include "fb.h" - -#include "ray_scene.h" -#include "ray_threads.h" - -#define BUSY_WAIT_NUM 1000000000 /* How much to spin before sleeping in pthread_cond_wait() */ - -/* for now assuming x86 */ -#define cpu_relax() \ - __asm__ __volatile__ ( "pause\n" : : : "memory") - -/* This is a very simple/naive implementation, there's certainly room for improvement. - * - * Without the BUSY_WAIT_NUM spinning this approach seems to leave a fairly - * substantial proportion of CPU idle while waiting for the render thread to - * complete on my core 2 duo. - * - * It's probably just latency in getting the render thread woken when the work - * is submitted, and since the fragments are split equally the main thread gets - * a head start and has to wait when it finishes first. The spinning is just - * an attempt to avoid going to sleep while the render threads finish, there - * still needs to be improvement in how the work is submitted. - * - * I haven't spent much time on optimizing the raytracer yet. - */ - -static void * ray_thread_func(void *_thread) -{ - ray_thread_t *thread = _thread; - - for (;;) { - pthread_mutex_lock(&thread->mutex); - while (thread->fragment == NULL) - pthread_cond_wait(&thread->cond, &thread->mutex); - - ray_scene_render_fragment(thread->scene, thread->camera, thread->fragment); - thread->fragment = NULL; - pthread_mutex_unlock(&thread->mutex); - pthread_cond_signal(&thread->cond); - } - - return NULL; -} - - -void ray_thread_fragment_submit(ray_thread_t *thread, ray_scene_t *scene, ray_camera_t *camera, fb_fragment_t *fragment) -{ - pthread_mutex_lock(&thread->mutex); - while (thread->fragment != NULL) /* XXX: never true due to ray_thread_wait_idle() */ - pthread_cond_wait(&thread->cond, &thread->mutex); - - thread->fragment = fragment; - thread->scene = scene; - thread->camera = camera; - - pthread_mutex_unlock(&thread->mutex); - pthread_cond_signal(&thread->cond); -} - - -void ray_thread_wait_idle(ray_thread_t *thread) -{ - unsigned n; - - /* Spin before going to sleep, the other thread should not take substantially longer. */ - for (n = 0; thread->fragment != NULL && n < BUSY_WAIT_NUM; n++) - cpu_relax(); - - pthread_mutex_lock(&thread->mutex); - while (thread->fragment != NULL) - pthread_cond_wait(&thread->cond, &thread->mutex); - pthread_mutex_unlock(&thread->mutex); -} - - -ray_threads_t * ray_threads_create(unsigned num) -{ - ray_threads_t *threads; - unsigned i; - - threads = malloc(sizeof(ray_threads_t) + sizeof(ray_thread_t) * num); - if (!threads) - return NULL; - - for (i = 0; i < num; i++) { - pthread_mutex_init(&threads->threads[i].mutex, NULL); - pthread_cond_init(&threads->threads[i].cond, NULL); - threads->threads[i].fragment = NULL; - pthread_create(&threads->threads[i].thread, NULL, ray_thread_func, &threads->threads[i]); - } - threads->n_threads = num; - - return threads; -} - - -void ray_threads_destroy(ray_threads_t *threads) -{ - unsigned i; - - for (i = 0; i < threads->n_threads; i++) - pthread_cancel(threads->threads[i].thread); - - for (i = 0; i < threads->n_threads; i++) - pthread_join(threads->threads[i].thread, NULL); - - free(threads); -} diff --git a/src/modules/ray/ray_threads.h b/src/modules/ray/ray_threads.h deleted file mode 100644 index b4c601d..0000000 --- a/src/modules/ray/ray_threads.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef _RAY_THREADS_H -#define _RAY_THREADS_H - -#include <pthread.h> - -typedef struct ray_scene_t ray_scene_t; -typedef struct ray_camera_t ray_camera_t; -typedef struct fb_fragment_t fb_fragment_t; - -typedef struct ray_thread_t { - pthread_t thread; - pthread_mutex_t mutex; - pthread_cond_t cond; - ray_scene_t *scene; - ray_camera_t *camera; - fb_fragment_t *fragment; -} ray_thread_t; - -typedef struct ray_threads_t { - unsigned n_threads; - ray_thread_t threads[]; -} ray_threads_t; - - -ray_threads_t * ray_threads_create(unsigned num); -void ray_threads_destroy(ray_threads_t *threads); - -void ray_thread_fragment_submit(ray_thread_t *thread, ray_scene_t *scene, ray_camera_t *camera, fb_fragment_t *fragment); -void ray_thread_wait_idle(ray_thread_t *thread); -#endif |