nvc0: do not randomly emit fences.

We track fences in a global list and have a per context "current" fence
which we randomly attach things to. If we take such a fence and emit it
without also creating a new fence for future tasks we can get out of sync
leading to random failures.

Some of our queries could trigger such cases and even though this issues
appears to be triggered by the MT rework, I'm convinced that this was only
made more visible by those fixes and we had this bug lurking for quite a
while.

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/7429
Fixes: df0a4d02f2 ("nvc0: make state handling race free")
Signed-off-by: Karol Herbst <git@karolherbst.de>
Acked-by: M Henning <drawoc@darkrefraction.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22722>
This commit is contained in:
Karol Herbst 2023-04-26 22:06:44 +02:00 committed by Marge Bot
parent a86e8969c7
commit 37c6c5c624
3 changed files with 6 additions and 6 deletions

View File

@ -374,10 +374,11 @@ nouveau_fence_wait(struct nouveau_fence *fence, struct util_debug_callback *debu
}
void
nouveau_fence_emit(struct nouveau_fence *fence)
nouveau_fence_next_if_current(struct nouveau_context *nv, struct nouveau_fence *fence)
{
simple_mtx_lock(&fence->screen->fence.lock);
_nouveau_fence_emit(fence);
if (nv->fence == fence)
_nouveau_fence_next(nv);
simple_mtx_unlock(&fence->screen->fence.lock);
}

View File

@ -58,12 +58,11 @@ void _nouveau_fence_update(struct nouveau_screen *, bool flushed);
void _nouveau_fence_next(struct nouveau_context *);
void _nouveau_fence_ref(struct nouveau_fence *, struct nouveau_fence **);
void nouveau_fence_emit(struct nouveau_fence *);
bool nouveau_fence_new(struct nouveau_context *, struct nouveau_fence **);
void nouveau_fence_cleanup(struct nouveau_context *);
bool nouveau_fence_work(struct nouveau_fence *, void (*)(void *), void *);
void nouveau_fence_update(struct nouveau_screen *, bool flushed);
void nouveau_fence_next(struct nouveau_context *);
void nouveau_fence_next_if_current(struct nouveau_context *, struct nouveau_fence *);
bool nouveau_fence_wait(struct nouveau_fence *, struct util_debug_callback *);
bool nouveau_fence_signalled(struct nouveau_fence *);
void nouveau_fence_ref(struct nouveau_fence *, struct nouveau_fence **);

View File

@ -421,7 +421,7 @@ nvc0_hw_get_query_result_resource(struct nvc0_context *nvc0,
* of the following logic more complicated.
*/
if (hq->is64bit)
nouveau_fence_emit(hq->fence);
nouveau_fence_next_if_current(&nvc0->base, hq->fence);
/* We either need to compute a 32- or 64-bit difference between 2 values,
* and then store the result as either a 32- or 64-bit value. As such let's
@ -643,7 +643,7 @@ nvc0_hw_query_fifo_wait(struct nvc0_context *nvc0, struct nvc0_query *q)
/* ensure the query's fence has been emitted */
if (hq->is64bit)
nouveau_fence_emit(hq->fence);
nouveau_fence_next_if_current(&nvc0->base, hq->fence);
PUSH_SPACE(push, 5);
PUSH_REF1 (push, hq->bo, NOUVEAU_BO_GART | NOUVEAU_BO_RD);