From: Dave Airlie Date: Sun, 16 Aug 2009 08:42:24 +0000 (+1000) Subject: r300: OQ rework X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=9ad76e9479c9c3cb8b2947d5144de33bb31197b8;p=mesa.git 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. --- diff --git a/src/mesa/drivers/dri/r300/Makefile b/src/mesa/drivers/dri/r300/Makefile index 77b3d168f34..188efcb7a07 100644 --- a/src/mesa/drivers/dri/r300/Makefile +++ b/src/mesa/drivers/dri/r300/Makefile @@ -37,7 +37,8 @@ RADEON_COMMON_SOURCES = \ radeon_mipmap_tree.c \ radeon_span.c \ radeon_fbo.c \ - radeon_buffer_objects.c + radeon_buffer_objects.c \ + radeon_queryobj.c DRIVER_SOURCES = \ radeon_screen.c \ @@ -54,7 +55,6 @@ DRIVER_SOURCES = \ r300_shader.c \ r300_emit.c \ r300_swtcl.c \ - r300_queryobj.c \ $(RADEON_COMMON_SOURCES) \ $(EGL_SOURCES) \ $(CS_SOURCES) diff --git a/src/mesa/drivers/dri/r300/r300_cmdbuf.c b/src/mesa/drivers/dri/r300/r300_cmdbuf.c index 9042bbc1d77..1ca9eacda10 100644 --- a/src/mesa/drivers/dri/r300/r300_cmdbuf.c +++ b/src/mesa/drivers/dri/r300/r300_cmdbuf.c @@ -54,6 +54,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "radeon_mipmap_tree.h" #include "r300_state.h" #include "radeon_reg.h" +#include "radeon_queryobj.h" /** # of dwords reserved for additional instructions that may need to be written * during flushing. @@ -793,6 +794,17 @@ void r300InitCmdBuf(r300ContextPtr r300) r300->hw.tex.border_color.cmd[R300_TEX_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_TX_BORDER_COLOR_0, 0); + radeon_init_query_stateobj(&r300->radeon, R300_QUERYOBJ_CMDSIZE); + if (r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV530) { + r300->radeon.query.queryobj.cmd[R300_QUERYOBJ_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, RV530_FG_ZBREG_DEST, 1); + r300->radeon.query.queryobj.cmd[R300_QUERYOBJ_DATA_0] = RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL; + } else { + r300->radeon.query.queryobj.cmd[R300_QUERYOBJ_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_SU_REG_DEST, 1); + r300->radeon.query.queryobj.cmd[R300_QUERYOBJ_DATA_0] = R300_RASTER_PIPE_SELECT_ALL; + } + r300->radeon.query.queryobj.cmd[R300_QUERYOBJ_CMD_1] = cmdpacket0(r300->radeon.radeonScreen, R300_ZB_ZPASS_DATA, 1); + r300->radeon.query.queryobj.cmd[R300_QUERYOBJ_DATA_1] = 0; + r300->radeon.hw.is_dirty = GL_TRUE; r300->radeon.hw.all_dirty = GL_TRUE; diff --git a/src/mesa/drivers/dri/r300/r300_context.c b/src/mesa/drivers/dri/r300/r300_context.c index 91fa77a1690..7508de6fe18 100644 --- a/src/mesa/drivers/dri/r300/r300_context.c +++ b/src/mesa/drivers/dri/r300/r300_context.c @@ -64,11 +64,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "r300_ioctl.h" #include "r300_tex.h" #include "r300_emit.h" -#include "r300_queryobj.h" #include "r300_swtcl.h" #include "radeon_bocs_wrapper.h" #include "radeon_buffer_objects.h" - +#include "radeon_queryobj.h" #include "vblank.h" #include "utils.h" @@ -234,6 +233,85 @@ static void r300_fallback(GLcontext *ctx, GLuint bit, GLboolean mode) r300->radeon.Fallback &= ~bit; } +static void r300_emit_query_finish(radeonContextPtr radeon) +{ + r300ContextPtr r300 = (r300ContextPtr)radeon; + struct radeon_query_object *query = radeon->query.current; + BATCH_LOCALS(radeon); + + BEGIN_BATCH_NO_AUTOSTATE(3 * 2 *r300->num_z_pipes + 2); + switch (r300->num_z_pipes) { + case 4: + OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_3); + OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1); + OUT_BATCH_RELOC(0, query->bo, query->curr_offset+3*sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0); + case 3: + OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_2); + OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1); + OUT_BATCH_RELOC(0, query->bo, query->curr_offset+2*sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0); + case 2: + if (r300->radeon.radeonScreen->chip_family <= CHIP_FAMILY_RV380) { + OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_3); + } else { + OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_1); + } + OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1); + OUT_BATCH_RELOC(0, query->bo, query->curr_offset+1*sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0); + case 1: + default: + OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_0); + OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1); + OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0); + break; + } + OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_ALL); + END_BATCH(); + query->curr_offset += r300->num_z_pipes * sizeof(uint32_t); + assert(query->curr_offset < RADEON_QUERY_PAGE_SIZE); + query->emitted_begin = GL_FALSE; +} + +static void rv530_emit_query_finish_single_z(radeonContextPtr radeon) +{ + r300ContextPtr r300 = (r300ContextPtr)radeon; + BATCH_LOCALS(radeon); + struct radeon_query_object *query = radeon->query.current; + + BEGIN_BATCH_NO_AUTOSTATE(8); + OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0); + OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1); + OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0); + OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL); + END_BATCH(); + + query->curr_offset += sizeof(uint32_t); + assert(query->curr_offset < RADEON_QUERY_PAGE_SIZE); + query->emitted_begin = GL_FALSE; +} + +#if 0 +static void rv530_emit_query_finish_double_z(radeonContextPtr radeon) +{ + r300ContextPtr r300 = (r300ContextPtr)radeon; + BATCH_LOCALS(radeon); + struct radeon_query_object *query = radeon->query.current; + + BEGIN_BATCH_NO_AUTOSTATE(6); + OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0); + OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1); + OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0); + OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_1); + OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1); + OUT_BATCH_RELOC(0, query->bo, query->curr_offset + sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0); + OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL); + END_BATCH(); + + query->curr_offset += 2 * sizeof(uint32_t); + assert(query->curr_offset < RADEON_QUERY_PAGE_SIZE); + query->emitted_begin = GL_FALSE; +} +#endif + static void r300_init_vtbl(radeonContextPtr radeon) { radeon->vtbl.get_lock = r300_get_lock; @@ -242,6 +320,12 @@ static void r300_init_vtbl(radeonContextPtr radeon) radeon->vtbl.swtcl_flush = r300_swtcl_flush; radeon->vtbl.pre_emit_atoms = r300_vtbl_pre_emit_atoms; radeon->vtbl.fallback = r300_fallback; + if (radeon->radeonScreen->chip_family == CHIP_FAMILY_RV530) + /* single Z gives me correct results on my hw need to check if we ever need + * double z */ + radeon->vtbl.emit_query_finish = rv530_emit_query_finish_single_z; + else + radeon->vtbl.emit_query_finish = r300_emit_query_finish; } static void r300InitConstValues(GLcontext *ctx, radeonScreenPtr screen) @@ -361,8 +445,7 @@ static void r300InitGLExtensions(GLcontext *ctx) _mesa_disable_extension(ctx, "GL_EXT_texture_compression_s3tc"); } - if (!r300->radeon.radeonScreen->drmSupportsOcclusionQueries || - !r300->options.hw_tcl_enabled) { + if (!r300->radeon.radeonScreen->drmSupportsOcclusionQueries) { _mesa_disable_extension(ctx, "GL_ARB_occlusion_query"); } } @@ -389,6 +472,7 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual, r300ParseOptions(r300, screen); + r300->radeon.radeonScreen = screen; r300_init_vtbl(&r300->radeon); _mesa_init_driver_functions(&functions); @@ -396,7 +480,7 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual, r300InitStateFuncs(&functions); r300InitTextureFuncs(&functions); r300InitShaderFuncs(&functions); - r300InitQueryObjFunctions(&functions); + radeonInitQueryObjFunctions(&functions); radeonInitBufferObjectFuncs(&functions); if (!radeonInitContext(&r300->radeon, &functions, @@ -453,8 +537,6 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual, r300InitGLExtensions(ctx); - make_empty_list(&r300->query.not_flushed_head); - return GL_TRUE; } diff --git a/src/mesa/drivers/dri/r300/r300_context.h b/src/mesa/drivers/dri/r300/r300_context.h index 3ba34266084..65e0d466113 100644 --- a/src/mesa/drivers/dri/r300/r300_context.h +++ b/src/mesa/drivers/dri/r300/r300_context.h @@ -290,6 +290,12 @@ typedef struct r300_context *r300ContextPtr; #define R300_TEX_CMDSIZE (MAX_TEXTURE_UNITS+1) */ +#define R300_QUERYOBJ_CMD_0 0 +#define R300_QUERYOBJ_DATA_0 1 +#define R300_QUERYOBJ_CMD_1 2 +#define R300_QUERYOBJ_DATA_1 3 +#define R300_QUERYOBJ_CMDSIZE 4 + /** * Cache for hardware register state. */ @@ -380,7 +386,6 @@ struct r300_hw_state { struct radeon_state_atom border_color; } tex; struct radeon_state_atom txe; /* tex enable (4104) */ - radeonTexObj *textures[R300_MAX_TEXTURE_UNITS]; }; @@ -505,15 +510,6 @@ struct r300_index_buffer { GLuint count; }; -struct r300_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 r300_query_object *prev, *next; -}; /** * \brief R300 context structure. @@ -549,12 +545,6 @@ struct r300_context { uint32_t fallback; DECLARE_RENDERINPUTS(render_inputs_bitset); - - struct { - struct r300_query_object *current; - struct r300_query_object not_flushed_head; - } query; - int num_z_pipes; }; diff --git a/src/mesa/drivers/dri/r300/r300_draw.c b/src/mesa/drivers/dri/r300/r300_draw.c index d524d602998..239cfe11238 100644 --- a/src/mesa/drivers/dri/r300/r300_draw.c +++ b/src/mesa/drivers/dri/r300/r300_draw.c @@ -36,7 +36,6 @@ #include "r300_context.h" #include "r300_emit.h" #include "r300_render.h" -#include "r300_queryobj.h" #include "r300_state.h" #include "r300_tex.h" @@ -583,16 +582,12 @@ static GLboolean r300TryDrawPrims(GLcontext *ctx, r300EmitCacheFlush(r300); radeonEmitState(&r300->radeon); - r300EmitQueryBegin(ctx); - for (i = 0; i < nr_prims; ++i) { r300RunRenderPrimitive(ctx, prim[i].start, prim[i].start + prim[i].count, prim[i].mode); } r300EmitCacheFlush(r300); - r300EmitQueryEnd(ctx); - r300FreeData(ctx); return GL_TRUE; diff --git a/src/mesa/drivers/dri/r300/r300_ioctl.c b/src/mesa/drivers/dri/r300/r300_ioctl.c index da801f42e4c..7ab6928247a 100644 --- a/src/mesa/drivers/dri/r300/r300_ioctl.c +++ b/src/mesa/drivers/dri/r300/r300_ioctl.c @@ -57,7 +57,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "radeon_reg.h" #include "r300_emit.h" #include "r300_context.h" -#include "r300_queryobj.h" #include "vblank.h" @@ -755,19 +754,9 @@ static void r300Clear(GLcontext * ctx, GLbitfield mask) } } -static void r300Flush(GLcontext *ctx) -{ - r300ContextPtr r300 = R300_CONTEXT(ctx); - - radeonFlush(ctx); - - make_empty_list(&r300->query.not_flushed_head); -} - - void r300InitIoctlFuncs(struct dd_function_table *functions) { functions->Clear = r300Clear; functions->Finish = radeonFinish; - functions->Flush = r300Flush; + functions->Flush = radeonFlush; } diff --git a/src/mesa/drivers/dri/r300/r300_queryobj.c b/src/mesa/drivers/dri/r300/r300_queryobj.c deleted file mode 100644 index df1fb32ee78..00000000000 --- a/src/mesa/drivers/dri/r300/r300_queryobj.c +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright © 2008-2009 Maciej Cencora - * - * 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 - * - */ - -#include "r300_queryobj.h" -#include "r300_emit.h" - -#include "main/imports.h" -#include "main/simple_list.h" - -#define DDEBUG 0 - -#define PAGE_SIZE 4096 - -static void r300QueryGetResult(GLcontext *ctx, struct gl_query_object *q) -{ - struct r300_query_object *query = (struct r300_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 * r300NewQueryObject(GLcontext *ctx, GLuint id) -{ - struct r300_query_object *query; - - query = _mesa_calloc(sizeof(struct r300_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 r300DeleteQuery(GLcontext *ctx, struct gl_query_object *q) -{ - struct r300_query_object *query = (struct r300_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 r300BeginQuery(GLcontext *ctx, struct gl_query_object *q) -{ - r300ContextPtr r300 = R300_CONTEXT(ctx); - struct r300_query_object *query = (struct r300_query_object *)q; - - if (DDEBUG) fprintf(stderr, "%s: query id %d\n", __FUNCTION__, q->Id); - - assert(r300->query.current == NULL); - - if (!query->bo) { - query->bo = radeon_bo_open(r300->radeon.radeonScreen->bom, 0, PAGE_SIZE, PAGE_SIZE, RADEON_GEM_DOMAIN_GTT, 0); - } - query->curr_offset = 0; - - r300->query.current = query; - insert_at_tail(&r300->query.not_flushed_head, query); -} - -static void r300EndQuery(GLcontext *ctx, struct gl_query_object *q) -{ - r300ContextPtr r300 = R300_CONTEXT(ctx); - - if (DDEBUG) fprintf(stderr, "%s: query id %d\n", __FUNCTION__, q->Id); - - r300EmitQueryEnd(ctx); - - r300->query.current = NULL; -} - -static void r300WaitQuery(GLcontext *ctx, struct gl_query_object *q) -{ - r300ContextPtr r300 = R300_CONTEXT(ctx); - struct r300_query_object *tmp, *query = (struct r300_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, &r300->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); - - r300QueryGetResult(ctx, q); - - query->Base.Ready = GL_TRUE; -} - - -/** - * TODO: - * should check if bo is idle, bo there's no interface to do it - * just wait for result now - */ -static void r300CheckQuery(GLcontext *ctx, struct gl_query_object *q) -{ - if (DDEBUG) fprintf(stderr, "%s: query id %d\n", __FUNCTION__, q->Id); - - r300WaitQuery(ctx, q); -} - -void r300EmitQueryBegin(GLcontext *ctx) -{ - r300ContextPtr r300 = R300_CONTEXT(ctx); - struct r300_query_object *query = r300->query.current; - BATCH_LOCALS(&r300->radeon); - - if (!query || query->emitted_begin) - return; - - if (DDEBUG) fprintf(stderr, "%s: query id %d\n", __FUNCTION__, query->Base.Id); - - if (r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV530) { - BEGIN_BATCH_NO_AUTOSTATE(4); - OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL); - OUT_BATCH_REGVAL(R300_ZB_ZPASS_DATA, 0); - END_BATCH(); - } else { - BEGIN_BATCH_NO_AUTOSTATE(4); - OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_ALL); - OUT_BATCH_REGVAL(R300_ZB_ZPASS_DATA, 0); - END_BATCH(); - } - - query->emitted_begin = GL_TRUE; -} - -void r300EmitQueryEnd(GLcontext *ctx) -{ - r300ContextPtr r300 = R300_CONTEXT(ctx); - struct r300_query_object *query = r300->query.current; - BATCH_LOCALS(&r300->radeon); - - if (!query || !query->emitted_begin) - 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(r300->radeon.cmdbuf.cs, - query->bo, - 0, RADEON_GEM_DOMAIN_GTT); - - if (r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV530) { - BEGIN_BATCH_NO_AUTOSTATE(14); - OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0); - OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0); - OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_1); - OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_BATCH_RELOC(0, query->bo, query->curr_offset + sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0); - OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL); - END_BATCH(); - } else { - BEGIN_BATCH_NO_AUTOSTATE(3 * 2 *r300->num_z_pipes + 2); - switch (r300->num_z_pipes) { - case 4: - OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_3); - OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_BATCH_RELOC(0, query->bo, query->curr_offset+3*sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0); - case 3: - OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_2); - OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_BATCH_RELOC(0, query->bo, query->curr_offset+2*sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0); - case 2: - if (r300->radeon.radeonScreen->chip_family <= CHIP_FAMILY_RV380) { - OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_3); - } else { - OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_1); - } - OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_BATCH_RELOC(0, query->bo, query->curr_offset+1*sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0); - case 1: - default: - OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_0); - OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0); - break; - } - OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_ALL); - END_BATCH(); - } - - query->curr_offset += r300->num_z_pipes * sizeof(uint32_t); - assert(query->curr_offset < PAGE_SIZE); - query->emitted_begin = GL_FALSE; -} - -void r300InitQueryObjFunctions(struct dd_function_table *functions) -{ - functions->NewQueryObject = r300NewQueryObject; - functions->DeleteQuery = r300DeleteQuery; - functions->BeginQuery = r300BeginQuery; - functions->EndQuery = r300EndQuery; - functions->CheckQuery = r300CheckQuery; - functions->WaitQuery = r300WaitQuery; -} diff --git a/src/mesa/drivers/dri/r300/r300_queryobj.h b/src/mesa/drivers/dri/r300/r300_queryobj.h deleted file mode 100644 index f301f0b1133..00000000000 --- a/src/mesa/drivers/dri/r300/r300_queryobj.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright © 2008 Maciej Cencora - * - * 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 - * - */ - -#include "main/imports.h" -#include "r300_context.h" - -extern void r300EmitQueryBegin(GLcontext *ctx); -extern void r300EmitQueryEnd(GLcontext *ctx); - -extern void r300InitQueryObjFunctions(struct dd_function_table *functions); diff --git a/src/mesa/drivers/dri/r300/r300_render.c b/src/mesa/drivers/dri/r300/r300_render.c index 45330cda3c1..e1a6fae57f3 100644 --- a/src/mesa/drivers/dri/r300/r300_render.c +++ b/src/mesa/drivers/dri/r300/r300_render.c @@ -76,7 +76,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "r300_tex.h" #include "r300_emit.h" #include "r300_fragprog_common.h" -#include "r300_queryobj.h" #include "r300_swtcl.h" /** diff --git a/src/mesa/drivers/dri/r300/r300_state.c b/src/mesa/drivers/dri/r300/r300_state.c index 6081c337864..ce0666b9019 100644 --- a/src/mesa/drivers/dri/r300/r300_state.c +++ b/src/mesa/drivers/dri/r300/r300_state.c @@ -471,7 +471,7 @@ static void r300SetEarlyZState(GLcontext * ctx) topZ = R300_ZTOP_DISABLE; else if (ctx->FragmentProgram._Current && ctx->FragmentProgram._Current->UsesKill) topZ = R300_ZTOP_DISABLE; - else if (r300->query.current) + else if (r300->radeon.query.current) topZ = R300_ZTOP_DISABLE; if (topZ != r300->hw.zstencil_format.cmd[2]) { diff --git a/src/mesa/drivers/dri/r300/radeon_queryobj.c b/src/mesa/drivers/dri/r300/radeon_queryobj.c new file mode 120000 index 00000000000..1d6ebc1c48b --- /dev/null +++ b/src/mesa/drivers/dri/r300/radeon_queryobj.c @@ -0,0 +1 @@ +../radeon/radeon_queryobj.c \ No newline at end of file diff --git a/src/mesa/drivers/dri/r300/radeon_queryobj.h b/src/mesa/drivers/dri/r300/radeon_queryobj.h new file mode 120000 index 00000000000..8f6f842b0a6 --- /dev/null +++ b/src/mesa/drivers/dri/r300/radeon_queryobj.h @@ -0,0 +1 @@ +../radeon/radeon_queryobj.h \ No newline at end of file diff --git a/src/mesa/drivers/dri/radeon/radeon_common.c b/src/mesa/drivers/dri/radeon/radeon_common.c index 0614c894595..0e9a1ae5d81 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 c0abcbfa21e..35622099bf0 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 ee46c1f81a6..a9480cd2e4c 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 { @@ -499,6 +511,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); @@ -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 00000000000..70251946dff --- /dev/null +++ b/src/mesa/drivers/dri/radeon/radeon_queryobj.c @@ -0,0 +1,216 @@ +/* + * Copyright © 2008-2009 Maciej Cencora + * + * 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 + * + */ +#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 00000000000..5e705838fea --- /dev/null +++ b/src/mesa/drivers/dri/radeon/radeon_queryobj.h @@ -0,0 +1,55 @@ +/* + * Copyright © 2008 Maciej Cencora + * + * 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 + * + */ + +#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); +} +