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 <vulkan/vulkan.h>
24
25#include "c11/threads.h"
26#include "util/bitscan.h"
27#include "util/compiler.h"
28#include "util/list.h"
29#include "util/macros.h"
30#include "util/os_time.h"
31#include "util/u_math.h"
32#include "util/xmlconfig.h"
33#include "vk_alloc.h"
34#include "vk_debug_report.h"
35#include "vk_device.h"
36#include "vk_instance.h"
37#include "vk_object.h"
38#include "vk_physical_device.h"
39#include "vk_util.h"
40
41#include "vn_entrypoints.h"
42
43#define VN_DEFAULT_ALIGN 8
44
45#define VN_DEBUG(category) (unlikely(vn_debug & VN_DEBUG_##category))
46
47#define vn_error(instance, error)                                            \
48   (VN_DEBUG(RESULT) ? vn_log_result((instance), (error), __func__) : (error))
49#define vn_result(instance, result)                                          \
50   ((result) >= VK_SUCCESS ? (result) : vn_error((instance), (result)))
51
52#ifdef ANDROID
53
54#include <cutils/trace.h>
55
56#define VN_TRACE_BEGIN(name) atrace_begin(ATRACE_TAG_GRAPHICS, name)
57#define VN_TRACE_END() atrace_end(ATRACE_TAG_GRAPHICS)
58
59#else
60
61/* XXX we would like to use perfetto, but it lacks a C header */
62#define VN_TRACE_BEGIN(name)
63#define VN_TRACE_END()
64
65#endif /* ANDROID */
66
67#if __has_attribute(cleanup) && __has_attribute(unused)
68
69#define VN_TRACE_SCOPE(name)                                                 \
70   int _vn_trace_scope_##__LINE__                                            \
71      __attribute__((cleanup(vn_trace_scope_end), unused)) =                 \
72         vn_trace_scope_begin(name)
73
74static inline int
75vn_trace_scope_begin(const char *name)
76{
77   VN_TRACE_BEGIN(name);
78   return 0;
79}
80
81static inline void
82vn_trace_scope_end(int *scope)
83{
84   VN_TRACE_END();
85}
86
87#else
88
89#define VN_TRACE_SCOPE(name)
90
91#endif /* __has_attribute(cleanup) && __has_attribute(unused) */
92
93#define VN_TRACE_FUNC() VN_TRACE_SCOPE(__func__)
94
95struct vn_instance;
96struct vn_physical_device;
97struct vn_device;
98struct vn_queue;
99struct vn_fence;
100struct vn_semaphore;
101struct vn_device_memory;
102struct vn_buffer;
103struct vn_buffer_view;
104struct vn_image;
105struct vn_image_view;
106struct vn_sampler;
107struct vn_sampler_ycbcr_conversion;
108struct vn_descriptor_set_layout;
109struct vn_descriptor_pool;
110struct vn_descriptor_set;
111struct vn_descriptor_update_template;
112struct vn_render_pass;
113struct vn_framebuffer;
114struct vn_event;
115struct vn_query_pool;
116struct vn_shader_module;
117struct vn_pipeline_layout;
118struct vn_pipeline_cache;
119struct vn_pipeline;
120struct vn_command_pool;
121struct vn_command_buffer;
122
123struct vn_cs_encoder;
124struct vn_cs_decoder;
125
126struct vn_renderer;
127struct vn_renderer_shmem;
128struct vn_renderer_bo;
129struct vn_renderer_sync;
130
131enum vn_debug {
132   VN_DEBUG_INIT = 1ull << 0,
133   VN_DEBUG_RESULT = 1ull << 1,
134   VN_DEBUG_VTEST = 1ull << 2,
135   VN_DEBUG_WSI = 1ull << 3,
136};
137
138typedef uint64_t vn_object_id;
139
140/* base class of vn_instance */
141struct vn_instance_base {
142   struct vk_instance base;
143   vn_object_id id;
144};
145
146/* base class of vn_physical_device */
147struct vn_physical_device_base {
148   struct vk_physical_device base;
149   vn_object_id id;
150};
151
152/* base class of vn_device */
153struct vn_device_base {
154   struct vk_device base;
155   vn_object_id id;
156};
157
158/* base class of other driver objects */
159struct vn_object_base {
160   struct vk_object_base base;
161   vn_object_id id;
162};
163
164struct vn_refcount {
165   atomic_int count;
166};
167
168extern uint64_t vn_debug;
169
170void
171vn_debug_init(void);
172
173void
174vn_trace_init(void);
175
176void
177vn_log(struct vn_instance *instance, const char *format, ...)
178   PRINTFLIKE(2, 3);
179
180VkResult
181vn_log_result(struct vn_instance *instance,
182              VkResult result,
183              const char *where);
184
185#define VN_REFCOUNT_INIT(val)                                                \
186   (struct vn_refcount) { .count = (val) }
187
188static inline int
189vn_refcount_load_relaxed(const struct vn_refcount *ref)
190{
191   return atomic_load_explicit(&ref->count, memory_order_relaxed);
192}
193
194static inline int
195vn_refcount_fetch_add_relaxed(struct vn_refcount *ref, int val)
196{
197   return atomic_fetch_add_explicit(&ref->count, val, memory_order_relaxed);
198}
199
200static inline int
201vn_refcount_fetch_sub_release(struct vn_refcount *ref, int val)
202{
203   return atomic_fetch_sub_explicit(&ref->count, val, memory_order_release);
204}
205
206static inline bool
207vn_refcount_is_valid(const struct vn_refcount *ref)
208{
209   return vn_refcount_load_relaxed(ref) > 0;
210}
211
212static inline void
213vn_refcount_inc(struct vn_refcount *ref)
214{
215   /* no ordering imposed */
216   ASSERTED const int old = vn_refcount_fetch_add_relaxed(ref, 1);
217   assert(old >= 1);
218}
219
220static inline bool
221vn_refcount_dec(struct vn_refcount *ref)
222{
223   /* prior reads/writes cannot be reordered after this */
224   const int old = vn_refcount_fetch_sub_release(ref, 1);
225   assert(old >= 1);
226
227   /* subsequent free cannot be reordered before this */
228   if (old == 1)
229      atomic_thread_fence(memory_order_acquire);
230
231   return old == 1;
232}
233
234void
235vn_relax(uint32_t *iter, const char *reason);
236
237static_assert(sizeof(vn_object_id) >= sizeof(uintptr_t), "");
238
239static inline VkResult
240vn_instance_base_init(
241   struct vn_instance_base *instance,
242   const struct vk_instance_extension_table *supported_extensions,
243   const struct vk_instance_dispatch_table *dispatch_table,
244   const VkInstanceCreateInfo *info,
245   const VkAllocationCallbacks *alloc)
246{
247   VkResult result = vk_instance_init(&instance->base, supported_extensions,
248                                      dispatch_table, info, alloc);
249   instance->id = (uintptr_t)instance;
250   return result;
251}
252
253static inline void
254vn_instance_base_fini(struct vn_instance_base *instance)
255{
256   vk_instance_finish(&instance->base);
257}
258
259static inline VkResult
260vn_physical_device_base_init(
261   struct vn_physical_device_base *physical_dev,
262   struct vn_instance_base *instance,
263   const struct vk_device_extension_table *supported_extensions,
264   const struct vk_physical_device_dispatch_table *dispatch_table)
265{
266   VkResult result =
267      vk_physical_device_init(&physical_dev->base, &instance->base,
268                              supported_extensions, dispatch_table);
269   physical_dev->id = (uintptr_t)physical_dev;
270   return result;
271}
272
273static inline void
274vn_physical_device_base_fini(struct vn_physical_device_base *physical_dev)
275{
276   vk_physical_device_finish(&physical_dev->base);
277}
278
279static inline VkResult
280vn_device_base_init(struct vn_device_base *dev,
281                    struct vn_physical_device_base *physical_dev,
282                    const struct vk_device_dispatch_table *dispatch_table,
283                    const VkDeviceCreateInfo *info,
284                    const VkAllocationCallbacks *alloc)
285{
286   VkResult result = vk_device_init(&dev->base, &physical_dev->base,
287                                    dispatch_table, info, alloc);
288   dev->id = (uintptr_t)dev;
289   return result;
290}
291
292static inline void
293vn_device_base_fini(struct vn_device_base *dev)
294{
295   vk_device_finish(&dev->base);
296}
297
298static inline void
299vn_object_base_init(struct vn_object_base *obj,
300                    VkObjectType type,
301                    struct vn_device_base *dev)
302{
303   vk_object_base_init(&dev->base, &obj->base, type);
304   obj->id = (uintptr_t)obj;
305}
306
307static inline void
308vn_object_base_fini(struct vn_object_base *obj)
309{
310   vk_object_base_finish(&obj->base);
311}
312
313static inline void
314vn_object_set_id(void *obj, vn_object_id id, VkObjectType type)
315{
316   assert(((const struct vk_object_base *)obj)->type == type);
317   switch (type) {
318   case VK_OBJECT_TYPE_INSTANCE:
319      ((struct vn_instance_base *)obj)->id = id;
320      break;
321   case VK_OBJECT_TYPE_PHYSICAL_DEVICE:
322      ((struct vn_physical_device_base *)obj)->id = id;
323      break;
324   case VK_OBJECT_TYPE_DEVICE:
325      ((struct vn_device_base *)obj)->id = id;
326      break;
327   default:
328      ((struct vn_object_base *)obj)->id = id;
329      break;
330   }
331}
332
333static inline vn_object_id
334vn_object_get_id(const void *obj, VkObjectType type)
335{
336   assert(((const struct vk_object_base *)obj)->type == type);
337   switch (type) {
338   case VK_OBJECT_TYPE_INSTANCE:
339      return ((struct vn_instance_base *)obj)->id;
340   case VK_OBJECT_TYPE_PHYSICAL_DEVICE:
341      return ((struct vn_physical_device_base *)obj)->id;
342   case VK_OBJECT_TYPE_DEVICE:
343      return ((struct vn_device_base *)obj)->id;
344   default:
345      return ((struct vn_object_base *)obj)->id;
346   }
347}
348
349#endif /* VN_COMMON_H */
350