/* * 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_context.h" #include "vrend_iov.h" #include "vkr_cs.h" struct virgl_resource; /* * When a virgl_resource is attached in vkr_context_attach_resource, a * vkr_resource_attachment is created. A vkr_resource_attachment is valid * until the resource it tracks is detached. */ struct vkr_resource_attachment { struct virgl_resource *resource; /* if VIRGL_RESOURCE_FD_SHM, this is the mapping of the shm and iov below * points to this */ struct iovec shm_iov; const struct iovec *iov; int iov_count; }; 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_cpu_sync { uint32_t flags; uint32_t ring_idx; uint64_t fence_id; struct list_head head; }; struct vkr_context { struct virgl_context base; char *debug_name; enum vkr_context_validate_level validate_level; bool validate_fatal; mtx_t mutex; struct list_head rings; struct hash_table *object_table; struct hash_table *resource_table; struct vkr_cs_encoder encoder; struct vkr_cs_decoder decoder; struct vn_dispatch_context dispatch; int fence_eventfd; struct list_head busy_queues; struct list_head signaled_syncs; struct list_head signaled_cpu_syncs; struct vkr_queue *sync_queues[64]; struct vkr_instance *instance; char *instance_name; }; void vkr_context_free_resource(struct hash_entry *entry); static inline void vkr_context_add_resource(struct vkr_context *ctx, struct vkr_resource_attachment *att) { assert(!_mesa_hash_table_search(ctx->resource_table, &att->resource->res_id)); _mesa_hash_table_insert(ctx->resource_table, &att->resource->res_id, att); } static inline void vkr_context_remove_resource(struct vkr_context *ctx, uint32_t res_id) { struct hash_entry *entry = _mesa_hash_table_search(ctx->resource_table, &res_id); if (likely(entry)) { vkr_context_free_resource(entry); _mesa_hash_table_remove(ctx->resource_table, entry); } } static inline struct vkr_resource_attachment * vkr_context_get_resource(struct vkr_context *ctx, uint32_t res_id) { const struct hash_entry *entry = _mesa_hash_table_search(ctx->resource_table, &res_id); return likely(entry) ? entry->data : NULL; } static inline bool vkr_context_validate_object_id(struct vkr_context *ctx, vkr_object_id id) { if (unlikely(!id || _mesa_hash_table_search(ctx->object_table, &id))) { vkr_log("invalid object id %" PRIu64, id); vkr_cs_decoder_set_fatal(&ctx->decoder); return false; } 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); assert(!_mesa_hash_table_search(ctx->object_table, &obj->id)); _mesa_hash_table_insert(ctx->object_table, &obj->id, obj); } static inline void vkr_context_remove_object(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_objects(struct vkr_context *ctx, struct list_head *objects) { struct vkr_object *obj, *tmp; LIST_FOR_EACH_ENTRY_SAFE (obj, tmp, objects, track_head) vkr_context_remove_object(ctx, obj); /* objects should be reinitialized if to be reused */ } static inline void * vkr_context_get_object(struct vkr_context *ctx, vkr_object_id obj_id) { const struct hash_entry *entry = _mesa_hash_table_search(ctx->object_table, &obj_id); return likely(entry) ? entry->data : NULL; } static inline const char * vkr_context_get_name(const struct vkr_context *ctx) { /* ctx->instance_name is the application name while ctx->debug_name is * usually the guest process name or the hypervisor name. This never * returns NULL because ctx->debug_name is never NULL. */ return ctx->instance_name ? ctx->instance_name : ctx->debug_name; } 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 */