vrend: track fence contexts

Replace the unused ctx_id by a vrend_context pointer.  When a
vrend_context is destroyed, remove fences associated with the context to
avoid dangling pointers.

For now, the context is always ctx0 which is never destroyed before the
fences.  That will change later when per-context fencing is introduced.

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 17796a3a9d
commit 5379986993
  1. 7
      src/virglrenderer.c
  2. 57
      src/vrend_renderer.c
  3. 3
      src/vrend_renderer.h

@ -348,10 +348,13 @@ void virgl_renderer_resource_detach_iov(int res_handle, struct iovec **iov_p, in
virgl_resource_detach_iov(res); virgl_resource_detach_iov(res);
} }
int virgl_renderer_create_fence(int client_fence_id, uint32_t ctx_id) int virgl_renderer_create_fence(int client_fence_id, UNUSED uint32_t ctx_id)
{ {
TRACE_FUNC(); TRACE_FUNC();
return vrend_renderer_create_fence(client_fence_id, ctx_id); const uint32_t fence_id = (uint32_t)client_fence_id;
if (state.vrend_initialized)
return vrend_renderer_create_ctx0_fence(fence_id);
return EINVAL;
} }
void virgl_renderer_force_ctx_0(void) void virgl_renderer_force_ctx_0(void)

