mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 07:28:11 +02:00
llvmpipe: rework fences and queries
This commit is contained in:
parent
5024d9b90e
commit
18452c1e87
7 changed files with 125 additions and 93 deletions
|
|
@ -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++;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
}
|
||||
|
||||
if (setup->scene->fence)
|
||||
setup->scene->fence->issued = TRUE;
|
||||
}
|
||||
|
||||
set_scene_state( setup, SETUP_FLUSHED );
|
||||
|
||||
if (fence) {
|
||||
lp_fence_reference((struct lp_fence **)fence, setup->last_fence);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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);
|
||||
assert(setup->active_query == NULL);
|
||||
|
||||
if (setup->scene) {
|
||||
lp_scene_bin_everywhere(setup->scene,
|
||||
lp_rast_begin_query,
|
||||
lp_rast_arg_query(pq));
|
||||
}
|
||||
|
||||
memset(pq->count, 0, sizeof(pq->count)); /* reset all counters */
|
||||
|
||||
set_scene_state( setup, SETUP_ACTIVE );
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue