1 /*
2 * Copyright 2018 Collabora Ltd.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24 #ifndef ZINK_SCREEN_H
25 #define ZINK_SCREEN_H
26
27 #include "zink_types.h"
28
29
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33
34 struct util_dl_library;
35
36 void
37 zink_init_screen_pipeline_libs(struct zink_screen *screen);
38
39
40 /* update last_finished to account for batch_id wrapping */
41 static inline void
zink_screen_update_last_finished(struct zink_screen * screen,uint64_t batch_id)42 zink_screen_update_last_finished(struct zink_screen *screen, uint64_t batch_id)
43 {
44 const uint32_t check_id = (uint32_t)batch_id;
45 /* last_finished may have wrapped */
46 if (screen->last_finished < UINT_MAX / 2) {
47 /* last_finished has wrapped, batch_id has not */
48 if (check_id > UINT_MAX / 2)
49 return;
50 } else if (check_id < UINT_MAX / 2) {
51 /* batch_id has wrapped, last_finished has not */
52 screen->last_finished = check_id;
53 return;
54 }
55 /* neither have wrapped */
56 screen->last_finished = MAX2(check_id, screen->last_finished);
57 }
58
59 /* check a batch_id against last_finished while accounting for wrapping */
60 static inline bool
zink_screen_check_last_finished(struct zink_screen * screen,uint32_t batch_id)61 zink_screen_check_last_finished(struct zink_screen *screen, uint32_t batch_id)
62 {
63 const uint32_t check_id = (uint32_t)batch_id;
64 assert(check_id);
65 /* last_finished may have wrapped */
66 if (screen->last_finished < UINT_MAX / 2) {
67 /* last_finished has wrapped, batch_id has not */
68 if (check_id > UINT_MAX / 2)
69 return true;
70 } else if (check_id < UINT_MAX / 2) {
71 /* batch_id has wrapped, last_finished has not */
72 return false;
73 }
74 return screen->last_finished >= check_id;
75 }
76
77 bool
78 zink_screen_init_semaphore(struct zink_screen *screen);
79
80 static inline bool
zink_screen_handle_vkresult(struct zink_screen * screen,VkResult ret)81 zink_screen_handle_vkresult(struct zink_screen *screen, VkResult ret)
82 {
83 bool success = false;
84 switch (ret) {
85 case VK_SUCCESS:
86 success = true;
87 break;
88 case VK_ERROR_DEVICE_LOST:
89 screen->device_lost = true;
90 mesa_loge("zink: DEVICE LOST!\n");
91 /* if nothing can save us, abort */
92 if (screen->abort_on_hang && !screen->robust_ctx_count)
93 abort();
94 FALLTHROUGH;
95 default:
96 success = false;
97 break;
98 }
99 return success;
100 }
101
102 typedef const char *(*zink_vkflags_func)(uint64_t);
103
104 static inline unsigned
zink_string_vkflags_unroll(char * buf,size_t bufsize,uint64_t flags,zink_vkflags_func func)105 zink_string_vkflags_unroll(char *buf, size_t bufsize, uint64_t flags, zink_vkflags_func func)
106 {
107 bool first = true;
108 unsigned idx = 0;
109 u_foreach_bit64(bit, flags) {
110 if (!first)
111 buf[idx++] = '|';
112 idx += snprintf(&buf[idx], bufsize - idx, "%s", func((BITFIELD64_BIT(bit))));
113 first = false;
114 }
115 return idx;
116 }
117
118 #define VRAM_ALLOC_LOOP(RET, DOIT, ...) \
119 do { \
120 unsigned _us[] = {0, 1000, 10000, 500000, 1000000}; \
121 for (unsigned _i = 0; _i < ARRAY_SIZE(_us); _i++) { \
122 RET = DOIT; \
123 if (RET == VK_SUCCESS || RET != VK_ERROR_OUT_OF_DEVICE_MEMORY) \
124 break; \
125 os_time_sleep(_us[_i]); \
126 } \
127 __VA_ARGS__ \
128 } while (0)
129
130 VkSemaphore
131 zink_create_semaphore(struct zink_screen *screen);
132
133 void
134 zink_screen_lock_context(struct zink_screen *screen);
135 void
136 zink_screen_unlock_context(struct zink_screen *screen);
137
138 VkSemaphore
139 zink_create_exportable_semaphore(struct zink_screen *screen);
140 VkSemaphore
141 zink_screen_export_dmabuf_semaphore(struct zink_screen *screen, struct zink_resource *res);
142 bool
143 zink_screen_import_dmabuf_semaphore(struct zink_screen *screen, struct zink_resource *res, VkSemaphore sem);
144
145 VkFormat
146 zink_get_format(struct zink_screen *screen, enum pipe_format format);
147
148 void
149 zink_convert_color(const struct zink_screen *screen, enum pipe_format format,
150 union pipe_color_union *dst,
151 const union pipe_color_union *src);
152
153 bool
154 zink_screen_timeline_wait(struct zink_screen *screen, uint64_t batch_id, uint64_t timeout);
155
156 bool
157 zink_is_depth_format_supported(struct zink_screen *screen, VkFormat format);
158
159 #define GET_PROC_ADDR_INSTANCE_LOCAL(screen, instance, x) PFN_vk##x vk_##x = (PFN_vk##x)(screen)->vk_GetInstanceProcAddr(instance, "vk"#x)
160
161 void
162 zink_screen_update_pipeline_cache(struct zink_screen *screen, struct zink_program *pg, bool in_thread);
163
164 void
165 zink_screen_get_pipeline_cache(struct zink_screen *screen, struct zink_program *pg, bool in_thread);
166
167 void
168 zink_stub_function_not_loaded(void);
169
170 bool
171 zink_screen_debug_marker_begin(struct zink_screen *screen, const char *fmt, ...);
172 void
173 zink_screen_debug_marker_end(struct zink_screen *screen, bool emitted);
174
175 #define warn_missing_feature(warned, feat) \
176 do { \
177 if (!warned) { \
178 if (!(zink_debug & ZINK_DEBUG_QUIET)) \
179 mesa_logw("WARNING: Incorrect rendering will happen " \
180 "because the Vulkan device doesn't support " \
181 "the '%s' feature\n", feat); \
182 warned = true; \
183 } \
184 } while (0)
185
186 #ifdef __cplusplus
187 }
188 #endif
189
190 #endif
191