vrend: hook up per-context fencing internally

Other than hooking things up, vrend_renderer_check_fences and
vrend_renderer_export_ctx0_fence have some non-trivial changes.  This is
because fence->ctx is no longer always vrend_state.ctx0.  It can also
point to a user context or be NULL now.

Signed-off-by: Chia-I Wu <olvaffe@gmail.com>
Acked-by: Gert Wollny <gert.wollny@collabora.com>
Reviewed-by: Louis-Francis Ratté-Boulianne <lfrb@collabora.com>
macos/master
Chia-I Wu 4 years ago
parent 3ae1b379f9
commit 3a2a537c69
  1. 14
      src/virglrenderer.c
  2. 40
      src/vrend_decode.c
  3. 153
      src/vrend_renderer.c
  4. 13
      src/vrend_renderer.h

@ -165,6 +165,12 @@ void virgl_renderer_fill_caps(uint32_t set, uint32_t version,
} }
} }
static void per_context_fence_retire(UNUSED struct virgl_context *ctx,
UNUSED uint64_t queue_id,
UNUSED void *fence_cookie)
{
}
int virgl_renderer_context_create_with_flags(uint32_t ctx_id, int virgl_renderer_context_create_with_flags(uint32_t ctx_id,
uint32_t ctx_flags, uint32_t ctx_flags,
uint32_t nlen, uint32_t nlen,
@ -204,7 +210,7 @@ int virgl_renderer_context_create_with_flags(uint32_t ctx_id,
ctx->ctx_id = ctx_id; ctx->ctx_id = ctx_id;
ctx->capset_id = capset_id; ctx->capset_id = capset_id;
ctx->fence_retire = NULL; ctx->fence_retire = per_context_fence_retire;
ret = virgl_context_add(ctx); ret = virgl_context_add(ctx);
if (ret) { if (ret) {
@ -436,8 +442,10 @@ void virgl_renderer_get_rect(int resource_id, struct iovec *iov, unsigned int nu
} }
static void virgl_write_fence(uint32_t fence_id) static void ctx0_fence_retire(void *fence_cookie,
UNUSED void *retire_data)
{ {
const uint32_t fence_id = (uint32_t)(uintptr_t)fence_cookie;
state.cbs->write_fence(state.cookie, fence_id); state.cbs->write_fence(state.cookie, fence_id);
} }
@ -474,7 +482,7 @@ static int make_current(virgl_renderer_gl_context ctx)
} }
static const struct vrend_if_cbs vrend_cbs = { static const struct vrend_if_cbs vrend_cbs = {
virgl_write_fence, ctx0_fence_retire,
create_gl_context, create_gl_context,
destroy_gl_context, destroy_gl_context,
make_current, make_current,

@ -1462,6 +1462,13 @@ static int vrend_decode_pipe_resource_set_type(struct vrend_context *ctx, const
static void vrend_decode_ctx_init_base(struct vrend_decode_ctx *dctx, static void vrend_decode_ctx_init_base(struct vrend_decode_ctx *dctx,
uint32_t ctx_id); uint32_t ctx_id);
static void vrend_decode_ctx_fence_retire(void *fence_cookie,
void *retire_data)
{
struct vrend_decode_ctx *dctx = retire_data;
dctx->base.fence_retire(&dctx->base, 0, fence_cookie);
}
struct virgl_context *vrend_renderer_context_create(uint32_t handle, struct virgl_context *vrend_renderer_context_create(uint32_t handle,
uint32_t nlen, uint32_t nlen,
const char *debug_name) const char *debug_name)
@ -1480,6 +1487,10 @@ struct virgl_context *vrend_renderer_context_create(uint32_t handle,
return NULL; return NULL;
} }
vrend_renderer_set_fence_retire(dctx->grctx,
vrend_decode_ctx_fence_retire,
dctx);
return &dctx->base; return &dctx->base;
} }
@ -1667,6 +1678,29 @@ static int vrend_decode_ctx_submit_cmd(struct virgl_context *ctx,
return 0; return 0;
} }
static int vrend_decode_ctx_get_fencing_fd(UNUSED struct virgl_context *ctx)
{
return vrend_renderer_get_poll_fd();
}
static void vrend_decode_ctx_retire_fences(UNUSED struct virgl_context *ctx)
{
vrend_renderer_check_fences();
}
static int vrend_decode_ctx_submit_fence(struct virgl_context *ctx,
uint32_t flags,
uint64_t queue_id,
void *fence_cookie)
{
struct vrend_decode_ctx *dctx = (struct vrend_decode_ctx *)ctx;
if (queue_id)
return -EINVAL;
return vrend_renderer_create_fence(dctx->grctx, flags, fence_cookie);
}
static void vrend_decode_ctx_init_base(struct vrend_decode_ctx *dctx, static void vrend_decode_ctx_init_base(struct vrend_decode_ctx *dctx,
uint32_t ctx_id) uint32_t ctx_id)
{ {
@ -1684,7 +1718,7 @@ static void vrend_decode_ctx_init_base(struct vrend_decode_ctx *dctx,
ctx->get_blob_done = NULL; ctx->get_blob_done = NULL;
ctx->submit_cmd = vrend_decode_ctx_submit_cmd; ctx->submit_cmd = vrend_decode_ctx_submit_cmd;
ctx->get_fencing_fd = NULL; ctx->get_fencing_fd = vrend_decode_ctx_get_fencing_fd;
ctx->retire_fences = NULL; ctx->retire_fences = vrend_decode_ctx_retire_fences;
ctx->submit_fence = NULL; ctx->submit_fence = vrend_decode_ctx_submit_fence;
} }

@ -86,6 +86,7 @@ struct vrend_fence {
* valid. * valid.
*/ */
struct vrend_context *ctx; struct vrend_context *ctx;
uint32_t flags;
void *fence_cookie; void *fence_cookie;
union { union {
@ -739,6 +740,9 @@ struct vrend_context {
struct vrend_shader_cfg shader_cfg; struct vrend_shader_cfg shader_cfg;
unsigned debug_flags; unsigned debug_flags;
vrend_context_fence_retire fence_retire;
void *fence_retire_data;
}; };
static struct vrend_resource *vrend_renderer_ctx_res_lookup(struct vrend_context *ctx, int res_handle); static struct vrend_resource *vrend_renderer_ctx_res_lookup(struct vrend_context *ctx, int res_handle);
@ -6420,6 +6424,9 @@ struct vrend_context *vrend_create_context(int id, uint32_t nlen, const char *de
vrender_get_glsl_version(&grctx->shader_cfg.glsl_version); vrender_get_glsl_version(&grctx->shader_cfg.glsl_version);
if (!grctx->ctx_id)
grctx->fence_retire = vrend_clicbs->ctx0_fence_retire;
return grctx; return grctx;
} }
@ -9158,7 +9165,18 @@ void vrend_renderer_blit(struct vrend_context *ctx,
vrend_pause_render_condition(ctx, false); vrend_pause_render_condition(ctx, false);
} }
int vrend_renderer_create_fence(struct vrend_context *ctx, void *fence_cookie) void vrend_renderer_set_fence_retire(struct vrend_context *ctx,
vrend_context_fence_retire retire,
void *retire_data)
{
assert(ctx->ctx_id);
ctx->fence_retire = retire;
ctx->fence_retire_data = retire_data;
}
int vrend_renderer_create_fence(struct vrend_context *ctx,
uint32_t flags,
void *fence_cookie)
{ {
struct vrend_fence *fence; struct vrend_fence *fence;
@ -9170,6 +9188,7 @@ int vrend_renderer_create_fence(struct vrend_context *ctx, void *fence_cookie)
return ENOMEM; return ENOMEM;
fence->ctx = ctx; fence->ctx = ctx;
fence->flags = flags;
fence->fence_cookie = fence_cookie; fence->fence_cookie = fence_cookie;
#ifdef HAVE_EPOXY_EGL_H #ifdef HAVE_EPOXY_EGL_H
@ -9202,19 +9221,47 @@ int vrend_renderer_create_fence(struct vrend_context *ctx, void *fence_cookie)
static void vrend_renderer_check_queries(void); static void vrend_renderer_check_queries(void);
static bool need_fence_retire_signal_locked(struct vrend_fence *fence)
{
struct vrend_fence *next;
/* last fence */
if (fence->fences.next == &vrend_state.fence_list)
return true;
/* next fence belongs to a different context */
next = LIST_ENTRY(struct vrend_fence, fence->fences.next, fences);
if (next->ctx != fence->ctx)
return true;
return false;
}
void vrend_renderer_check_fences(void) void vrend_renderer_check_fences(void)
{ {
struct list_head retired_fences;
struct vrend_fence *fence, *stor; struct vrend_fence *fence, *stor;
bool fence_cookie_valid = false;
void *fence_cookie; list_inithead(&retired_fences);
if (vrend_state.sync_thread) { if (vrend_state.sync_thread) {
flush_eventfd(vrend_state.eventfd); flush_eventfd(vrend_state.eventfd);
pipe_mutex_lock(vrend_state.fence_mutex); pipe_mutex_lock(vrend_state.fence_mutex);
LIST_FOR_EACH_ENTRY_SAFE(fence, stor, &vrend_state.fence_list, fences) { LIST_FOR_EACH_ENTRY_SAFE(fence, stor, &vrend_state.fence_list, fences) {
fence_cookie_valid = true; /* vrend_free_fences_for_context might have marked the fence invalid
fence_cookie = fence->fence_cookie; * by setting fence->ctx to NULL
*/
if (!fence->ctx) {
free_fence_locked(fence); free_fence_locked(fence);
continue;
}
if (need_fence_retire_signal_locked(fence)) {
list_del(&fence->fences);
list_addtail(&fence->fences, &retired_fences);
} else {
free_fence_locked(fence);
}
} }
pipe_mutex_unlock(vrend_state.fence_mutex); pipe_mutex_unlock(vrend_state.fence_mutex);
} else { } else {
@ -9222,9 +9269,12 @@ void vrend_renderer_check_fences(void)
LIST_FOR_EACH_ENTRY_SAFE(fence, stor, &vrend_state.fence_list, fences) { LIST_FOR_EACH_ENTRY_SAFE(fence, stor, &vrend_state.fence_list, fences) {
if (do_wait(fence, /* can_block */ false)) { if (do_wait(fence, /* can_block */ false)) {
fence_cookie_valid = true; if (need_fence_retire_signal_locked(fence)) {
fence_cookie = fence->fence_cookie; list_del(&fence->fences);
list_addtail(&fence->fences, &retired_fences);
} else {
free_fence_locked(fence); free_fence_locked(fence);
}
} else { } else {
/* don't bother checking any subsequent ones */ /* don't bother checking any subsequent ones */
break; break;
@ -9232,12 +9282,17 @@ void vrend_renderer_check_fences(void)
} }
} }
if (!fence_cookie_valid) if (LIST_IS_EMPTY(&retired_fences))
return; return;
vrend_renderer_check_queries(); vrend_renderer_check_queries();
vrend_clicbs->write_fence((uint32_t)(uintptr_t)fence_cookie); LIST_FOR_EACH_ENTRY_SAFE(fence, stor, &retired_fences, fences) {
struct vrend_context *ctx = fence->ctx;
ctx->fence_retire(fence->fence_cookie, ctx->fence_retire_data);
free_fence_locked(fence);
}
} }
static bool vrend_get_one_query_result(GLuint query_id, bool use_64, uint64_t *result) static bool vrend_get_one_query_result(GLuint query_id, bool use_64, uint64_t *result)
@ -10963,7 +11018,34 @@ int vrend_renderer_resource_unmap(struct pipe_resource *pres)
int vrend_renderer_create_ctx0_fence(uint32_t fence_id) int vrend_renderer_create_ctx0_fence(uint32_t fence_id)
{ {
void *fence_cookie = (void *)(uintptr_t)fence_id; void *fence_cookie = (void *)(uintptr_t)fence_id;
return vrend_renderer_create_fence(vrend_state.ctx0, fence_cookie); return vrend_renderer_create_fence(vrend_state.ctx0, 0, fence_cookie);
}
static bool find_ctx0_fence_locked(struct list_head *fence_list,
void *fence_cookie,
bool *seen_first,
struct vrend_fence **fence)
{
struct vrend_fence *iter;
LIST_FOR_EACH_ENTRY(iter, fence_list, fences) {
/* only consider ctx0 fences */
if (iter->ctx != vrend_state.ctx0)
continue;
if (iter->fence_cookie == fence_cookie) {
*fence = iter;
return true;
}
if (!*seen_first) {
if (fence_cookie < iter->fence_cookie)
return true;
*seen_first = true;
}
}
return false;
} }
int vrend_renderer_export_ctx0_fence(uint32_t fence_id, int* out_fd) { int vrend_renderer_export_ctx0_fence(uint32_t fence_id, int* out_fd) {
@ -10976,45 +11058,30 @@ int vrend_renderer_export_ctx0_fence(uint32_t fence_id, int* out_fd) {
pipe_mutex_lock(vrend_state.fence_mutex); pipe_mutex_lock(vrend_state.fence_mutex);
void *fence_cookie = (void *)(uintptr_t)fence_id; void *fence_cookie = (void *)(uintptr_t)fence_id;
bool seen_first = false;
struct vrend_fence *fence = NULL; struct vrend_fence *fence = NULL;
struct vrend_fence *iter; bool found = find_ctx0_fence_locked(&vrend_state.fence_list,
uint32_t min_fence_id = UINT_MAX; fence_cookie,
&seen_first,
if (!LIST_IS_EMPTY(&vrend_state.fence_list)) { &fence);
iter = LIST_ENTRY(struct vrend_fence, vrend_state.fence_list.next, fences); if (!found) {
min_fence_id = (uint32_t)(uintptr_t)iter->fence_cookie; found = find_ctx0_fence_locked(&vrend_state.fence_wait_list,
} else if (!LIST_IS_EMPTY(&vrend_state.fence_wait_list)) { fence_cookie,
iter = LIST_ENTRY(struct vrend_fence, vrend_state.fence_wait_list.next, fences); &seen_first,
min_fence_id = (uint32_t)(uintptr_t)iter->fence_cookie; &fence);
} /* consider signaled when no active ctx0 fence at all */
if (!found && !seen_first)
if (fence_id < min_fence_id) { found = true;
if (vrend_state.sync_thread)
pipe_mutex_unlock(vrend_state.fence_mutex);
return virgl_egl_export_signaled_fence(egl, out_fd) ? 0 : -EINVAL;
}
LIST_FOR_EACH_ENTRY(iter, &vrend_state.fence_list, fences) {
if (iter->fence_cookie == fence_cookie) {
fence = iter;
break;
}
}
if (!fence) {
LIST_FOR_EACH_ENTRY(iter, &vrend_state.fence_wait_list, fences) {
if (iter->fence_cookie == fence_cookie) {
fence = iter;
break;
}
}
} }
if (vrend_state.sync_thread) if (vrend_state.sync_thread)
pipe_mutex_unlock(vrend_state.fence_mutex); pipe_mutex_unlock(vrend_state.fence_mutex);
if (fence && virgl_egl_export_fence(egl, fence->eglsyncobj, out_fd)) { if (found) {
return 0; if (fence)
return virgl_egl_export_fence(egl, fence->eglsyncobj, out_fd) ? 0 : -EINVAL;
else
return virgl_egl_export_signaled_fence(egl, out_fd) ? 0 : -EINVAL;
} }
#endif #endif
return -EINVAL; return -EINVAL;

@ -107,8 +107,11 @@ struct vrend_format_table {
uint32_t flags; uint32_t flags;
}; };
typedef void (*vrend_context_fence_retire)(void *fence_cookie,
void *retire_data);
struct vrend_if_cbs { struct vrend_if_cbs {
void (*write_fence)(unsigned fence_id); vrend_context_fence_retire ctx0_fence_retire;
virgl_gl_context (*create_gl_context)(int scanout, struct virgl_gl_ctx_param *params); virgl_gl_context (*create_gl_context)(int scanout, struct virgl_gl_ctx_param *params);
void (*destroy_gl_context)(virgl_gl_context ctx); void (*destroy_gl_context)(virgl_gl_context ctx);
@ -352,7 +355,13 @@ void vrend_set_tess_state(struct vrend_context *ctx, const float tess_factors[6]
void vrend_renderer_fini(void); void vrend_renderer_fini(void);
int vrend_renderer_create_fence(struct vrend_context *ctx, void *fence_cookie); void vrend_renderer_set_fence_retire(struct vrend_context *ctx,
vrend_context_fence_retire retire,
void *retire_data);
int vrend_renderer_create_fence(struct vrend_context *ctx,
uint32_t flags,
void *fence_cookie);
void vrend_renderer_check_fences(void); void vrend_renderer_check_fences(void);

Loading…
Cancel
Save