nouveau: be more careful about freeing temporary transfer buffers
authorIlia Mirkin <imirkin@alum.mit.edu>
Fri, 25 Sep 2015 20:34:07 +0000 (16:34 -0400)
committerIlia Mirkin <imirkin@alum.mit.edu>
Mon, 28 Sep 2015 21:28:54 +0000 (17:28 -0400)
Deleting a buffer does not flush the command stream. Make sure that we
wait for the copies to finish before deleting the temporary bo.

Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
Cc: mesa-stable@lists.freedesktop.org
Tested-by: Marcin Ĺšlusarz <marcin.slusarz@gmail.com>
src/gallium/drivers/nouveau/nouveau_fence.c
src/gallium/drivers/nouveau/nouveau_fence.h
src/gallium/drivers/nouveau/nv30/nv30_miptree.c
src/gallium/drivers/nouveau/nv50/nv50_transfer.c
src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c

index abcdb47995412e70ba979f80a4a14aefecb0dab5..ee4e08dd520d50740200418674df8e0669955d94 100644 (file)
@@ -231,3 +231,11 @@ nouveau_fence_next(struct nouveau_screen *screen)
 
    nouveau_fence_new(screen, &screen->fence.current, false);
 }
+
+void
+nouveau_fence_unref_bo(void *data)
+{
+   struct nouveau_bo *bo = data;
+
+   nouveau_bo_ref(NULL, &bo);
+}
index a1587051b0f42d39dc70e58fd7a3a53e338e6c97..2efcab2172dc2ce99b8e3d073d17477e5ae493bf 100644 (file)
@@ -37,6 +37,9 @@ void nouveau_fence_next(struct nouveau_screen *);
 bool nouveau_fence_wait(struct nouveau_fence *);
 bool nouveau_fence_signalled(struct nouveau_fence *);
 
+void nouveau_fence_unref_bo(void *data); /* generic unref bo callback */
+
+
 static inline void
 nouveau_fence_ref(struct nouveau_fence *fence, struct nouveau_fence **ref)
 {
index 735c718c4b32c8c194fb9eb4174867fc1a3cf2da..c6f696500681d431c08180e2fe53fbd07c72bf08 100644 (file)
@@ -339,10 +339,15 @@ nv30_miptree_transfer_unmap(struct pipe_context *pipe,
    struct nv30_context *nv30 = nv30_context(pipe);
    struct nv30_transfer *tx = nv30_transfer(ptx);
 
-   if (ptx->usage & PIPE_TRANSFER_WRITE)
+   if (ptx->usage & PIPE_TRANSFER_WRITE) {
       nv30_transfer_rect(nv30, NEAREST, &tx->tmp, &tx->img);
 
-   nouveau_bo_ref(NULL, &tx->tmp.bo);
+      /* Allow the copies above to finish executing before freeing the source */
+      nouveau_fence_work(nv30->screen->base.fence.current,
+                         nouveau_fence_unref_bo, tx->tmp.bo);
+   } else {
+      nouveau_bo_ref(NULL, &tx->tmp.bo);
+   }
    pipe_resource_reference(&ptx->resource, NULL);
    FREE(tx);
 }
index fc6b24aac289ef3f8ab9392cf18dd70043964ee0..be514077d32606adae32f7bf3417ea6963657b12 100644 (file)
@@ -365,9 +365,14 @@ nv50_miptree_transfer_unmap(struct pipe_context *pctx,
             tx->rect[0].base += mt->layer_stride;
          tx->rect[1].base += tx->nblocksy * tx->base.stride;
       }
+
+      /* Allow the copies above to finish executing before freeing the source */
+      nouveau_fence_work(nv50->screen->base.fence.current,
+                         nouveau_fence_unref_bo, tx->rect[1].bo);
+   } else {
+      nouveau_bo_ref(NULL, &tx->rect[1].bo);
    }
 
-   nouveau_bo_ref(NULL, &tx->rect[1].bo);
    pipe_resource_reference(&transfer->resource, NULL);
 
    FREE(tx);
index d4831bfd9d45db09dd004960ddaf455b3368afa1..aaec60a5ac222b18d20eaf1f46334fd1348bf595 100644 (file)
@@ -495,11 +495,16 @@ nvc0_miptree_transfer_unmap(struct pipe_context *pctx,
          tx->rect[1].base += tx->nblocksy * tx->base.stride;
       }
       NOUVEAU_DRV_STAT(&nvc0->screen->base, tex_transfers_wr, 1);
+
+      /* Allow the copies above to finish executing before freeing the source */
+      nouveau_fence_work(nvc0->screen->base.fence.current,
+                         nouveau_fence_unref_bo, tx->rect[1].bo);
+   } else {
+      nouveau_bo_ref(NULL, &tx->rect[1].bo);
    }
    if (tx->base.usage & PIPE_TRANSFER_READ)
       NOUVEAU_DRV_STAT(&nvc0->screen->base, tex_transfers_rd, 1);
 
-   nouveau_bo_ref(NULL, &tx->rect[1].bo);
    pipe_resource_reference(&transfer->resource, NULL);
 
    FREE(tx);