diff options
author | Luca Barbieri <[email protected]> | 2010-01-18 01:02:55 +0100 |
---|---|---|
committer | Luca Barbieri <[email protected]> | 2010-04-12 23:36:21 +0200 |
commit | 9ad385fef95e8f8b9ecf89c85fb443e30196e9c2 (patch) | |
tree | 0a40214011a89573d2c48d92fb6939e4cdb25ace /src/gallium/drivers/nvfx | |
parent | 202760b4372fbe8488b0c6b93578697ae81fd430 (diff) |
nvfx: support an unlimited number of occlusion queries
Currently on nv30/nv40 an assert will be triggered once 32 queries are
outstanding.
This violates the OpenGL/Gallium interface, which requires support for
an unlimited number of fences.
This patch fixes the problem by putting queries in a linked list and
waiting on the oldest one if allocation fails.
nVidia seems to use a similar strategy, but with 1024 instead of 32 fences.
The next patch will improve this.
Diffstat (limited to 'src/gallium/drivers/nvfx')
-rw-r--r-- | src/gallium/drivers/nvfx/nvfx_query.c | 26 | ||||
-rw-r--r-- | src/gallium/drivers/nvfx/nvfx_screen.c | 2 | ||||
-rw-r--r-- | src/gallium/drivers/nvfx/nvfx_screen.h | 2 |
3 files changed, 22 insertions, 8 deletions
diff --git a/src/gallium/drivers/nvfx/nvfx_query.c b/src/gallium/drivers/nvfx/nvfx_query.c index acbaf75a236..1b20b5245d7 100644 --- a/src/gallium/drivers/nvfx/nvfx_query.c +++ b/src/gallium/drivers/nvfx/nvfx_query.c @@ -3,6 +3,7 @@ #include "nvfx_context.h" struct nvfx_query { + struct list_head list; struct nouveau_resource *object; unsigned type; boolean ready; @@ -23,6 +24,8 @@ nvfx_query_create(struct pipe_context *pipe, unsigned query_type) q = CALLOC(1, sizeof(struct nvfx_query)); q->type = query_type; + assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER); + return (struct pipe_query *)q; } @@ -32,7 +35,10 @@ nvfx_query_destroy(struct pipe_context *pipe, struct pipe_query *pq) struct nvfx_query *q = nvfx_query(pq); if (q->object) + { nouveau_resource_free(&q->object); + LIST_DEL(&q->list); + } FREE(q); } @@ -44,20 +50,25 @@ nvfx_query_begin(struct pipe_context *pipe, struct pipe_query *pq) struct nvfx_screen *screen = nvfx->screen; struct nouveau_channel *chan = screen->base.channel; struct nouveau_grobj *eng3d = screen->eng3d; - - assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER); + uint64_t tmp; /* 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. */ - if (q->object) { - uint64_t tmp; + if (q->object) pipe->get_query_result(pipe, pq, 1, &tmp); + + while (nouveau_resource_alloc(nvfx->screen->query_heap, 1, NULL, &q->object)) + { + struct nvfx_query* oldestq; + assert(!LIST_IS_EMPTY(&nvfx->screen->query_list)); + oldestq = LIST_ENTRY(struct nvfx_query, nvfx->screen->query_list.next, list); + pipe->get_query_result(pipe, (struct pipe_query*)oldestq, 1, &tmp); } - if (nouveau_resource_alloc(nvfx->screen->query_heap, 1, NULL, &q->object)) - assert(0); + LIST_ADDTAIL(&q->list, &nvfx->screen->query_list); + nouveau_notifier_reset(nvfx->screen->query, q->object->start); BEGIN_RING(chan, eng3d, NV34TCL_QUERY_RESET, 1); @@ -90,8 +101,6 @@ nvfx_query_result(struct pipe_context *pipe, struct pipe_query *pq, struct nvfx_context *nvfx = nvfx_context(pipe); struct nvfx_query *q = nvfx_query(pq); - assert(q->object && q->type == PIPE_QUERY_OCCLUSION_COUNTER); - if (!q->ready) { unsigned status; @@ -110,6 +119,7 @@ nvfx_query_result(struct pipe_context *pipe, struct pipe_query *pq, q->object->start); q->ready = TRUE; nouveau_resource_free(&q->object); + LIST_DEL(&q->list); } *result = q->result; diff --git a/src/gallium/drivers/nvfx/nvfx_screen.c b/src/gallium/drivers/nvfx/nvfx_screen.c index 9236c8d256a..651e6ee64b6 100644 --- a/src/gallium/drivers/nvfx/nvfx_screen.c +++ b/src/gallium/drivers/nvfx/nvfx_screen.c @@ -411,6 +411,8 @@ nvfx_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) return NULL; } + LIST_INITHEAD(&screen->query_list); + /* Vtxprog resources */ if (nouveau_resource_init(&screen->vp_exec_heap, 0, screen->is_nv4x ? 512 : 256) || nouveau_resource_init(&screen->vp_data_heap, 0, 256)) { diff --git a/src/gallium/drivers/nvfx/nvfx_screen.h b/src/gallium/drivers/nvfx/nvfx_screen.h index ba9a6993ece..678ee406016 100644 --- a/src/gallium/drivers/nvfx/nvfx_screen.h +++ b/src/gallium/drivers/nvfx/nvfx_screen.h @@ -1,6 +1,7 @@ #ifndef __NVFX_SCREEN_H__ #define __NVFX_SCREEN_H__ +#include <util/u_double_list.h> #include "nouveau/nouveau_screen.h" #include "nv04_surface_2d.h" #include "nvfx_context.h" @@ -24,6 +25,7 @@ struct nvfx_screen { /* Query object resources */ struct nouveau_notifier *query; struct nouveau_resource *query_heap; + struct list_head query_list; /* Vtxprog resources */ struct nouveau_resource *vp_exec_heap; |