diff options
author | Dave Airlie <airlied@redhat.com> | 2009-08-16 18:42:24 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2009-08-18 20:10:50 +1000 |
commit | 9ad76e9479c9c3cb8b2947d5144de33bb31197b8 (patch) | |
tree | 360207b69b08fd5281c0353feb622c7ae1aeeecf /src/mesa/drivers/dri/radeon | |
parent | 0e705c0dd397fe3c607551f988614178dacb9fa4 (diff) |
r300: OQ rework
Move to common code base so radeon/r200 can add support for this.
Make OQ start a state emitted like all normal state, and make no-tcl
flushing work in proper places.
Really need a generic post emit space reservation mechanism like max_state
so we can reserve some space for the emit
this code passes demos/arbocclude, piglit occlusion query and
glean occlusion query with TCL and NO-TCL on my rv530.
Diffstat (limited to 'src/mesa/drivers/dri/radeon')
-rw-r--r-- | src/mesa/drivers/dri/radeon/radeon_common.c | 6 | ||||
-rw-r--r-- | src/mesa/drivers/dri/radeon/radeon_common_context.c | 2 | ||||
-rw-r--r-- | src/mesa/drivers/dri/radeon/radeon_common_context.h | 20 | ||||
-rw-r--r-- | src/mesa/drivers/dri/radeon/radeon_queryobj.c | 216 | ||||
-rw-r--r-- | src/mesa/drivers/dri/radeon/radeon_queryobj.h | 55 |
5 files changed, 298 insertions, 1 deletions
diff --git a/src/mesa/drivers/dri/radeon/radeon_common.c b/src/mesa/drivers/dri/radeon/radeon_common.c index 0614c89459..0e9a1ae5d8 100644 --- a/src/mesa/drivers/dri/radeon/radeon_common.c +++ b/src/mesa/drivers/dri/radeon/radeon_common.c @@ -83,6 +83,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "radeon_lock.h" #include "radeon_drm.h" #include "radeon_mipmap_tree.h" +#include "radeon_queryobj.h" #define DEBUG_CMDBUF 0 @@ -1072,6 +1073,9 @@ void radeonFlush(GLcontext *ctx) } } } + + make_empty_list(&radeon->query.not_flushed_head); + } /* Make sure all commands have been sent to the hardware and have @@ -1128,6 +1132,8 @@ int rcommonFlushCmdBufLocked(radeonContextPtr rmesa, const char *caller) __FUNCTION__, caller, rmesa->numClipRects); } + radeonEmitQueryEnd(rmesa->glCtx); + if (rmesa->cmdbuf.cs->cdw) { ret = radeon_cs_emit(rmesa->cmdbuf.cs); rmesa->hw.all_dirty = GL_TRUE; diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.c b/src/mesa/drivers/dri/radeon/radeon_common_context.c index c0abcbfa21..35622099bf 100644 --- a/src/mesa/drivers/dri/radeon/radeon_common_context.c +++ b/src/mesa/drivers/dri/radeon/radeon_common_context.c @@ -263,6 +263,8 @@ GLboolean radeonInitContext(radeonContextPtr radeon, radeon->texture_compressed_row_align = 64; } + make_empty_list(&radeon->query.not_flushed_head); + return GL_TRUE; } diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.h b/src/mesa/drivers/dri/radeon/radeon_common_context.h index ee46c1f81a..a9480cd2e4 100644 --- a/src/mesa/drivers/dri/radeon/radeon_common_context.h +++ b/src/mesa/drivers/dri/radeon/radeon_common_context.h @@ -163,6 +163,7 @@ struct radeon_hw_state { /* Head of the linked list of state atoms. */ struct radeon_state_atom atomlist; int max_state_size; /* Number of bytes necessary for a full state emit. */ + int max_post_flush_size; /* Number of bytes necessary for post flushing emits */ GLboolean is_dirty, all_dirty; }; @@ -254,6 +255,17 @@ static INLINE radeonTexObj* radeon_tex_obj(struct gl_texture_object *texObj) return (radeonTexObj*)texObj; } +/* occlusion query */ +struct radeon_query_object { + struct gl_query_object Base; + struct radeon_bo *bo; + int curr_offset; + GLboolean emitted_begin; + + /* Double linked list of not flushed query objects */ + struct radeon_query_object *prev, *next; +}; + /* Need refcounting on dma buffers: */ struct radeon_dma_buffer { @@ -500,6 +512,12 @@ struct radeon_context { struct dri_metaops meta; struct { + struct radeon_query_object *current; + struct radeon_query_object not_flushed_head; + struct radeon_state_atom queryobj; + } query; + + struct { void (*get_lock)(radeonContextPtr radeon); void (*update_viewport_offset)(GLcontext *ctx); void (*emit_cs_header)(struct radeon_cs *cs, radeonContextPtr rmesa); @@ -508,6 +526,7 @@ struct radeon_context { void (*pre_emit_state)(radeonContextPtr rmesa); void (*fallback)(GLcontext *ctx, GLuint bit, GLboolean mode); void (*free_context)(GLcontext *ctx); + void (*emit_query_finish)(radeonContextPtr radeon); } vtbl; }; @@ -523,7 +542,6 @@ static inline __DRIdrawablePrivate* radeon_get_readable(radeonContextPtr radeon) return radeon->dri.context->driReadablePriv; } - /** * This function takes a float and packs it into a uint32_t */ diff --git a/src/mesa/drivers/dri/radeon/radeon_queryobj.c b/src/mesa/drivers/dri/radeon/radeon_queryobj.c new file mode 100644 index 0000000000..70251946df --- /dev/null +++ b/src/mesa/drivers/dri/radeon/radeon_queryobj.c @@ -0,0 +1,216 @@ +/* + * Copyright © 2008-2009 Maciej Cencora <m.cencora@gmail.com> + * + * 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, sublicense, + * 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 NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS 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. + * + * Authors: + * Maciej Cencora <m.cencora@gmail.com> + * + */ +#include "radeon_common.h" +#include "radeon_queryobj.h" + +#include "main/imports.h" +#include "main/simple_list.h" + +#define DDEBUG 0 + +#define PAGE_SIZE 4096 + +static void radeonQueryGetResult(GLcontext *ctx, struct gl_query_object *q) +{ + struct radeon_query_object *query = (struct radeon_query_object *)q; + uint32_t *result; + int i; + + if (DDEBUG) fprintf(stderr, "%s: query id %d, result %d\n", __FUNCTION__, query->Base.Id, (int) query->Base.Result); + + radeon_bo_map(query->bo, GL_FALSE); + + result = query->bo->ptr; + + query->Base.Result = 0; + for (i = 0; i < query->curr_offset/sizeof(uint32_t); ++i) { + query->Base.Result += result[i]; + if (DDEBUG) fprintf(stderr, "result[%d] = %d\n", i, result[i]); + } + + radeon_bo_unmap(query->bo); +} + +static struct gl_query_object * radeonNewQueryObject(GLcontext *ctx, GLuint id) +{ + struct radeon_query_object *query; + + query = _mesa_calloc(sizeof(struct radeon_query_object)); + + query->Base.Id = id; + query->Base.Result = 0; + query->Base.Active = GL_FALSE; + query->Base.Ready = GL_TRUE; + + if (DDEBUG) fprintf(stderr, "%s: query id %d\n", __FUNCTION__, query->Base.Id); + + return &query->Base; +} + +static void radeonDeleteQuery(GLcontext *ctx, struct gl_query_object *q) +{ + struct radeon_query_object *query = (struct radeon_query_object *)q; + + if (DDEBUG) fprintf(stderr, "%s: query id %d\n", __FUNCTION__, q->Id); + + if (query->bo) { + radeon_bo_unref(query->bo); + } + + _mesa_free(query); +} + +static void radeonWaitQuery(GLcontext *ctx, struct gl_query_object *q) +{ + radeonContextPtr radeon = RADEON_CONTEXT(ctx); + struct radeon_query_object *tmp, *query = (struct radeon_query_object *)q; + + /* If the cmdbuf with packets for this query hasn't been flushed yet, do it now */ + { + GLboolean found = GL_FALSE; + foreach(tmp, &radeon->query.not_flushed_head) { + if (tmp == query) { + found = GL_TRUE; + break; + } + } + + if (found) + ctx->Driver.Flush(ctx); + } + + if (DDEBUG) fprintf(stderr, "%s: query id %d, bo %p, offset %d\n", __FUNCTION__, q->Id, query->bo, query->curr_offset); + + radeonQueryGetResult(ctx, q); + + query->Base.Ready = GL_TRUE; +} + + +static void radeonBeginQuery(GLcontext *ctx, struct gl_query_object *q) +{ + radeonContextPtr radeon = RADEON_CONTEXT(ctx); + struct radeon_query_object *query = (struct radeon_query_object *)q; + + if (DDEBUG) fprintf(stderr, "%s: query id %d\n", __FUNCTION__, q->Id); + + assert(radeon->query.current == NULL); + + if (radeon->dma.flush) + radeon->dma.flush(radeon->glCtx); + + if (!query->bo) { + query->bo = radeon_bo_open(radeon->radeonScreen->bom, 0, PAGE_SIZE, PAGE_SIZE, RADEON_GEM_DOMAIN_GTT, 0); + } + query->curr_offset = 0; + + radeon->query.current = query; + + radeon->query.queryobj.dirty = GL_TRUE; + insert_at_tail(&radeon->query.not_flushed_head, query); + +} + +void radeonEmitQueryEnd(GLcontext *ctx) +{ + radeonContextPtr radeon = RADEON_CONTEXT(ctx); + struct radeon_query_object *query = radeon->query.current; + + if (!query) + return; + + if (query->emitted_begin == GL_FALSE) + return; + + if (DDEBUG) fprintf(stderr, "%s: query id %d, bo %p, offset %d\n", __FUNCTION__, query->Base.Id, query->bo, query->curr_offset); + + radeon_cs_space_check_with_bo(radeon->cmdbuf.cs, + query->bo, + 0, RADEON_GEM_DOMAIN_GTT); + + radeon->vtbl.emit_query_finish(radeon); +} + +static void radeonEndQuery(GLcontext *ctx, struct gl_query_object *q) +{ + radeonContextPtr radeon = RADEON_CONTEXT(ctx); + + if (DDEBUG) fprintf(stderr, "%s: query id %d\n", __FUNCTION__, q->Id); + + if (radeon->dma.flush) + radeon->dma.flush(radeon->glCtx); + radeonEmitQueryEnd(ctx); + + radeon->query.current = NULL; +} + +/** + * TODO: + * should check if bo is idle, bo there's no interface to do it + * just wait for result now + */ +static void radeonCheckQuery(GLcontext *ctx, struct gl_query_object *q) +{ + if (DDEBUG) fprintf(stderr, "%s: query id %d\n", __FUNCTION__, q->Id); + + radeonWaitQuery(ctx, q); +} + +void radeonInitQueryObjFunctions(struct dd_function_table *functions) +{ + functions->NewQueryObject = radeonNewQueryObject; + functions->DeleteQuery = radeonDeleteQuery; + functions->BeginQuery = radeonBeginQuery; + functions->EndQuery = radeonEndQuery; + functions->CheckQuery = radeonCheckQuery; + functions->WaitQuery = radeonWaitQuery; +} + +int radeon_check_query_active(GLcontext *ctx, struct radeon_state_atom *atom) +{ + radeonContextPtr radeon = RADEON_CONTEXT(ctx); + struct radeon_query_object *query = radeon->query.current; + + if (!query || query->emitted_begin) + return 0; + return atom->cmd_size; +} + +void radeon_emit_queryobj(GLcontext *ctx, struct radeon_state_atom *atom) +{ + radeonContextPtr radeon = RADEON_CONTEXT(ctx); + BATCH_LOCALS(radeon); + int dwords; + + dwords = (*atom->check) (ctx, atom); + + BEGIN_BATCH_NO_AUTOSTATE(dwords); + OUT_BATCH_TABLE(atom->cmd, dwords); + END_BATCH(); + + radeon->query.current->emitted_begin = GL_TRUE; +} diff --git a/src/mesa/drivers/dri/radeon/radeon_queryobj.h b/src/mesa/drivers/dri/radeon/radeon_queryobj.h new file mode 100644 index 0000000000..5e705838fe --- /dev/null +++ b/src/mesa/drivers/dri/radeon/radeon_queryobj.h @@ -0,0 +1,55 @@ +/* + * Copyright © 2008 Maciej Cencora <m.cencora@gmail.com> + * + * 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, sublicense, + * 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 NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS 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. + * + * Authors: + * Maciej Cencora <m.cencora@gmail.com> + * + */ + +#include "main/imports.h" +#include "main/simple_list.h" +#include "radeon_context.h" + +extern void radeonEmitQueryBegin(GLcontext *ctx); +extern void radeonEmitQueryEnd(GLcontext *ctx); + +extern void radeonInitQueryObjFunctions(struct dd_function_table *functions); + +#define RADEON_QUERY_PAGE_SIZE 4096 + +int radeon_check_query_active(GLcontext *ctx, struct radeon_state_atom *atom); +void radeon_emit_queryobj(GLcontext *ctx, struct radeon_state_atom *atom); + +static inline void radeon_init_query_stateobj(radeonContextPtr radeon, int SZ) +{ + radeon->query.queryobj.cmd_size = (SZ); + radeon->query.queryobj.cmd = (uint32_t*)CALLOC((SZ) * sizeof(uint32_t)); + radeon->query.queryobj.name = "queryobj"; + radeon->query.queryobj.idx = 0; + radeon->query.queryobj.check = radeon_check_query_active; + radeon->query.queryobj.dirty = GL_FALSE; + radeon->query.queryobj.emit = radeon_emit_queryobj; + + radeon->hw.max_state_size += (SZ); + insert_at_tail(&radeon->hw.atomlist, &radeon->query.queryobj); +} + |