From: Rob Clark Date: Mon, 15 Aug 2016 18:27:10 +0000 (-0400) Subject: freedreno: native fence fd support X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0b98e84e9ba082b9aa00b24fded3fb56224c6fc6;p=mesa.git freedreno: native fence fd support Signed-off-by: Rob Clark --- diff --git a/src/gallium/drivers/freedreno/freedreno_batch.c b/src/gallium/drivers/freedreno/freedreno_batch.c index 369b7e9cda4..646c76fb57d 100644 --- a/src/gallium/drivers/freedreno/freedreno_batch.c +++ b/src/gallium/drivers/freedreno/freedreno_batch.c @@ -60,6 +60,8 @@ batch_init(struct fd_batch *batch) fd_ringbuffer_set_parent(batch->draw, batch->gmem); fd_ringbuffer_set_parent(batch->binning, batch->gmem); + batch->in_fence_fd = -1; + batch->cleared = batch->partial_cleared = 0; batch->restore = batch->resolve = 0; batch->needs_flush = false; @@ -109,6 +111,9 @@ batch_fini(struct fd_batch *batch) { pipe_resource_reference(&batch->query_buf, NULL); + if (batch->in_fence_fd != -1) + close(batch->in_fence_fd); + fd_ringbuffer_del(batch->draw); fd_ringbuffer_del(batch->binning); fd_ringbuffer_del(batch->gmem); diff --git a/src/gallium/drivers/freedreno/freedreno_batch.h b/src/gallium/drivers/freedreno/freedreno_batch.h index 1e9545971be..095d214468b 100644 --- a/src/gallium/drivers/freedreno/freedreno_batch.h +++ b/src/gallium/drivers/freedreno/freedreno_batch.h @@ -68,6 +68,9 @@ struct fd_batch { unsigned seqno; unsigned idx; + int in_fence_fd; + bool needs_out_fence_fd; + struct fd_context *ctx; struct util_queue_fence flush_fence; diff --git a/src/gallium/drivers/freedreno/freedreno_context.c b/src/gallium/drivers/freedreno/freedreno_context.c index 70220f88dee..03645075bdc 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.c +++ b/src/gallium/drivers/freedreno/freedreno_context.c @@ -44,6 +44,9 @@ fd_context_flush(struct pipe_context *pctx, struct pipe_fence_handle **fence, { struct fd_context *ctx = fd_context(pctx); + if (flags & PIPE_FLUSH_FENCE_FD) + ctx->batch->needs_out_fence_fd = true; + if (!ctx->screen->reorder) { fd_batch_flush(ctx->batch, true); } else { @@ -251,6 +254,8 @@ fd_context_init(struct fd_context *ctx, struct pipe_screen *pscreen, pctx->flush = fd_context_flush; pctx->emit_string_marker = fd_emit_string_marker; pctx->set_debug_callback = fd_set_debug_callback; + pctx->create_fence_fd = fd_create_fence_fd; + pctx->fence_server_sync = fd_fence_server_sync; /* TODO what about compute? Ideally it creates it's own independent * batches per compute job (since it isn't using tiling, so no point diff --git a/src/gallium/drivers/freedreno/freedreno_fence.c b/src/gallium/drivers/freedreno/freedreno_fence.c index a5f717169f9..f20c6ac120e 100644 --- a/src/gallium/drivers/freedreno/freedreno_fence.c +++ b/src/gallium/drivers/freedreno/freedreno_fence.c @@ -26,6 +26,8 @@ * Rob Clark */ +#include + #include "util/u_inlines.h" #include "freedreno_fence.h" @@ -36,16 +38,23 @@ struct pipe_fence_handle { struct pipe_reference reference; struct fd_context *ctx; struct fd_screen *screen; + int fence_fd; uint32_t timestamp; }; -void -fd_fence_ref(struct pipe_screen *pscreen, +static void fd_fence_destroy(struct pipe_fence_handle *fence) +{ + if (fence->fence_fd != -1) + close(fence->fence_fd); + FREE(fence); +} + +void fd_fence_ref(struct pipe_screen *pscreen, struct pipe_fence_handle **ptr, struct pipe_fence_handle *pfence) { if (pipe_reference(&(*ptr)->reference, &pfence->reference)) - FREE(*ptr); + fd_fence_destroy(*ptr); *ptr = pfence; } @@ -55,14 +64,42 @@ boolean fd_fence_finish(struct pipe_screen *pscreen, struct pipe_fence_handle *fence, uint64_t timeout) { + if (fence->fence_fd != -1) { + int ret = sync_wait(fence->fence_fd, timeout / 1000000); + return ret == 0; + } + if (fd_pipe_wait_timeout(fence->screen->pipe, fence->timestamp, timeout)) return false; return true; } +void fd_create_fence_fd(struct pipe_context *pctx, + struct pipe_fence_handle **pfence, int fd) +{ + *pfence = fd_fence_create(fd_context(pctx), 0, dup(fd)); +} + +void fd_fence_server_sync(struct pipe_context *pctx, + struct pipe_fence_handle *fence) +{ + struct fd_context *ctx = fd_context(pctx); + struct fd_batch *batch = ctx->batch; + + if (sync_accumulate("freedreno", &batch->in_fence_fd, fence->fence_fd)) { + /* error */ + } +} + +int fd_fence_get_fd(struct pipe_screen *pscreen, + struct pipe_fence_handle *fence) +{ + return dup(fence->fence_fd); +} + struct pipe_fence_handle * fd_fence_create(struct fd_context *ctx, - uint32_t timestamp) + uint32_t timestamp, int fence_fd) { struct pipe_fence_handle *fence; @@ -75,6 +112,7 @@ struct pipe_fence_handle * fd_fence_create(struct fd_context *ctx, fence->ctx = ctx; fence->screen = ctx->screen; fence->timestamp = timestamp; + fence->fence_fd = fence_fd; return fence; } diff --git a/src/gallium/drivers/freedreno/freedreno_fence.h b/src/gallium/drivers/freedreno/freedreno_fence.h index 32bfacc7627..1de2d0a5146 100644 --- a/src/gallium/drivers/freedreno/freedreno_fence.h +++ b/src/gallium/drivers/freedreno/freedreno_fence.h @@ -38,9 +38,15 @@ boolean fd_fence_finish(struct pipe_screen *screen, struct pipe_context *ctx, struct pipe_fence_handle *pfence, uint64_t timeout); +void fd_create_fence_fd(struct pipe_context *pctx, + struct pipe_fence_handle **pfence, int fd); +void fd_fence_server_sync(struct pipe_context *pctx, + struct pipe_fence_handle *fence); +int fd_fence_get_fd(struct pipe_screen *pscreen, + struct pipe_fence_handle *pfence); struct fd_context; struct pipe_fence_handle * fd_fence_create(struct fd_context *ctx, - uint32_t timestamp); + uint32_t timestamp, int fence_fd); #endif /* FREEDRENO_FENCE_H_ */ diff --git a/src/gallium/drivers/freedreno/freedreno_gmem.c b/src/gallium/drivers/freedreno/freedreno_gmem.c index 6d243c6d1e2..69fb16d058b 100644 --- a/src/gallium/drivers/freedreno/freedreno_gmem.c +++ b/src/gallium/drivers/freedreno/freedreno_gmem.c @@ -399,10 +399,13 @@ fd_gmem_render_tiles(struct fd_batch *batch) ctx->stats.batch_gmem++; } - fd_ringbuffer_flush(batch->gmem); + int out_fence_fd = -1; + fd_ringbuffer_flush2(batch->gmem, batch->in_fence_fd, + batch->needs_out_fence_fd ? &out_fence_fd : NULL); fd_fence_ref(&ctx->screen->base, &ctx->last_fence, NULL); - ctx->last_fence = fd_fence_create(ctx, fd_ringbuffer_timestamp(batch->gmem)); + ctx->last_fence = fd_fence_create(ctx, + fd_ringbuffer_timestamp(batch->gmem), out_fence_fd); } /* tile needs restore if it isn't completely contained within the diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c index 07212dc0941..8ab0e37fa0d 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -380,7 +380,7 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_UMA: return 1; case PIPE_CAP_NATIVE_FENCE_FD: - return 0; + return fd_device_version(screen->dev) >= FD_VERSION_FENCE_FD; } debug_printf("unknown param %d\n", param); return 0; @@ -713,6 +713,7 @@ fd_screen_create(struct fd_device *dev) pscreen->fence_reference = fd_fence_ref; pscreen->fence_finish = fd_fence_finish; + pscreen->fence_get_fd = fd_fence_get_fd; slab_create_parent(&screen->transfer_pool, sizeof(struct fd_transfer), 16);