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