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 static inline VkDriverId
zink_driverid(const struct zink_screen * screen)134 zink_driverid(const struct zink_screen *screen)
135 {
136 if (!screen->info.have_KHR_maintenance7 || screen->info.layered_props.layeredAPI != VK_PHYSICAL_DEVICE_LAYERED_API_VULKAN_KHR)
137 return screen->info.driver_props.driverID;
138 /* if maint7 is supported, codegen ensures this will always be the "right" value */
139 return screen->info.vk_layered_driver_props.driverID;
140 }
141
142 void
143 zink_screen_lock_context(struct zink_screen *screen);
144 void
145 zink_screen_unlock_context(struct zink_screen *screen);
146
147 VkSemaphore
148 zink_create_exportable_semaphore(struct zink_screen *screen);
149 VkSemaphore
150 zink_screen_export_dmabuf_semaphore(struct zink_screen *screen, struct zink_resource *res);
151 bool
152 zink_screen_import_dmabuf_semaphore(struct zink_screen *screen, struct zink_resource *res, VkSemaphore sem);
153
154 void
155 zink_init_format_props(struct zink_screen *screen, enum pipe_format pformat);
156
157 static inline const struct zink_modifier_props *
zink_get_modifier_props(struct zink_screen * screen,enum pipe_format pformat)158 zink_get_modifier_props(struct zink_screen *screen, enum pipe_format pformat)
159 {
160 if (unlikely(!screen->format_props_init[pformat]))
161 zink_init_format_props(screen, pformat);
162 return &screen->modifier_props[pformat];
163 }
164
165 static inline const struct zink_format_props *
zink_get_format_props(struct zink_screen * screen,enum pipe_format pformat)166 zink_get_format_props(struct zink_screen *screen, enum pipe_format pformat)
167 {
168 if (unlikely(!screen->format_props_init[pformat]))
169 zink_init_format_props(screen, pformat);
170 return &screen->format_props[pformat];
171 }
172
173 VkFormat
174 zink_get_format(struct zink_screen *screen, enum pipe_format format);
175
176 void
177 zink_convert_color(const struct zink_screen *screen, enum pipe_format format,
178 union pipe_color_union *dst,
179 const union pipe_color_union *src);
180
181 bool
182 zink_screen_timeline_wait(struct zink_screen *screen, uint64_t batch_id, uint64_t timeout);
183
184 bool
185 zink_is_depth_format_supported(struct zink_screen *screen, VkFormat format);
186
187 #define GET_PROC_ADDR_INSTANCE_LOCAL(screen, instance, x) PFN_vk##x vk_##x = (PFN_vk##x)(screen)->vk_GetInstanceProcAddr(instance, "vk"#x)
188
189 void
190 zink_screen_update_pipeline_cache(struct zink_screen *screen, struct zink_program *pg, bool in_thread);
191
192 void
193 zink_screen_get_pipeline_cache(struct zink_screen *screen, struct zink_program *pg, bool in_thread);
194
195 void VKAPI_PTR
196 zink_stub_function_not_loaded(void);
197
198 bool
199 zink_screen_debug_marker_begin(struct zink_screen *screen, const char *fmt, ...);
200 void
201 zink_screen_debug_marker_end(struct zink_screen *screen, bool emitted);
202
203 #define warn_missing_feature(warned, feat) \
204 do { \
205 if (!warned) { \
206 if (!(zink_debug & ZINK_DEBUG_QUIET)) \
207 mesa_logw("WARNING: Incorrect rendering will happen " \
208 "because the Vulkan device doesn't support " \
209 "the '%s' feature\n", feat); \
210 warned = true; \
211 } \
212 } while (0)
213
214 #ifdef __cplusplus
215 }
216 #endif
217
218 #endif
219