summaryrefslogtreecommitdiffstats
path: root/src/gallium
diff options
context:
space:
mode:
authorIlia Mirkin <[email protected]>2015-09-25 16:34:07 -0400
committerIlia Mirkin <[email protected]>2015-09-28 17:28:54 -0400
commitd4e650b07bc80075f0d088e7d85df9efa45e11bd (patch)
tree6b0d171131dfca4ea705397f66256e1069c1be49 /src/gallium
parent4c5308bbf4fa5c6ac274f6e1ab7c8846a2866976 (diff)
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 <[email protected]> Cc: [email protected] Tested-by: Marcin Ĺšlusarz <[email protected]>
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/drivers/nouveau/nouveau_fence.c8
-rw-r--r--src/gallium/drivers/nouveau/nouveau_fence.h3
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_miptree.c9
-rw-r--r--src/gallium/drivers/nouveau/nv50/nv50_transfer.c7
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c7
5 files changed, 30 insertions, 4 deletions
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);