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