From: Ilia Mirkin Date: Fri, 25 Sep 2015 20:34:07 +0000 (-0400) Subject: nouveau: be more careful about freeing temporary transfer buffers X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d4e650b07bc80075f0d088e7d85df9efa45e11bd;p=mesa.git nouveau: be more careful about freeing temporary transfer buffers 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 Cc: mesa-stable@lists.freedesktop.org Tested-by: Marcin Ĺšlusarz --- diff --git a/src/gallium/drivers/nouveau/nouveau_fence.c b/src/gallium/drivers/nouveau/nouveau_fence.c index abcdb479954..ee4e08dd520 100644 --- a/src/gallium/drivers/nouveau/nouveau_fence.c +++ b/src/gallium/drivers/nouveau/nouveau_fence.c @@ -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); +} diff --git a/src/gallium/drivers/nouveau/nouveau_fence.h b/src/gallium/drivers/nouveau/nouveau_fence.h index a1587051b0f..2efcab2172d 100644 --- a/src/gallium/drivers/nouveau/nouveau_fence.h +++ b/src/gallium/drivers/nouveau/nouveau_fence.h @@ -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) { diff --git a/src/gallium/drivers/nouveau/nv30/nv30_miptree.c b/src/gallium/drivers/nouveau/nv30/nv30_miptree.c index 735c718c4b3..c6f69650068 100644 --- a/src/gallium/drivers/nouveau/nv30/nv30_miptree.c +++ b/src/gallium/drivers/nouveau/nv30/nv30_miptree.c @@ -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); } diff --git a/src/gallium/drivers/nouveau/nv50/nv50_transfer.c b/src/gallium/drivers/nouveau/nv50/nv50_transfer.c index fc6b24aac28..be514077d32 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_transfer.c +++ b/src/gallium/drivers/nouveau/nv50/nv50_transfer.c @@ -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); diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c b/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c index d4831bfd9d4..aaec60a5ac2 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c @@ -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);