From b5d59222ccbec9db23b6847737765a4dc0d8c47b Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 25 Sep 2008 17:19:47 -0700 Subject: Remove TNL-to-VP tracking from i965 The i965 driver previously had it's own set of code to convert fixed-function TNL state to a vertex program. Core Mesa has code to do this, so there is no reason to duplicate that effort in the driver. In fact, this duplication leads to bugs when other aspects of the Mesa infrastructure change. --- src/mesa/drivers/dri/i965/brw_context.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/mesa/drivers/dri/i965/brw_context.c') diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c index 92629016d9..5f60477176 100644 --- a/src/mesa/drivers/dri/i965/brw_context.c +++ b/src/mesa/drivers/dri/i965/brw_context.c @@ -152,8 +152,6 @@ GLboolean brwCreateContext( const __GLcontextModes *mesaVis, brw_draw_init( brw ); - brw_ProgramCacheInit( ctx ); - return GL_TRUE; } -- cgit v1.2.3 From c157cfc6376f7469ab272b18868183e5ff9ac754 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 6 Oct 2008 17:34:51 -0700 Subject: i965: Add ARB_occlusion_query support. --- src/mesa/drivers/dri/i965/Makefile | 1 + src/mesa/drivers/dri/i965/brw_context.c | 4 + src/mesa/drivers/dri/i965/brw_context.h | 30 +++- src/mesa/drivers/dri/i965/brw_draw.c | 2 +- src/mesa/drivers/dri/i965/brw_draw_upload.c | 3 + src/mesa/drivers/dri/i965/brw_queryobj.c | 263 ++++++++++++++++++++++++++++ src/mesa/drivers/dri/i965/brw_vtbl.c | 10 ++ src/mesa/drivers/dri/intel/intel_context.c | 51 +----- src/mesa/drivers/dri/intel/intel_reg.h | 19 ++ 9 files changed, 331 insertions(+), 52 deletions(-) create mode 100644 src/mesa/drivers/dri/i965/brw_queryobj.c (limited to 'src/mesa/drivers/dri/i965/brw_context.c') diff --git a/src/mesa/drivers/dri/i965/Makefile b/src/mesa/drivers/dri/i965/Makefile index c2d555cd0c..7bc16a02c8 100644 --- a/src/mesa/drivers/dri/i965/Makefile +++ b/src/mesa/drivers/dri/i965/Makefile @@ -51,6 +51,7 @@ DRIVER_SOURCES = \ brw_metaops.c \ brw_misc_state.c \ brw_program.c \ + brw_queryobj.c \ brw_sf.c \ brw_sf_emit.c \ brw_sf_state.c \ diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c index 5f60477176..474158b484 100644 --- a/src/mesa/drivers/dri/i965/brw_context.c +++ b/src/mesa/drivers/dri/i965/brw_context.c @@ -33,6 +33,7 @@ #include "main/imports.h" #include "main/api_noop.h" #include "main/vtxfmt.h" +#include "main/simple_list.h" #include "shader/shader_api.h" #include "brw_context.h" @@ -68,6 +69,7 @@ static void brwInitDriverFunctions( struct dd_function_table *functions ) brwInitFragProgFuncs( functions ); brwInitProgFuncs( functions ); + brw_init_queryobj_functions(functions); } @@ -150,6 +152,8 @@ GLboolean brwCreateContext( const __GLcontextModes *mesaVis, ctx->VertexProgram._MaintainTnlProgram = GL_TRUE; ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE; + make_empty_list(&brw->query.active_head); + brw_draw_init( brw ); return GL_TRUE; diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h index 8bddc9da40..1c6a0dede0 100644 --- a/src/mesa/drivers/dri/i965/brw_context.h +++ b/src/mesa/drivers/dri/i965/brw_context.h @@ -410,7 +410,22 @@ struct brw_tnl_cache { GLuint size, n_items; }; +struct brw_query_object { + struct gl_query_object Base; + /** Doubly linked list of active query objects in the context. */ + struct brw_query_object *prev, *next; + + /** Last query BO associated with this query. */ + dri_bo *bo; + /** First index in bo with query data for this object. */ + int first_index; + /** Last index in bo with query data for this object. */ + int last_index; + + /* Total count of pixels from previous BOs */ + unsigned int count; +}; struct brw_context { @@ -626,7 +641,12 @@ struct brw_context dri_bo *vp_bo; } cc; - + struct { + struct brw_query_object active_head; + dri_bo *bo; + int index; + GLboolean active; + } query; /* Used to give every program string a unique id */ GLuint program_id; @@ -651,7 +671,13 @@ GLboolean brwCreateContext( const __GLcontextModes *mesaVis, __DRIcontextPrivate *driContextPriv, void *sharedContextPrivate); - +/*====================================================================== + * brw_queryobj.c + */ +void brw_init_queryobj_functions(struct dd_function_table *functions); +void brw_prepare_query_begin(struct brw_context *brw); +void brw_emit_query_begin(struct brw_context *brw); +void brw_emit_query_end(struct brw_context *brw); /*====================================================================== * brw_state.c diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c index 39ce8eb4b6..6c71b4abcf 100644 --- a/src/mesa/drivers/dri/i965/brw_draw.c +++ b/src/mesa/drivers/dri/i965/brw_draw.c @@ -382,7 +382,6 @@ void brw_draw_prims( GLcontext *ctx, return; } - /* Make a first attempt at drawing: */ retval = brw_try_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index); @@ -395,6 +394,7 @@ void brw_draw_prims( GLcontext *ctx, _swsetup_Wakeup(ctx); _tnl_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index); } + } void brw_draw_init( struct brw_context *brw ) diff --git a/src/mesa/drivers/dri/i965/brw_draw_upload.c b/src/mesa/drivers/dri/i965/brw_draw_upload.c index cc3d9396ac..7b88b5eaa1 100644 --- a/src/mesa/drivers/dri/i965/brw_draw_upload.c +++ b/src/mesa/drivers/dri/i965/brw_draw_upload.c @@ -415,6 +415,8 @@ static void brw_prepare_vertices(struct brw_context *brw) copy_array_to_vbo_array(brw, upload[i], upload[i]->element_size); } } + + brw_prepare_query_begin(brw); } static void brw_emit_vertices(struct brw_context *brw) @@ -435,6 +437,7 @@ static void brw_emit_vertices(struct brw_context *brw) enabled[nr_enabled++] = input; } + brw_emit_query_begin(brw); /* Now emit VB and VEP state packets. * diff --git a/src/mesa/drivers/dri/i965/brw_queryobj.c b/src/mesa/drivers/dri/i965/brw_queryobj.c new file mode 100644 index 0000000000..a1a1353dee --- /dev/null +++ b/src/mesa/drivers/dri/i965/brw_queryobj.c @@ -0,0 +1,263 @@ +/* + * Copyright © 2008 Intel Corporation + * + * 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: + * Eric Anholt + * + */ + +/** @file support for ARB_query_object + * + * ARB_query_object is implemented by using the PIPE_CONTROL command to stall + * execution on the completion of previous depth tests, and write the + * current PS_DEPTH_COUNT to a buffer object. + * + * We use before and after counts when drawing during a query so that + * we don't pick up other clients' query data in ours. To reduce overhead, + * a single BO is used to record the query data for all active queries at + * once. This also gives us a simple bound on how much batchbuffer space is + * required for handling queries, so that we can be sure that we won't + * have to emit a batchbuffer without getting the ending PS_DEPTH_COUNT. + */ +#include "main/simple_list.h" +#include "main/imports.h" + +#include "brw_context.h" +#include "intel_batchbuffer.h" +#include "intel_reg.h" + +/** Waits on the query object's BO and totals the results for this query */ +static void +brw_queryobj_get_results(struct brw_query_object *query) +{ + int i; + uint64_t *results; + + if (query->bo == NULL) + return; + + /* Map and count the pixels from the current query BO */ + dri_bo_map(query->bo, GL_FALSE); + results = query->bo->virtual; + for (i = query->first_index; i <= query->last_index; i++) { + query->Base.Result += results[i * 2 + 1] - results[i * 2]; + } + dri_bo_unmap(query->bo); + + dri_bo_unreference(query->bo); + query->bo = NULL; +} + +static struct gl_query_object * +brw_new_query_object(GLcontext *ctx, GLuint id) +{ + struct brw_query_object *query; + + query = _mesa_calloc(sizeof(struct brw_query_object)); + + query->Base.Id = id; + query->Base.Result = 0; + query->Base.Active = GL_FALSE; + query->Base.Ready = GL_TRUE; + + return &query->Base; +} + +static void +brw_delete_query(GLcontext *ctx, struct gl_query_object *q) +{ + struct brw_query_object *query = (struct brw_query_object *)q; + + dri_bo_unreference(query->bo); + _mesa_free(query); +} + +static void +brw_begin_query(GLcontext *ctx, struct gl_query_object *q) +{ + struct brw_context *brw = brw_context(ctx); + struct intel_context *intel = intel_context(ctx); + struct brw_query_object *query = (struct brw_query_object *)q; + + /* Reset our driver's tracking of query state. */ + dri_bo_unreference(query->bo); + query->bo = NULL; + query->first_index = -1; + query->last_index = -1; + + insert_at_head(&brw->query.active_head, query); + intel->stats_wm++; +} + +/** + * Begin the ARB_occlusion_query query on a query object. + */ +static void +brw_end_query(GLcontext *ctx, struct gl_query_object *q) +{ + struct brw_context *brw = brw_context(ctx); + struct intel_context *intel = intel_context(ctx); + struct brw_query_object *query = (struct brw_query_object *)q; + + /* Flush the batchbuffer in case it has writes to our query BO. + * Have later queries write to a new query BO so that further rendering + * doesn't delay the collection of our results. + */ + if (query->bo) { + brw_emit_query_end(brw); + intel_batchbuffer_flush(intel->batch); + + dri_bo_unreference(brw->query.bo); + brw->query.bo = NULL; + } + + remove_from_list(query); + + intel->stats_wm--; +} + +static void brw_wait_query(GLcontext *ctx, struct gl_query_object *q) +{ + struct brw_query_object *query = (struct brw_query_object *)q; + + brw_queryobj_get_results(query); + query->Base.Ready = GL_TRUE; +} + +static void brw_check_query(GLcontext *ctx, struct gl_query_object *q) +{ + /* XXX: Need to expose dri_bo_is_idle from bufmgr. */ +#if 0 + struct brw_query_object *query = (struct brw_query_object *)q; + + if (dri_bo_is_idle(query->bo)) { + brw_queryobj_get_results(query); + query->Base.Ready = GL_TRUE; + } +#else + brw_wait_query(ctx, q); +#endif +} + +/** Called to set up the query BO and account for its aperture space */ +void +brw_prepare_query_begin(struct brw_context *brw) +{ + struct intel_context *intel = &brw->intel; + dri_bo *aper_array[] = { + intel->batch->buf, + brw->query.bo, + }; + + /* Skip if we're not doing any queries. */ + if (is_empty_list(&brw->query.active_head)) + return; + + /* Get a new query BO if we're going to need it. */ + if (brw->query.bo == NULL || + brw->query.index * 2 + 1 >= 4096 / sizeof(uint64_t)) { + dri_bo_unreference(brw->query.bo); + brw->query.bo = NULL; + + brw->query.bo = dri_bo_alloc(intel->bufmgr, "query", 4096, 1); + brw->query.index = 0; + } + + if (dri_bufmgr_check_aperture_space(aper_array, ARRAY_SIZE(aper_array))) + intel_batchbuffer_flush(intel->batch); +} + +/** Called just before primitive drawing to get a beginning PS_DEPTH_COUNT. */ +void +brw_emit_query_begin(struct brw_context *brw) +{ + struct intel_context *intel = &brw->intel; + struct brw_query_object *query; + + /* Skip if we're not doing any queries, or we've emitted the start. */ + if (brw->query.active || is_empty_list(&brw->query.active_head)) + return; + + BEGIN_BATCH(4, IGNORE_CLIPRECTS); + OUT_BATCH(_3DSTATE_PIPE_CONTROL | + PIPE_CONTROL_DEPTH_STALL | + PIPE_CONTROL_WRITE_DEPTH_COUNT); + /* This object could be mapped cacheable, but we don't have an exposed + * mechanism to support that. Since it's going uncached, tell GEM that + * we're writing to it. The usual clflush should be all that's required + * to pick up the results. + */ + OUT_RELOC(brw->query.bo, + I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, + PIPE_CONTROL_GLOBAL_GTT_WRITE | + ((brw->query.index * 2) * sizeof(uint64_t))); + OUT_BATCH(0); + OUT_BATCH(0); + ADVANCE_BATCH(); + + foreach(query, &brw->query.active_head) { + if (query->bo != brw->query.bo) { + if (query->bo != NULL) + brw_queryobj_get_results(query); + dri_bo_reference(brw->query.bo); + query->bo = brw->query.bo; + query->first_index = brw->query.index; + } + query->last_index = brw->query.index; + } + brw->query.active = GL_TRUE; +} + +/** Called at batchbuffer flush to get an ending PS_DEPTH_COUNT */ +void +brw_emit_query_end(struct brw_context *brw) +{ + struct intel_context *intel = &brw->intel; + + if (!brw->query.active) + return; + + BEGIN_BATCH(4, IGNORE_CLIPRECTS); + OUT_BATCH(_3DSTATE_PIPE_CONTROL | + PIPE_CONTROL_DEPTH_STALL | + PIPE_CONTROL_WRITE_DEPTH_COUNT); + OUT_RELOC(brw->query.bo, + I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, + PIPE_CONTROL_GLOBAL_GTT_WRITE | + ((brw->query.index * 2 + 1) * sizeof(uint64_t))); + OUT_BATCH(0); + OUT_BATCH(0); + ADVANCE_BATCH(); + + brw->query.active = GL_FALSE; + brw->query.index++; +} + +void brw_init_queryobj_functions(struct dd_function_table *functions) +{ + functions->NewQueryObject = brw_new_query_object; + functions->DeleteQuery = brw_delete_query; + functions->BeginQuery = brw_begin_query; + functions->EndQuery = brw_end_query; + functions->CheckQuery = brw_check_query; + functions->WaitQuery = brw_wait_query; +} diff --git a/src/mesa/drivers/dri/i965/brw_vtbl.c b/src/mesa/drivers/dri/i965/brw_vtbl.c index cd074dfed6..a64e437860 100644 --- a/src/mesa/drivers/dri/i965/brw_vtbl.c +++ b/src/mesa/drivers/dri/i965/brw_vtbl.c @@ -120,6 +120,15 @@ static void brw_set_draw_region( struct intel_context *intel, brw->state.nr_draw_regions = num_regions; } +/* called from intel_batchbuffer_flush and children before sending a + * batchbuffer off. + */ +static void brw_finish_batch(struct intel_context *intel) +{ + struct brw_context *brw = brw_context(&intel->ctx); + + brw_emit_query_end(brw); +} /* called from intelFlushBatchLocked */ @@ -218,6 +227,7 @@ void brwInitVtbl( struct brw_context *brw ) brw->intel.vtbl.note_fence = brw_note_fence; brw->intel.vtbl.note_unlock = brw_note_unlock; brw->intel.vtbl.new_batch = brw_new_batch; + brw->intel.vtbl.finish_batch = brw_finish_batch; brw->intel.vtbl.destroy = brw_destroy_context; brw->intel.vtbl.set_draw_region = brw_set_draw_region; brw->intel.vtbl.flush_cmd = brw_flush_cmd; diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c index 9dc32e487f..e6c0d3175e 100644 --- a/src/mesa/drivers/dri/intel/intel_context.c +++ b/src/mesa/drivers/dri/intel/intel_context.c @@ -394,6 +394,7 @@ static const struct dri_extension brw_extensions[] = { { "GL_ARB_fragment_program", NULL }, { "GL_ARB_fragment_program_shadow", NULL }, { "GL_ARB_fragment_shader", NULL }, + { "GL_ARB_occlusion_query", GL_ARB_occlusion_query_functions }, { "GL_ARB_point_sprite", NULL }, { "GL_ARB_shader_objects", GL_ARB_shader_objects_functions }, { "GL_ARB_shading_language_100", GL_VERSION_2_0_functions }, @@ -407,12 +408,9 @@ static const struct dri_extension brw_extensions[] = { { NULL, NULL } }; -#ifdef I915_MMIO_READ -static const struct dri_extension arb_oc_extensions[] = { - { "GL_ARB_occlusion_query", GL_ARB_occlusion_query_functions }, +static const struct dri_extension arb_oq_extensions[] = { { NULL, NULL } }; -#endif static const struct dri_extension ttm_extensions[] = { { "GL_ARB_pixel_buffer_object", NULL }, @@ -437,13 +435,6 @@ void intelInitExtensions(GLcontext *ctx, GLboolean enable_imaging) if (intel == NULL || intel->ttm) driInitExtensions(ctx, ttm_extensions, GL_FALSE); -#ifdef I915_MMIO_READ - if (intel == NULL || - (IS_965(intel->intelScreen->deviceID) && - intel->intelScreen->drmMinor >= 8)) - driInitExtensions(ctx, arb_oc_extensions, GL_FALSE); -#endif - if (intel == NULL || IS_965(intel->intelScreen->deviceID)) driInitExtensions(ctx, brw_extensions, GL_FALSE); } @@ -540,39 +531,6 @@ intelFinish(GLcontext * ctx) } } -#ifdef I915_MMIO_READ -static void -intelBeginQuery(GLcontext *ctx, struct gl_query_object *q) -{ - struct intel_context *intel = intel_context( ctx ); - struct drm_i915_mmio io = { - .read_write = I915_MMIO_READ, - .reg = MMIO_REGS_PS_DEPTH_COUNT, - .data = &q->Result - }; - intel->stats_wm++; - intelFinish(&intel->ctx); - drmCommandWrite(intel->driFd, DRM_I915_MMIO, &io, sizeof(io)); -} - -static void -intelEndQuery(GLcontext *ctx, struct gl_query_object *q) -{ - struct intel_context *intel = intel_context( ctx ); - GLuint64EXT tmp; - struct drm_i915_mmio io = { - .read_write = I915_MMIO_READ, - .reg = MMIO_REGS_PS_DEPTH_COUNT, - .data = &tmp - }; - intelFinish(&intel->ctx); - drmCommandWrite(intel->driFd, DRM_I915_MMIO, &io, sizeof(io)); - q->Result = tmp - q->Result; - q->Ready = GL_TRUE; - intel->stats_wm--; -} -#endif - void intelInitDriverFunctions(struct dd_function_table *functions) { @@ -589,11 +547,6 @@ intelInitDriverFunctions(struct dd_function_table *functions) functions->CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D; functions->CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D; -#ifdef I915_MMIO_READ - functions->BeginQuery = intelBeginQuery; - functions->EndQuery = intelEndQuery; -#endif - intelInitTextureFuncs(functions); intelInitStateFuncs(functions); intelInitBufferFuncs(functions); diff --git a/src/mesa/drivers/dri/intel/intel_reg.h b/src/mesa/drivers/dri/intel/intel_reg.h index 96af7e1a03..c21f408093 100644 --- a/src/mesa/drivers/dri/intel/intel_reg.h +++ b/src/mesa/drivers/dri/intel/intel_reg.h @@ -44,6 +44,25 @@ #define _3DSTATE_LOAD_STATE_IMMEDIATE_1 (CMD_3D | (0x1d<<24) | (0x04<<16)) #define I1_LOAD_S(n) (1<<(4+n)) +/** @{ + * + * PIPE_CONTROL operation, a combination MI_FLUSH and register write with + * additional flushing control. + */ +#define _3DSTATE_PIPE_CONTROL (CMD_3D | (3 << 27) | (2 << 24) | 2) +#define PIPE_CONTROL_NO_WRITE (0 << 14) +#define PIPE_CONTROL_WRITE_IMMEDIATE (1 << 14) +#define PIPE_CONTROL_WRITE_DEPTH_COUNT (2 << 14) +#define PIPE_CONTROL_WRITE_TIMESTAMP (3 << 14) +#define PIPE_CONTROL_DEPTH_STALL (1 << 13) +#define PIPE_CONTROL_WRITE_FLUSH (1 << 12) +#define PIPE_CONTROL_INSTRUCTION_FLUSH (1 << 11) +#define PIPE_CONTROL_INTERRUPT_ENABLE (1 << 8) +#define PIPE_CONTROL_PPGTT_WRITE (0 << 2) +#define PIPE_CONTROL_GLOBAL_GTT_WRITE (1 << 2) + +/** @} */ + /** @{ * 915 definitions */ -- cgit v1.2.3