blob: 931d103ce4a08254f9758449bfce91e65ab4ba74 [file] [log] [blame]
/*
* Copyright 2020 Google LLC
* SPDX-License-Identifier: MIT
*/
#ifndef VKR_CONTEXT_H
#define VKR_CONTEXT_H
#include "vkr_common.h"
#include "venus-protocol/vn_protocol_renderer_defines.h"
#include "virgl_resource.h"
#include "vkr_cs.h"
/*
* When vkr_context_create_resource or vkr_context_import_resource is called, a
* vkr_resource is created, and is valid until vkr_context_destroy_resource.
*/
struct vkr_resource {
uint32_t res_id;
enum virgl_resource_fd_type fd_type;
union {
/* valid when fd_type is dma_buf or opaque */
int fd;
/* valid when fd_type is shm */
uint8_t *data;
} u;
size_t size;
};
enum vkr_context_validate_level {
/* no validation */
VKR_CONTEXT_VALIDATE_NONE,
/* force enabling a subset of the validation layer */
VKR_CONTEXT_VALIDATE_ON,
/* force enabling the validation layer */
VKR_CONTEXT_VALIDATE_FULL,
};
struct vkr_context {
uint32_t ctx_id;
vkr_renderer_retire_fence_callback_type retire_fence;
char *debug_name;
enum vkr_context_validate_level validate_level;
bool validate_fatal;
mtx_t ring_mutex;
struct list_head rings;
struct {
mtx_t mutex;
cnd_t cond;
uint64_t id;
/* This represents the ring head position to be waited on. The protocol supports
* 64bit seqno and we only use 32bit internally because the delta between the ring
* head and ring current will never exceed the ring size, which is far smaller than
* 32bit int limit in practice.
*/
uint32_t seqno;
} wait_ring;
struct {
mtx_t mutex;
cnd_t cond;
thrd_t thread;
atomic_bool started;
/* When monitoring multiple rings, wake to report on all rings at the minimum of
* per-ring maxReportingPeriodMicroseconds to ensure that every ring is marked ALIVE
* before the next renderer check.
*/
atomic_uint report_period_us;
} ring_monitor;
mtx_t object_mutex;
struct hash_table *object_table;
mtx_t resource_mutex;
struct hash_table *resource_table;
bool cs_fatal_error;
struct vkr_cs_encoder encoder;
struct vkr_cs_decoder decoder;
struct vn_dispatch_context dispatch;
struct vkr_queue *sync_queues[64];
struct vkr_instance *instance;
char *instance_name;
struct list_head head;
};
struct vkr_context *
vkr_context_create(uint32_t ctx_id,
vkr_renderer_retire_fence_callback_type cb,
size_t debug_len,
const char *debug_name);
void
vkr_context_destroy(struct vkr_context *ctx);
bool
vkr_context_ring_monitor_init(struct vkr_context *ctx, uint32_t report_period_us);
bool
vkr_context_submit_fence(struct vkr_context *ctx,
uint32_t flags,
uint32_t ring_idx,
uint64_t fence_id);
bool
vkr_context_submit_cmd(struct vkr_context *ctx, const void *buffer, size_t size);
bool
vkr_context_create_resource(struct vkr_context *ctx,
uint32_t res_id,
uint64_t blob_id,
uint64_t blob_size,
uint32_t blob_flags,
struct virgl_context_blob *out_blob);
bool
vkr_context_import_resource(struct vkr_context *ctx,
uint32_t res_id,
enum virgl_resource_fd_type fd_type,
int fd,
uint64_t size);
void
vkr_context_destroy_resource(struct vkr_context *ctx, uint32_t res_id);
static inline struct vkr_resource *
vkr_context_get_resource(struct vkr_context *ctx, uint32_t res_id)
{
mtx_lock(&ctx->resource_mutex);
const struct hash_entry *entry = _mesa_hash_table_search(ctx->resource_table, &res_id);
mtx_unlock(&ctx->resource_mutex);
return likely(entry) ? entry->data : NULL;
}
static inline void
vkr_context_set_fatal(struct vkr_context *ctx)
{
ctx->cs_fatal_error = true;
}
static inline bool
vkr_context_get_fatal(struct vkr_context *ctx)
{
return ctx->cs_fatal_error;
}
static inline bool
vkr_context_validate_object_id(struct vkr_context *ctx, vkr_object_id id)
{
mtx_lock(&ctx->object_mutex);
if (unlikely(!id || _mesa_hash_table_search(ctx->object_table, &id))) {
mtx_unlock(&ctx->object_mutex);
vkr_log("invalid object id %" PRIu64, id);
vkr_context_set_fatal(ctx);
return false;
}
mtx_unlock(&ctx->object_mutex);
return true;
}
static inline void *
vkr_context_alloc_object(UNUSED struct vkr_context *ctx,
size_t size,
VkObjectType type,
const void *id_handle)
{
const vkr_object_id id = vkr_cs_handle_load_id((const void **)id_handle, type);
if (!vkr_context_validate_object_id(ctx, id))
return NULL;
return vkr_object_alloc(size, type, id);
}
void
vkr_context_free_object(struct hash_entry *entry);
static inline void
vkr_context_add_object(struct vkr_context *ctx, struct vkr_object *obj)
{
assert(vkr_is_recognized_object_type(obj->type));
assert(obj->id);
mtx_lock(&ctx->object_mutex);
assert(!_mesa_hash_table_search(ctx->object_table, &obj->id));
_mesa_hash_table_insert(ctx->object_table, &obj->id, obj);
mtx_unlock(&ctx->object_mutex);
}
static inline void
vkr_context_remove_object_locked(struct vkr_context *ctx, struct vkr_object *obj)
{
assert(_mesa_hash_table_search(ctx->object_table, &obj->id));
struct hash_entry *entry = _mesa_hash_table_search(ctx->object_table, &obj->id);
if (likely(entry)) {
vkr_context_free_object(entry);
_mesa_hash_table_remove(ctx->object_table, entry);
}
}
static inline void
vkr_context_remove_object(struct vkr_context *ctx, struct vkr_object *obj)
{
mtx_lock(&ctx->object_mutex);
vkr_context_remove_object_locked(ctx, obj);
mtx_unlock(&ctx->object_mutex);
}
static inline void
vkr_context_remove_objects(struct vkr_context *ctx, struct list_head *objects)
{
struct vkr_object *obj, *tmp;
mtx_lock(&ctx->object_mutex);
LIST_FOR_EACH_ENTRY_SAFE (obj, tmp, objects, track_head)
vkr_context_remove_object_locked(ctx, obj);
mtx_unlock(&ctx->object_mutex);
/* objects should be reinitialized if to be reused */
}
static inline void *
vkr_context_get_object(struct vkr_context *ctx, vkr_object_id obj_id)
{
mtx_lock(&ctx->object_mutex);
const struct hash_entry *entry = _mesa_hash_table_search(ctx->object_table, &obj_id);
mtx_unlock(&ctx->object_mutex);
return likely(entry) ? entry->data : NULL;
}
void
vkr_context_on_ring_seqno_update(struct vkr_context *ctx,
uint64_t ring_id,
uint64_t ring_seqno);
bool
vkr_context_wait_ring_seqno(struct vkr_context *ctx,
struct vkr_ring *ring,
uint64_t ring_seqno);
void
vkr_context_add_instance(struct vkr_context *ctx,
struct vkr_instance *instance,
const char *name);
void
vkr_context_remove_instance(struct vkr_context *ctx, struct vkr_instance *instance);
#endif /* VKR_CONTEXT_H */