1 /*
2 * Copyright 2020 Google LLC
3 * SPDX-License-Identifier: MIT
4 */
5
6 #ifndef VKR_CONTEXT_H
7 #define VKR_CONTEXT_H
8
9 #include "vkr_common.h"
10
11 #include "venus-protocol/vn_protocol_renderer_defines.h"
12 #include "virgl_context.h"
13 #include "vrend_iov.h"
14
15 #include "vkr_cs.h"
16
17 struct virgl_resource;
18
19 /*
20 * When a virgl_resource is attached in vkr_context_attach_resource, a
21 * vkr_resource_attachment is created. A vkr_resource_attachment is valid
22 * until the resource it tracks is detached.
23 */
24 struct vkr_resource_attachment {
25 struct virgl_resource *resource;
26
27 /* if VIRGL_RESOURCE_FD_SHM, this is the mapping of the shm and iov below
28 * points to this
29 */
30 struct iovec shm_iov;
31
32 const struct iovec *iov;
33 int iov_count;
34 };
35
36 enum vkr_context_validate_level {
37 /* no validation */
38 VKR_CONTEXT_VALIDATE_NONE,
39 /* force enabling a subset of the validation layer */
40 VKR_CONTEXT_VALIDATE_ON,
41 /* force enabling the validation layer */
42 VKR_CONTEXT_VALIDATE_FULL,
43 };
44
45 struct vkr_cpu_sync {
46 uint32_t flags;
47 uint32_t ring_idx;
48 uint64_t fence_id;
49
50 struct list_head head;
51 };
52
53 struct vkr_context {
54 struct virgl_context base;
55
56 char *debug_name;
57 enum vkr_context_validate_level validate_level;
58 bool validate_fatal;
59
60 mtx_t mutex;
61
62 struct list_head rings;
63 struct hash_table *object_table;
64 struct hash_table *resource_table;
65
66 struct vkr_cs_encoder encoder;
67 struct vkr_cs_decoder decoder;
68 struct vn_dispatch_context dispatch;
69
70 int fence_eventfd;
71 struct list_head busy_queues;
72 struct list_head signaled_syncs;
73 struct list_head signaled_cpu_syncs;
74
75 struct vkr_queue *sync_queues[64];
76
77 struct vkr_instance *instance;
78 char *instance_name;
79 };
80
81 void
82 vkr_context_free_resource(struct hash_entry *entry);
83
84 static inline void
vkr_context_add_resource(struct vkr_context * ctx,struct vkr_resource_attachment * att)85 vkr_context_add_resource(struct vkr_context *ctx, struct vkr_resource_attachment *att)
86 {
87 assert(!_mesa_hash_table_search(ctx->resource_table, &att->resource->res_id));
88 _mesa_hash_table_insert(ctx->resource_table, &att->resource->res_id, att);
89 }
90
91 static inline void
vkr_context_remove_resource(struct vkr_context * ctx,uint32_t res_id)92 vkr_context_remove_resource(struct vkr_context *ctx, uint32_t res_id)
93 {
94 struct hash_entry *entry = _mesa_hash_table_search(ctx->resource_table, &res_id);
95 if (likely(entry)) {
96 vkr_context_free_resource(entry);
97 _mesa_hash_table_remove(ctx->resource_table, entry);
98 }
99 }
100
101 static inline struct vkr_resource_attachment *
vkr_context_get_resource(struct vkr_context * ctx,uint32_t res_id)102 vkr_context_get_resource(struct vkr_context *ctx, uint32_t res_id)
103 {
104 const struct hash_entry *entry = _mesa_hash_table_search(ctx->resource_table, &res_id);
105 return likely(entry) ? entry->data : NULL;
106 }
107
108 static inline bool
vkr_context_validate_object_id(struct vkr_context * ctx,vkr_object_id id)109 vkr_context_validate_object_id(struct vkr_context *ctx, vkr_object_id id)
110 {
111 if (unlikely(!id || _mesa_hash_table_search(ctx->object_table, &id))) {
112 vkr_log("invalid object id %" PRIu64, id);
113 vkr_cs_decoder_set_fatal(&ctx->decoder);
114 return false;
115 }
116
117 return true;
118 }
119
120 static inline void *
vkr_context_alloc_object(UNUSED struct vkr_context * ctx,size_t size,VkObjectType type,const void * id_handle)121 vkr_context_alloc_object(UNUSED struct vkr_context *ctx,
122 size_t size,
123 VkObjectType type,
124 const void *id_handle)
125 {
126 const vkr_object_id id = vkr_cs_handle_load_id((const void **)id_handle, type);
127 if (!vkr_context_validate_object_id(ctx, id))
128 return NULL;
129
130 return vkr_object_alloc(size, type, id);
131 }
132
133 void
134 vkr_context_free_object(struct hash_entry *entry);
135
136 static inline void
vkr_context_add_object(struct vkr_context * ctx,struct vkr_object * obj)137 vkr_context_add_object(struct vkr_context *ctx, struct vkr_object *obj)
138 {
139 assert(vkr_is_recognized_object_type(obj->type));
140 assert(obj->id);
141 assert(!_mesa_hash_table_search(ctx->object_table, &obj->id));
142
143 _mesa_hash_table_insert(ctx->object_table, &obj->id, obj);
144 }
145
146 static inline void
vkr_context_remove_object(struct vkr_context * ctx,struct vkr_object * obj)147 vkr_context_remove_object(struct vkr_context *ctx, struct vkr_object *obj)
148 {
149 assert(_mesa_hash_table_search(ctx->object_table, &obj->id));
150
151 struct hash_entry *entry = _mesa_hash_table_search(ctx->object_table, &obj->id);
152 if (likely(entry)) {
153 vkr_context_free_object(entry);
154 _mesa_hash_table_remove(ctx->object_table, entry);
155 }
156 }
157
158 static inline void
vkr_context_remove_objects(struct vkr_context * ctx,struct list_head * objects)159 vkr_context_remove_objects(struct vkr_context *ctx, struct list_head *objects)
160 {
161 struct vkr_object *obj, *tmp;
162 LIST_FOR_EACH_ENTRY_SAFE (obj, tmp, objects, track_head)
163 vkr_context_remove_object(ctx, obj);
164 /* objects should be reinitialized if to be reused */
165 }
166
167 static inline void *
vkr_context_get_object(struct vkr_context * ctx,vkr_object_id obj_id)168 vkr_context_get_object(struct vkr_context *ctx, vkr_object_id obj_id)
169 {
170 const struct hash_entry *entry = _mesa_hash_table_search(ctx->object_table, &obj_id);
171 return likely(entry) ? entry->data : NULL;
172 }
173
174 static inline const char *
vkr_context_get_name(const struct vkr_context * ctx)175 vkr_context_get_name(const struct vkr_context *ctx)
176 {
177 /* ctx->instance_name is the application name while ctx->debug_name is
178 * usually the guest process name or the hypervisor name. This never
179 * returns NULL because ctx->debug_name is never NULL.
180 */
181 return ctx->instance_name ? ctx->instance_name : ctx->debug_name;
182 }
183
184 void
185 vkr_context_add_instance(struct vkr_context *ctx,
186 struct vkr_instance *instance,
187 const char *name);
188
189 void
190 vkr_context_remove_instance(struct vkr_context *ctx, struct vkr_instance *instance);
191
192 #endif /* VKR_CONTEXT_H */
193