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 VkFormat
155 zink_get_format(struct zink_screen *screen, enum pipe_format format);
156
157 void
158 zink_convert_color(const struct zink_screen *screen, enum pipe_format format,
159 union pipe_color_union *dst,
160 const union pipe_color_union *src);
161
162 bool
163 zink_screen_timeline_wait(struct zink_screen *screen, uint64_t batch_id, uint64_t timeout);
164
165 bool
166 zink_is_depth_format_supported(struct zink_screen *screen, VkFormat format);
167
168 #define GET_PROC_ADDR_INSTANCE_LOCAL(screen, instance, x) PFN_vk##x vk_##x = (PFN_vk##x)(screen)->vk_GetInstanceProcAddr(instance, "vk"#x)
169
170 void
171 zink_screen_update_pipeline_cache(struct zink_screen *screen, struct zink_program *pg, bool in_thread);
172
173 void
174 zink_screen_get_pipeline_cache(struct zink_screen *screen, struct zink_program *pg, bool in_thread);
175
176 void VKAPI_PTR
177 zink_stub_function_not_loaded(void);
178
179 bool
180 zink_screen_debug_marker_begin(struct zink_screen *screen, const char *fmt, ...);
181 void
182 zink_screen_debug_marker_end(struct zink_screen *screen, bool emitted);
183
184 #define warn_missing_feature(warned, feat) \
185 do { \
186 if (!warned) { \
187 if (!(zink_debug & ZINK_DEBUG_QUIET)) \
188 mesa_logw("WARNING: Incorrect rendering will happen " \
189 "because the Vulkan device doesn't support " \
190 "the '%s' feature\n", feat); \
191 warned = true; \
192 } \
193 } while (0)
194
195 #ifdef __cplusplus
196 }
197 #endif
198
199 #endif
200