1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright 2019 Google LLC
3bf215546Sopenharmony_ci * SPDX-License-Identifier: MIT
4bf215546Sopenharmony_ci *
5bf215546Sopenharmony_ci * based in part on anv and radv which are:
6bf215546Sopenharmony_ci * Copyright © 2015 Intel Corporation
7bf215546Sopenharmony_ci * Copyright © 2016 Red Hat.
8bf215546Sopenharmony_ci * Copyright © 2016 Bas Nieuwenhuizen
9bf215546Sopenharmony_ci */
10bf215546Sopenharmony_ci
11bf215546Sopenharmony_ci#include "vn_common.h"
12bf215546Sopenharmony_ci
13bf215546Sopenharmony_ci#include <stdarg.h>
14bf215546Sopenharmony_ci
15bf215546Sopenharmony_ci#include "util/debug.h"
16bf215546Sopenharmony_ci#include "util/log.h"
17bf215546Sopenharmony_ci#include "util/os_misc.h"
18bf215546Sopenharmony_ci#include "util/u_debug.h"
19bf215546Sopenharmony_ci#include "venus-protocol/vn_protocol_driver_info.h"
20bf215546Sopenharmony_ci#include "vk_enum_to_str.h"
21bf215546Sopenharmony_ci
22bf215546Sopenharmony_ci#define VN_RELAX_MIN_BASE_SLEEP_US (10)
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_cistatic const struct debug_control vn_debug_options[] = {
25bf215546Sopenharmony_ci   { "init", VN_DEBUG_INIT },
26bf215546Sopenharmony_ci   { "result", VN_DEBUG_RESULT },
27bf215546Sopenharmony_ci   { "vtest", VN_DEBUG_VTEST },
28bf215546Sopenharmony_ci   { "wsi", VN_DEBUG_WSI },
29bf215546Sopenharmony_ci   { "no_abort", VN_DEBUG_NO_ABORT },
30bf215546Sopenharmony_ci   { NULL, 0 },
31bf215546Sopenharmony_ci};
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_cistatic const struct debug_control vn_perf_options[] = {
34bf215546Sopenharmony_ci   { "no_async_set_alloc", VN_PERF_NO_ASYNC_SET_ALLOC },
35bf215546Sopenharmony_ci   { "no_async_buffer_create", VN_PERF_NO_ASYNC_BUFFER_CREATE },
36bf215546Sopenharmony_ci   { "no_async_queue_submit", VN_PERF_NO_ASYNC_QUEUE_SUBMIT },
37bf215546Sopenharmony_ci   { "no_event_feedback", VN_PERF_NO_EVENT_FEEDBACK },
38bf215546Sopenharmony_ci   { "no_fence_feedback", VN_PERF_NO_FENCE_FEEDBACK },
39bf215546Sopenharmony_ci   { NULL, 0 },
40bf215546Sopenharmony_ci};
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_cistruct vn_env vn_env;
43bf215546Sopenharmony_ci
44bf215546Sopenharmony_cistatic void
45bf215546Sopenharmony_civn_env_init_once(void)
46bf215546Sopenharmony_ci{
47bf215546Sopenharmony_ci   vn_env.debug =
48bf215546Sopenharmony_ci      parse_debug_string(os_get_option("VN_DEBUG"), vn_debug_options);
49bf215546Sopenharmony_ci   vn_env.perf =
50bf215546Sopenharmony_ci      parse_debug_string(os_get_option("VN_PERF"), vn_perf_options);
51bf215546Sopenharmony_ci   vn_env.draw_cmd_batch_limit =
52bf215546Sopenharmony_ci      debug_get_num_option("VN_DRAW_CMD_BATCH_LIMIT", UINT32_MAX);
53bf215546Sopenharmony_ci   if (!vn_env.draw_cmd_batch_limit)
54bf215546Sopenharmony_ci      vn_env.draw_cmd_batch_limit = UINT32_MAX;
55bf215546Sopenharmony_ci   vn_env.relax_base_sleep_us = debug_get_num_option(
56bf215546Sopenharmony_ci      "VN_RELAX_BASE_SLEEP_US", VN_RELAX_MIN_BASE_SLEEP_US);
57bf215546Sopenharmony_ci   vn_env.relax_base_sleep_us =
58bf215546Sopenharmony_ci      MAX2(vn_env.relax_base_sleep_us, VN_RELAX_MIN_BASE_SLEEP_US);
59bf215546Sopenharmony_ci}
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_civoid
62bf215546Sopenharmony_civn_env_init(void)
63bf215546Sopenharmony_ci{
64bf215546Sopenharmony_ci   static once_flag once = ONCE_FLAG_INIT;
65bf215546Sopenharmony_ci   call_once(&once, vn_env_init_once);
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_ci   /* log per VkInstance creation */
68bf215546Sopenharmony_ci   if (VN_DEBUG(INIT)) {
69bf215546Sopenharmony_ci      vn_log(NULL,
70bf215546Sopenharmony_ci             "vn_env is as below:"
71bf215546Sopenharmony_ci             "\n\tdebug = 0x%" PRIx64 ""
72bf215546Sopenharmony_ci             "\n\tperf = 0x%" PRIx64 ""
73bf215546Sopenharmony_ci             "\n\tdraw_cmd_batch_limit = %u"
74bf215546Sopenharmony_ci             "\n\trelax_base_sleep_us = %u",
75bf215546Sopenharmony_ci             vn_env.debug, vn_env.perf, vn_env.draw_cmd_batch_limit,
76bf215546Sopenharmony_ci             vn_env.relax_base_sleep_us);
77bf215546Sopenharmony_ci   }
78bf215546Sopenharmony_ci}
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_civoid
81bf215546Sopenharmony_civn_trace_init(void)
82bf215546Sopenharmony_ci{
83bf215546Sopenharmony_ci#ifdef ANDROID
84bf215546Sopenharmony_ci   atrace_init();
85bf215546Sopenharmony_ci#endif
86bf215546Sopenharmony_ci}
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_civoid
89bf215546Sopenharmony_civn_log(struct vn_instance *instance, const char *format, ...)
90bf215546Sopenharmony_ci{
91bf215546Sopenharmony_ci   va_list ap;
92bf215546Sopenharmony_ci
93bf215546Sopenharmony_ci   va_start(ap, format);
94bf215546Sopenharmony_ci   mesa_log_v(MESA_LOG_DEBUG, "MESA-VIRTIO", format, ap);
95bf215546Sopenharmony_ci   va_end(ap);
96bf215546Sopenharmony_ci
97bf215546Sopenharmony_ci   /* instance may be NULL or partially initialized */
98bf215546Sopenharmony_ci}
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ciVkResult
101bf215546Sopenharmony_civn_log_result(struct vn_instance *instance,
102bf215546Sopenharmony_ci              VkResult result,
103bf215546Sopenharmony_ci              const char *where)
104bf215546Sopenharmony_ci{
105bf215546Sopenharmony_ci   vn_log(instance, "%s: %s", where, vk_Result_to_str(result));
106bf215546Sopenharmony_ci   return result;
107bf215546Sopenharmony_ci}
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_ciuint32_t
110bf215546Sopenharmony_civn_extension_get_spec_version(const char *name)
111bf215546Sopenharmony_ci{
112bf215546Sopenharmony_ci   const int32_t index = vn_info_extension_index(name);
113bf215546Sopenharmony_ci   return index >= 0 ? vn_info_extension_get(index)->spec_version : 0;
114bf215546Sopenharmony_ci}
115bf215546Sopenharmony_ci
116bf215546Sopenharmony_civoid
117bf215546Sopenharmony_civn_relax(uint32_t *iter, const char *reason)
118bf215546Sopenharmony_ci{
119bf215546Sopenharmony_ci   /* Yield for the first 2^busy_wait_order times and then sleep for
120bf215546Sopenharmony_ci    * base_sleep_us microseconds for the same number of times.  After that,
121bf215546Sopenharmony_ci    * keep doubling both sleep length and count.
122bf215546Sopenharmony_ci    */
123bf215546Sopenharmony_ci   const uint32_t busy_wait_order = 4;
124bf215546Sopenharmony_ci   const uint32_t base_sleep_us = vn_env.relax_base_sleep_us;
125bf215546Sopenharmony_ci   const uint32_t warn_order = 12;
126bf215546Sopenharmony_ci   const uint32_t abort_order = 14;
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci   (*iter)++;
129bf215546Sopenharmony_ci   if (*iter < (1 << busy_wait_order)) {
130bf215546Sopenharmony_ci      thrd_yield();
131bf215546Sopenharmony_ci      return;
132bf215546Sopenharmony_ci   }
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_ci   /* warn occasionally if we have slept at least 1.28ms for 2048 times (plus
135bf215546Sopenharmony_ci    * another 2047 shorter sleeps)
136bf215546Sopenharmony_ci    */
137bf215546Sopenharmony_ci   if (unlikely(*iter % (1 << warn_order) == 0)) {
138bf215546Sopenharmony_ci      vn_log(NULL, "stuck in %s wait with iter at %d", reason, *iter);
139bf215546Sopenharmony_ci
140bf215546Sopenharmony_ci      if (*iter >= (1 << abort_order) && !VN_DEBUG(NO_ABORT)) {
141bf215546Sopenharmony_ci         vn_log(NULL, "aborting");
142bf215546Sopenharmony_ci         abort();
143bf215546Sopenharmony_ci      }
144bf215546Sopenharmony_ci   }
145bf215546Sopenharmony_ci
146bf215546Sopenharmony_ci   const uint32_t shift = util_last_bit(*iter) - busy_wait_order - 1;
147bf215546Sopenharmony_ci   os_time_sleep(base_sleep_us << shift);
148bf215546Sopenharmony_ci}
149