1 /*
2 * Copyright 2019 Google LLC
3 * SPDX-License-Identifier: MIT
4 *
5 * based in part on anv and radv which are:
6 * Copyright © 2015 Intel Corporation
7 * Copyright © 2016 Red Hat.
8 * Copyright © 2016 Bas Nieuwenhuizen
9 */
10
11 #ifndef VN_COMMON_H
12 #define VN_COMMON_H
13
14 #include <assert.h>
15 #include <inttypes.h>
16 #include <limits.h>
17 #include <stdatomic.h>
18 #include <stdbool.h>
19 #include <stddef.h>
20 #include <stdint.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/syscall.h>
24 #include <vulkan/vulkan.h>
25
26 #include "c11/threads.h"
27 #include "drm-uapi/drm_fourcc.h"
28 #include "util/bitscan.h"
29 #include "util/bitset.h"
30 #include "util/compiler.h"
31 #include "util/detect_os.h"
32 #include "util/libsync.h"
33 #include "util/list.h"
34 #include "util/macros.h"
35 #include "util/os_time.h"
36 #include "util/perf/cpu_trace.h"
37 #include "util/simple_mtx.h"
38 #include "util/u_atomic.h"
39 #include "util/u_math.h"
40 #include "util/xmlconfig.h"
41 #include "vk_alloc.h"
42 #include "vk_debug_report.h"
43 #include "vk_device.h"
44 #include "vk_device_memory.h"
45 #include "vk_image.h"
46 #include "vk_instance.h"
47 #include "vk_object.h"
48 #include "vk_physical_device.h"
49 #include "vk_queue.h"
50 #include "vk_util.h"
51
52 #include "vn_entrypoints.h"
53
54 #define VN_DEFAULT_ALIGN 8
55 #define VN_WATCHDOG_REPORT_PERIOD_US 3000000
56
57 #define VN_DEBUG(category) (unlikely(vn_env.debug & VN_DEBUG_##category))
58 #define VN_PERF(category) (unlikely(vn_env.perf & VN_PERF_##category))
59
60 #define vn_error(instance, error) \
61 (VN_DEBUG(RESULT) ? vn_log_result((instance), (error), __func__) : (error))
62 #define vn_result(instance, result) \
63 ((result) >= VK_SUCCESS ? (result) : vn_error((instance), (result)))
64
65 #define VN_TRACE_SCOPE(name) MESA_TRACE_SCOPE(name)
66 #define VN_TRACE_FUNC() MESA_TRACE_SCOPE(__func__)
67
68 struct vn_instance;
69 struct vn_physical_device;
70 struct vn_device;
71 struct vn_queue;
72 struct vn_fence;
73 struct vn_semaphore;
74 struct vn_device_memory;
75 struct vn_buffer;
76 struct vn_buffer_view;
77 struct vn_image;
78 struct vn_image_view;
79 struct vn_sampler;
80 struct vn_sampler_ycbcr_conversion;
81 struct vn_descriptor_set_layout;
82 struct vn_descriptor_pool;
83 struct vn_descriptor_set;
84 struct vn_descriptor_update_template;
85 struct vn_render_pass;
86 struct vn_framebuffer;
87 struct vn_event;
88 struct vn_query_pool;
89 struct vn_shader_module;
90 struct vn_pipeline_layout;
91 struct vn_pipeline_cache;
92 struct vn_pipeline;
93 struct vn_command_pool;
94 struct vn_command_buffer;
95
96 struct vn_cs_encoder;
97 struct vn_cs_decoder;
98 struct vn_ring;
99
100 struct vn_renderer;
101 struct vn_renderer_shmem;
102 struct vn_renderer_bo;
103 struct vn_renderer_sync;
104
105 enum vn_debug {
106 VN_DEBUG_INIT = 1ull << 0,
107 VN_DEBUG_RESULT = 1ull << 1,
108 VN_DEBUG_VTEST = 1ull << 2,
109 VN_DEBUG_WSI = 1ull << 3,
110 VN_DEBUG_NO_ABORT = 1ull << 4,
111 VN_DEBUG_LOG_CTX_INFO = 1ull << 5,
112 VN_DEBUG_CACHE = 1ull << 6,
113 VN_DEBUG_NO_SPARSE = 1ull << 7,
114 VN_DEBUG_NO_GPL = 1ull << 8,
115 };
116
117 enum vn_perf {
118 VN_PERF_NO_ASYNC_SET_ALLOC = 1ull << 0,
119 VN_PERF_NO_ASYNC_BUFFER_CREATE = 1ull << 1,
120 VN_PERF_NO_ASYNC_QUEUE_SUBMIT = 1ull << 2,
121 VN_PERF_NO_EVENT_FEEDBACK = 1ull << 3,
122 VN_PERF_NO_FENCE_FEEDBACK = 1ull << 4,
123 VN_PERF_NO_MEMORY_SUBALLOC = 1ull << 5,
124 VN_PERF_NO_CMD_BATCHING = 1ull << 6,
125 VN_PERF_NO_SEMAPHORE_FEEDBACK = 1ull << 7,
126 VN_PERF_NO_QUERY_FEEDBACK = 1ull << 8,
127 VN_PERF_NO_ASYNC_MEM_ALLOC = 1ull << 9,
128 VN_PERF_NO_TILED_WSI_IMAGE = 1ull << 10,
129 VN_PERF_NO_MULTI_RING = 1ull << 11,
130 VN_PERF_NO_ASYNC_IMAGE_CREATE = 1ull << 12,
131 VN_PERF_NO_ASYNC_IMAGE_FORMAT = 1ull << 13,
132 };
133
134 typedef uint64_t vn_object_id;
135
136 /* base class of vn_instance */
137 struct vn_instance_base {
138 struct vk_instance base;
139 vn_object_id id;
140 };
141
142 /* base class of vn_physical_device */
143 struct vn_physical_device_base {
144 struct vk_physical_device base;
145 vn_object_id id;
146 };
147
148 /* base class of vn_device */
149 struct vn_device_base {
150 struct vk_device base;
151 vn_object_id id;
152 };
153
154 /* base class of vn_queue */
155 struct vn_queue_base {
156 struct vk_queue base;
157 vn_object_id id;
158 };
159
160 /* base class of vn_device_memory */
161 struct vn_device_memory_base {
162 struct vk_device_memory base;
163 vn_object_id id;
164 };
165
166 /* base class of vn_image */
167 struct vn_image_base {
168 struct vk_image base;
169 vn_object_id id;
170 };
171
172 /* base class of other driver objects */
173 struct vn_object_base {
174 struct vk_object_base base;
175 vn_object_id id;
176 };
177
178 struct vn_refcount {
179 atomic_int count;
180 };
181
182 struct vn_env {
183 uint64_t debug;
184 uint64_t perf;
185 /* zero will be overridden to UINT32_MAX as no limit */
186 uint32_t draw_cmd_batch_limit;
187 uint32_t relax_base_sleep_us;
188 };
189 extern struct vn_env vn_env;
190
191 /* Only one "waiting" thread may fulfill the "watchdog" role at a time. Every
192 * VN_WATCHDOG_REPORT_PERIOD_US or longer, the watchdog tests the ring's ALIVE
193 * status, updates the "alive" atomic, and resets the ALIVE status for the
194 * next cycle. Other waiting threads just check the "alive" atomic. The
195 * watchdog role may be released and acquired by another waiting thread
196 * dynamically.
197 *
198 * Examples of "waiting" are to wait for:
199 * - ring to reach a seqno
200 * - ring space to be released
201 * - sync primitives to signal
202 * - query result being available
203 */
204 struct vn_watchdog {
205 mtx_t mutex;
206 atomic_int tid;
207 atomic_bool alive;
208 };
209
210 struct vn_relax_state {
211 struct vn_instance *instance;
212 uint32_t iter;
213 const char *reason;
214 };
215
216 /* TLS ring
217 * - co-owned by TLS and VkInstance
218 * - initialized in TLS upon requested
219 * - teardown happens upon thread exit or instance destroy
220 * - teardown is split into 2 stages:
221 * 1. one owner locks and destroys the ring and mark destroyed
222 * 2. the other owner locks and frees up the tls ring storage
223 */
224 struct vn_tls_ring {
225 mtx_t mutex;
226 struct vn_ring *ring;
227 struct vn_instance *instance;
228 struct list_head tls_head;
229 struct list_head vk_head;
230 };
231
232 struct vn_tls {
233 /* Track the threads on which swapchain and command pool creations occur.
234 * Pipeline create on those threads are forced async via the primary ring.
235 */
236 bool async_pipeline_create;
237 /* Track TLS rings owned across instances. */
238 struct list_head tls_rings;
239 };
240
241 /* A cached storage for object internal usages with below constraints:
242 * - It belongs to the object and shares the lifetime.
243 * - The storage reuse is protected by external synchronization.
244 * - The returned storage is not zero-initialized.
245 * - It never shrinks unless being purged via fini.
246 *
247 * The current users are:
248 * - VkCommandPool
249 * - VkQueue
250 */
251 struct vn_cached_storage {
252 const VkAllocationCallbacks *alloc;
253 size_t size;
254 void *data;
255 };
256
257 void
258 vn_env_init(void);
259
260 void
261 vn_trace_init(void);
262
263 void
264 vn_log(struct vn_instance *instance, const char *format, ...)
265 PRINTFLIKE(2, 3);
266
267 VkResult
268 vn_log_result(struct vn_instance *instance,
269 VkResult result,
270 const char *where);
271
272 #define VN_REFCOUNT_INIT(val) \
273 (struct vn_refcount) \
274 { \
275 .count = (val), \
276 }
277
278 static inline int
vn_refcount_load_relaxed(const struct vn_refcount * ref)279 vn_refcount_load_relaxed(const struct vn_refcount *ref)
280 {
281 return atomic_load_explicit(&ref->count, memory_order_relaxed);
282 }
283
284 static inline int
vn_refcount_fetch_add_relaxed(struct vn_refcount * ref,int val)285 vn_refcount_fetch_add_relaxed(struct vn_refcount *ref, int val)
286 {
287 return atomic_fetch_add_explicit(&ref->count, val, memory_order_relaxed);
288 }
289
290 static inline int
vn_refcount_fetch_sub_release(struct vn_refcount * ref,int val)291 vn_refcount_fetch_sub_release(struct vn_refcount *ref, int val)
292 {
293 return atomic_fetch_sub_explicit(&ref->count, val, memory_order_release);
294 }
295
296 static inline bool
vn_refcount_is_valid(const struct vn_refcount * ref)297 vn_refcount_is_valid(const struct vn_refcount *ref)
298 {
299 return vn_refcount_load_relaxed(ref) > 0;
300 }
301
302 static inline void
vn_refcount_inc(struct vn_refcount * ref)303 vn_refcount_inc(struct vn_refcount *ref)
304 {
305 /* no ordering imposed */
306 ASSERTED const int old = vn_refcount_fetch_add_relaxed(ref, 1);
307 assert(old >= 1);
308 }
309
310 static inline bool
vn_refcount_dec(struct vn_refcount * ref)311 vn_refcount_dec(struct vn_refcount *ref)
312 {
313 /* prior reads/writes cannot be reordered after this */
314 const int old = vn_refcount_fetch_sub_release(ref, 1);
315 assert(old >= 1);
316
317 /* subsequent free cannot be reordered before this */
318 if (old == 1)
319 atomic_thread_fence(memory_order_acquire);
320
321 return old == 1;
322 }
323
324 extern uint64_t vn_next_obj_id;
325
326 static inline uint64_t
vn_get_next_obj_id(void)327 vn_get_next_obj_id(void)
328 {
329 return p_atomic_fetch_add(&vn_next_obj_id, 1);
330 }
331
332 uint32_t
333 vn_extension_get_spec_version(const char *name);
334
335 static inline void
vn_watchdog_init(struct vn_watchdog * watchdog)336 vn_watchdog_init(struct vn_watchdog *watchdog)
337 {
338 #ifndef NDEBUG
339 /* ensure minimum check period is greater than maximum renderer
340 * reporting period (with margin of safety to ensure no false
341 * positives).
342 *
343 * first_warn_time is pre-calculated based on parameters in vn_relax
344 * and must update together.
345 */
346 static const uint32_t first_warn_time = 3481600;
347 static const uint32_t safety_margin = 250000;
348 assert(first_warn_time - safety_margin >= VN_WATCHDOG_REPORT_PERIOD_US);
349 #endif
350
351 mtx_init(&watchdog->mutex, mtx_plain);
352
353 watchdog->tid = 0;
354
355 /* initialized to be alive to avoid vn_watchdog_timout false alarm */
356 watchdog->alive = true;
357 }
358
359 static inline void
vn_watchdog_fini(struct vn_watchdog * watchdog)360 vn_watchdog_fini(struct vn_watchdog *watchdog)
361 {
362 mtx_destroy(&watchdog->mutex);
363 }
364
365 struct vn_relax_state
366 vn_relax_init(struct vn_instance *instance, const char *reason);
367
368 void
369 vn_relax(struct vn_relax_state *state);
370
371 void
372 vn_relax_fini(struct vn_relax_state *state);
373
374 static_assert(sizeof(vn_object_id) >= sizeof(uintptr_t), "");
375
376 static inline VkResult
vn_instance_base_init(struct vn_instance_base * instance,const struct vk_instance_extension_table * supported_extensions,const struct vk_instance_dispatch_table * dispatch_table,const VkInstanceCreateInfo * info,const VkAllocationCallbacks * alloc)377 vn_instance_base_init(
378 struct vn_instance_base *instance,
379 const struct vk_instance_extension_table *supported_extensions,
380 const struct vk_instance_dispatch_table *dispatch_table,
381 const VkInstanceCreateInfo *info,
382 const VkAllocationCallbacks *alloc)
383 {
384 VkResult result = vk_instance_init(&instance->base, supported_extensions,
385 dispatch_table, info, alloc);
386 instance->id = vn_get_next_obj_id();
387 return result;
388 }
389
390 static inline void
vn_instance_base_fini(struct vn_instance_base * instance)391 vn_instance_base_fini(struct vn_instance_base *instance)
392 {
393 vk_instance_finish(&instance->base);
394 }
395
396 static inline VkResult
vn_physical_device_base_init(struct vn_physical_device_base * physical_dev,struct vn_instance_base * instance,const struct vk_device_extension_table * supported_extensions,const struct vk_physical_device_dispatch_table * dispatch_table)397 vn_physical_device_base_init(
398 struct vn_physical_device_base *physical_dev,
399 struct vn_instance_base *instance,
400 const struct vk_device_extension_table *supported_extensions,
401 const struct vk_physical_device_dispatch_table *dispatch_table)
402 {
403 VkResult result = vk_physical_device_init(
404 &physical_dev->base, &instance->base, supported_extensions, NULL, NULL,
405 dispatch_table);
406 physical_dev->id = vn_get_next_obj_id();
407 return result;
408 }
409
410 static inline void
vn_physical_device_base_fini(struct vn_physical_device_base * physical_dev)411 vn_physical_device_base_fini(struct vn_physical_device_base *physical_dev)
412 {
413 vk_physical_device_finish(&physical_dev->base);
414 }
415
416 static inline VkResult
vn_device_base_init(struct vn_device_base * dev,struct vn_physical_device_base * physical_dev,const struct vk_device_dispatch_table * dispatch_table,const VkDeviceCreateInfo * info,const VkAllocationCallbacks * alloc)417 vn_device_base_init(struct vn_device_base *dev,
418 struct vn_physical_device_base *physical_dev,
419 const struct vk_device_dispatch_table *dispatch_table,
420 const VkDeviceCreateInfo *info,
421 const VkAllocationCallbacks *alloc)
422 {
423 VkResult result = vk_device_init(&dev->base, &physical_dev->base,
424 dispatch_table, info, alloc);
425 dev->id = vn_get_next_obj_id();
426 return result;
427 }
428
429 static inline void
vn_device_base_fini(struct vn_device_base * dev)430 vn_device_base_fini(struct vn_device_base *dev)
431 {
432 vk_device_finish(&dev->base);
433 }
434
435 static inline VkResult
vn_queue_base_init(struct vn_queue_base * queue,struct vn_device_base * dev,const VkDeviceQueueCreateInfo * queue_info,uint32_t queue_index)436 vn_queue_base_init(struct vn_queue_base *queue,
437 struct vn_device_base *dev,
438 const VkDeviceQueueCreateInfo *queue_info,
439 uint32_t queue_index)
440 {
441 VkResult result =
442 vk_queue_init(&queue->base, &dev->base, queue_info, queue_index);
443 queue->id = vn_get_next_obj_id();
444 return result;
445 }
446
447 static inline void
vn_queue_base_fini(struct vn_queue_base * queue)448 vn_queue_base_fini(struct vn_queue_base *queue)
449 {
450 vk_queue_finish(&queue->base);
451 }
452
453 static inline void
vn_object_base_init(struct vn_object_base * obj,VkObjectType type,struct vn_device_base * dev)454 vn_object_base_init(struct vn_object_base *obj,
455 VkObjectType type,
456 struct vn_device_base *dev)
457 {
458 vk_object_base_init(&dev->base, &obj->base, type);
459 obj->id = vn_get_next_obj_id();
460 }
461
462 static inline void
vn_object_base_fini(struct vn_object_base * obj)463 vn_object_base_fini(struct vn_object_base *obj)
464 {
465 vk_object_base_finish(&obj->base);
466 }
467
468 static inline void
vn_object_set_id(void * obj,vn_object_id id,VkObjectType type)469 vn_object_set_id(void *obj, vn_object_id id, VkObjectType type)
470 {
471 assert(((const struct vk_object_base *)obj)->type == type);
472 switch (type) {
473 case VK_OBJECT_TYPE_INSTANCE:
474 ((struct vn_instance_base *)obj)->id = id;
475 break;
476 case VK_OBJECT_TYPE_PHYSICAL_DEVICE:
477 ((struct vn_physical_device_base *)obj)->id = id;
478 break;
479 case VK_OBJECT_TYPE_DEVICE:
480 ((struct vn_device_base *)obj)->id = id;
481 break;
482 case VK_OBJECT_TYPE_QUEUE:
483 ((struct vn_queue_base *)obj)->id = id;
484 break;
485 case VK_OBJECT_TYPE_DEVICE_MEMORY:
486 ((struct vn_device_memory_base *)obj)->id = id;
487 break;
488 case VK_OBJECT_TYPE_IMAGE:
489 ((struct vn_image_base *)obj)->id = id;
490 break;
491 default:
492 ((struct vn_object_base *)obj)->id = id;
493 break;
494 }
495 }
496
497 static inline vn_object_id
vn_object_get_id(const void * obj,VkObjectType type)498 vn_object_get_id(const void *obj, VkObjectType type)
499 {
500 assert(((const struct vk_object_base *)obj)->type == type);
501 switch (type) {
502 case VK_OBJECT_TYPE_INSTANCE:
503 return ((struct vn_instance_base *)obj)->id;
504 case VK_OBJECT_TYPE_PHYSICAL_DEVICE:
505 return ((struct vn_physical_device_base *)obj)->id;
506 case VK_OBJECT_TYPE_DEVICE:
507 return ((struct vn_device_base *)obj)->id;
508 case VK_OBJECT_TYPE_QUEUE:
509 return ((struct vn_queue_base *)obj)->id;
510 case VK_OBJECT_TYPE_DEVICE_MEMORY:
511 return ((struct vn_device_memory_base *)obj)->id;
512 case VK_OBJECT_TYPE_IMAGE:
513 return ((struct vn_image_base *)obj)->id;
514 default:
515 return ((struct vn_object_base *)obj)->id;
516 }
517 }
518
519 static inline pid_t
vn_gettid(void)520 vn_gettid(void)
521 {
522 #if DETECT_OS_ANDROID
523 return gettid();
524 #else
525 return syscall(SYS_gettid);
526 #endif
527 }
528
529 struct vn_tls *
530 vn_tls_get(void);
531
532 static inline void
vn_tls_set_async_pipeline_create(void)533 vn_tls_set_async_pipeline_create(void)
534 {
535 struct vn_tls *tls = vn_tls_get();
536 if (likely(tls))
537 tls->async_pipeline_create = true;
538 }
539
540 static inline bool
vn_tls_get_async_pipeline_create(void)541 vn_tls_get_async_pipeline_create(void)
542 {
543 const struct vn_tls *tls = vn_tls_get();
544 if (likely(tls))
545 return tls->async_pipeline_create;
546 return true;
547 }
548
549 struct vn_ring *
550 vn_tls_get_ring(struct vn_instance *instance);
551
552 void
553 vn_tls_destroy_ring(struct vn_tls_ring *tls_ring);
554
555 static inline uint32_t
vn_cache_key_hash_function(const void * key)556 vn_cache_key_hash_function(const void *key)
557 {
558 return _mesa_hash_data(key, SHA1_DIGEST_LENGTH);
559 }
560
561 static inline bool
vn_cache_key_equal_function(const void * key1,const void * key2)562 vn_cache_key_equal_function(const void *key1, const void *key2)
563 {
564 return memcmp(key1, key2, SHA1_DIGEST_LENGTH) == 0;
565 }
566
567 static inline void
vn_cached_storage_init(struct vn_cached_storage * storage,const VkAllocationCallbacks * alloc)568 vn_cached_storage_init(struct vn_cached_storage *storage,
569 const VkAllocationCallbacks *alloc)
570 {
571 storage->alloc = alloc;
572 storage->size = 0;
573 storage->data = NULL;
574 }
575
576 static inline void *
vn_cached_storage_get(struct vn_cached_storage * storage,size_t size)577 vn_cached_storage_get(struct vn_cached_storage *storage, size_t size)
578 {
579 if (size > storage->size) {
580 void *data =
581 vk_realloc(storage->alloc, storage->data, size, VN_DEFAULT_ALIGN,
582 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
583 if (!data)
584 return NULL;
585
586 storage->size = size;
587 storage->data = data;
588 }
589 return storage->data;
590 }
591
592 static inline void
vn_cached_storage_fini(struct vn_cached_storage * storage)593 vn_cached_storage_fini(struct vn_cached_storage *storage)
594 {
595 vk_free(storage->alloc, storage->data);
596 }
597
598 #endif /* VN_COMMON_H */
599