virgl: add fencing interface to virgl_context

Being an interface of virgl_context, this provides per-context fencing.

This is motivated by Vulkan, where each context (i.e., VkInstance) is
independent from one another.  Fences submitted to difference contexts
do not signal in the order they are submitted.  It is in theory and in
practice also true for OpenGL when SW/HW scheduling or context priority
is considered.

Besides being per-context, fences in Vulkan are also per-VkDevice and
per-VkQueue within a context.  This interface uses an opaque uint64_t to
identify the queue a fence is submitted to, similar to how an opaque
uint64_t is used to identify a blob.

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 d9aad06ba2
commit 17796a3a9d
  1. 31
      src/virgl_context.h
  2. 1
      src/virglrenderer.c
  3. 4
      src/vrend_decode.c

@ -48,6 +48,12 @@ struct virgl_context_blob {
void *renderer_data; void *renderer_data;
}; };
struct virgl_context;
typedef void (*virgl_context_fence_retire)(struct virgl_context *ctx,
uint64_t queue_id,
void *fence_cookie);
/** /**
* Base class for renderer contexts. For example, vrend_decode_ctx is a * Base class for renderer contexts. For example, vrend_decode_ctx is a
* subclass of virgl_context. * subclass of virgl_context.
@ -57,6 +63,16 @@ struct virgl_context {
enum virgl_renderer_capset capset_id; enum virgl_renderer_capset capset_id;
/*
* Each fence goes through submitted, signaled, and retired. This callback
* is called from virgl_context::retire_fences to retire signaled fences of
* each queue. When a queue has multiple signaled fences by the time
* virgl_context::retire_fences is called, this callback might not be called
* on all fences but only on the latest one, depending on the flags of the
* fences.
*/
virgl_context_fence_retire fence_retire;
void (*destroy)(struct virgl_context *ctx); void (*destroy)(struct virgl_context *ctx);
void (*attach_resource)(struct virgl_context *ctx, void (*attach_resource)(struct virgl_context *ctx,
@ -89,6 +105,21 @@ struct virgl_context {
int (*submit_cmd)(struct virgl_context *ctx, int (*submit_cmd)(struct virgl_context *ctx,
const void *buffer, const void *buffer,
size_t size); size_t size);
/*
* Return an fd that is readable whenever there is any signaled fence in
* any queue, or -1 if not supported.
*/
int (*get_fencing_fd)(struct virgl_context *ctx);
/* retire signaled fences of all queues */
void (*retire_fences)(struct virgl_context *ctx);
/* submit a fence to the queue identified by queue_id */
int (*submit_fence)(struct virgl_context *ctx,
uint32_t flags,
uint64_t queue_id,
void *fence_cookie);
}; };
struct virgl_context_foreach_args { struct virgl_context_foreach_args {

@ -204,6 +204,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;
ret = virgl_context_add(ctx); ret = virgl_context_add(ctx);
if (ret) { if (ret) {

@ -1683,4 +1683,8 @@ static void vrend_decode_ctx_init_base(struct vrend_decode_ctx *dctx,
ctx->get_blob = vrend_decode_ctx_get_blob; ctx->get_blob = vrend_decode_ctx_get_blob;
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->retire_fences = NULL;
ctx->submit_fence = NULL;
} }

Loading…
Cancel
Save