From 4e52861bb580ac41eaf8df2dd4c99029c3706cf3 Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Fri, 15 Apr 2022 11:26:24 -0700 Subject: til_threads: propagate threaded til_fb_fragment.zeroed Currently when a threaded renderer performed til_fb_fragment_zero() in render_fragment() vs. prepare_frame(), the til_fb_fragment.zeroed maintenance would stay isolated to the ephemeral fragment generated by the fragmenter. With this commit, when all ephemeral fragments rendered in a threaded fashion for a given frame returned a set .zeroed member, the outer frame's .zeroed member gets set. This should enable proper threaded zeroing of the frame in render_fragment(). Note that since it's careful to actually count the number of zeroed ephemeral subfragments and only propagates when that count matches the number of subfragments rendered in the entire frame, it's also supported to use til_fb_fragment_zero() conditionally on just some fragments while not zeroing others and the entire frame will not get its .zeroed member set. Imagine a renderer which randomly zeroes out some fragments, while drawing into others, this will be honored as a non-zeroed frame on the whole. --- src/til_threads.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/til_threads.c b/src/til_threads.c index 7c68d52..6f01db1 100644 --- a/src/til_threads.c +++ b/src/til_threads.c @@ -18,6 +18,8 @@ typedef struct til_threads_t { pthread_mutex_t idle_mutex; pthread_cond_t idle_cond; + unsigned idle_n_fragments; + unsigned idle_n_zeroed; unsigned n_idle; pthread_mutex_t frame_mutex; @@ -45,6 +47,7 @@ static void * thread_func(void *_thread) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); for (;;) { + unsigned n_fragments = 0, n_zeroed = 0; /* wait for a new frame */ pthread_mutex_lock(&threads->frame_mutex); @@ -65,14 +68,22 @@ static void * thread_func(void *_thread) break; threads->render_fragment_func(threads->context, threads->ticks, thread->id, &fragment); + n_zeroed += fragment.zeroed; + n_fragments++; } /* report as idle */ pthread_mutex_lock(&threads->idle_mutex); pthread_cleanup_push((void (*)(void *))pthread_mutex_unlock, &threads->idle_mutex); + threads->idle_n_fragments += n_fragments; + threads->idle_n_zeroed += n_zeroed; threads->n_idle++; - if (threads->n_idle == threads->n_threads) /* Frame finished! Notify potential waiter. */ + if (threads->n_idle == threads->n_threads) { /* Frame finished! Notify potential waiter. */ + if (threads->idle_n_zeroed == threads->idle_n_fragments) + threads->fragment->zeroed = 1; + pthread_cond_signal(&threads->idle_cond); + } pthread_cleanup_pop(1); } @@ -104,7 +115,7 @@ void til_threads_frame_submit(til_threads_t *threads, til_fb_fragment_t *fragmen threads->context = context; threads->ticks = ticks; threads->frame_num++; - threads->n_idle = threads->next_fragment = 0; + threads->n_idle = threads->idle_n_zeroed = threads->idle_n_fragments = threads->next_fragment = 0; pthread_cond_broadcast(&threads->frame_cond); pthread_cleanup_pop(1); } -- cgit v1.2.1