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