X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fllvmpipe%2Flp_query.c;h=922913d743110da15652ea0029c8cccb52bf7c05;hb=8975dc798d6b7790de7a788c8263b636cfd02184;hp=67fd797af228526827b2a001176008caf978587f;hpb=222d2f2ac2c7d93cbc0643082c78278ad2c8cfce;p=mesa.git diff --git a/src/gallium/drivers/llvmpipe/lp_query.c b/src/gallium/drivers/llvmpipe/lp_query.c index 67fd797af22..922913d7431 100644 --- a/src/gallium/drivers/llvmpipe/lp_query.c +++ b/src/gallium/drivers/llvmpipe/lp_query.c @@ -33,10 +33,12 @@ #include "draw/draw_context.h" #include "pipe/p_defines.h" #include "util/u_memory.h" +#include "os/os_time.h" #include "lp_context.h" #include "lp_flush.h" #include "lp_fence.h" #include "lp_query.h" +#include "lp_screen.h" #include "lp_state.h" @@ -51,11 +53,12 @@ llvmpipe_create_query(struct pipe_context *pipe, { struct llvmpipe_query *pq; - assert(type == PIPE_QUERY_OCCLUSION_COUNTER); + assert(type < PIPE_QUERY_TYPES); pq = CALLOC_STRUCT( llvmpipe_query ); + if (pq) { - pipe_mutex_init(pq->mutex); + pq->type = type; } return (struct pipe_query *) pq; @@ -66,12 +69,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, 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); } @@ -80,26 +91,83 @@ static boolean llvmpipe_get_query_result(struct pipe_context *pipe, struct pipe_query *q, boolean wait, - void *vresult) + union pipe_query_result *vresult) { + struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); + unsigned num_threads = MAX2(1, screen->num_threads); struct llvmpipe_query *pq = llvmpipe_query(q); uint64_t *result = (uint64_t *)vresult; + int i; + + if (!pq->fence) { + /* no fence because there was no scene, so results is zero */ + *result = 0; + return TRUE; + } + + if (!lp_fence_signalled(pq->fence)) { + if (!lp_fence_issued(pq->fence)) + llvmpipe_flush(pipe, NULL, __FUNCTION__); + + if (!wait) + return FALSE; + + lp_fence_wait(pq->fence); + } + + /* Sum the results from each of the threads: + */ + *result = 0; - if (!pq->done) { - if (wait) { - llvmpipe_finish(pipe, __FUNCTION__); + switch (pq->type) { + case PIPE_QUERY_OCCLUSION_COUNTER: + for (i = 0; i < num_threads; i++) { + *result += pq->count[i]; } - /* this is a bit inconsequent but should be ok */ - else { - llvmpipe_flush(pipe, 0, NULL, __FUNCTION__); + break; + case PIPE_QUERY_OCCLUSION_PREDICATE: + for (i = 0; i < num_threads; i++) { + /* safer (still not guaranteed) when there's an overflow */ + *result = *result || pq->count[i]; } + break; + case PIPE_QUERY_TIMESTAMP: + for (i = 0; i < num_threads; i++) { + if (pq->count[i] > *result) { + *result = pq->count[i]; + } + if (*result == 0) + *result = os_time_get_nano(); + } + break; + case PIPE_QUERY_PRIMITIVES_GENERATED: + *result = pq->num_primitives_generated; + break; + case PIPE_QUERY_PRIMITIVES_EMITTED: + *result = pq->num_primitives_written; + break; + case PIPE_QUERY_SO_OVERFLOW_PREDICATE: + *result = pq->so_has_overflown; + break; + case PIPE_QUERY_SO_STATISTICS: { + struct pipe_query_data_so_statistics *stats = + (struct pipe_query_data_so_statistics *)vresult; + stats->num_primitives_written = pq->num_primitives_written; + stats->primitives_storage_needed = pq->num_primitives_generated; } - - if (pq->done) { - *result = pq->result; + break; + case PIPE_QUERY_PIPELINE_STATISTICS: { + struct pipe_query_data_pipeline_statistics *stats = + (struct pipe_query_data_pipeline_statistics *)vresult; + *stats = pq->stats; + } + break; + default: + assert(0); + break; } - return pq->done; + return TRUE; } @@ -113,14 +181,51 @@ llvmpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q) * flush the scene now. Real apps shouldn't re-use a query in a * frame of rendering. */ - if (pq->binned) { + if (pq->fence && !lp_fence_issued(pq->fence)) { llvmpipe_finish(pipe, __FUNCTION__); } + + memset(pq->count, 0, sizeof(pq->count)); lp_setup_begin_query(llvmpipe->setup, pq); - llvmpipe->active_query_count++; - llvmpipe->dirty |= LP_NEW_QUERY; + switch (pq->type) { + case PIPE_QUERY_PRIMITIVES_EMITTED: + pq->num_primitives_written = 0; + llvmpipe->so_stats.num_primitives_written = 0; + break; + case PIPE_QUERY_PRIMITIVES_GENERATED: + pq->num_primitives_generated = 0; + llvmpipe->num_primitives_generated = 0; + break; + case PIPE_QUERY_SO_STATISTICS: + pq->num_primitives_written = 0; + llvmpipe->so_stats.num_primitives_written = 0; + pq->num_primitives_generated = 0; + llvmpipe->num_primitives_generated = 0; + break; + case PIPE_QUERY_SO_OVERFLOW_PREDICATE: + pq->so_has_overflown = FALSE; + break; + case PIPE_QUERY_PIPELINE_STATISTICS: + /* reset our cache */ + if (llvmpipe->active_statistics_queries == 0) { + memset(&llvmpipe->pipeline_statistics, 0, + sizeof(llvmpipe->pipeline_statistics)); + } + memcpy(&pq->stats, &llvmpipe->pipeline_statistics, sizeof(pq->stats)); + llvmpipe->active_statistics_queries++; + break; + case PIPE_QUERY_OCCLUSION_COUNTER: + case PIPE_QUERY_OCCLUSION_PREDICATE: + /* Both active at same time will still fail all over the place. + * Then again several of each type can be active too... */ + llvmpipe->active_occlusion_query++; + llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY; + break; + default: + break; + } } @@ -132,11 +237,72 @@ llvmpipe_end_query(struct pipe_context *pipe, struct pipe_query *q) lp_setup_end_query(llvmpipe->setup, pq); - assert(llvmpipe->active_query_count); - llvmpipe->active_query_count--; - llvmpipe->dirty |= LP_NEW_QUERY; + switch (pq->type) { + + case PIPE_QUERY_PRIMITIVES_EMITTED: + pq->num_primitives_written = llvmpipe->so_stats.num_primitives_written; + break; + case PIPE_QUERY_PRIMITIVES_GENERATED: + pq->num_primitives_generated = llvmpipe->num_primitives_generated; + break; + case PIPE_QUERY_SO_STATISTICS: + pq->num_primitives_written = llvmpipe->so_stats.num_primitives_written; + pq->num_primitives_generated = llvmpipe->num_primitives_generated; + break; + case PIPE_QUERY_SO_OVERFLOW_PREDICATE: + pq->so_has_overflown = (llvmpipe->num_primitives_generated > + llvmpipe->so_stats.num_primitives_written); + break; + case PIPE_QUERY_PIPELINE_STATISTICS: + pq->stats.ia_vertices = + llvmpipe->pipeline_statistics.ia_vertices - pq->stats.ia_vertices; + pq->stats.ia_primitives = + llvmpipe->pipeline_statistics.ia_primitives - pq->stats.ia_primitives; + pq->stats.vs_invocations = + llvmpipe->pipeline_statistics.vs_invocations - pq->stats.vs_invocations; + pq->stats.gs_invocations = + llvmpipe->pipeline_statistics.gs_invocations - pq->stats.gs_invocations; + pq->stats.gs_primitives = + llvmpipe->pipeline_statistics.gs_primitives - pq->stats.gs_primitives; + pq->stats.c_invocations = + llvmpipe->pipeline_statistics.c_invocations - pq->stats.c_invocations; + pq->stats.c_primitives = + llvmpipe->pipeline_statistics.c_primitives - pq->stats.c_primitives; + pq->stats.ps_invocations = + llvmpipe->pipeline_statistics.ps_invocations - pq->stats.ps_invocations; + + llvmpipe->active_statistics_queries--; + break; + case PIPE_QUERY_OCCLUSION_COUNTER: + case PIPE_QUERY_OCCLUSION_PREDICATE: + assert(llvmpipe->active_occlusion_query); + llvmpipe->active_occlusion_query--; + llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY; + break; + default: + break; + } } +boolean +llvmpipe_check_render_cond(struct llvmpipe_context *lp) +{ + struct pipe_context *pipe = &lp->pipe; + boolean b, wait; + uint64_t result; + + if (!lp->render_cond_query) + return TRUE; /* no query predicate, draw normally */ + + wait = (lp->render_cond_mode == PIPE_RENDER_COND_WAIT || + lp->render_cond_mode == PIPE_RENDER_COND_BY_REGION_WAIT); + + b = pipe->get_query_result(pipe, lp->render_cond_query, wait, (void*)&result); + if (b) + return (!result == lp->render_cond_cond); + else + return TRUE; +} void llvmpipe_init_query_funcs(struct llvmpipe_context *llvmpipe ) {