From 939b26639fdc0913c5670b7fa20aab1f41b2b155 Mon Sep 17 00:00:00 2001 From: Christoph Bumiller Date: Thu, 19 Apr 2012 14:44:56 +0200 Subject: [PATCH] nv50,nvc0: prevent multiple flushes when user spins on get_query_result --- src/gallium/drivers/nv50/nv50_query.c | 7 ++++- src/gallium/drivers/nvc0/nvc0_query.c | 43 ++++++++++++++++----------- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/src/gallium/drivers/nv50/nv50_query.c b/src/gallium/drivers/nv50/nv50_query.c index 220b166f985..5275e74964a 100644 --- a/src/gallium/drivers/nv50/nv50_query.c +++ b/src/gallium/drivers/nv50/nv50_query.c @@ -42,6 +42,7 @@ struct nv50_query { uint32_t base; uint32_t offset; /* base + i * 16 */ boolean ready; + boolean flushed; boolean is64bit; struct nouveau_mm_allocation *mm; }; @@ -230,6 +231,7 @@ nv50_query_end(struct pipe_context *pipe, struct pipe_query *pq) assert(0); break; } + q->flushed = FALSE; } static INLINE boolean @@ -253,7 +255,10 @@ nv50_query_result(struct pipe_context *pipe, struct pipe_query *pq, if (!q->ready) { if (!wait) { /* for broken apps that spin on GL_QUERY_RESULT_AVAILABLE */ - PUSH_KICK(nv50->base.pushbuf); + if (!q->flushed) { + q->flushed = TRUE; + PUSH_KICK(nv50->base.pushbuf); + } return FALSE; } if (nouveau_bo_wait(q->bo, NOUVEAU_BO_RD, nv50->screen->base.client)) diff --git a/src/gallium/drivers/nvc0/nvc0_query.c b/src/gallium/drivers/nvc0/nvc0_query.c index b0ef83a1df2..8dfda378374 100644 --- a/src/gallium/drivers/nvc0/nvc0_query.c +++ b/src/gallium/drivers/nvc0/nvc0_query.c @@ -27,6 +27,11 @@ #include "nvc0_context.h" #include "nouveau/nv_object.xml.h" +#define NVC0_QUERY_STATE_READY 0 +#define NVC0_QUERY_STATE_ACTIVE 1 +#define NVC0_QUERY_STATE_ENDED 2 +#define NVC0_QUERY_STATE_FLUSHED 3 + struct nvc0_query { uint32_t *data; uint16_t type; @@ -35,8 +40,7 @@ struct nvc0_query { struct nouveau_bo *bo; uint32_t base; uint32_t offset; /* base + i * rotate */ - boolean ready; - boolean active; + uint8_t state; boolean is64bit; uint8_t rotate; int nesting; /* only used for occlusion queries */ @@ -60,7 +64,7 @@ nvc0_query_allocate(struct nvc0_context *nvc0, struct nvc0_query *q, int size) if (q->bo) { nouveau_bo_ref(NULL, &q->bo); if (q->mm) { - if (q->ready) + if (q->state == NVC0_QUERY_STATE_READY) nouveau_mm_free(q->mm); else nouveau_fence_work(screen->base.fence.current, @@ -242,8 +246,7 @@ nvc0_query_begin(struct pipe_context *pipe, struct pipe_query *pq) default: break; } - q->ready = FALSE; - q->active = TRUE; + q->state = NVC0_QUERY_STATE_ACTIVE; } static void @@ -253,14 +256,13 @@ nvc0_query_end(struct pipe_context *pipe, struct pipe_query *pq) struct nouveau_pushbuf *push = nvc0->base.pushbuf; struct nvc0_query *q = nvc0_query(pq); - if (!q->active) { + if (q->state != NVC0_QUERY_STATE_ACTIVE) { /* some queries don't require 'begin' to be called (e.g. GPU_FINISHED) */ if (q->rotate) nvc0_query_rotate(nvc0, q); q->sequence++; } - q->ready = FALSE; - q->active = FALSE; + q->state = NVC0_QUERY_STATE_ENDED; switch (q->type) { case PIPE_QUERY_OCCLUSION_COUNTER: @@ -317,13 +319,15 @@ nvc0_query_end(struct pipe_context *pipe, struct pipe_query *pq) } } -static INLINE boolean -nvc0_query_ready(struct nouveau_client *cli, struct nvc0_query *q) +static INLINE void +nvc0_query_update(struct nouveau_client *cli, struct nvc0_query *q) { if (q->is64bit) { - return !nouveau_bo_map(q->bo, NOUVEAU_BO_RD | NOUVEAU_BO_NOBLOCK, cli); + if (!nouveau_bo_map(q->bo, NOUVEAU_BO_RD | NOUVEAU_BO_NOBLOCK, cli)) + q->state = NVC0_QUERY_STATE_READY; } else { - return q->data[0] == q->sequence; + if (q->data[0] == q->sequence) + q->state = NVC0_QUERY_STATE_READY; } } @@ -339,19 +343,22 @@ nvc0_query_result(struct pipe_context *pipe, struct pipe_query *pq, uint64_t *data64 = (uint64_t *)q->data; unsigned i; - if (!q->ready) /* update ? */ - q->ready = nvc0_query_ready(nvc0->screen->base.client, q); - if (!q->ready) { + if (q->state != NVC0_QUERY_STATE_READY) + nvc0_query_update(nvc0->screen->base.client, q); + + if (q->state != NVC0_QUERY_STATE_READY) { if (!wait) { - /* flush for silly apps that spin on GL_QUERY_RESULT_AVAILABLE */ - if (nouveau_pushbuf_refd(nvc0->base.pushbuf, q->bo) & NOUVEAU_BO_WR) + if (q->state != NVC0_QUERY_STATE_FLUSHED) { + q->state = NVC0_QUERY_STATE_FLUSHED; + /* flush for silly apps that spin on GL_QUERY_RESULT_AVAILABLE */ PUSH_KICK(nvc0->base.pushbuf); + } return FALSE; } if (nouveau_bo_wait(q->bo, NOUVEAU_BO_RD, nvc0->screen->base.client)) return FALSE; } - q->ready = TRUE; + q->state = NVC0_QUERY_STATE_READY; switch (q->type) { case PIPE_QUERY_GPU_FINISHED: -- 2.30.2