X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fllvmpipe%2Flp_query.c;h=fcb5c6ac340b919dbcc209c24173c09cee162c07;hb=ff74cf62b1244bd3bc53e83b685582f73fe6ffdd;hp=5554285425deb52ab50150a095929a181b989a73;hpb=5d526ed21ac9f1ec9220c2adb4c905893eb9d990;p=mesa.git diff --git a/src/gallium/drivers/llvmpipe/lp_query.c b/src/gallium/drivers/llvmpipe/lp_query.c index 5554285425d..fcb5c6ac340 100644 --- a/src/gallium/drivers/llvmpipe/lp_query.c +++ b/src/gallium/drivers/llvmpipe/lp_query.c @@ -1,6 +1,7 @@ /************************************************************************** * * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2010 VMware, Inc. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -18,29 +19,28 @@ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * **************************************************************************/ -/* Author: - * Keith Whitwell +/* Authors: + * Keith Whitwell, Qicheng Christopher Li, Brian Paul */ #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" -struct llvmpipe_query { - uint64_t start; - uint64_t end; -}; - static struct llvmpipe_query *llvmpipe_query( struct pipe_query *p ) { @@ -49,17 +49,115 @@ static struct llvmpipe_query *llvmpipe_query( struct pipe_query *p ) static struct pipe_query * llvmpipe_create_query(struct pipe_context *pipe, - unsigned type) + unsigned type) { - assert(type == PIPE_QUERY_OCCLUSION_COUNTER); - return (struct pipe_query *)CALLOC_STRUCT( llvmpipe_query ); + struct llvmpipe_query *pq; + + assert(type < PIPE_QUERY_TYPES); + + pq = CALLOC_STRUCT( llvmpipe_query ); + + if (pq) { + pq->type = type; + } + + return (struct pipe_query *) pq; } static void llvmpipe_destroy_query(struct pipe_context *pipe, struct pipe_query *q) { - FREE(q); + struct llvmpipe_query *pq = llvmpipe_query(q); + + /* 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); + } + + FREE(pq); +} + + +static boolean +llvmpipe_get_query_result(struct pipe_context *pipe, + struct pipe_query *q, + boolean wait, + union pipe_query_result *vresult) +{ + struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); + 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; + + switch (pq->type) { + case PIPE_QUERY_OCCLUSION_COUNTER: + for (i = 0; i < screen->num_threads; i++) { + *result += pq->count[i]; + } + break; + case PIPE_QUERY_TIMESTAMP: + for (i = 0; i < screen->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_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; + } + 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 TRUE; } @@ -67,11 +165,51 @@ static void llvmpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q) { struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe ); - struct llvmpipe_query *sq = llvmpipe_query(q); - - sq->start = llvmpipe->occlusion_count; - llvmpipe->active_query_count++; - llvmpipe->dirty |= LP_NEW_QUERY; + 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->fence && !lp_fence_issued(pq->fence)) { + llvmpipe_finish(pipe, __FUNCTION__); + } + + + memset(pq->count, 0, sizeof(pq->count)); + lp_setup_begin_query(llvmpipe->setup, pq); + + if (pq->type == PIPE_QUERY_PRIMITIVES_EMITTED) { + pq->num_primitives_written = 0; + llvmpipe->so_stats.num_primitives_written = 0; + } + + if (pq->type == PIPE_QUERY_PRIMITIVES_GENERATED) { + pq->num_primitives_generated = 0; + llvmpipe->num_primitives_generated = 0; + } + + if (pq->type == 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; + } + + if (pq->type == 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++; + } + + if (pq->type == PIPE_QUERY_OCCLUSION_COUNTER) { + llvmpipe->active_occlusion_query = TRUE; + llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY; + } } @@ -79,25 +217,69 @@ static void llvmpipe_end_query(struct pipe_context *pipe, struct pipe_query *q) { struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe ); - struct llvmpipe_query *sq = llvmpipe_query(q); + struct llvmpipe_query *pq = llvmpipe_query(q); - llvmpipe->active_query_count--; - sq->end = llvmpipe->occlusion_count; - llvmpipe->dirty |= LP_NEW_QUERY; -} + lp_setup_end_query(llvmpipe->setup, pq); + if (pq->type == PIPE_QUERY_PRIMITIVES_EMITTED) { + pq->num_primitives_written = llvmpipe->so_stats.num_primitives_written; + } -static boolean -llvmpipe_get_query_result(struct pipe_context *pipe, - struct pipe_query *q, - boolean wait, - uint64_t *result ) -{ - struct llvmpipe_query *sq = llvmpipe_query(q); - *result = sq->end - sq->start; - return TRUE; + if (pq->type == PIPE_QUERY_PRIMITIVES_GENERATED) { + pq->num_primitives_generated = llvmpipe->num_primitives_generated; + } + + if (pq->type == PIPE_QUERY_SO_STATISTICS) { + pq->num_primitives_written = llvmpipe->so_stats.num_primitives_written; + pq->num_primitives_generated = llvmpipe->num_primitives_generated; + } + + if (pq->type == 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--; + } + + if (pq->type == PIPE_QUERY_OCCLUSION_COUNTER) { + assert(llvmpipe->active_occlusion_query); + llvmpipe->active_occlusion_query = FALSE; + llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY; + } } +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 > 0; + else + return TRUE; +} void llvmpipe_init_query_funcs(struct llvmpipe_context *llvmpipe ) {