From 49b493ddd0bd6718fe02258a070121f5f4aa10d8 Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Sun, 5 Sep 2010 08:27:12 +0200 Subject: [PATCH] nvfx: pause occlusion queries during blitter usage Thanks for Dave Airlie and Jerome Glisse for their code which made me realize I need this too. --- src/gallium/drivers/nouveau/nouveau_class.h | 2 +- src/gallium/drivers/nvfx/nvfx_context.h | 1 + src/gallium/drivers/nvfx/nvfx_query.c | 27 ++++++++++++++------- src/gallium/drivers/nvfx/nvfx_surface.c | 16 ++++++++++++ 4 files changed, 36 insertions(+), 10 deletions(-) diff --git a/src/gallium/drivers/nouveau/nouveau_class.h b/src/gallium/drivers/nouveau/nouveau_class.h index 72ddf9bf760..2c616886a39 100644 --- a/src/gallium/drivers/nouveau/nouveau_class.h +++ b/src/gallium/drivers/nouveau/nouveau_class.h @@ -6205,7 +6205,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define NV34TCL_COLOR_MATERIAL_BACK_B 0x000017b8 #define NV34TCL_COLOR_MATERIAL_BACK_A 0x000017c0 #define NV34TCL_QUERY_RESET 0x000017c8 -#define NV34TCL_QUERY_UNK17CC 0x000017cc +#define NV34TCL_QUERY_ENABLE 0x000017cc #define NV34TCL_QUERY_GET 0x00001800 #define NV34TCL_QUERY_GET_UNK24_SHIFT 24 #define NV34TCL_QUERY_GET_UNK24_MASK 0xff000000 diff --git a/src/gallium/drivers/nvfx/nvfx_context.h b/src/gallium/drivers/nvfx/nvfx_context.h index 369c2163882..a164ba6c10b 100644 --- a/src/gallium/drivers/nvfx/nvfx_context.h +++ b/src/gallium/drivers/nvfx/nvfx_context.h @@ -177,6 +177,7 @@ struct nvfx_context { struct nvfx_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS]; struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS]; struct nvfx_pipe_fragment_program* dummy_fs; + struct pipe_query* query; unsigned nr_samplers; unsigned nr_textures; diff --git a/src/gallium/drivers/nvfx/nvfx_query.c b/src/gallium/drivers/nvfx/nvfx_query.c index 1dab20c41a0..eeeb8976610 100644 --- a/src/gallium/drivers/nvfx/nvfx_query.c +++ b/src/gallium/drivers/nvfx/nvfx_query.c @@ -49,9 +49,10 @@ nvfx_query_begin(struct pipe_context *pipe, struct pipe_query *pq) struct nvfx_query *q = nvfx_query(pq); struct nvfx_screen *screen = nvfx->screen; struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *eng3d = screen->eng3d; uint64_t tmp; + assert(!nvfx->query); + /* Happens when end_query() is called, then another begin_query() * without querying the result in-between. For now we'll wait for * the existing query to notify completion, but it could be better. @@ -71,27 +72,35 @@ nvfx_query_begin(struct pipe_context *pipe, struct pipe_query *pq) nouveau_notifier_reset(nvfx->screen->query, q->object->start); - BEGIN_RING(chan, eng3d, NV34TCL_QUERY_RESET, 1); - OUT_RING (chan, 1); - BEGIN_RING(chan, eng3d, NV34TCL_QUERY_UNK17CC, 1); - OUT_RING (chan, 1); + WAIT_RING(chan, 4); + OUT_RING(chan, RING_3D(NV34TCL_QUERY_RESET, 1)); + OUT_RING(chan, 1); + OUT_RING(chan, RING_3D(NV34TCL_QUERY_ENABLE, 1)); + OUT_RING(chan, 1); q->ready = FALSE; + + nvfx->query = pq; } static void nvfx_query_end(struct pipe_context *pipe, struct pipe_query *pq) { struct nvfx_context *nvfx = nvfx_context(pipe); - struct nvfx_screen *screen = nvfx->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *eng3d = screen->eng3d; + struct nouveau_channel *chan = nvfx->screen->base.channel; struct nvfx_query *q = nvfx_query(pq); - BEGIN_RING(chan, eng3d, NV34TCL_QUERY_GET, 1); + assert(nvfx->query == pq); + + WAIT_RING(chan, 4); + OUT_RING(chan, RING_3D(NV34TCL_QUERY_GET, 1)); OUT_RING (chan, (0x01 << NV34TCL_QUERY_GET_UNK24_SHIFT) | ((q->object->start * 32) << NV34TCL_QUERY_GET_OFFSET_SHIFT)); + OUT_RING(chan, RING_3D(NV34TCL_QUERY_ENABLE, 1)); + OUT_RING(chan, 0); FIRE_RING(chan); + + nvfx->query = 0; } static boolean diff --git a/src/gallium/drivers/nvfx/nvfx_surface.c b/src/gallium/drivers/nvfx/nvfx_surface.c index aff7ac54b7f..e39f7f15a31 100644 --- a/src/gallium/drivers/nvfx/nvfx_surface.c +++ b/src/gallium/drivers/nvfx/nvfx_surface.c @@ -163,6 +163,14 @@ nvfx_get_blitter(struct pipe_context* pipe, int copy) assert(nvfx->blitters_in_use < Elements(nvfx->blitter)); + if(nvfx->query && !nvfx->blitters_in_use) + { + struct nouveau_channel* chan = nvfx->screen->base.channel; + WAIT_RING(chan, 2); + OUT_RING(chan, RING_3D(NV34TCL_QUERY_ENABLE, 1)); + OUT_RING(chan, 0); + } + struct blitter_context** pblitter = &nvfx->blitter[nvfx->blitters_in_use++]; if(!*pblitter) *pblitter = util_blitter_create(pipe); @@ -195,6 +203,14 @@ nvfx_put_blitter(struct pipe_context* pipe, struct blitter_context* blitter) struct nvfx_context* nvfx = nvfx_context(pipe); --nvfx->blitters_in_use; assert(nvfx->blitters_in_use >= 0); + + if(nvfx->query && !nvfx->blitters_in_use) + { + struct nouveau_channel* chan = nvfx->screen->base.channel; + WAIT_RING(chan, 2); + OUT_RING(chan, RING_3D(NV34TCL_QUERY_ENABLE, 1)); + OUT_RING(chan, 1); + } } static unsigned -- 2.30.2