summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeith Whitwell <[email protected]>2010-08-27 17:14:49 +0100
committerKeith Whitwell <[email protected]>2010-09-07 13:22:55 +0100
commit18452c1e87f79327fbd5f27478028b481ee72a5d (patch)
tree5e78425be5e348db5248a546e953e79bda13d5ff
parent5024d9b90e88cdc3d8aca14d45cf845efbfb8633 (diff)
llvmpipe: rework fences and queries
-rw-r--r--src/gallium/drivers/llvmpipe/lp_query.c56
-rw-r--r--src/gallium/drivers/llvmpipe/lp_query.h8
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast.c57
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast.h11
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast_priv.h1
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup.c80
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_context.h3
7 files changed, 124 insertions, 92 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_query.c b/src/gallium/drivers/llvmpipe/lp_query.c
index 67fd797af22..76d0231fd1c 100644
--- a/src/gallium/drivers/llvmpipe/lp_query.c
+++ b/src/gallium/drivers/llvmpipe/lp_query.c
@@ -54,9 +54,6 @@ llvmpipe_create_query(struct pipe_context *pipe,
assert(type == PIPE_QUERY_OCCLUSION_COUNTER);
pq = CALLOC_STRUCT( llvmpipe_query );
- if (pq) {
- pipe_mutex_init(pq->mutex);
- }
return (struct pipe_query *) pq;
}
@@ -66,12 +63,20 @@ static void
llvmpipe_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
{
struct llvmpipe_query *pq = llvmpipe_query(q);
- /* query might still be in process if we never waited for the result */
- if (!pq->done) {
- llvmpipe_finish(pipe, __FUNCTION__);
+
+ /* Ideally we would refcount queries & not get destroyed until the
+ * last scene had finished with us.
+ */
+ if (pq->fence) {
+ if (!lp_fence_issued(pq->fence))
+ llvmpipe_flush(pipe, 0, NULL, __FUNCTION__);
+
+ if (!lp_fence_signalled(pq->fence))
+ lp_fence_wait(pq->fence);
+
+ lp_fence_reference(&pq->fence, NULL);
}
- pipe_mutex_destroy(pq->mutex);
FREE(pq);
}
@@ -84,22 +89,31 @@ llvmpipe_get_query_result(struct pipe_context *pipe,
{
struct llvmpipe_query *pq = llvmpipe_query(q);
uint64_t *result = (uint64_t *)vresult;
+ int i;
- if (!pq->done) {
- if (wait) {
- llvmpipe_finish(pipe, __FUNCTION__);
- }
- /* this is a bit inconsequent but should be ok */
- else {
+ if (!pq->fence) {
+ assert(0); /* query not in issued state */
+ return FALSE;
+ }
+
+ if (!lp_fence_signalled(pq->fence)) {
+ if (!lp_fence_issued(pq->fence))
llvmpipe_flush(pipe, 0, NULL, __FUNCTION__);
- }
+
+ if (!wait)
+ return FALSE;
+
+ lp_fence_wait(pq->fence);
}
- if (pq->done) {
- *result = pq->result;
+ /* Sum the results from each of the threads:
+ */
+ *result = 0;
+ for (i = 0; i < LP_MAX_THREADS; i++) {
+ *result += pq->count[i];
}
- return pq->done;
+ return TRUE;
}
@@ -109,14 +123,6 @@ llvmpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q)
struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
struct llvmpipe_query *pq = llvmpipe_query(q);
- /* Check if the query is already in the scene. If so, we need to
- * flush the scene now. Real apps shouldn't re-use a query in a
- * frame of rendering.
- */
- if (pq->binned) {
- llvmpipe_finish(pipe, __FUNCTION__);
- }
-
lp_setup_begin_query(llvmpipe->setup, pq);
llvmpipe->active_query_count++;
diff --git a/src/gallium/drivers/llvmpipe/lp_query.h b/src/gallium/drivers/llvmpipe/lp_query.h
index 721c41cb5c9..e93842a2fd0 100644
--- a/src/gallium/drivers/llvmpipe/lp_query.h
+++ b/src/gallium/drivers/llvmpipe/lp_query.h
@@ -43,13 +43,7 @@ struct llvmpipe_context;
struct llvmpipe_query {
uint64_t count[LP_MAX_THREADS]; /**< a counter for each thread */
- uint64_t result; /**< total of all counters */
-
- pipe_mutex mutex;
- unsigned num_tiles, tile_count;
-
- boolean done;
- boolean binned; /**< has this query been binned in the scene? */
+ struct lp_fence *fence; /* fence from last scene this was binned in */
};
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c
index b1c306bbe94..ce6896d16e4 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.c
+++ b/src/gallium/drivers/llvmpipe/lp_rast.c
@@ -568,6 +568,11 @@ lp_rast_tile_end(struct lp_rasterizer_task *task)
lp_rast_store_linear_color(task, dummy);
}
+ if (task->query) {
+ union lp_rast_cmd_arg dummy = {0};
+ lp_rast_end_query(task, dummy);
+ }
+
/* debug */
memset(task->color_tiles, 0, sizeof(task->color_tiles));
task->depth_tile = NULL;
@@ -597,8 +602,26 @@ void
lp_rast_begin_query(struct lp_rasterizer_task *task,
const union lp_rast_cmd_arg arg)
{
- /* Reset the per-task counter */
+ struct llvmpipe_query *pq = arg.query_obj;
+
+ assert(task->query == NULL);
task->vis_counter = 0;
+ task->query = pq;
+ pq->count[task->thread_index] = 0;
+}
+
+
+/* Much like begin_query, but don't reset the counter to zero.
+ */
+void
+lp_rast_restart_query(struct lp_rasterizer_task *task,
+ const union lp_rast_cmd_arg arg)
+{
+ struct llvmpipe_query *pq = arg.query_obj;
+
+ assert(task->query == NULL);
+ task->vis_counter = 0;
+ task->query = pq;
}
@@ -611,35 +634,8 @@ void
lp_rast_end_query(struct lp_rasterizer_task *task,
const union lp_rast_cmd_arg arg)
{
- struct llvmpipe_query *pq = arg.query_obj;
-
- pipe_mutex_lock(pq->mutex);
- {
- /* Accumulate the visible fragment counter from this tile in
- * the query object.
- */
- pq->count[task->thread_index] += task->vis_counter;
-
- /* check if this is the last tile in the scene */
- pq->tile_count++;
- if (pq->tile_count == pq->num_tiles) {
- uint i;
-
- /* sum the per-thread counters for the query */
- pq->result = 0;
- for (i = 0; i < LP_MAX_THREADS; i++) {
- pq->result += pq->count[i];
- }
-
- /* reset counters (in case this query is re-used in the scene) */
- memset(pq->count, 0, sizeof(pq->count));
-
- pq->tile_count = 0;
- pq->binned = FALSE;
- pq->done = TRUE;
- }
- }
- pipe_mutex_unlock(pq->mutex);
+ task->query->count[task->thread_index] += task->vis_counter;
+ task->query = NULL;
}
@@ -697,6 +693,7 @@ static struct {
RAST(store_linear_color),
RAST(fence),
RAST(begin_query),
+ RAST(restart_query),
RAST(end_query),
};
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.h b/src/gallium/drivers/llvmpipe/lp_rast.h
index ebe88182af4..9d3deb4e886 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast.h
@@ -210,6 +210,14 @@ lp_rast_arg_null( void )
return arg;
}
+static INLINE union lp_rast_cmd_arg
+lp_rast_arg_query( struct llvmpipe_query *pq )
+{
+ union lp_rast_cmd_arg arg;
+ arg.query_obj = pq;
+ return arg;
+}
+
/**
* Binnable Commands.
@@ -256,6 +264,9 @@ void lp_rast_store_linear_color( struct lp_rasterizer_task *,
void lp_rast_begin_query(struct lp_rasterizer_task *,
const union lp_rast_cmd_arg );
+void lp_rast_restart_query(struct lp_rasterizer_task *,
+ const union lp_rast_cmd_arg );
+
void lp_rast_end_query(struct lp_rasterizer_task *,
const union lp_rast_cmd_arg );
diff --git a/src/gallium/drivers/llvmpipe/lp_rast_priv.h b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
index fae7f6d3dc2..6bc10159120 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast_priv.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
@@ -89,6 +89,7 @@ struct lp_rasterizer_task
/* occlude counter for visiable pixels */
uint32_t vis_counter;
+ struct llvmpipe_query *query;
pipe_semaphore work_ready;
pipe_semaphore work_done;
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c
index 3da9097154e..ae6d6785025 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup.c
@@ -154,6 +154,11 @@ lp_setup_rasterize_scene( struct lp_setup_context *setup )
struct lp_scene *scene = lp_setup_get_current_scene(setup);
struct llvmpipe_screen *screen = llvmpipe_screen(scene->pipe->screen);
+ lp_fence_reference(&setup->last_fence, scene->fence);
+
+ if (setup->last_fence)
+ setup->last_fence->issued = TRUE;
+
pipe_mutex_lock(screen->rast_mutex);
lp_scene_rasterize(scene, screen->rast);
pipe_mutex_unlock(screen->rast_mutex);
@@ -170,6 +175,12 @@ begin_binning( struct lp_setup_context *setup )
{
struct lp_scene *scene = lp_setup_get_current_scene(setup);
boolean need_zsload = FALSE;
+
+ /* Always create a fence when threads are active:
+ */
+ if (setup->num_threads)
+ scene->fence = lp_fence_create(setup->num_threads);
+
if (setup->fb.zsbuf &&
((setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) &&
util_format_is_depth_and_stencil(setup->fb.zsbuf->format))
@@ -198,6 +209,13 @@ begin_binning( struct lp_setup_context *setup )
}
}
+ if (setup->active_query) {
+ lp_scene_bin_everywhere( scene,
+ lp_rast_restart_query,
+ lp_rast_arg_query(setup->active_query) );
+ }
+
+
LP_DBG(DEBUG_SETUP, "%s done\n", __FUNCTION__);
}
@@ -280,19 +298,11 @@ lp_setup_flush( struct lp_setup_context *setup,
{
LP_DBG(DEBUG_SETUP, "%s %s\n", __FUNCTION__, reason);
- if (setup->scene) {
- 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 );
- if (setup->scene->fence)
- setup->scene->fence->issued = TRUE;
+ if (fence) {
+ lp_fence_reference((struct lp_fence **)fence, setup->last_fence);
}
-
- set_scene_state( setup, SETUP_FLUSHED );
}
@@ -955,22 +965,16 @@ void
lp_setup_begin_query(struct lp_setup_context *setup,
struct llvmpipe_query *pq)
{
- struct lp_scene * scene = lp_setup_get_current_scene(setup);
- union lp_rast_cmd_arg cmd_arg;
-
/* init the query to its beginning state */
- pq->done = FALSE;
- pq->tile_count = 0;
- pq->num_tiles = scene->tiles_x * scene->tiles_y;
- assert(pq->num_tiles > 0);
-
- memset(pq->count, 0, sizeof(pq->count)); /* reset all counters */
-
- set_scene_state( setup, SETUP_ACTIVE );
+ assert(setup->active_query == NULL);
+
+ if (setup->scene) {
+ lp_scene_bin_everywhere(setup->scene,
+ lp_rast_begin_query,
+ lp_rast_arg_query(pq));
+ }
- cmd_arg.query_obj = pq;
- lp_scene_bin_everywhere(scene, lp_rast_begin_query, cmd_arg);
- pq->binned = TRUE;
+ setup->active_query = pq;
}
@@ -980,11 +984,27 @@ lp_setup_begin_query(struct lp_setup_context *setup,
void
lp_setup_end_query(struct lp_setup_context *setup, struct llvmpipe_query *pq)
{
- struct lp_scene * scene = lp_setup_get_current_scene(setup);
- union lp_rast_cmd_arg cmd_arg;
+ union lp_rast_cmd_arg dummy = { 0 };
- set_scene_state( setup, SETUP_ACTIVE );
+ assert(setup->active_query == pq);
+ setup->active_query = NULL;
- cmd_arg.query_obj = pq;
- lp_scene_bin_everywhere(scene, lp_rast_end_query, cmd_arg);
+ /* Setup will automatically re-issue any query which carried over a
+ * scene boundary, and the rasterizer automatically "ends" queries
+ * which are active at the end of a scene, so there is no need to
+ * retry this commands on failure.
+ */
+ if (setup->scene) {
+ /* pq->fence should be the fence of the *last* scene which
+ * contributed to the query result.
+ */
+ lp_fence_reference(&pq->fence, setup->scene->fence);
+
+ lp_scene_bin_everywhere(setup->scene, lp_rast_end_query, dummy);
+ }
+ else {
+ lp_fence_reference(&pq->fence, setup->last_fence);
+ }
}
+
+
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_context.h b/src/gallium/drivers/llvmpipe/lp_setup_context.h
index 877a492c6d8..91b5d4d79f0 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_context.h
+++ b/src/gallium/drivers/llvmpipe/lp_setup_context.h
@@ -87,6 +87,9 @@ struct lp_setup_context
struct lp_scene *scene; /**< current scene being built */
struct lp_scene_queue *empty_scenes; /**< queue of empty scenes */
+ struct lp_fence *last_fence;
+ struct llvmpipe_query *active_query;
+
boolean flatshade_first;
boolean ccw_is_frontface;
boolean scissor_test;