mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-04-26 04:40:39 +02:00
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.
This commit is contained in:
parent
202760b437
commit
9ad385fef9
3 changed files with 22 additions and 8 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue