aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChia-I Wu <olvaffe@gmail.com>2020-10-01 12:21:28 -0700
committerChia-I Wu <olvaffe@gmail.com>2021-03-04 17:00:33 -0800
commit3a2a537c69c981797ce89905725429bb24d15d2c (patch)
treedfab5c64534c6fb757b05cb5a1b665ac807107ae
parent3ae1b379f9b145fa1d3f019fe361b90f3d5f2d76 (diff)
downloadvirglrenderer-3a2a537c69c981797ce89905725429bb24d15d2c.tar.gz
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>
-rw-r--r--src/virglrenderer.c14
-rw-r--r--src/vrend_decode.c40
-rw-r--r--src/vrend_renderer.c157
-rw-r--r--src/vrend_renderer.h13
4 files changed, 171 insertions, 53 deletions
diff --git a/src/virglrenderer.c b/src/virglrenderer.c
index 36efd59e..80f7f5ba 100644
--- a/src/virglrenderer.c
+++ b/src/virglrenderer.c
@@ -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,
uint32_t ctx_flags,
uint32_t nlen,
@@ -204,7 +210,7 @@ int virgl_renderer_context_create_with_flags(uint32_t ctx_id,
ctx->ctx_id = ctx_id;
ctx->capset_id = capset_id;
- ctx->fence_retire = NULL;
+ ctx->fence_retire = per_context_fence_retire;
ret = virgl_context_add(ctx);
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);
}
@@ -474,7 +482,7 @@ static int make_current(virgl_renderer_gl_context ctx)
}
static const struct vrend_if_cbs vrend_cbs = {
- virgl_write_fence,
+ ctx0_fence_retire,
create_gl_context,
destroy_gl_context,
make_current,
diff --git a/src/vrend_decode.c b/src/vrend_decode.c
index 557ad026..bf162bd6 100644
--- a/src/vrend_decode.c
+++ b/src/vrend_decode.c
@@ -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,
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,
uint32_t nlen,
const char *debug_name)
@@ -1480,6 +1487,10 @@ struct virgl_context *vrend_renderer_context_create(uint32_t handle,
return NULL;
}
+ vrend_renderer_set_fence_retire(dctx->grctx,
+ vrend_decode_ctx_fence_retire,
+ dctx);
+
return &dctx->base;
}
@@ -1667,6 +1678,29 @@ static int vrend_decode_ctx_submit_cmd(struct virgl_context *ctx,
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,
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->submit_cmd = vrend_decode_ctx_submit_cmd;
- ctx->get_fencing_fd = NULL;
- ctx->retire_fences = NULL;
- ctx->submit_fence = NULL;
+ ctx->get_fencing_fd = vrend_decode_ctx_get_fencing_fd;
+ ctx->retire_fences = vrend_decode_ctx_retire_fences;
+ ctx->submit_fence = vrend_decode_ctx_submit_fence;
}
diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c
index 066324dd..02bf3f6c 100644
--- a/src/vrend_renderer.c
+++ b/src/vrend_renderer.c
@@ -86,6 +86,7 @@ struct vrend_fence {
* valid.
*/
struct vrend_context *ctx;
+ uint32_t flags;
void *fence_cookie;
union {
@@ -739,6 +740,9 @@ struct vrend_context {
struct vrend_shader_cfg shader_cfg;
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);
@@ -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);
+ if (!grctx->ctx_id)
+ grctx->fence_retire = vrend_clicbs->ctx0_fence_retire;
+
return grctx;
}
@@ -9158,7 +9165,18 @@ void vrend_renderer_blit(struct vrend_context *ctx,
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;
@@ -9170,6 +9188,7 @@ int vrend_renderer_create_fence(struct vrend_context *ctx, void *fence_cookie)
return ENOMEM;
fence->ctx = ctx;
+ fence->flags = flags;
fence->fence_cookie = fence_cookie;
#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 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)
{
+ struct list_head retired_fences;
struct vrend_fence *fence, *stor;
- bool fence_cookie_valid = false;
- void *fence_cookie;
+
+ list_inithead(&retired_fences);
if (vrend_state.sync_thread) {
flush_eventfd(vrend_state.eventfd);
pipe_mutex_lock(vrend_state.fence_mutex);
LIST_FOR_EACH_ENTRY_SAFE(fence, stor, &vrend_state.fence_list, fences) {
- fence_cookie_valid = true;
- fence_cookie = fence->fence_cookie;
- free_fence_locked(fence);
+ /* vrend_free_fences_for_context might have marked the fence invalid
+ * by setting fence->ctx to NULL
+ */
+ if (!fence->ctx) {
+ 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);
} else {
@@ -9222,9 +9269,12 @@ void vrend_renderer_check_fences(void)
LIST_FOR_EACH_ENTRY_SAFE(fence, stor, &vrend_state.fence_list, fences) {
if (do_wait(fence, /* can_block */ false)) {
- fence_cookie_valid = true;
- fence_cookie = fence->fence_cookie;
- free_fence_locked(fence);
+ if (need_fence_retire_signal_locked(fence)) {
+ list_del(&fence->fences);
+ list_addtail(&fence->fences, &retired_fences);
+ } else {
+ free_fence_locked(fence);
+ }
} else {
/* don't bother checking any subsequent ones */
break;
@@ -9232,12 +9282,17 @@ void vrend_renderer_check_fences(void)
}
}
- if (!fence_cookie_valid)
+ if (LIST_IS_EMPTY(&retired_fences))
return;
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)
@@ -10963,7 +11018,34 @@ int vrend_renderer_resource_unmap(struct pipe_resource *pres)
int vrend_renderer_create_ctx0_fence(uint32_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) {
@@ -10976,45 +11058,30 @@ int vrend_renderer_export_ctx0_fence(uint32_t fence_id, int* out_fd) {
pipe_mutex_lock(vrend_state.fence_mutex);
void *fence_cookie = (void *)(uintptr_t)fence_id;
+ bool seen_first = false;
struct vrend_fence *fence = NULL;
- struct vrend_fence *iter;
- uint32_t min_fence_id = UINT_MAX;
-
- if (!LIST_IS_EMPTY(&vrend_state.fence_list)) {
- iter = LIST_ENTRY(struct vrend_fence, vrend_state.fence_list.next, fences);
- min_fence_id = (uint32_t)(uintptr_t)iter->fence_cookie;
- } else if (!LIST_IS_EMPTY(&vrend_state.fence_wait_list)) {
- iter = LIST_ENTRY(struct vrend_fence, vrend_state.fence_wait_list.next, fences);
- min_fence_id = (uint32_t)(uintptr_t)iter->fence_cookie;
- }
-
- if (fence_id < min_fence_id) {
- 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;
- }
- }
+ bool found = find_ctx0_fence_locked(&vrend_state.fence_list,
+ fence_cookie,
+ &seen_first,
+ &fence);
+ if (!found) {
+ found = find_ctx0_fence_locked(&vrend_state.fence_wait_list,
+ fence_cookie,
+ &seen_first,
+ &fence);
+ /* consider signaled when no active ctx0 fence at all */
+ if (!found && !seen_first)
+ found = true;
}
if (vrend_state.sync_thread)
pipe_mutex_unlock(vrend_state.fence_mutex);
- if (fence && virgl_egl_export_fence(egl, fence->eglsyncobj, out_fd)) {
- return 0;
+ if (found) {
+ 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
return -EINVAL;
diff --git a/src/vrend_renderer.h b/src/vrend_renderer.h
index 79e1ed9b..297fc5c9 100644
--- a/src/vrend_renderer.h
+++ b/src/vrend_renderer.h
@@ -107,8 +107,11 @@ struct vrend_format_table {
uint32_t flags;
};
+typedef void (*vrend_context_fence_retire)(void *fence_cookie,
+ void *retire_data);
+
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);
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);
-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);