From 3bd9aedbac79eec16bfe6f5fc6f6a021eebe769a Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Thu, 8 Jul 2010 15:13:35 +0100 Subject: [PATCH] llvmpipe: move fences from per-bin to per-thread Rather than inserting an lp_rast_fence command at the end of each bin, have each rasterizer thread call this function directly once it has run out of work to do on a particular scene. This results in fewer calls to the mutex & related functions, but more importantly makes it easier to recognize empty bins. --- src/gallium/drivers/llvmpipe/lp_fence.c | 9 ++---- src/gallium/drivers/llvmpipe/lp_fence.h | 18 ++++++++++++ src/gallium/drivers/llvmpipe/lp_flush.c | 10 +------ src/gallium/drivers/llvmpipe/lp_rast.c | 4 +++ src/gallium/drivers/llvmpipe/lp_scene.c | 3 ++ src/gallium/drivers/llvmpipe/lp_scene.h | 1 + src/gallium/drivers/llvmpipe/lp_setup.c | 39 ++++++++++++++++--------- src/gallium/drivers/llvmpipe/lp_setup.h | 3 +- 8 files changed, 58 insertions(+), 29 deletions(-) diff --git a/src/gallium/drivers/llvmpipe/lp_fence.c b/src/gallium/drivers/llvmpipe/lp_fence.c index 75d8d2b8251..f9805e5d688 100644 --- a/src/gallium/drivers/llvmpipe/lp_fence.c +++ b/src/gallium/drivers/llvmpipe/lp_fence.c @@ -28,7 +28,6 @@ #include "pipe/p_screen.h" #include "util/u_memory.h" -#include "util/u_inlines.h" #include "lp_debug.h" #include "lp_fence.h" @@ -59,7 +58,7 @@ lp_fence_create(unsigned rank) /** Destroy a fence. Called when refcount hits zero. */ -static void +void lp_fence_destroy(struct lp_fence *fence) { pipe_mutex_destroy(fence->mutex); @@ -77,12 +76,10 @@ llvmpipe_fence_reference(struct pipe_screen *screen, struct pipe_fence_handle **ptr, struct pipe_fence_handle *fence) { - struct lp_fence *old = (struct lp_fence *) *ptr; + struct lp_fence **old = (struct lp_fence **) ptr; struct lp_fence *f = (struct lp_fence *) fence; - if (pipe_reference(&old->reference, &f->reference)) { - lp_fence_destroy(old); - } + lp_fence_reference(old, f); } diff --git a/src/gallium/drivers/llvmpipe/lp_fence.h b/src/gallium/drivers/llvmpipe/lp_fence.h index d9270f5784a..13358fb99f2 100644 --- a/src/gallium/drivers/llvmpipe/lp_fence.h +++ b/src/gallium/drivers/llvmpipe/lp_fence.h @@ -32,6 +32,7 @@ #include "os/os_thread.h" #include "pipe/p_state.h" +#include "util/u_inlines.h" struct pipe_screen; @@ -61,4 +62,21 @@ void llvmpipe_init_screen_fence_funcs(struct pipe_screen *screen); +void +lp_fence_destroy(struct lp_fence *fence); + +static INLINE void +lp_fence_reference(struct lp_fence **ptr, + struct lp_fence *f) +{ + struct lp_fence *old = *ptr; + + if (pipe_reference(&old->reference, &f->reference)) { + lp_fence_destroy(old); + } + + *ptr = f; +} + + #endif /* LP_FENCE_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_flush.c b/src/gallium/drivers/llvmpipe/lp_flush.c index 0cd288bb73a..d78656f4628 100644 --- a/src/gallium/drivers/llvmpipe/lp_flush.c +++ b/src/gallium/drivers/llvmpipe/lp_flush.c @@ -51,16 +51,8 @@ llvmpipe_flush( struct pipe_context *pipe, draw_flush(llvmpipe->draw); - if (fence) { - /* if we're going to flush the setup/rasterization modules, emit - * a fence. - * XXX this (and the code below) may need fine tuning... - */ - *fence = lp_setup_fence( llvmpipe->setup ); - } - /* ask the setup module to flush */ - lp_setup_flush(llvmpipe->setup, flags); + lp_setup_flush(llvmpipe->setup, flags, fence); /* Enable to dump BMPs of the color/depth buffers each frame */ if (0) { diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c index 1a82dd5694e..1dde327836c 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.c +++ b/src/gallium/drivers/llvmpipe/lp_rast.c @@ -815,6 +815,10 @@ rasterize_scene(struct lp_rasterizer_task *task, } } #endif + + if (scene->fence) { + lp_rast_fence(task, lp_rast_arg_fence(scene->fence)); + } } diff --git a/src/gallium/drivers/llvmpipe/lp_scene.c b/src/gallium/drivers/llvmpipe/lp_scene.c index e8d36bbdc50..f2226a538a5 100644 --- a/src/gallium/drivers/llvmpipe/lp_scene.c +++ b/src/gallium/drivers/llvmpipe/lp_scene.c @@ -32,6 +32,7 @@ #include "util/u_simple_list.h" #include "lp_scene.h" #include "lp_scene_queue.h" +#include "lp_fence.h" /** List of texture references */ @@ -198,6 +199,8 @@ lp_scene_reset(struct lp_scene *scene ) make_empty_list(ref_list); } + lp_fence_reference(&scene->fence, NULL); + scene->scene_size = 0; scene->has_color_clear = FALSE; diff --git a/src/gallium/drivers/llvmpipe/lp_scene.h b/src/gallium/drivers/llvmpipe/lp_scene.h index 4e55d431746..fa1b311fa17 100644 --- a/src/gallium/drivers/llvmpipe/lp_scene.h +++ b/src/gallium/drivers/llvmpipe/lp_scene.h @@ -112,6 +112,7 @@ struct resource_ref { */ struct lp_scene { struct pipe_context *pipe; + struct lp_fence *fence; /** the framebuffer to render the scene into */ struct pipe_framebuffer_state fb; diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index 2bd6fcebe7f..3b83f4e7428 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -271,7 +271,8 @@ set_scene_state( struct lp_setup_context *setup, */ void lp_setup_flush( struct lp_setup_context *setup, - unsigned flags ) + unsigned flags, + struct pipe_fence_handle **fence) { LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); @@ -288,6 +289,15 @@ lp_setup_flush( struct lp_setup_context *setup, */ lp_scene_bin_everywhere(scene, lp_rast_store_color, dummy); } + + + if (fence) { + /* if we're going to flush the setup/rasterization modules, emit + * a fence. + */ + *fence = lp_setup_fence( setup ); + } + } set_scene_state( setup, SETUP_FLUSHED ); @@ -433,24 +443,27 @@ lp_setup_clear( struct lp_setup_context *setup, struct pipe_fence_handle * lp_setup_fence( struct lp_setup_context *setup ) { - if (setup->num_threads == 0) { + if (setup->scene == NULL) return NULL; - } - else { + else if (setup->num_threads == 0) + return NULL; + else + { struct lp_scene *scene = lp_setup_get_current_scene(setup); - const unsigned rank = lp_scene_get_num_bins( scene ); /* xxx */ - struct lp_fence *fence = lp_fence_create(rank); - - LP_DBG(DEBUG_SETUP, "%s rank %u\n", __FUNCTION__, rank); + const unsigned rank = setup->num_threads; set_scene_state( setup, SETUP_ACTIVE ); + + assert(scene->fence == NULL); - /* insert the fence into all command bins */ - lp_scene_bin_everywhere( scene, - lp_rast_fence, - lp_rast_arg_fence(fence) ); + /* The caller gets a reference, we keep a copy too, so need to + * bump the refcount: + */ + lp_fence_reference(&scene->fence, lp_fence_create(rank)); + + LP_DBG(DEBUG_SETUP, "%s rank %u\n", __FUNCTION__, rank); - return (struct pipe_fence_handle *) fence; + return (struct pipe_fence_handle *) scene->fence; } } diff --git a/src/gallium/drivers/llvmpipe/lp_setup.h b/src/gallium/drivers/llvmpipe/lp_setup.h index 6a0dc551290..73b1c85325a 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.h +++ b/src/gallium/drivers/llvmpipe/lp_setup.h @@ -84,7 +84,8 @@ lp_setup_fence( struct lp_setup_context *setup ); void lp_setup_flush( struct lp_setup_context *setup, - unsigned flags ); + unsigned flags, + struct pipe_fence_handle **fence); void -- 2.30.2