st/nine: Unmap buffers after full unlock

Do not unmap anything until all buffer unlocks
were received.

A buffer can be filled in several threads, and thus
in the case of double locks, it's not possible to know
which unlock is received first.
Thus only unmap the buffers when the last unlock is
received.

Signed-off-by: Axel Davy <davyaxel0@gmail.com>
Acked-by: Timur Kristóf <timur.kristof@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9177>
This commit is contained in:
Axel Davy
2020-12-20 19:37:13 +01:00
parent 3dd6b79215
commit 6a3451e170
2 changed files with 28 additions and 17 deletions

View File

@@ -55,6 +55,7 @@ NineBuffer9_ctor( struct NineBuffer9 *This,
This->maps = MALLOC(sizeof(struct NineTransfer)); This->maps = MALLOC(sizeof(struct NineTransfer));
if (!This->maps) if (!This->maps)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
This->nlocks = 0;
This->nmaps = 0; This->nmaps = 0;
This->maxmaps = 1; This->maxmaps = 1;
This->size = Size; This->size = Size;
@@ -152,9 +153,10 @@ NineBuffer9_dtor( struct NineBuffer9 *This )
DBG("This=%p\n", This); DBG("This=%p\n", This);
if (This->maps) { if (This->maps) {
while (This->nmaps) { while (This->nlocks) {
NineBuffer9_Unlock(This); NineBuffer9_Unlock(This);
} }
assert(!This->nmaps);
FREE(This->maps); FREE(This->maps);
} }
@@ -259,7 +261,7 @@ NineBuffer9_Lock( struct NineBuffer9 *This,
} }
*ppbData = (char *)This->managed.data + OffsetToLock; *ppbData = (char *)This->managed.data + OffsetToLock;
DBG("returning pointer %p\n", *ppbData); DBG("returning pointer %p\n", *ppbData);
This->nmaps++; This->nlocks++;
return D3D_OK; return D3D_OK;
} }
@@ -355,6 +357,7 @@ NineBuffer9_Lock( struct NineBuffer9 *This,
if (This->buf) { if (This->buf) {
This->maps[This->nmaps].buf = This->buf; This->maps[This->nmaps].buf = This->buf;
This->nmaps++; This->nmaps++;
This->nlocks++;
*ppbData = nine_upload_buffer_get_map(This->buf) + OffsetToLock; *ppbData = nine_upload_buffer_get_map(This->buf) + OffsetToLock;
return D3D_OK; return D3D_OK;
} else { } else {
@@ -419,6 +422,7 @@ NineBuffer9_Lock( struct NineBuffer9 *This,
DBG("returning pointer %p\n", data); DBG("returning pointer %p\n", data);
This->nmaps++; This->nmaps++;
This->nlocks++;
*ppbData = data; *ppbData = data;
return D3D_OK; return D3D_OK;
@@ -429,23 +433,30 @@ NineBuffer9_Unlock( struct NineBuffer9 *This )
{ {
struct NineDevice9 *device = This->base.base.device; struct NineDevice9 *device = This->base.base.device;
struct pipe_context *pipe; struct pipe_context *pipe;
int i;
DBG("This=%p\n", This); DBG("This=%p\n", This);
user_assert(This->nmaps > 0, D3DERR_INVALIDCALL); user_assert(This->nlocks > 0, D3DERR_INVALIDCALL);
This->nmaps--; This->nlocks--;
if (This->nlocks > 0)
return D3D_OK; /* Pending unlocks. Wait all unlocks before unmapping */
if (This->base.pool != D3DPOOL_MANAGED) { if (This->base.pool != D3DPOOL_MANAGED) {
if (!This->maps[This->nmaps].buf) { for (i = 0; i < This->nmaps; i++) {
pipe = This->maps[This->nmaps].is_pipe_secondary ? if (!This->maps[i].buf) {
device->pipe_secondary : pipe = This->maps[i].is_pipe_secondary ?
nine_context_get_pipe_acquire(device); device->pipe_secondary :
pipe->transfer_unmap(pipe, This->maps[This->nmaps].transfer); nine_context_get_pipe_acquire(device);
/* We need to flush in case the driver does implicit copies */ pipe->transfer_unmap(pipe, This->maps[i].transfer);
if (This->maps[This->nmaps].is_pipe_secondary) /* We need to flush in case the driver does implicit copies */
pipe->flush(pipe, NULL, 0); if (This->maps[i].is_pipe_secondary)
else pipe->flush(pipe, NULL, 0);
nine_context_get_pipe_release(device); else
} else if (This->maps[This->nmaps].should_destroy_buf) nine_context_get_pipe_release(device);
nine_upload_release_buffer(device->buffer_upload, This->maps[This->nmaps].buf); } else if (This->maps[i].should_destroy_buf)
nine_upload_release_buffer(device->buffer_upload, This->maps[i].buf);
}
This->nmaps = 0;
} }
return D3D_OK; return D3D_OK;
} }

View File

@@ -49,7 +49,7 @@ struct NineBuffer9
/* G3D */ /* G3D */
struct NineTransfer *maps; struct NineTransfer *maps;
int nmaps, maxmaps; int nlocks, nmaps, maxmaps;
UINT size; UINT size;
int16_t bind_count; /* to Device9->state.stream */ int16_t bind_count; /* to Device9->state.stream */