nvc0: do not randomly emit fences.
authorKarol Herbst <git@karolherbst.de>
Wed, 26 Apr 2023 20:06:44 +0000 (22:06 +0200)
committerMarge Bot <emma+marge@anholt.net>
Tue, 2 May 2023 18:54:04 +0000 (18:54 +0000)
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: df0a4d02f26 ("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>

src/gallium/drivers/nouveau/nouveau_fence.c
src/gallium/drivers/nouveau/nouveau_fence.h
src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c

index 3651699..9fad60c 100644 (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);
 }
 
index 444598b..384084b 100644 (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 **);
index e4c36a8..c727c9d 100644 (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);