From 13699463a33c1adf44005125c488e886e074a05b Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Tue, 11 Dec 2007 17:10:26 +0000 Subject: Rework gallium and mesa queries a little. Add a 'CheckQuery()' driver callback to mesa to check query completion. Make pipe_query an opaque type. Rework softpipe queries, support overlapping occlusion queries. --- src/mesa/drivers/common/driverfuncs.c | 1 + src/mesa/main/dd.h | 2 + src/mesa/main/queryobj.c | 18 +++-- src/mesa/main/queryobj.h | 3 + src/mesa/pipe/i915simple/i915_context.c | 17 ----- src/mesa/pipe/p_context.h | 20 +++++- src/mesa/pipe/p_state.h | 10 --- src/mesa/pipe/softpipe/Makefile | 1 + src/mesa/pipe/softpipe/sp_context.c | 36 +--------- src/mesa/pipe/softpipe/sp_context.h | 6 +- src/mesa/pipe/softpipe/sp_quad_occlusion.c | 16 +++-- src/mesa/pipe/softpipe/sp_query.c | 107 +++++++++++++++++++++++++++++ src/mesa/pipe/softpipe/sp_query.h | 39 +++++++++++ src/mesa/state_tracker/st_cb_queryobj.c | 68 +++++++++++++----- 14 files changed, 247 insertions(+), 97 deletions(-) create mode 100644 src/mesa/pipe/softpipe/sp_query.c create mode 100644 src/mesa/pipe/softpipe/sp_query.h (limited to 'src/mesa') diff --git a/src/mesa/drivers/common/driverfuncs.c b/src/mesa/drivers/common/driverfuncs.c index ea0cc51d4a..33caf7dae1 100644 --- a/src/mesa/drivers/common/driverfuncs.c +++ b/src/mesa/drivers/common/driverfuncs.c @@ -224,6 +224,7 @@ _mesa_init_driver_functions(struct dd_function_table *driver) /* query objects */ driver->NewQueryObject = _mesa_new_query_object; + driver->DeleteQuery = _mesa_delete_query; driver->BeginQuery = _mesa_begin_query; driver->EndQuery = _mesa_end_query; driver->WaitQuery = _mesa_wait_query; diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h index f089fcb48f..3bec3bd433 100644 --- a/src/mesa/main/dd.h +++ b/src/mesa/main/dd.h @@ -811,8 +811,10 @@ struct dd_function_table { */ /*@{*/ struct gl_query_object * (*NewQueryObject)(GLcontext *ctx, GLuint id); + void (*DeleteQuery)(GLcontext *ctx, struct gl_query_object *q); void (*BeginQuery)(GLcontext *ctx, struct gl_query_object *q); void (*EndQuery)(GLcontext *ctx, struct gl_query_object *q); + void (*CheckQuery)(GLcontext *ctx, struct gl_query_object *q); void (*WaitQuery)(GLcontext *ctx, struct gl_query_object *q); /*@}*/ diff --git a/src/mesa/main/queryobj.c b/src/mesa/main/queryobj.c index 688d0fc7bc..e30f5480da 100644 --- a/src/mesa/main/queryobj.c +++ b/src/mesa/main/queryobj.c @@ -94,8 +94,8 @@ _mesa_wait_query(GLcontext *ctx, struct gl_query_object *q) * Not removed from hash table here. * XXX maybe add Delete() method to gl_query_object class and call that instead */ -static void -delete_query_object(struct gl_query_object *q) +void +_mesa_delete_query(struct gl_query_object *q) { _mesa_free(q); } @@ -171,7 +171,7 @@ _mesa_DeleteQueriesARB(GLsizei n, const GLuint *ids) if (q) { ASSERT(!q->Active); /* should be caught earlier */ _mesa_HashRemove(ctx->Query.QueryObjects, ids[i]); - delete_query_object(q); + ctx->Driver.DeleteQuery(ctx, q); } } } @@ -386,6 +386,8 @@ _mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params) } break; case GL_QUERY_RESULT_AVAILABLE_ARB: + if (!q->Ready) + ctx->Driver.CheckQuery( ctx, q ); *params = q->Ready; break; default: @@ -424,6 +426,8 @@ _mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params) } break; case GL_QUERY_RESULT_AVAILABLE_ARB: + if (!q->Ready) + ctx->Driver.CheckQuery( ctx, q ); *params = q->Ready; break; default: @@ -461,6 +465,8 @@ _mesa_GetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64EXT *params) *params = q->Result; break; case GL_QUERY_RESULT_AVAILABLE_ARB: + if (!q->Ready) + ctx->Driver.CheckQuery( ctx, q ); *params = q->Ready; break; default: @@ -496,6 +502,8 @@ _mesa_GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64EXT *params) *params = q->Result; break; case GL_QUERY_RESULT_AVAILABLE_ARB: + if (!q->Ready) + ctx->Driver.CheckQuery( ctx, q ); *params = q->Ready; break; default: @@ -527,8 +535,8 @@ static void delete_queryobj_cb(GLuint id, void *data, void *userData) { struct gl_query_object *q= (struct gl_query_object *) data; - (void) userData; - delete_query_object(q); + GLcontext *ctx = (GLcontext *)userData; + ctx->Driver.DeleteQuery(ctx, q); } diff --git a/src/mesa/main/queryobj.h b/src/mesa/main/queryobj.h index d466aae652..c05a1f3da8 100644 --- a/src/mesa/main/queryobj.h +++ b/src/mesa/main/queryobj.h @@ -36,6 +36,9 @@ _mesa_init_query(GLcontext *ctx); extern void _mesa_free_query_data(GLcontext *ctx); +extern void +_mesa_delete_query(struct gl_query_object *q); + extern void _mesa_begin_query(GLcontext *ctx, struct gl_query_object *q); diff --git a/src/mesa/pipe/i915simple/i915_context.c b/src/mesa/pipe/i915simple/i915_context.c index d2bbeea16a..a08cf5087e 100644 --- a/src/mesa/pipe/i915simple/i915_context.c +++ b/src/mesa/pipe/i915simple/i915_context.c @@ -170,21 +170,6 @@ static void i915_destroy( struct pipe_context *pipe ) -static void -i915_begin_query(struct pipe_context *pipe, struct pipe_query_object *q) -{ - /* should never be called */ - assert(0); -} - - -static void -i915_end_query(struct pipe_context *pipe, struct pipe_query_object *q) -{ - /* should never be called */ - assert(0); -} - static boolean i915_draw_elements( struct pipe_context *pipe, @@ -298,8 +283,6 @@ struct pipe_context *i915_create( struct pipe_winsys *pipe_winsys, i915->pipe.clear = i915_clear; - i915->pipe.begin_query = i915_begin_query; - i915->pipe.end_query = i915_end_query; i915->pipe.draw_arrays = i915_draw_arrays; i915->pipe.draw_elements = i915_draw_elements; diff --git a/src/mesa/pipe/p_context.h b/src/mesa/pipe/p_context.h index 83b4ab07fb..92ca7dd8e3 100644 --- a/src/mesa/pipe/p_context.h +++ b/src/mesa/pipe/p_context.h @@ -29,9 +29,13 @@ #define PIPE_CONTEXT_H #include "p_state.h" +#include struct pipe_state_cache; +/* Opaque driver handles: + */ +struct pipe_query; /** * Gallium rendering context. Basically: @@ -81,9 +85,19 @@ struct pipe_context { /** * Query objects */ - void (*begin_query)(struct pipe_context *pipe, struct pipe_query_object *q); - void (*end_query)(struct pipe_context *pipe, struct pipe_query_object *q); - void (*wait_query)(struct pipe_context *pipe, struct pipe_query_object *q); + struct pipe_query *(*create_query)( struct pipe_context *pipe, + unsigned query_type ); + + void (*destroy_query)(struct pipe_context *pipe, + struct pipe_query *q); + + void (*begin_query)(struct pipe_context *pipe, struct pipe_query *q); + void (*end_query)(struct pipe_context *pipe, struct pipe_query *q); + + boolean (*get_query_result)(struct pipe_context *pipe, + struct pipe_query *q, + boolean wait, + uint64_t *result); /* * State functions diff --git a/src/mesa/pipe/p_state.h b/src/mesa/pipe/p_state.h index a571071ea9..109913b040 100644 --- a/src/mesa/pipe/p_state.h +++ b/src/mesa/pipe/p_state.h @@ -317,14 +317,4 @@ struct pipe_vertex_element -/** - * Hardware queries (occlusion, transform feedback, timing, etc) - */ -struct pipe_query_object { - uint type:3; /**< PIPE_QUERY_x */ - uint ready:1; /**< is result ready? */ - uint64 count; -}; - - #endif diff --git a/src/mesa/pipe/softpipe/Makefile b/src/mesa/pipe/softpipe/Makefile index 5e6886a37e..31438a882e 100644 --- a/src/mesa/pipe/softpipe/Makefile +++ b/src/mesa/pipe/softpipe/Makefile @@ -7,6 +7,7 @@ LIBNAME = softpipe DRIVER_SOURCES = \ sp_clear.c \ sp_flush.c \ + sp_query.c \ sp_context.c \ sp_draw_arrays.c \ sp_prim_setup.c \ diff --git a/src/mesa/pipe/softpipe/sp_context.c b/src/mesa/pipe/softpipe/sp_context.c index 7d243aaabb..107c8f8597 100644 --- a/src/mesa/pipe/softpipe/sp_context.c +++ b/src/mesa/pipe/softpipe/sp_context.c @@ -42,6 +42,7 @@ #include "sp_tile_cache.h" #include "sp_texture.h" #include "sp_winsys.h" +#include "sp_query.h" @@ -150,37 +151,6 @@ static void softpipe_destroy( struct pipe_context *pipe ) } -static void -softpipe_begin_query(struct pipe_context *pipe, struct pipe_query_object *q) -{ - struct softpipe_context *softpipe = softpipe_context( pipe ); - assert(q->type < PIPE_QUERY_TYPES); - assert(!softpipe->queries[q->type]); - softpipe->queries[q->type] = q; -} - - -static void -softpipe_end_query(struct pipe_context *pipe, struct pipe_query_object *q) -{ - struct softpipe_context *softpipe = softpipe_context( pipe ); - assert(q->type < PIPE_QUERY_TYPES); - assert(softpipe->queries[q->type]); - q->ready = 1; /* software rendering is synchronous */ - softpipe->queries[q->type] = NULL; -} - - -static void -softpipe_wait_query(struct pipe_context *pipe, struct pipe_query_object *q) -{ - /* Should never get here since we indicated that the result was - * ready in softpipe_end_query(). - */ - assert(0); -} - - static const char *softpipe_get_name( struct pipe_context *pipe ) { return "softpipe"; @@ -320,9 +290,7 @@ struct pipe_context *softpipe_create( struct pipe_winsys *pipe_winsys, softpipe->pipe.clear = softpipe_clear; softpipe->pipe.flush = softpipe_flush; - softpipe->pipe.begin_query = softpipe_begin_query; - softpipe->pipe.end_query = softpipe_end_query; - softpipe->pipe.wait_query = softpipe_wait_query; + softpipe_init_query_funcs( softpipe ); /* textures */ softpipe->pipe.texture_create = softpipe_texture_create; diff --git a/src/mesa/pipe/softpipe/sp_context.h b/src/mesa/pipe/softpipe/sp_context.h index afdd0ec88e..2c038de5f7 100644 --- a/src/mesa/pipe/softpipe/sp_context.h +++ b/src/mesa/pipe/softpipe/sp_context.h @@ -93,10 +93,10 @@ struct softpipe_context { struct pipe_vertex_element vertex_element[PIPE_ATTRIB_MAX]; unsigned dirty; - /* - * Active queries + /* Counter for occlusion queries. Note this supports overlapping + * queries. */ - struct pipe_query_object *queries[PIPE_QUERY_TYPES]; + uint64_t occlusion_count; /* * Mapped vertex buffers diff --git a/src/mesa/pipe/softpipe/sp_quad_occlusion.c b/src/mesa/pipe/softpipe/sp_quad_occlusion.c index d65fdbdab7..54254df1f1 100644 --- a/src/mesa/pipe/softpipe/sp_quad_occlusion.c +++ b/src/mesa/pipe/softpipe/sp_quad_occlusion.c @@ -39,18 +39,22 @@ #include "sp_surface.h" #include "sp_quad.h" +static unsigned count_bits( unsigned val ) +{ + unsigned i; + + for (i = 0; val ; val >>= 1) + i += (val & 1); + + return i; +} static void occlusion_count_quad(struct quad_stage *qs, struct quad_header *quad) { struct softpipe_context *softpipe = qs->softpipe; - struct pipe_query_object *occ - = softpipe->queries[PIPE_QUERY_OCCLUSION_COUNTER]; - occ->count += (quad->mask ) & 1; - occ->count += (quad->mask >> 1) & 1; - occ->count += (quad->mask >> 2) & 1; - occ->count += (quad->mask >> 3) & 1; + softpipe->occlusion_count += count_bits(quad->mask); qs->next->run(qs->next, quad); } diff --git a/src/mesa/pipe/softpipe/sp_query.c b/src/mesa/pipe/softpipe/sp_query.c new file mode 100644 index 0000000000..bf753dad98 --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_query.c @@ -0,0 +1,107 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * 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 + * 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 + */ + +#include "pipe/draw/draw_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_inlines.h" +#include "pipe/p_util.h" +#include "sp_context.h" +#include "sp_query.h" + +struct softpipe_query { + uint64_t start; + uint64_t end; +}; + + +static struct softpipe_query *softpipe_query( struct pipe_query *p ) +{ + return (struct softpipe_query *)p; +} + +static struct pipe_query * +softpipe_create_query(struct pipe_context *pipe, + unsigned type) +{ + assert(type == PIPE_QUERY_OCCLUSION_COUNTER); + return (struct pipe_query *)CALLOC_STRUCT( softpipe_query ); +} + + +static void +softpipe_destroy_query(struct pipe_context *pipe, struct pipe_query *q) +{ + FREE(q); +} + + +static void +softpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q) +{ + struct softpipe_context *softpipe = softpipe_context( pipe ); + struct softpipe_query *sq = softpipe_query(q); + + sq->start = softpipe->occlusion_count; +} + + +static void +softpipe_end_query(struct pipe_context *pipe, struct pipe_query *q) +{ + struct softpipe_context *softpipe = softpipe_context( pipe ); + struct softpipe_query *sq = softpipe_query(q); + + sq->end = softpipe->occlusion_count; +} + + +static boolean +softpipe_get_query_result(struct pipe_context *pipe, + struct pipe_query *q, + boolean wait, + uint64_t *result ) +{ + struct softpipe_query *sq = softpipe_query(q); + *result = sq->end - sq->start; + return TRUE; +} + + +void softpipe_init_query_funcs(struct softpipe_context *softpipe ) +{ + softpipe->pipe.create_query = softpipe_create_query; + softpipe->pipe.destroy_query = softpipe_destroy_query; + softpipe->pipe.begin_query = softpipe_begin_query; + softpipe->pipe.end_query = softpipe_end_query; + softpipe->pipe.get_query_result = softpipe_get_query_result; +} + + diff --git a/src/mesa/pipe/softpipe/sp_query.h b/src/mesa/pipe/softpipe/sp_query.h new file mode 100644 index 0000000000..05060a4575 --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_query.h @@ -0,0 +1,39 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * 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 + * 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 + */ + +#ifndef SP_QUERY_H +#define SP_QUERY_H + +struct softpipe_context; +extern void softpipe_init_query_funcs(struct softpipe_context * ); + + +#endif /* SP_QUERY_H */ diff --git a/src/mesa/state_tracker/st_cb_queryobj.c b/src/mesa/state_tracker/st_cb_queryobj.c index 5b95dd7fd3..c1d0d086b4 100644 --- a/src/mesa/state_tracker/st_cb_queryobj.c +++ b/src/mesa/state_tracker/st_cb_queryobj.c @@ -47,7 +47,7 @@ struct st_query_object { struct gl_query_object base; - struct pipe_query_object pq; + struct pipe_query *pq; }; @@ -68,12 +68,28 @@ st_NewQueryObject(GLcontext *ctx, GLuint id) if (stq) { stq->base.Id = id; stq->base.Ready = GL_TRUE; + stq->pq = NULL; return &stq->base; } return NULL; } + +static void +st_DeleteQuery(GLcontext *ctx, struct gl_query_object *q) +{ + struct pipe_context *pipe = ctx->st->pipe; + struct st_query_object *stq = st_query_object(q); + + if (stq->pq) { + pipe->destroy_query(pipe, stq->pq); + stq->pq = NULL; + } + + FREE(stq); +} + /** * Do glReadPixels by getting rows from the framebuffer surface with * get_tile(). Convert to requested format/type with Mesa image routines. @@ -85,25 +101,17 @@ st_BeginQuery(GLcontext *ctx, struct gl_query_object *q) struct pipe_context *pipe = ctx->st->pipe; struct st_query_object *stq = st_query_object(q); - stq->pq.count = 0; - switch (q->Target) { case GL_SAMPLES_PASSED_ARB: - stq->pq.type = PIPE_QUERY_OCCLUSION_COUNTER; - break; - case GL_PRIMITIVES_GENERATED_NV: - /* someday */ - stq->pq.type = PIPE_QUERY_PRIMITIVES_GENERATED; - break; - case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV: - /* someday */ - stq->pq.type = PIPE_QUERY_PRIMITIVES_EMITTED; + if (!stq->pq) + stq->pq = pipe->create_query( pipe, PIPE_QUERY_OCCLUSION_COUNTER ); break; default: assert(0); + return; } - pipe->begin_query(pipe, &stq->pq); + pipe->begin_query(pipe, stq->pq); } @@ -113,10 +121,7 @@ st_EndQuery(GLcontext *ctx, struct gl_query_object *q) struct pipe_context *pipe = ctx->st->pipe; struct st_query_object *stq = st_query_object(q); - pipe->end_query(pipe, &stq->pq); - stq->base.Ready = stq->pq.ready; - if (stq->base.Ready) - stq->base.Result = stq->pq.count; + pipe->end_query(pipe, stq->pq); } @@ -129,17 +134,42 @@ st_WaitQuery(GLcontext *ctx, struct gl_query_object *q) /* this function should only be called if we don't have a ready result */ assert(!stq->base.Ready); - pipe->wait_query(pipe, &stq->pq); + while (!stq->base.Ready && + !pipe->get_query_result(pipe, + stq->pq, + TRUE, + &q->Result)) + { + /* nothing */ + } + q->Ready = GL_TRUE; - q->Result = stq->pq.count; } +static void +st_CheckQuery(GLcontext *ctx, struct gl_query_object *q) +{ + struct pipe_context *pipe = ctx->st->pipe; + struct st_query_object *stq = st_query_object(q); + + if (!q->Ready) { + q->Ready = pipe->get_query_result(pipe, + stq->pq, + FALSE, + &q->Result); + } +} + + + void st_init_query_functions(struct dd_function_table *functions) { functions->NewQueryObject = st_NewQueryObject; + functions->DeleteQuery = st_DeleteQuery; functions->BeginQuery = st_BeginQuery; functions->EndQuery = st_EndQuery; functions->WaitQuery = st_WaitQuery; + functions->CheckQuery = st_CheckQuery; } -- cgit v1.2.3