Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/egl/drivers/dri2/platform_x11_dri3.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,22 @@ egl_dri3_flush_drawable(struct loader_dri3_drawable *draw, unsigned flags)
dri2_flush_drawable_for_swapbuffers(disp, &dri3_surf->surf.base);
}

static int
egl_dri3_flush_drawable_with_fence_fd(struct loader_dri3_drawable *draw,
unsigned flags)
{
return loader_dri3_flush_with_fence_fd(
draw, __DRI2_FLUSH_DRAWABLE | __DRI2_FLUSH_INVALIDATE_ANCILLARY,
__DRI2_THROTTLE_SWAPBUFFER);
}

static const struct loader_dri3_vtable egl_dri3_vtable = {
.set_drawable_size = egl_dri3_set_drawable_size,
.in_current_context = egl_dri3_in_current_context,
.get_dri_context = egl_dri3_get_dri_context,
.get_dri_screen = egl_dri3_get_dri_screen,
.flush_drawable = egl_dri3_flush_drawable,
.flush_drawable_with_fence_fd = egl_dri3_flush_drawable_with_fence_fd,
};

static EGLBoolean
Expand Down
15 changes: 12 additions & 3 deletions src/freedreno/drm/kgsl/kgsl_ringbuffer_sp.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,6 @@ flush_submit_list(struct list_head *submit_list)
DEBUG_MSG("merged %u submits", cmd_idx);
break;
}

list_del(&submit->node);
fd_submit_del(submit);
}

struct kgsl_cmd_syncpoint_fence sync_fence = {
Expand Down Expand Up @@ -109,6 +106,18 @@ flush_submit_list(struct list_head *submit_list)
close(fd_submit->in_fence_fd);

fail:
/* Keep merged submits alive until KGSL has consumed the command list and,
* on success, populated the shared kernel timestamp. Dropping them before
* IOCTL_KGSL_GPU_COMMAND can free BOs that the command stream still uses.
*/
foreach_submit_safe (submit, submit_list) {
if (submit == last_submit(submit_list))
break;

list_del(&submit->node);
fd_submit_del(submit);
}

return ret;
}

Expand Down
8 changes: 8 additions & 0 deletions src/gallium/drivers/freedreno/freedreno_batch.c
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,14 @@ batch_flush(struct fd_batch *batch, bool last_batch)
if (last_batch && !batch->fence)
batch->fence = fd_pipe_fence_create(batch);

/* flush_resource() can submit the drawable's writer before the frontend's
* context flush reaches fd_context_flush(). Mark that writer's fence for
* native-fd export here so the Present fence still comes from the rendering
* submission rather than a following empty submit.
*/
if (last_batch && batch->ctx->explicit_present_fence && batch->fence)
batch->fence->use_fence_fd = true;

if (batch->fence)
fd_pipe_fence_ref(&batch->ctx->last_fence, batch->fence);

Expand Down
19 changes: 19 additions & 0 deletions src/gallium/drivers/freedreno/freedreno_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ fd_context_flush(struct pipe_context *pctx, struct pipe_fence_handle **fencep,
fd_bc_dump(ctx, "need fence, last_fence=%p", ctx->last_fence);
batch = fd_context_batch(ctx);
} else if (!batch) {
ctx->explicit_present_fence = false;
return;
}