@ -81,8 +81,13 @@ static const uint32_t fake_occlusion_query_samples_passed_default = 1024;
const struct vrend_if_cbs *vrend_clicbs; const struct vrend_if_cbs *vrend_clicbs;
struct vrend_fence { struct vrend_fence {
/* When the sync thread is waiting on the fence and the main thread
* destroys the context, ctx is set to NULL. Otherwise, ctx is always
* valid.
*/
struct vrend_context *ctx;
uint32_t fence_id; uint32_t fence_id;
uint32_t ctx_id;
union { union {
GLsync glsyncobj; GLsync glsyncobj;
#ifdef HAVE_EPOXY_EGL_H #ifdef HAVE_EPOXY_EGL_H
@ -327,8 +332,12 @@ struct global_renderer_state {
int eventfd; int eventfd;
pipe_mutex fence_mutex; pipe_mutex fence_mutex;
/* a fence is always on either of the lists, or is pointed to by
* fence_waiting
*/
struct list_head fence_list; struct list_head fence_list;
struct list_head fence_wait_list; struct list_head fence_wait_list;
struct vrend_fence *fence_waiting;
pipe_condvar fence_cond; pipe_condvar fence_cond;
struct vrend_context *ctx0; struct vrend_context *ctx0;
@ -5877,6 +5886,33 @@ static void vrend_free_fences(void)
free_fence_locked(fence); free_fence_locked(fence);
} }
static void vrend_free_fences_for_context(struct vrend_context *ctx)
{
struct vrend_fence *fence, *stor;
if (vrend_state.sync_thread) {
pipe_mutex_lock(vrend_state.fence_mutex);
LIST_FOR_EACH_ENTRY_SAFE(fence, stor, &vrend_state.fence_list, fences) {
if (fence->ctx == ctx)
free_fence_locked(fence);
}
LIST_FOR_EACH_ENTRY_SAFE(fence, stor, &vrend_state.fence_wait_list, fences) {
if (fence->ctx == ctx)
free_fence_locked(fence);
}
if (vrend_state.fence_waiting) {
/* mark the fence invalid as the sync thread is still waiting on it */
vrend_state.fence_waiting->ctx = NULL;
}
pipe_mutex_unlock(vrend_state.fence_mutex);
} else {
LIST_FOR_EACH_ENTRY_SAFE(fence, stor, &vrend_state.fence_list, fences) {
if (fence->ctx == ctx)
free_fence_locked(fence);
}
}
}
static bool do_wait(struct vrend_fence *fence, bool can_block) static bool do_wait(struct vrend_fence *fence, bool can_block)
{ {
bool done = false; bool done = false;
@ -5908,6 +5944,7 @@ static void wait_sync(struct vrend_fence *fence)
pipe_mutex_lock(vrend_state.fence_mutex); pipe_mutex_lock(vrend_state.fence_mutex);
list_addtail(&fence->fences, &vrend_state.fence_list); list_addtail(&fence->fences, &vrend_state.fence_list);
vrend_state.fence_waiting = NULL;
pipe_mutex_unlock(vrend_state.fence_mutex); pipe_mutex_unlock(vrend_state.fence_mutex);
if (write_eventfd(vrend_state.eventfd, 1)) { if (write_eventfd(vrend_state.eventfd, 1)) {
@ -5935,6 +5972,7 @@ static int thread_sync(UNUSED void *arg)
if (vrend_state.stop_sync_thread) if (vrend_state.stop_sync_thread)
break; break;
list_del(&fence->fences); list_del(&fence->fences);
vrend_state.fence_waiting = fence;
pipe_mutex_unlock(vrend_state.fence_mutex); pipe_mutex_unlock(vrend_state.fence_mutex);
wait_sync(fence); wait_sync(fence);
pipe_mutex_lock(vrend_state.fence_mutex); pipe_mutex_lock(vrend_state.fence_mutex);
@ -6329,6 +6367,8 @@ void vrend_destroy_context(struct vrend_context *ctx)
if(ctx->ctx_id) if(ctx->ctx_id)
vrend_renderer_force_ctx_0(); vrend_renderer_force_ctx_0();
vrend_free_fences_for_context(ctx);
LIST_FOR_EACH_ENTRY_SAFE(untyped_res, untyped_res_tmp, &ctx->untyped_resources, head) LIST_FOR_EACH_ENTRY_SAFE(untyped_res, untyped_res_tmp, &ctx->untyped_resources, head)
free(untyped_res); free(untyped_res);
vrend_ctx_resource_fini_table(ctx->res_hash); vrend_ctx_resource_fini_table(ctx->res_hash);
@ -9118,16 +9158,20 @@ 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(int client_fence_id, uint32_t ctx_id) int vrend_renderer_create_fence(struct vrend_context *ctx, uint32_t fence_id)
{ {
struct vrend_fence *fence; struct vrend_fence *fence;
if (!ctx)
return EINVAL;
fence = malloc(sizeof(struct vrend_fence)); fence = malloc(sizeof(struct vrend_fence));
if (!fence) if (!fence)
return ENOMEM; return ENOMEM;
fence->ctx_id = ctx_id; fence->ctx = ctx;
fence->fence_id = client_fence_id; fence->fence_id = fence_id;
#ifdef HAVE_EPOXY_EGL_H #ifdef HAVE_EPOXY_EGL_H
if (vrend_state.use_egl_fence) { if (vrend_state.use_egl_fence) {
fence->eglsyncobj = virgl_egl_fence_create(egl); fence->eglsyncobj = virgl_egl_fence_create(egl);
@ -10914,6 +10958,11 @@ int vrend_renderer_resource_unmap(struct pipe_resource *pres)
return 0; return 0;
} }
int vrend_renderer_create_ctx0_fence(uint32_t fence_id)
{
return vrend_renderer_create_fence(vrend_state.ctx0, fence_id);
}
int vrend_renderer_export_fence(uint32_t fence_id, int* out_fd) { int vrend_renderer_export_fence(uint32_t fence_id, int* out_fd) {
#ifdef HAVE_EPOXY_EGL_H #ifdef HAVE_EPOXY_EGL_H
if (!vrend_state.use_egl_fence) { if (!vrend_state.use_egl_fence) {

@ -352,10 +352,11 @@ 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(int client_fence_id, uint32_t ctx_id); int vrend_renderer_create_fence(struct vrend_context *ctx, uint32_t fence_id);
void vrend_renderer_check_fences(void); void vrend_renderer_check_fences(void);
int vrend_renderer_create_ctx0_fence(uint32_t fence_id);
int vrend_renderer_export_fence(uint32_t fence_id, int* out_fd); int vrend_renderer_export_fence(uint32_t fence_id, int* out_fd);
bool vrend_hw_switch_context(struct vrend_context *ctx, bool now); bool vrend_hw_switch_context(struct vrend_context *ctx, bool now);

Loading…
Cancel
Save