Expand Down Expand Up @@ -118,6 +119,8 @@ fd_context_flush(struct pipe_context *pctx, struct pipe_fence_handle **fencep,
fd_bc_dump(ctx, "%p: remaining:\n", ctx);

out:
ctx->explicit_present_fence = false;

if (fencep)
fd_pipe_fence_ref(fencep, fence);

Expand All @@ -134,6 +137,21 @@ fd_context_flush(struct pipe_context *pctx, struct pipe_fence_handle **fencep,
assert(pctx->get_device_reset_status(pctx) == PIPE_NO_RESET);
}

static void
fd_set_context_param(struct pipe_context *pctx, enum pipe_context_param param,
unsigned value)
{
struct fd_context *ctx = fd_context(pctx);

switch (param) {
case PIPE_CONTEXT_PARAM_EXPLICIT_PRESENT_FENCE:
ctx->explicit_present_fence = value;
break;
default:
break;
}
}

static void
fd_texture_barrier(struct pipe_context *pctx, unsigned flags) in_dt
{
Expand Down Expand Up @@ -699,6 +717,7 @@ fd_context_init(struct fd_context *ctx, struct pipe_screen *pscreen,
pctx->screen = pscreen;
pctx->priv = priv;
pctx->flush = fd_context_flush;
pctx->set_context_param = fd_set_context_param;
pctx->emit_string_marker = fd_emit_string_marker;
pctx->set_debug_callback = fd_set_debug_callback;
pctx->create_fence_fd = fd_create_pipe_fence_fd;
Expand Down
5 changes: 5 additions & 0 deletions src/gallium/drivers/freedreno/freedreno_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,11 @@ struct fd_context {
*/
struct pipe_fence_handle *last_fence dt;

/* The next context flush exports the render-completion fence directly to
* the window-system presentation path.
*/
bool explicit_present_fence;

/*
* Counter to keep track of batch's most recent update. Ie. the batch with
* the higher update count is the one that has been drawn/etc to the most
Expand Down
11 changes: 10 additions & 1 deletion src/gallium/drivers/freedreno/freedreno_resource.c
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,7 @@ fd_flush_resource(struct pipe_context *pctx, struct pipe_resource *prsc)
* to the kernel for the fence to be added to the backing GEM
* object.
*/
if (ctx->no_implicit_sync)
if (ctx->no_implicit_sync && !ctx->screen->is_kgsl)
return;

flush_resource(ctx, rsc, PIPE_MAP_READ);
Expand All @@ -703,6 +703,15 @@ fd_flush_resource(struct pipe_context *pctx, struct pipe_resource *prsc)
* way to the kernel:
*/
fd_resource_wait(ctx, rsc, FD_BO_PREP_FLUSH);

/* KGSL does not attach Mesa's tracked render fence to an exported dma-buf.
* If the window-system path is not carrying the next submission's native
* fence explicitly, wait here before handing the resource to an
* implicit-sync consumer. The explicit Present-fence path avoids this
* per-frame CPU stall.
*/
if (ctx->screen->is_kgsl && !ctx->explicit_present_fence)
fd_resource_wait(ctx, rsc, FD_BO_PREP_READ);
}

static void
Expand Down
92 changes: 73 additions & 19 deletions src/gallium/frontends/dri/dri_drawable.c
Original file line number Diff line number Diff line change
Expand Up @@ -455,28 +455,33 @@ notify_before_flush_cb(void* _args)
* \param flags a combination of _DRI2_FLUSH_xxx flags
* \param throttle_reason the reason for throttling, 0 = no throttling
*/
void
dri_flush(struct dri_context *ctx,
struct dri_drawable *drawable,
unsigned flags,
enum __DRI2throttleReason reason)
static int
dri_flush_impl(struct dri_context *ctx,
struct dri_drawable *drawable,
unsigned flags,
enum __DRI2throttleReason reason,
bool request_fence_fd)
{
struct st_context *st;
struct pipe_screen *screen;
struct pipe_fence_handle *new_fence = NULL;
unsigned flush_flags;
int fence_fd = -1;
struct notify_before_flush_cb_args args = { 0 };

if (!ctx) {
assert(0);
return;
return -1;
}

st = ctx->st;
screen = ctx->screen->base.screen;
_mesa_glthread_finish(st->ctx);

if (drawable) {
/* prevent recursion */
if (drawable->flushing)
return;
return -1;

drawable->flushing = true;
}
Expand Down Expand Up @@ -505,23 +510,53 @@ dri_flush(struct dri_context *ctx,
reason == __DRI2_NOTHROTTLE_SWAPBUFFER)
flush_flags |= ST_FLUSH_END_OF_FRAME;

/* Flush the context and throttle if needed. */
if (ctx->screen->throttle &&
drawable &&
(reason == __DRI2_THROTTLE_SWAPBUFFER ||
reason == __DRI2_THROTTLE_FLUSHFRONT)) {
if (request_fence_fd && screen->caps.native_fence_fd) {
if (st->pipe->set_context_param) {
st->pipe->set_context_param(st->pipe,
PIPE_CONTEXT_PARAM_EXPLICIT_PRESENT_FENCE,
true);
}
flush_flags |= ST_FLUSH_FENCE_FD;
} else {
request_fence_fd = false;
}

struct pipe_screen *screen = drawable->screen->base.screen;
struct pipe_fence_handle *new_fence = NULL;
/* Flush the context and throttle if needed. */
const bool throttle = ctx->screen->throttle && drawable &&
(reason == __DRI2_THROTTLE_SWAPBUFFER ||
reason == __DRI2_THROTTLE_FLUSHFRONT);

if ((flags & (__DRI2_FLUSH_DRAWABLE | __DRI2_FLUSH_CONTEXT)) &&
(throttle || request_fence_fd)) {
st_context_flush(st, flush_flags, &new_fence, args.ctx ? notify_before_flush_cb : NULL, &args);

/* throttle on the previous fence */
if (drawable->throttle_fence) {
screen->fence_finish(screen, NULL, drawable->throttle_fence, OS_TIMEOUT_INFINITE);
screen->fence_reference(screen, &drawable->throttle_fence, NULL);
if (request_fence_fd && new_fence)
fence_fd = screen->fence_get_fd(screen, new_fence);

/* If native-fence export failed after the rendering flush, wait on the
* exact pipe fence before allowing an unfenced Present request.
*/
if (request_fence_fd && fence_fd < 0) {
if (!new_fence)
st_context_flush(st, 0, &new_fence, NULL, NULL);
if (new_fence)
screen->fence_finish(screen, NULL, new_fence,
OS_TIMEOUT_INFINITE);
}
drawable->throttle_fence = new_fence;

if (throttle) {
/* throttle on the previous fence */
if (drawable->throttle_fence) {
screen->fence_finish(screen, NULL, drawable->throttle_fence,
OS_TIMEOUT_INFINITE);
screen->fence_reference(screen, &drawable->throttle_fence, NULL);
}
drawable->throttle_fence = new_fence;
new_fence = NULL;
}

if (new_fence)
screen->fence_reference(screen, &new_fence, NULL);
}
else if (flags & (__DRI2_FLUSH_DRAWABLE | __DRI2_FLUSH_CONTEXT)) {
st_context_flush(st, flush_flags, NULL, args.ctx ? notify_before_flush_cb : NULL, &args);
Expand Down Expand Up @@ -550,6 +585,25 @@ dri_flush(struct dri_context *ctx,
}

st_context_invalidate_state(st, ST_INVALIDATE_FB_STATE);
return fence_fd;
}

void
dri_flush(struct dri_context *ctx,
struct dri_drawable *drawable,
unsigned flags,
enum __DRI2throttleReason reason)
{
dri_flush_impl(ctx, drawable, flags, reason, false);
}

int
dri_flush_with_fence_fd(struct dri_context *ctx,
struct dri_drawable *drawable,
unsigned flags,
enum __DRI2throttleReason reason)
{
return dri_flush_impl(ctx, drawable, flags, reason, true);
}

/**
Expand Down
6 changes: 6 additions & 0 deletions src/gallium/frontends/dri/dri_drawable.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,12 @@ dri_flush(struct dri_context *ctx,
unsigned flags,
enum __DRI2throttleReason reason);

int
dri_flush_with_fence_fd(struct dri_context *ctx,
struct dri_drawable *drawable,
unsigned flags,
enum __DRI2throttleReason reason);

void
dri_flush_drawable(struct dri_drawable *dPriv);

Expand Down
5 changes: 5 additions & 0 deletions src/gallium/frontends/dri/dri_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@ dri_flush(struct dri_context *cPriv,
struct dri_drawable *dPriv,
unsigned flags,
enum __DRI2throttleReason reason);
PUBLIC int
dri_flush_with_fence_fd(struct dri_context *cPriv,
struct dri_drawable *dPriv,
unsigned flags,
enum __DRI2throttleReason reason);
PUBLIC void
dri_invalidate_drawable(struct dri_drawable *drawable);

Expand Down
Loading