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 #include "zink_screen.h"
25
26 #include "zink_kopper.h"
27 #include "zink_compiler.h"
28 #include "zink_context.h"
29 #include "zink_descriptors.h"
30 #include "zink_fence.h"
31 #include "vk_format.h"
32 #include "zink_format.h"
33 #include "zink_framebuffer.h"
34 #include "zink_program.h"
35 #include "zink_public.h"
36 #include "zink_query.h"
37 #include "zink_resource.h"
38 #include "zink_state.h"
39 #include "nir_to_spirv/nir_to_spirv.h" // for SPIRV_VERSION
40
41 #include "util/u_debug.h"
42 #include "util/u_dl.h"
43 #include "util/os_file.h"
44 #include "util/u_memory.h"
45 #include "util/u_screen.h"
46 #include "util/u_string.h"
47 #include "util/perf/u_trace.h"
48 #include "util/u_transfer_helper.h"
49 #include "util/hex.h"
50 #include "util/xmlconfig.h"
51
52 #include "util/u_cpu_detect.h"
53
54 #ifdef HAVE_LIBDRM
55 #include <xf86drm.h>
56 #include <fcntl.h>
57 #include <sys/stat.h>
58 #ifdef MAJOR_IN_MKDEV
59 #include <sys/mkdev.h>
60 #endif
61 #ifdef MAJOR_IN_SYSMACROS
62 #include <sys/sysmacros.h>
63 #endif
64 #endif
65
66 static int num_screens = 0;
67 bool zink_tracing = false;
68
69 #if DETECT_OS_WINDOWS
70 #include <io.h>
71 #define VK_LIBNAME "vulkan-1.dll"
72 #else
73 #include <unistd.h>
74 #if DETECT_OS_APPLE
75 #define VK_LIBNAME "libvulkan.1.dylib"
76 #elif DETECT_OS_ANDROID
77 #define VK_LIBNAME "libvulkan.so"
78 #else
79 #define VK_LIBNAME "libvulkan.so.1"
80 #endif
81 #endif
82
83 #ifdef __APPLE__
84 #include "MoltenVK/mvk_vulkan.h"
85 // Source of MVK_VERSION
86 #include "MoltenVK/mvk_config.h"
87 #define VK_NO_PROTOTYPES
88 #include "MoltenVK/mvk_deprecated_api.h"
89 #include "MoltenVK/mvk_private_api.h"
90 #endif /* __APPLE__ */
91
92 #ifdef HAVE_LIBDRM
93 #include "drm-uapi/dma-buf.h"
94 #include <xf86drm.h>
95 #endif
96
97 static const struct debug_named_value
98 zink_debug_options[] = {
99 { "nir", ZINK_DEBUG_NIR, "Dump NIR during program compile" },
100 { "spirv", ZINK_DEBUG_SPIRV, "Dump SPIR-V during program compile" },
101 { "tgsi", ZINK_DEBUG_TGSI, "Dump TGSI during program compile" },
102 { "validation", ZINK_DEBUG_VALIDATION, "Dump Validation layer output" },
103 { "vvl", ZINK_DEBUG_VALIDATION, "Dump Validation layer output" },
104 { "sync", ZINK_DEBUG_SYNC, "Force synchronization before draws/dispatches" },
105 { "compact", ZINK_DEBUG_COMPACT, "Use only 4 descriptor sets" },
106 { "noreorder", ZINK_DEBUG_NOREORDER, "Do not reorder command streams" },
107 { "gpl", ZINK_DEBUG_GPL, "Force using Graphics Pipeline Library for all shaders" },
108 { "shaderdb", ZINK_DEBUG_SHADERDB, "Do stuff to make shader-db work" },
109 { "rp", ZINK_DEBUG_RP, "Enable renderpass tracking/optimizations" },
110 { "norp", ZINK_DEBUG_NORP, "Disable renderpass tracking/optimizations" },
111 { "map", ZINK_DEBUG_MAP, "Track amount of mapped VRAM" },
112 { "flushsync", ZINK_DEBUG_FLUSHSYNC, "Force synchronous flushes/presents" },
113 { "noshobj", ZINK_DEBUG_NOSHOBJ, "Disable EXT_shader_object" },
114 { "optimal_keys", ZINK_DEBUG_OPTIMAL_KEYS, "Debug/use optimal_keys" },
115 { "noopt", ZINK_DEBUG_NOOPT, "Disable async optimized pipeline compiles" },
116 { "nobgc", ZINK_DEBUG_NOBGC, "Disable all async pipeline compiles" },
117 { "mem", ZINK_DEBUG_MEM, "Debug memory allocations" },
118 { "quiet", ZINK_DEBUG_QUIET, "Suppress warnings" },
119 { "ioopt", ZINK_DEBUG_IOOPT, "Optimize IO" },
120 { "nopc", ZINK_DEBUG_NOPC, "No precompilation" },
121 DEBUG_NAMED_VALUE_END
122 };
123
124 DEBUG_GET_ONCE_FLAGS_OPTION(zink_debug, "ZINK_DEBUG", zink_debug_options, 0)
125
126 uint32_t
127 zink_debug;
128
129
130 static const struct debug_named_value
131 zink_descriptor_options[] = {
132 { "auto", ZINK_DESCRIPTOR_MODE_AUTO, "Automatically detect best mode" },
133 { "lazy", ZINK_DESCRIPTOR_MODE_LAZY, "Don't cache, do least amount of updates" },
134 { "db", ZINK_DESCRIPTOR_MODE_DB, "Use descriptor buffers" },
135 DEBUG_NAMED_VALUE_END
136 };
137
138 DEBUG_GET_ONCE_FLAGS_OPTION(zink_descriptor_mode, "ZINK_DESCRIPTORS", zink_descriptor_options, ZINK_DESCRIPTOR_MODE_AUTO)
139
140 enum zink_descriptor_mode zink_descriptor_mode;
141
142 static const char *
zink_get_vendor(struct pipe_screen * pscreen)143 zink_get_vendor(struct pipe_screen *pscreen)
144 {
145 return "Mesa";
146 }
147
148 static const char *
zink_get_device_vendor(struct pipe_screen * pscreen)149 zink_get_device_vendor(struct pipe_screen *pscreen)
150 {
151 return zink_screen(pscreen)->vendor_name;
152 }
153
154 static const char *
zink_get_name(struct pipe_screen * pscreen)155 zink_get_name(struct pipe_screen *pscreen)
156 {
157 return zink_screen(pscreen)->device_name;
158 }
159
160 static int
zink_set_driver_strings(struct zink_screen * screen)161 zink_set_driver_strings(struct zink_screen *screen)
162 {
163 char buf[1000];
164 const char *driver_name = vk_DriverId_to_str(zink_driverid(screen)) + strlen("VK_DRIVER_ID_");
165 int written = snprintf(buf, sizeof(buf), "zink Vulkan %d.%d(%s (%s))",
166 VK_VERSION_MAJOR(screen->info.device_version),
167 VK_VERSION_MINOR(screen->info.device_version),
168 screen->info.props.deviceName,
169 strstr(vk_DriverId_to_str(zink_driverid(screen)), "VK_DRIVER_ID_") ? driver_name : "Driver Unknown"
170 );
171 if (written < 0)
172 return written;
173 assert(written < sizeof(buf));
174 screen->device_name = ralloc_strdup(screen, buf);
175
176 written = snprintf(buf, sizeof(buf), "Unknown (vendor-id: 0x%04x)", screen->info.props.vendorID);
177 if (written < 0)
178 return written;
179 assert(written < sizeof(buf));
180 screen->vendor_name = ralloc_strdup(screen, buf);
181 return 0;
182 }
183
184 static void
zink_get_driver_uuid(struct pipe_screen * pscreen,char * uuid)185 zink_get_driver_uuid(struct pipe_screen *pscreen, char *uuid)
186 {
187 struct zink_screen *screen = zink_screen(pscreen);
188 if (screen->vk_version >= VK_MAKE_VERSION(1,2,0)) {
189 memcpy(uuid, screen->info.props11.driverUUID, VK_UUID_SIZE);
190 } else {
191 memcpy(uuid, screen->info.deviceid_props.driverUUID, VK_UUID_SIZE);
192 }
193 }
194
195 static void
zink_get_device_uuid(struct pipe_screen * pscreen,char * uuid)196 zink_get_device_uuid(struct pipe_screen *pscreen, char *uuid)
197 {
198 struct zink_screen *screen = zink_screen(pscreen);
199 if (screen->vk_version >= VK_MAKE_VERSION(1,2,0)) {
200 memcpy(uuid, screen->info.props11.deviceUUID, VK_UUID_SIZE);
201 } else {
202 memcpy(uuid, screen->info.deviceid_props.deviceUUID, VK_UUID_SIZE);
203 }
204 }
205
206 static void
zink_get_device_luid(struct pipe_screen * pscreen,char * luid)207 zink_get_device_luid(struct pipe_screen *pscreen, char *luid)
208 {
209 struct zink_screen *screen = zink_screen(pscreen);
210 if (screen->info.have_vulkan12) {
211 memcpy(luid, screen->info.props11.deviceLUID, VK_LUID_SIZE);
212 } else {
213 memcpy(luid, screen->info.deviceid_props.deviceLUID, VK_LUID_SIZE);
214 }
215 }
216
217 static uint32_t
zink_get_device_node_mask(struct pipe_screen * pscreen)218 zink_get_device_node_mask(struct pipe_screen *pscreen)
219 {
220 struct zink_screen *screen = zink_screen(pscreen);
221 if (screen->info.have_vulkan12) {
222 return screen->info.props11.deviceNodeMask;
223 } else {
224 return screen->info.deviceid_props.deviceNodeMask;
225 }
226 }
227
228 static void
zink_set_max_shader_compiler_threads(struct pipe_screen * pscreen,unsigned max_threads)229 zink_set_max_shader_compiler_threads(struct pipe_screen *pscreen, unsigned max_threads)
230 {
231 struct zink_screen *screen = zink_screen(pscreen);
232 util_queue_adjust_num_threads(&screen->cache_get_thread, max_threads, false);
233 }
234
235 static bool
zink_is_parallel_shader_compilation_finished(struct pipe_screen * screen,void * shader,enum pipe_shader_type shader_type)236 zink_is_parallel_shader_compilation_finished(struct pipe_screen *screen, void *shader, enum pipe_shader_type shader_type)
237 {
238 if (shader_type == MESA_SHADER_COMPUTE) {
239 struct zink_program *pg = shader;
240 return !pg->can_precompile || util_queue_fence_is_signalled(&pg->cache_fence);
241 }
242
243 struct zink_shader *zs = shader;
244 if (!util_queue_fence_is_signalled(&zs->precompile.fence))
245 return false;
246 bool finished = true;
247 set_foreach(zs->programs, entry) {
248 struct zink_gfx_program *prog = (void*)entry->key;
249 finished &= util_queue_fence_is_signalled(&prog->base.cache_fence);
250 }
251 return finished;
252 }
253
254 static VkDeviceSize
get_video_mem(struct zink_screen * screen)255 get_video_mem(struct zink_screen *screen)
256 {
257 VkDeviceSize size = 0;
258 for (uint32_t i = 0; i < screen->info.mem_props.memoryHeapCount; ++i) {
259 if (screen->info.mem_props.memoryHeaps[i].flags &
260 VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)
261 size += screen->info.mem_props.memoryHeaps[i].size;
262 }
263 return size;
264 }
265
266 /**
267 * Creates the disk cache used by mesa/st frontend for caching the GLSL -> NIR
268 * path.
269 *
270 * The output that gets stored in the frontend's cache is the result of
271 * zink_shader_finalize(). So, our blake3 cache key here needs to include
272 * everything that would change the NIR we generate from a given set of GLSL
273 * source, including our driver build, the Vulkan device and driver (which could
274 * affect the pipe caps we show the frontend), and any debug flags that change
275 * codegen.
276 *
277 * This disk cache also gets used by zink itself for storing its output from NIR
278 * -> SPIRV translation.
279 */
280 static bool
disk_cache_init(struct zink_screen * screen)281 disk_cache_init(struct zink_screen *screen)
282 {
283 if (zink_debug & ZINK_DEBUG_SHADERDB)
284 return true;
285
286 #ifdef ENABLE_SHADER_CACHE
287 struct mesa_blake3 ctx;
288 _mesa_blake3_init(&ctx);
289
290 #ifdef HAVE_DL_ITERATE_PHDR
291 /* Hash in the zink driver build. */
292 const struct build_id_note *note =
293 build_id_find_nhdr_for_addr(disk_cache_init);
294 unsigned build_id_len = build_id_length(note);
295 assert(note && build_id_len == 20); /* blake3 */
296 _mesa_blake3_update(&ctx, build_id_data(note), build_id_len);
297 #endif
298
299 /* Hash in the Vulkan pipeline cache UUID to identify the combination of
300 * vulkan device and driver (or any inserted layer that would invalidate our
301 * cached pipelines).
302 *
303 * "Although they have identical descriptions, VkPhysicalDeviceIDProperties
304 * ::deviceUUID may differ from
305 * VkPhysicalDeviceProperties2::pipelineCacheUUID. The former is intended to
306 * identify and correlate devices across API and driver boundaries, while the
307 * latter is used to identify a compatible device and driver combination to
308 * use when serializing and de-serializing pipeline state."
309 */
310 _mesa_blake3_update(&ctx, screen->info.props.pipelineCacheUUID, VK_UUID_SIZE);
311
312 /* Hash in our debug flags that affect NIR generation as of finalize_nir */
313 unsigned shader_debug_flags = zink_debug & ZINK_DEBUG_COMPACT;
314 _mesa_blake3_update(&ctx, &shader_debug_flags, sizeof(shader_debug_flags));
315
316 /* add in these shader keys */
317 _mesa_blake3_update(&ctx, &screen->driver_compiler_workarounds, sizeof(screen->driver_compiler_workarounds));
318
319 /* Some of the driconf options change shaders. Let's just hash the whole
320 * thing to not forget any (especially as options get added).
321 */
322 _mesa_blake3_update(&ctx, &screen->driconf, sizeof(screen->driconf));
323
324 /* EXT_shader_object causes different descriptor layouts for separate shaders */
325 _mesa_blake3_update(&ctx, &screen->info.have_EXT_shader_object, sizeof(screen->info.have_EXT_shader_object));
326
327 /* Finish the blake3 and format it as text. */
328 blake3_hash blake3;
329 _mesa_blake3_final(&ctx, blake3);
330
331 char cache_id[20 * 2 + 1];
332 mesa_bytes_to_hex(cache_id, blake3, 20);
333
334 screen->disk_cache = disk_cache_create("zink", cache_id, 0);
335
336 if (!screen->disk_cache)
337 return true;
338
339 if (!util_queue_init(&screen->cache_put_thread, "zcq", 8, 1, UTIL_QUEUE_INIT_RESIZE_IF_FULL, screen)) {
340 mesa_loge("zink: Failed to create disk cache queue\n");
341
342 disk_cache_destroy(screen->disk_cache);
343 screen->disk_cache = NULL;
344
345 return false;
346 }
347 #endif
348
349 return true;
350 }
351
352
353 static void
cache_put_job(void * data,void * gdata,int thread_index)354 cache_put_job(void *data, void *gdata, int thread_index)
355 {
356 struct zink_program *pg = data;
357 struct zink_screen *screen = gdata;
358 size_t size = 0;
359 u_rwlock_rdlock(&pg->pipeline_cache_lock);
360 VkResult result = VKSCR(GetPipelineCacheData)(screen->dev, pg->pipeline_cache, &size, NULL);
361 if (result != VK_SUCCESS) {
362 u_rwlock_rdunlock(&pg->pipeline_cache_lock);
363 mesa_loge("ZINK: vkGetPipelineCacheData failed (%s)", vk_Result_to_str(result));
364 return;
365 }
366 if (pg->pipeline_cache_size == size) {
367 u_rwlock_rdunlock(&pg->pipeline_cache_lock);
368 return;
369 }
370 void *pipeline_data = malloc(size);
371 if (!pipeline_data) {
372 u_rwlock_rdunlock(&pg->pipeline_cache_lock);
373 return;
374 }
375 result = VKSCR(GetPipelineCacheData)(screen->dev, pg->pipeline_cache, &size, pipeline_data);
376 u_rwlock_rdunlock(&pg->pipeline_cache_lock);
377 if (result == VK_SUCCESS) {
378 pg->pipeline_cache_size = size;
379
380 cache_key key;
381 disk_cache_compute_key(screen->disk_cache, pg->blake3, sizeof(pg->blake3), key);
382 disk_cache_put_nocopy(screen->disk_cache, key, pipeline_data, size, NULL);
383 } else {
384 mesa_loge("ZINK: vkGetPipelineCacheData failed (%s)", vk_Result_to_str(result));
385 }
386 }
387
388 void
zink_screen_update_pipeline_cache(struct zink_screen * screen,struct zink_program * pg,bool in_thread)389 zink_screen_update_pipeline_cache(struct zink_screen *screen, struct zink_program *pg, bool in_thread)
390 {
391 if (!screen->disk_cache || !pg->pipeline_cache)
392 return;
393
394 if (in_thread)
395 cache_put_job(pg, screen, 0);
396 else if (util_queue_fence_is_signalled(&pg->cache_fence))
397 util_queue_add_job(&screen->cache_put_thread, pg, &pg->cache_fence, cache_put_job, NULL, 0);
398 }
399
400 static void
cache_get_job(void * data,void * gdata,int thread_index)401 cache_get_job(void *data, void *gdata, int thread_index)
402 {
403 struct zink_program *pg = data;
404 struct zink_screen *screen = gdata;
405
406 VkPipelineCacheCreateInfo pcci;
407 pcci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
408 pcci.pNext = NULL;
409 pcci.flags = screen->info.have_EXT_pipeline_creation_cache_control ? VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT : 0;
410 pcci.initialDataSize = 0;
411 pcci.pInitialData = NULL;
412
413 cache_key key;
414 disk_cache_compute_key(screen->disk_cache, pg->blake3, sizeof(pg->blake3), key);
415 pcci.pInitialData = disk_cache_get(screen->disk_cache, key, &pg->pipeline_cache_size);
416 pcci.initialDataSize = pg->pipeline_cache_size;
417
418 VkResult res = VKSCR(CreatePipelineCache)(screen->dev, &pcci, NULL, &pg->pipeline_cache);
419 if (res != VK_SUCCESS) {
420 mesa_loge("ZINK: vkCreatePipelineCache failed (%s)", vk_Result_to_str(res));
421 }
422 free((void*)pcci.pInitialData);
423 }
424
425 void
zink_screen_get_pipeline_cache(struct zink_screen * screen,struct zink_program * pg,bool in_thread)426 zink_screen_get_pipeline_cache(struct zink_screen *screen, struct zink_program *pg, bool in_thread)
427 {
428 if (!screen->disk_cache)
429 return;
430
431 if (in_thread)
432 cache_get_job(pg, screen, 0);
433 else
434 util_queue_add_job(&screen->cache_get_thread, pg, &pg->cache_fence, cache_get_job, NULL, 0);
435 }
436
437 static int
zink_get_compute_param(struct pipe_screen * pscreen,enum pipe_shader_ir ir_type,enum pipe_compute_cap param,void * ret)438 zink_get_compute_param(struct pipe_screen *pscreen, enum pipe_shader_ir ir_type,
439 enum pipe_compute_cap param, void *ret)
440 {
441 struct zink_screen *screen = zink_screen(pscreen);
442 #define RET(x) do { \
443 if (ret) \
444 memcpy(ret, x, sizeof(x)); \
445 return sizeof(x); \
446 } while (0)
447
448 switch (param) {
449 case PIPE_COMPUTE_CAP_ADDRESS_BITS:
450 RET((uint32_t []){ 64 });
451
452 case PIPE_COMPUTE_CAP_IR_TARGET:
453 if (ret)
454 strcpy(ret, "nir");
455 return 4;
456
457 case PIPE_COMPUTE_CAP_GRID_DIMENSION:
458 RET((uint64_t []) { 3 });
459
460 case PIPE_COMPUTE_CAP_MAX_GRID_SIZE:
461 RET(((uint64_t []) { screen->info.props.limits.maxComputeWorkGroupCount[0],
462 screen->info.props.limits.maxComputeWorkGroupCount[1],
463 screen->info.props.limits.maxComputeWorkGroupCount[2] }));
464
465 case PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE:
466 /* MaxComputeWorkGroupSize[0..2] */
467 RET(((uint64_t []) {screen->info.props.limits.maxComputeWorkGroupSize[0],
468 screen->info.props.limits.maxComputeWorkGroupSize[1],
469 screen->info.props.limits.maxComputeWorkGroupSize[2]}));
470
471 case PIPE_COMPUTE_CAP_MAX_THREADS_PER_BLOCK:
472 case PIPE_COMPUTE_CAP_MAX_VARIABLE_THREADS_PER_BLOCK:
473 RET((uint64_t []) { screen->info.props.limits.maxComputeWorkGroupInvocations });
474
475 case PIPE_COMPUTE_CAP_MAX_LOCAL_SIZE:
476 RET((uint64_t []) { screen->info.props.limits.maxComputeSharedMemorySize });
477
478 case PIPE_COMPUTE_CAP_IMAGES_SUPPORTED:
479 RET((uint32_t []) { 1 });
480
481 case PIPE_COMPUTE_CAP_SUBGROUP_SIZES:
482 RET((uint32_t []) { screen->info.props11.subgroupSize });
483
484 case PIPE_COMPUTE_CAP_MAX_MEM_ALLOC_SIZE:
485 RET((uint64_t []) { screen->clamp_video_mem });
486
487 case PIPE_COMPUTE_CAP_MAX_GLOBAL_SIZE:
488 RET((uint64_t []) { screen->total_video_mem });
489
490 case PIPE_COMPUTE_CAP_MAX_COMPUTE_UNITS:
491 // no way in vulkan to retrieve this information.
492 RET((uint32_t []) { 1 });
493
494 case PIPE_COMPUTE_CAP_MAX_SUBGROUPS:
495 case PIPE_COMPUTE_CAP_MAX_CLOCK_FREQUENCY:
496 case PIPE_COMPUTE_CAP_MAX_PRIVATE_SIZE:
497 case PIPE_COMPUTE_CAP_MAX_INPUT_SIZE:
498 // XXX: I think these are for Clover...
499 return 0;
500
501 default:
502 unreachable("unknown compute param");
503 }
504 }
505
506 static uint32_t
get_smallest_buffer_heap(struct zink_screen * screen)507 get_smallest_buffer_heap(struct zink_screen *screen)
508 {
509 enum zink_heap heaps[] = {
510 ZINK_HEAP_DEVICE_LOCAL,
511 ZINK_HEAP_DEVICE_LOCAL_VISIBLE,
512 ZINK_HEAP_HOST_VISIBLE_COHERENT,
513 ZINK_HEAP_HOST_VISIBLE_COHERENT
514 };
515 unsigned size = UINT32_MAX;
516 for (unsigned i = 0; i < ARRAY_SIZE(heaps); i++) {
517 for (unsigned j = 0; j < screen->heap_count[i]; j++) {
518 unsigned heap_idx = screen->info.mem_props.memoryTypes[screen->heap_map[i][j]].heapIndex;
519 size = MIN2(screen->info.mem_props.memoryHeaps[heap_idx].size, size);
520 }
521 }
522 return size;
523 }
524
525 static inline bool
have_fp32_filter_linear(struct zink_screen * screen)526 have_fp32_filter_linear(struct zink_screen *screen)
527 {
528 const VkFormat fp32_formats[] = {
529 VK_FORMAT_R32_SFLOAT,
530 VK_FORMAT_R32G32_SFLOAT,
531 VK_FORMAT_R32G32B32_SFLOAT,
532 VK_FORMAT_R32G32B32A32_SFLOAT,
533 VK_FORMAT_D32_SFLOAT,
534 };
535 for (int i = 0; i < ARRAY_SIZE(fp32_formats); ++i) {
536 VkFormatProperties props;
537 VKSCR(GetPhysicalDeviceFormatProperties)(screen->pdev,
538 fp32_formats[i],
539 &props);
540 if (((props.linearTilingFeatures | props.optimalTilingFeatures) &
541 (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
542 VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)) ==
543 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) {
544 return false;
545 }
546 }
547 return true;
548 }
549
550 static int
zink_get_param(struct pipe_screen * pscreen,enum pipe_cap param)551 zink_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
552 {
553 struct zink_screen *screen = zink_screen(pscreen);
554
555 switch (param) {
556 case PIPE_CAP_NULL_TEXTURES:
557 return screen->info.rb_image_feats.robustImageAccess;
558 case PIPE_CAP_MULTIVIEW:
559 /* support OVR_multiview and OVR_multiview2 */
560 return screen->info.have_vulkan13 ? 2 * screen->info.feats11.multiview : 0;
561 case PIPE_CAP_TEXRECT:
562 case PIPE_CAP_MULTI_DRAW_INDIRECT_PARTIAL_STRIDE:
563 return 0;
564 case PIPE_CAP_ANISOTROPIC_FILTER:
565 return screen->info.feats.features.samplerAnisotropy;
566 case PIPE_CAP_EMULATE_NONFIXED_PRIMITIVE_RESTART:
567 return 1;
568 case PIPE_CAP_SUPPORTED_PRIM_MODES_WITH_RESTART: {
569 uint32_t modes = BITFIELD_BIT(MESA_PRIM_LINE_STRIP) |
570 BITFIELD_BIT(MESA_PRIM_TRIANGLE_STRIP) |
571 BITFIELD_BIT(MESA_PRIM_LINE_STRIP_ADJACENCY) |
572 BITFIELD_BIT(MESA_PRIM_TRIANGLE_STRIP_ADJACENCY);
573 if (screen->have_triangle_fans)
574 modes |= BITFIELD_BIT(MESA_PRIM_TRIANGLE_FAN);
575 if (screen->info.have_EXT_primitive_topology_list_restart) {
576 modes |= BITFIELD_BIT(MESA_PRIM_POINTS) |
577 BITFIELD_BIT(MESA_PRIM_LINES) |
578 BITFIELD_BIT(MESA_PRIM_LINES_ADJACENCY) |
579 BITFIELD_BIT(MESA_PRIM_TRIANGLES) |
580 BITFIELD_BIT(MESA_PRIM_TRIANGLES_ADJACENCY);
581 if (screen->info.list_restart_feats.primitiveTopologyPatchListRestart)
582 modes |= BITFIELD_BIT(MESA_PRIM_PATCHES);
583 }
584 return modes;
585 }
586 case PIPE_CAP_SUPPORTED_PRIM_MODES: {
587 uint32_t modes = BITFIELD_MASK(MESA_PRIM_COUNT);
588 if (!screen->have_triangle_fans || !screen->info.feats.features.geometryShader)
589 modes &= ~BITFIELD_BIT(MESA_PRIM_QUADS);
590 modes &= ~BITFIELD_BIT(MESA_PRIM_QUAD_STRIP);
591 modes &= ~BITFIELD_BIT(MESA_PRIM_POLYGON);
592 modes &= ~BITFIELD_BIT(MESA_PRIM_LINE_LOOP);
593 if (!screen->have_triangle_fans)
594 modes &= ~BITFIELD_BIT(MESA_PRIM_TRIANGLE_FAN);
595 return modes;
596 }
597
598 case PIPE_CAP_FBFETCH:
599 return 1;
600 case PIPE_CAP_FBFETCH_COHERENT:
601 return screen->info.have_EXT_rasterization_order_attachment_access;
602
603 case PIPE_CAP_MEMOBJ:
604 return screen->instance_info.have_KHR_external_memory_capabilities && (screen->info.have_KHR_external_memory_fd || screen->info.have_KHR_external_memory_win32);
605 case PIPE_CAP_FENCE_SIGNAL:
606 return screen->info.have_KHR_external_semaphore_fd || screen->info.have_KHR_external_semaphore_win32;
607 case PIPE_CAP_NATIVE_FENCE_FD:
608 return screen->instance_info.have_KHR_external_semaphore_capabilities && screen->info.have_KHR_external_semaphore_fd;
609 case PIPE_CAP_RESOURCE_FROM_USER_MEMORY:
610 return screen->info.have_EXT_external_memory_host;
611
612 case PIPE_CAP_SURFACE_REINTERPRET_BLOCKS:
613 return screen->info.have_vulkan11 || screen->info.have_KHR_maintenance2;
614
615 case PIPE_CAP_VALIDATE_ALL_DIRTY_STATES:
616 case PIPE_CAP_ALLOW_MAPPED_BUFFERS_DURING_EXECUTION:
617 case PIPE_CAP_MAP_UNSYNCHRONIZED_THREAD_SAFE:
618 case PIPE_CAP_SHAREABLE_SHADERS:
619 case PIPE_CAP_DEVICE_RESET_STATUS_QUERY:
620 case PIPE_CAP_QUERY_MEMORY_INFO:
621 case PIPE_CAP_NPOT_TEXTURES:
622 case PIPE_CAP_TGSI_TEXCOORD:
623 case PIPE_CAP_DRAW_INDIRECT:
624 case PIPE_CAP_TEXTURE_QUERY_LOD:
625 case PIPE_CAP_GLSL_TESS_LEVELS_AS_INPUTS:
626 case PIPE_CAP_COPY_BETWEEN_COMPRESSED_AND_PLAIN_FORMATS:
627 case PIPE_CAP_FORCE_PERSAMPLE_INTERP:
628 case PIPE_CAP_FRAMEBUFFER_NO_ATTACHMENT:
629 case PIPE_CAP_SHADER_ARRAY_COMPONENTS:
630 case PIPE_CAP_QUERY_BUFFER_OBJECT:
631 case PIPE_CAP_CONDITIONAL_RENDER_INVERTED:
632 case PIPE_CAP_CLIP_HALFZ:
633 case PIPE_CAP_TEXTURE_QUERY_SAMPLES:
634 case PIPE_CAP_TEXTURE_BARRIER:
635 case PIPE_CAP_QUERY_SO_OVERFLOW:
636 case PIPE_CAP_GL_SPIRV:
637 case PIPE_CAP_CLEAR_SCISSORED:
638 case PIPE_CAP_INVALIDATE_BUFFER:
639 case PIPE_CAP_PREFER_REAL_BUFFER_IN_CONSTBUF0:
640 case PIPE_CAP_PACKED_UNIFORMS:
641 case PIPE_CAP_SHADER_PACK_HALF_FLOAT:
642 case PIPE_CAP_CULL_DISTANCE_NOCOMBINE:
643 case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
644 case PIPE_CAP_LOAD_CONSTBUF:
645 case PIPE_CAP_MULTISAMPLE_Z_RESOLVE:
646 case PIPE_CAP_ALLOW_GLTHREAD_BUFFER_SUBDATA_OPT:
647 case PIPE_CAP_NIR_SAMPLERS_AS_DEREF:
648 return 1;
649
650 case PIPE_CAP_DRAW_VERTEX_STATE:
651 return screen->info.have_EXT_vertex_input_dynamic_state;
652
653 case PIPE_CAP_SURFACE_SAMPLE_COUNT:
654 return screen->vk_version >= VK_MAKE_VERSION(1,2,0);
655
656 case PIPE_CAP_SHADER_GROUP_VOTE:
657 if (screen->info.have_vulkan11 &&
658 (screen->info.subgroup.supportedOperations & VK_SUBGROUP_FEATURE_VOTE_BIT) &&
659 (screen->info.subgroup.supportedStages & VK_SHADER_STAGE_COMPUTE_BIT))
660 return true;
661 if (screen->info.have_EXT_shader_subgroup_vote)
662 return true;
663 return false;
664 case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION:
665 return 1;
666
667 case PIPE_CAP_TEXTURE_MIRROR_CLAMP_TO_EDGE:
668 return screen->info.have_KHR_sampler_mirror_clamp_to_edge || (screen->info.have_vulkan12 && screen->info.feats12.samplerMirrorClampToEdge);
669
670 case PIPE_CAP_POLYGON_OFFSET_UNITS_UNSCALED:
671 return 1;
672
673 case PIPE_CAP_POLYGON_OFFSET_CLAMP:
674 return screen->info.feats.features.depthBiasClamp;
675
676 case PIPE_CAP_QUERY_PIPELINE_STATISTICS_SINGLE:
677 return screen->info.feats.features.pipelineStatisticsQuery;
678
679 case PIPE_CAP_ROBUST_BUFFER_ACCESS_BEHAVIOR:
680 return screen->info.feats.features.robustBufferAccess &&
681 (screen->info.rb2_feats.robustImageAccess2 || screen->driver_compiler_workarounds.lower_robustImageAccess2);
682
683 case PIPE_CAP_MULTI_DRAW_INDIRECT:
684 return screen->info.feats.features.multiDrawIndirect;
685
686 case PIPE_CAP_IMAGE_ATOMIC_FLOAT_ADD:
687 return (screen->info.have_EXT_shader_atomic_float &&
688 screen->info.atomic_float_feats.shaderSharedFloat32AtomicAdd &&
689 screen->info.atomic_float_feats.shaderBufferFloat32AtomicAdd);
690 case PIPE_CAP_SHADER_ATOMIC_INT64:
691 return (screen->info.have_KHR_shader_atomic_int64 &&
692 screen->info.atomic_int_feats.shaderSharedInt64Atomics &&
693 screen->info.atomic_int_feats.shaderBufferInt64Atomics);
694
695 case PIPE_CAP_MULTI_DRAW_INDIRECT_PARAMS:
696 return screen->info.have_KHR_draw_indirect_count;
697
698 case PIPE_CAP_START_INSTANCE:
699 case PIPE_CAP_DRAW_PARAMETERS:
700 return (screen->info.have_vulkan12 && screen->info.feats11.shaderDrawParameters) ||
701 screen->info.have_KHR_shader_draw_parameters;
702
703 case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR:
704 return screen->info.have_EXT_vertex_attribute_divisor;
705
706 case PIPE_CAP_MAX_VERTEX_STREAMS:
707 return screen->info.tf_props.maxTransformFeedbackStreams;
708
709 case PIPE_CAP_COMPUTE_SHADER_DERIVATIVES:
710 return screen->info.have_NV_compute_shader_derivatives;
711
712 case PIPE_CAP_INT64:
713 case PIPE_CAP_DOUBLES:
714 return 1;
715
716 case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
717 if (!screen->info.feats.features.dualSrcBlend)
718 return 0;
719 return screen->info.props.limits.maxFragmentDualSrcAttachments;
720
721 case PIPE_CAP_MAX_RENDER_TARGETS:
722 return screen->info.props.limits.maxColorAttachments;
723
724 case PIPE_CAP_OCCLUSION_QUERY:
725 return screen->info.feats.features.occlusionQueryPrecise;
726
727 case PIPE_CAP_PROGRAMMABLE_SAMPLE_LOCATIONS:
728 return screen->info.have_EXT_sample_locations && screen->info.have_EXT_extended_dynamic_state;
729
730 case PIPE_CAP_QUERY_TIME_ELAPSED:
731 return screen->timestamp_valid_bits > 0;
732
733 case PIPE_CAP_TEXTURE_MULTISAMPLE:
734 return 1;
735
736 case PIPE_CAP_FRAGMENT_SHADER_INTERLOCK:
737 return screen->info.have_EXT_fragment_shader_interlock;
738
739 case PIPE_CAP_SHADER_CLOCK:
740 return screen->info.have_KHR_shader_clock;
741
742 case PIPE_CAP_SHADER_BALLOT:
743 if (screen->info.props11.subgroupSize > 64)
744 return false;
745 if (screen->info.have_vulkan11 &&
746 screen->info.subgroup.supportedOperations & VK_SUBGROUP_FEATURE_BALLOT_BIT)
747 return true;
748 if (screen->info.have_EXT_shader_subgroup_ballot)
749 return true;
750 return false;
751
752 case PIPE_CAP_DEMOTE_TO_HELPER_INVOCATION:
753 return screen->spirv_version >= SPIRV_VERSION(1, 6) ||
754 screen->info.have_EXT_shader_demote_to_helper_invocation;
755
756 case PIPE_CAP_SAMPLE_SHADING:
757 return screen->info.feats.features.sampleRateShading;
758
759 case PIPE_CAP_TEXTURE_SWIZZLE:
760 return 1;
761
762 case PIPE_CAP_VERTEX_ATTRIB_ELEMENT_ALIGNED_ONLY:
763 return !screen->info.have_EXT_legacy_vertex_attributes;
764
765 case PIPE_CAP_GL_CLAMP:
766 return 0;
767
768 case PIPE_CAP_PREFER_IMM_ARRAYS_AS_CONSTBUF:
769 return 0; /* Assume that the vk driver is capable of moving imm arrays to some sort of constant storage on its own. */
770
771 case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK: {
772 enum pipe_quirk_texture_border_color_swizzle quirk = PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_ALPHA_NOT_W;
773 if (!screen->info.border_color_feats.customBorderColorWithoutFormat)
774 return quirk | PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_FREEDRENO;
775 /* assume that if drivers don't implement this extension they either:
776 * - don't support custom border colors
777 * - handle things correctly
778 * - hate border color accuracy
779 */
780 if (screen->info.have_EXT_border_color_swizzle &&
781 !screen->info.border_swizzle_feats.borderColorSwizzleFromImage)
782 return quirk | PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50;
783 return quirk;
784 }
785
786 case PIPE_CAP_MAX_TEXTURE_2D_SIZE:
787 return MIN2(screen->info.props.limits.maxImageDimension1D,
788 screen->info.props.limits.maxImageDimension2D);
789 case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
790 return 1 + util_logbase2(screen->info.props.limits.maxImageDimension3D);
791 case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
792 return 1 + util_logbase2(screen->info.props.limits.maxImageDimensionCube);
793
794 case PIPE_CAP_FRAGMENT_SHADER_TEXTURE_LOD:
795 case PIPE_CAP_FRAGMENT_SHADER_DERIVATIVES:
796 return 1;
797
798 case PIPE_CAP_BLEND_EQUATION_SEPARATE:
799 case PIPE_CAP_INDEP_BLEND_ENABLE:
800 case PIPE_CAP_INDEP_BLEND_FUNC:
801 return screen->info.feats.features.independentBlend;
802
803 case PIPE_CAP_DITHERING:
804 return 0;
805
806 case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:
807 return screen->info.have_EXT_transform_feedback ? screen->info.tf_props.maxTransformFeedbackBuffers : 0;
808 case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
809 case PIPE_CAP_STREAM_OUTPUT_INTERLEAVE_BUFFERS:
810 return screen->info.have_EXT_transform_feedback;
811
812 case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
813 return screen->info.props.limits.maxImageArrayLayers;
814
815 case PIPE_CAP_DEPTH_CLIP_DISABLE:
816 return screen->info.have_EXT_depth_clip_enable;
817
818 case PIPE_CAP_SHADER_STENCIL_EXPORT:
819 return screen->info.have_EXT_shader_stencil_export;
820
821 case PIPE_CAP_VS_INSTANCEID:
822 case PIPE_CAP_SEAMLESS_CUBE_MAP:
823 return 1;
824
825 case PIPE_CAP_MIN_TEXEL_OFFSET:
826 return screen->info.props.limits.minTexelOffset;
827 case PIPE_CAP_MAX_TEXEL_OFFSET:
828 return screen->info.props.limits.maxTexelOffset;
829
830 case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
831 return 1;
832
833 case PIPE_CAP_CONDITIONAL_RENDER:
834 return 1;
835
836 case PIPE_CAP_GLSL_FEATURE_LEVEL_COMPATIBILITY:
837 case PIPE_CAP_GLSL_FEATURE_LEVEL:
838 return 460;
839
840 case PIPE_CAP_COMPUTE:
841 return 1;
842
843 case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
844 return screen->info.props.limits.minUniformBufferOffsetAlignment;
845
846 case PIPE_CAP_QUERY_TIMESTAMP:
847 return screen->timestamp_valid_bits > 0;
848
849 case PIPE_CAP_QUERY_TIMESTAMP_BITS:
850 return screen->timestamp_valid_bits;
851
852 case PIPE_CAP_TIMER_RESOLUTION:
853 return ceil(screen->info.props.limits.timestampPeriod);
854
855 case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT:
856 return 1 << MIN_SLAB_ORDER;
857
858 case PIPE_CAP_CUBE_MAP_ARRAY:
859 return screen->info.feats.features.imageCubeArray;
860
861 case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
862 case PIPE_CAP_PRIMITIVE_RESTART:
863 return 1;
864
865 case PIPE_CAP_BINDLESS_TEXTURE:
866 if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB &&
867 (screen->info.db_props.maxDescriptorBufferBindings < 2 || screen->info.db_props.maxSamplerDescriptorBufferBindings < 2))
868 return 0;
869 return screen->info.have_EXT_descriptor_indexing;
870
871 case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
872 return screen->info.props.limits.minTexelBufferOffsetAlignment;
873
874 case PIPE_CAP_TEXTURE_TRANSFER_MODES: {
875 enum pipe_texture_transfer_mode mode = PIPE_TEXTURE_TRANSFER_BLIT;
876 if (!screen->is_cpu &&
877 screen->info.have_KHR_8bit_storage &&
878 screen->info.have_KHR_16bit_storage &&
879 screen->info.have_KHR_shader_float16_int8)
880 mode |= PIPE_TEXTURE_TRANSFER_COMPUTE;
881 return mode;
882 }
883
884 case PIPE_CAP_MAX_TEXEL_BUFFER_ELEMENTS_UINT:
885 return MIN2(get_smallest_buffer_heap(screen),
886 screen->info.props.limits.maxTexelBufferElements);
887
888 case PIPE_CAP_ENDIANNESS:
889 return PIPE_ENDIAN_NATIVE; /* unsure */
890
891 case PIPE_CAP_MAX_VIEWPORTS:
892 return MIN2(screen->info.props.limits.maxViewports, PIPE_MAX_VIEWPORTS);
893
894 case PIPE_CAP_IMAGE_LOAD_FORMATTED:
895 return screen->info.feats.features.shaderStorageImageReadWithoutFormat;
896
897 case PIPE_CAP_IMAGE_STORE_FORMATTED:
898 return screen->info.feats.features.shaderStorageImageWriteWithoutFormat;
899
900 case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES:
901 return 1;
902
903 case PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES:
904 return screen->info.props.limits.maxGeometryOutputVertices;
905 case PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS:
906 return screen->info.props.limits.maxGeometryTotalOutputComponents;
907
908 case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS:
909 return 4;
910
911 case PIPE_CAP_MIN_TEXTURE_GATHER_OFFSET:
912 return screen->info.props.limits.minTexelGatherOffset;
913 case PIPE_CAP_MAX_TEXTURE_GATHER_OFFSET:
914 return screen->info.props.limits.maxTexelGatherOffset;
915
916 case PIPE_CAP_SAMPLER_REDUCTION_MINMAX_ARB:
917 return screen->info.feats12.samplerFilterMinmax || screen->info.have_EXT_sampler_filter_minmax;
918
919 case PIPE_CAP_OPENCL_INTEGER_FUNCTIONS:
920 case PIPE_CAP_INTEGER_MULTIPLY_32X16:
921 return screen->info.have_INTEL_shader_integer_functions2;
922
923 case PIPE_CAP_FS_FINE_DERIVATIVE:
924 return 1;
925
926 case PIPE_CAP_VENDOR_ID:
927 return screen->info.props.vendorID;
928 case PIPE_CAP_DEVICE_ID:
929 return screen->info.props.deviceID;
930
931 case PIPE_CAP_ACCELERATED:
932 return !screen->is_cpu;
933 case PIPE_CAP_VIDEO_MEMORY:
934 return get_video_mem(screen) >> 20;
935 case PIPE_CAP_UMA:
936 return screen->info.props.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
937
938 case PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE:
939 return screen->info.props.limits.maxVertexInputBindingStride;
940
941 case PIPE_CAP_SAMPLER_VIEW_TARGET:
942 return 1;
943
944 case PIPE_CAP_VS_LAYER_VIEWPORT:
945 case PIPE_CAP_TES_LAYER_VIEWPORT:
946 return screen->info.have_EXT_shader_viewport_index_layer ||
947 (screen->spirv_version >= SPIRV_VERSION(1, 5) &&
948 screen->info.feats12.shaderOutputLayer &&
949 screen->info.feats12.shaderOutputViewportIndex);
950
951 case PIPE_CAP_TEXTURE_FLOAT_LINEAR:
952 return have_fp32_filter_linear(screen);
953
954 case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR:
955 return 1;
956
957 case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT:
958 return screen->info.props.limits.minStorageBufferOffsetAlignment;
959
960 case PIPE_CAP_PCI_GROUP:
961 case PIPE_CAP_PCI_BUS:
962 case PIPE_CAP_PCI_DEVICE:
963 case PIPE_CAP_PCI_FUNCTION:
964 return 0; /* TODO: figure these out */
965
966 case PIPE_CAP_CULL_DISTANCE:
967 return screen->info.feats.features.shaderCullDistance;
968
969 case PIPE_CAP_SPARSE_BUFFER_PAGE_SIZE:
970 return screen->info.feats.features.sparseResidencyBuffer ? ZINK_SPARSE_BUFFER_PAGE_SIZE : 0;
971
972 /* Sparse texture */
973 case PIPE_CAP_MAX_SPARSE_TEXTURE_SIZE:
974 return screen->info.feats.features.sparseResidencyImage2D ?
975 zink_get_param(pscreen, PIPE_CAP_MAX_TEXTURE_2D_SIZE) : 0;
976 case PIPE_CAP_MAX_SPARSE_3D_TEXTURE_SIZE:
977 return screen->info.feats.features.sparseResidencyImage3D ?
978 (1 << (zink_get_param(pscreen, PIPE_CAP_MAX_TEXTURE_3D_LEVELS) - 1)) : 0;
979 case PIPE_CAP_MAX_SPARSE_ARRAY_TEXTURE_LAYERS:
980 return screen->info.feats.features.sparseResidencyImage2D ?
981 zink_get_param(pscreen, PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS) : 0;
982 case PIPE_CAP_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS:
983 return screen->info.feats.features.sparseResidencyImage2D ? 1 : 0;
984 case PIPE_CAP_QUERY_SPARSE_TEXTURE_RESIDENCY:
985 return screen->info.feats.features.sparseResidency2Samples &&
986 screen->info.feats.features.shaderResourceResidency ? 1 : 0;
987 case PIPE_CAP_CLAMP_SPARSE_TEXTURE_LOD:
988 return screen->info.feats.features.shaderResourceMinLod &&
989 screen->info.feats.features.sparseResidency2Samples &&
990 screen->info.feats.features.shaderResourceResidency ? 1 : 0;
991
992 case PIPE_CAP_VIEWPORT_SUBPIXEL_BITS:
993 return screen->info.props.limits.viewportSubPixelBits;
994
995 case PIPE_CAP_MAX_GS_INVOCATIONS:
996 return screen->info.props.limits.maxGeometryShaderInvocations;
997
998 case PIPE_CAP_MAX_COMBINED_SHADER_BUFFERS:
999 /* gallium handles this automatically */
1000 return 0;
1001
1002 case PIPE_CAP_MAX_SHADER_BUFFER_SIZE_UINT:
1003 /* 1<<27 is required by VK spec */
1004 assert(screen->info.props.limits.maxStorageBufferRange >= 1 << 27);
1005 /* clamp to VK spec minimum */
1006 return MIN2(get_smallest_buffer_heap(screen), screen->info.props.limits.maxStorageBufferRange);
1007
1008 case PIPE_CAP_FS_COORD_ORIGIN_UPPER_LEFT:
1009 case PIPE_CAP_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
1010 return 1;
1011
1012 case PIPE_CAP_FS_COORD_ORIGIN_LOWER_LEFT:
1013 case PIPE_CAP_FS_COORD_PIXEL_CENTER_INTEGER:
1014 return 0;
1015
1016 case PIPE_CAP_FS_FACE_IS_INTEGER_SYSVAL:
1017 case PIPE_CAP_FS_POINT_IS_SYSVAL:
1018 return 1;
1019
1020 case PIPE_CAP_VIEWPORT_TRANSFORM_LOWERED:
1021 return 1;
1022
1023 case PIPE_CAP_POINT_SIZE_FIXED:
1024 return screen->info.have_KHR_maintenance5 ? PIPE_POINT_SIZE_LOWER_USER_ONLY : PIPE_POINT_SIZE_LOWER_ALWAYS;
1025 case PIPE_CAP_FLATSHADE:
1026 case PIPE_CAP_ALPHA_TEST:
1027 case PIPE_CAP_CLIP_PLANES:
1028 case PIPE_CAP_TWO_SIDED_COLOR:
1029 return 0;
1030
1031 case PIPE_CAP_MAX_SHADER_PATCH_VARYINGS:
1032 return screen->info.props.limits.maxTessellationControlPerPatchOutputComponents / 4;
1033 case PIPE_CAP_MAX_VARYINGS:
1034 /* need to reserve up to 60 of our varying components and 16 slots for streamout */
1035 return MIN2(screen->info.props.limits.maxVertexOutputComponents / 4 / 2, 16);
1036
1037 case PIPE_CAP_DMABUF:
1038 #if defined(HAVE_LIBDRM) && (DETECT_OS_LINUX || DETECT_OS_BSD)
1039 return screen->info.have_KHR_external_memory_fd &&
1040 screen->info.have_EXT_external_memory_dma_buf &&
1041 screen->info.have_EXT_queue_family_foreign
1042 ? DRM_PRIME_CAP_IMPORT | DRM_PRIME_CAP_EXPORT
1043 : 0;
1044 #else
1045 return 0;
1046 #endif
1047
1048 case PIPE_CAP_DEPTH_BOUNDS_TEST:
1049 return screen->info.feats.features.depthBounds;
1050
1051 case PIPE_CAP_POST_DEPTH_COVERAGE:
1052 return screen->info.have_EXT_post_depth_coverage;
1053
1054 case PIPE_CAP_STRING_MARKER:
1055 return screen->instance_info.have_EXT_debug_utils;
1056
1057 default:
1058 return u_pipe_screen_get_param_defaults(pscreen, param);
1059 }
1060 }
1061
1062 static float
zink_get_paramf(struct pipe_screen * pscreen,enum pipe_capf param)1063 zink_get_paramf(struct pipe_screen *pscreen, enum pipe_capf param)
1064 {
1065 struct zink_screen *screen = zink_screen(pscreen);
1066
1067 switch (param) {
1068 case PIPE_CAPF_MIN_LINE_WIDTH:
1069 case PIPE_CAPF_MIN_LINE_WIDTH_AA:
1070 if (!screen->info.feats.features.wideLines)
1071 return 1.0f;
1072 return MAX2(screen->info.props.limits.lineWidthRange[0], 0.01);
1073
1074 case PIPE_CAPF_MIN_POINT_SIZE:
1075 case PIPE_CAPF_MIN_POINT_SIZE_AA:
1076 if (!screen->info.feats.features.largePoints)
1077 return 1.0f;
1078 return MAX2(screen->info.props.limits.pointSizeRange[0], 0.01);
1079
1080
1081 case PIPE_CAPF_LINE_WIDTH_GRANULARITY:
1082 if (!screen->info.feats.features.wideLines)
1083 return 0.1f;
1084 return screen->info.props.limits.lineWidthGranularity;
1085
1086 case PIPE_CAPF_POINT_SIZE_GRANULARITY:
1087 if (!screen->info.feats.features.largePoints)
1088 return 0.1f;
1089 return screen->info.props.limits.pointSizeGranularity;
1090
1091
1092 case PIPE_CAPF_MAX_LINE_WIDTH:
1093 case PIPE_CAPF_MAX_LINE_WIDTH_AA:
1094 if (!screen->info.feats.features.wideLines)
1095 return 1.0f;
1096 return screen->info.props.limits.lineWidthRange[1];
1097
1098 case PIPE_CAPF_MAX_POINT_SIZE:
1099 case PIPE_CAPF_MAX_POINT_SIZE_AA:
1100 if (!screen->info.feats.features.largePoints)
1101 return 1.0f;
1102 return screen->info.props.limits.pointSizeRange[1];
1103
1104 case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY:
1105 if (!screen->info.feats.features.samplerAnisotropy)
1106 return 1.0f;
1107 return screen->info.props.limits.maxSamplerAnisotropy;
1108
1109 case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS:
1110 return screen->info.props.limits.maxSamplerLodBias;
1111
1112 case PIPE_CAPF_MIN_CONSERVATIVE_RASTER_DILATE:
1113 case PIPE_CAPF_MAX_CONSERVATIVE_RASTER_DILATE:
1114 case PIPE_CAPF_CONSERVATIVE_RASTER_DILATE_GRANULARITY:
1115 return 0.0f; /* not implemented */
1116 }
1117
1118 /* should only get here on unhandled cases */
1119 return 0.0f;
1120 }
1121
1122 static int
zink_get_shader_param(struct pipe_screen * pscreen,gl_shader_stage shader,enum pipe_shader_cap param)1123 zink_get_shader_param(struct pipe_screen *pscreen,
1124 gl_shader_stage shader,
1125 enum pipe_shader_cap param)
1126 {
1127 struct zink_screen *screen = zink_screen(pscreen);
1128
1129 switch (param) {
1130 case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
1131 switch (shader) {
1132 case MESA_SHADER_FRAGMENT:
1133 case MESA_SHADER_VERTEX:
1134 return INT_MAX;
1135 case MESA_SHADER_TESS_CTRL:
1136 case MESA_SHADER_TESS_EVAL:
1137 if (screen->info.feats.features.tessellationShader &&
1138 screen->info.have_KHR_maintenance2)
1139 return INT_MAX;
1140 break;
1141
1142 case MESA_SHADER_GEOMETRY:
1143 if (screen->info.feats.features.geometryShader)
1144 return INT_MAX;
1145 break;
1146
1147 case MESA_SHADER_COMPUTE:
1148 return INT_MAX;
1149 default:
1150 break;
1151 }
1152 return 0;
1153 case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
1154 case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
1155 case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
1156 case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
1157 return INT_MAX;
1158
1159 case PIPE_SHADER_CAP_MAX_INPUTS: {
1160 uint32_t max = 0;
1161 switch (shader) {
1162 case MESA_SHADER_VERTEX:
1163 max = MIN2(screen->info.props.limits.maxVertexInputAttributes, PIPE_MAX_ATTRIBS);
1164 break;
1165 case MESA_SHADER_TESS_CTRL:
1166 max = screen->info.props.limits.maxTessellationControlPerVertexInputComponents / 4;
1167 break;
1168 case MESA_SHADER_TESS_EVAL:
1169 max = screen->info.props.limits.maxTessellationEvaluationInputComponents / 4;
1170 break;
1171 case MESA_SHADER_GEOMETRY:
1172 max = screen->info.props.limits.maxGeometryInputComponents / 4;
1173 break;
1174 case MESA_SHADER_FRAGMENT:
1175 /* intel drivers report fewer components, but it's a value that's compatible
1176 * with what we need for GL, so we can still force a conformant value here
1177 */
1178 if (zink_driverid(screen) == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA ||
1179 zink_driverid(screen) == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS)
1180 return 32;
1181 max = screen->info.props.limits.maxFragmentInputComponents / 4;
1182 break;
1183 default:
1184 return 0; /* unsupported stage */
1185 }
1186 switch (shader) {
1187 case MESA_SHADER_VERTEX:
1188 case MESA_SHADER_TESS_EVAL:
1189 case MESA_SHADER_GEOMETRY:
1190 /* last vertex stage must support streamout, and this is capped in glsl compiler */
1191 return MIN2(max, MAX_VARYING);
1192 default: break;
1193 }
1194 return MIN2(max, 64); // prevent overflowing struct shader_info::inputs_read
1195 }
1196
1197 case PIPE_SHADER_CAP_MAX_OUTPUTS: {
1198 uint32_t max = 0;
1199 switch (shader) {
1200 case MESA_SHADER_VERTEX:
1201 max = screen->info.props.limits.maxVertexOutputComponents / 4;
1202 break;
1203 case MESA_SHADER_TESS_CTRL:
1204 max = screen->info.props.limits.maxTessellationControlPerVertexOutputComponents / 4;
1205 break;
1206 case MESA_SHADER_TESS_EVAL:
1207 max = screen->info.props.limits.maxTessellationEvaluationOutputComponents / 4;
1208 break;
1209 case MESA_SHADER_GEOMETRY:
1210 max = screen->info.props.limits.maxGeometryOutputComponents / 4;
1211 break;
1212 case MESA_SHADER_FRAGMENT:
1213 max = screen->info.props.limits.maxColorAttachments;
1214 break;
1215 default:
1216 return 0; /* unsupported stage */
1217 }
1218 return MIN2(max, 64); // prevent overflowing struct shader_info::outputs_read/written
1219 }
1220
1221 case PIPE_SHADER_CAP_MAX_CONST_BUFFER0_SIZE:
1222 /* At least 16384 is guaranteed by VK spec */
1223 assert(screen->info.props.limits.maxUniformBufferRange >= 16384);
1224 /* but Gallium can't handle values that are too big */
1225 return MIN3(get_smallest_buffer_heap(screen),
1226 screen->info.props.limits.maxUniformBufferRange, BITFIELD_BIT(31));
1227
1228 case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
1229 return MIN2(screen->info.props.limits.maxPerStageDescriptorUniformBuffers,
1230 PIPE_MAX_CONSTANT_BUFFERS);
1231
1232 case PIPE_SHADER_CAP_MAX_TEMPS:
1233 return INT_MAX;
1234
1235 case PIPE_SHADER_CAP_INTEGERS:
1236 return 1;
1237
1238 case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:
1239 case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:
1240 case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
1241 case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:
1242 return 1;
1243
1244 case PIPE_SHADER_CAP_SUBROUTINES:
1245 case PIPE_SHADER_CAP_INT64_ATOMICS:
1246 case PIPE_SHADER_CAP_GLSL_16BIT_CONSTS:
1247 return 0; /* not implemented */
1248
1249 case PIPE_SHADER_CAP_FP16_CONST_BUFFERS:
1250 //enabling this breaks GTF-GL46.gtf21.GL2Tests.glGetUniform.glGetUniform
1251 //return screen->info.feats11.uniformAndStorageBuffer16BitAccess ||
1252 //(screen->info.have_KHR_16bit_storage && screen->info.storage_16bit_feats.uniformAndStorageBuffer16BitAccess);
1253 return 0;
1254 case PIPE_SHADER_CAP_FP16_DERIVATIVES:
1255 return 0; //spirv requires 32bit derivative srcs and dests
1256 case PIPE_SHADER_CAP_FP16:
1257 return screen->info.feats12.shaderFloat16 ||
1258 (screen->info.have_KHR_shader_float16_int8 &&
1259 screen->info.shader_float16_int8_feats.shaderFloat16);
1260
1261 case PIPE_SHADER_CAP_INT16:
1262 return screen->info.feats.features.shaderInt16;
1263
1264 case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED:
1265 return 0; /* not implemented */
1266
1267 case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
1268 case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS:
1269 return MIN2(MIN2(screen->info.props.limits.maxPerStageDescriptorSamplers,
1270 screen->info.props.limits.maxPerStageDescriptorSampledImages),
1271 PIPE_MAX_SAMPLERS);
1272
1273 case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE:
1274 return 0; /* no idea */
1275
1276 case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS:
1277 switch (shader) {
1278 case MESA_SHADER_VERTEX:
1279 case MESA_SHADER_TESS_CTRL:
1280 case MESA_SHADER_TESS_EVAL:
1281 case MESA_SHADER_GEOMETRY:
1282 if (!screen->info.feats.features.vertexPipelineStoresAndAtomics)
1283 return 0;
1284 break;
1285
1286 case MESA_SHADER_FRAGMENT:
1287 if (!screen->info.feats.features.fragmentStoresAndAtomics)
1288 return 0;
1289 break;
1290
1291 default:
1292 break;
1293 }
1294
1295 /* TODO: this limitation is dumb, and will need some fixes in mesa */
1296 return MIN2(screen->info.props.limits.maxPerStageDescriptorStorageBuffers, PIPE_MAX_SHADER_BUFFERS);
1297
1298 case PIPE_SHADER_CAP_SUPPORTED_IRS:
1299 return (1 << PIPE_SHADER_IR_NIR) | (1 << PIPE_SHADER_IR_TGSI);
1300
1301 case PIPE_SHADER_CAP_MAX_SHADER_IMAGES:
1302 if (screen->info.feats.features.shaderStorageImageExtendedFormats &&
1303 screen->info.feats.features.shaderStorageImageWriteWithoutFormat)
1304 return MIN2(screen->info.props.limits.maxPerStageDescriptorStorageImages,
1305 ZINK_MAX_SHADER_IMAGES);
1306 return 0;
1307
1308 case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTERS:
1309 case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTER_BUFFERS:
1310 return 0; /* not implemented */
1311 case PIPE_SHADER_CAP_CONT_SUPPORTED:
1312 return 1;
1313 }
1314
1315 /* should only get here on unhandled cases */
1316 return 0;
1317 }
1318
1319 static VkSampleCountFlagBits
vk_sample_count_flags(uint32_t sample_count)1320 vk_sample_count_flags(uint32_t sample_count)
1321 {
1322 switch (sample_count) {
1323 case 1: return VK_SAMPLE_COUNT_1_BIT;
1324 case 2: return VK_SAMPLE_COUNT_2_BIT;
1325 case 4: return VK_SAMPLE_COUNT_4_BIT;
1326 case 8: return VK_SAMPLE_COUNT_8_BIT;
1327 case 16: return VK_SAMPLE_COUNT_16_BIT;
1328 case 32: return VK_SAMPLE_COUNT_32_BIT;
1329 case 64: return VK_SAMPLE_COUNT_64_BIT;
1330 default:
1331 return 0;
1332 }
1333 }
1334
1335 static bool
zink_is_compute_copy_faster(struct pipe_screen * pscreen,enum pipe_format src_format,enum pipe_format dst_format,unsigned width,unsigned height,unsigned depth,bool cpu)1336 zink_is_compute_copy_faster(struct pipe_screen *pscreen,
1337 enum pipe_format src_format,
1338 enum pipe_format dst_format,
1339 unsigned width,
1340 unsigned height,
1341 unsigned depth,
1342 bool cpu)
1343 {
1344 if (cpu)
1345 /* very basic for now, probably even worse for some cases,
1346 * but fixes lots of others
1347 */
1348 return width * height * depth > 64 * 64;
1349 return false;
1350 }
1351
1352 static bool
zink_is_format_supported(struct pipe_screen * pscreen,enum pipe_format format,enum pipe_texture_target target,unsigned sample_count,unsigned storage_sample_count,unsigned bind)1353 zink_is_format_supported(struct pipe_screen *pscreen,
1354 enum pipe_format format,
1355 enum pipe_texture_target target,
1356 unsigned sample_count,
1357 unsigned storage_sample_count,
1358 unsigned bind)
1359 {
1360 struct zink_screen *screen = zink_screen(pscreen);
1361
1362 if (storage_sample_count && !screen->info.feats.features.shaderStorageImageMultisample && bind & PIPE_BIND_SHADER_IMAGE)
1363 return false;
1364
1365 if (format == PIPE_FORMAT_NONE)
1366 return screen->info.props.limits.framebufferNoAttachmentsSampleCounts &
1367 vk_sample_count_flags(sample_count);
1368
1369 if (bind & PIPE_BIND_INDEX_BUFFER) {
1370 if (format == PIPE_FORMAT_R8_UINT &&
1371 !screen->info.have_EXT_index_type_uint8)
1372 return false;
1373 if (format != PIPE_FORMAT_R8_UINT &&
1374 format != PIPE_FORMAT_R16_UINT &&
1375 format != PIPE_FORMAT_R32_UINT)
1376 return false;
1377 }
1378
1379 /* always use superset to determine feature support */
1380 VkFormat vkformat = zink_get_format(screen, PIPE_FORMAT_A8_UNORM ? zink_format_get_emulated_alpha(format) : format);
1381 if (vkformat == VK_FORMAT_UNDEFINED)
1382 return false;
1383
1384 if (sample_count >= 1) {
1385 VkSampleCountFlagBits sample_mask = vk_sample_count_flags(sample_count);
1386 if (!sample_mask)
1387 return false;
1388 const struct util_format_description *desc = util_format_description(format);
1389 if (util_format_is_depth_or_stencil(format)) {
1390 if (util_format_has_depth(desc)) {
1391 if (bind & PIPE_BIND_DEPTH_STENCIL &&
1392 (screen->info.props.limits.framebufferDepthSampleCounts & sample_mask) != sample_mask)
1393 return false;
1394 if (bind & PIPE_BIND_SAMPLER_VIEW &&
1395 (screen->info.props.limits.sampledImageDepthSampleCounts & sample_mask) != sample_mask)
1396 return false;
1397 }
1398 if (util_format_has_stencil(desc)) {
1399 if (bind & PIPE_BIND_DEPTH_STENCIL &&
1400 (screen->info.props.limits.framebufferStencilSampleCounts & sample_mask) != sample_mask)
1401 return false;
1402 if (bind & PIPE_BIND_SAMPLER_VIEW &&
1403 (screen->info.props.limits.sampledImageStencilSampleCounts & sample_mask) != sample_mask)
1404 return false;
1405 }
1406 } else if (util_format_is_pure_integer(format)) {
1407 if (bind & PIPE_BIND_RENDER_TARGET &&
1408 !(screen->info.props.limits.framebufferColorSampleCounts & sample_mask))
1409 return false;
1410 if (bind & PIPE_BIND_SAMPLER_VIEW &&
1411 !(screen->info.props.limits.sampledImageIntegerSampleCounts & sample_mask))
1412 return false;
1413 } else {
1414 if (bind & PIPE_BIND_RENDER_TARGET &&
1415 !(screen->info.props.limits.framebufferColorSampleCounts & sample_mask))
1416 return false;
1417 if (bind & PIPE_BIND_SAMPLER_VIEW &&
1418 !(screen->info.props.limits.sampledImageColorSampleCounts & sample_mask))
1419 return false;
1420 }
1421 if (bind & PIPE_BIND_SHADER_IMAGE) {
1422 if (!(screen->info.props.limits.storageImageSampleCounts & sample_mask))
1423 return false;
1424 }
1425 VkResult ret;
1426 VkImageFormatProperties image_props;
1427 VkImageFormatProperties2 props2;
1428 props2.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
1429 props2.pNext = NULL;
1430 VkPhysicalDeviceImageFormatInfo2 info;
1431 info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2;
1432 info.pNext = NULL;
1433 info.format = vkformat;
1434 info.flags = 0;
1435 info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1436 info.tiling = VK_IMAGE_TILING_OPTIMAL;
1437 switch (target) {
1438 case PIPE_TEXTURE_1D:
1439 case PIPE_TEXTURE_1D_ARRAY: {
1440 bool need_2D = false;
1441 if (util_format_is_depth_or_stencil(format))
1442 need_2D |= screen->need_2D_zs;
1443 info.type = need_2D ? VK_IMAGE_TYPE_2D : VK_IMAGE_TYPE_1D;
1444 break;
1445 }
1446
1447 case PIPE_TEXTURE_CUBE:
1448 case PIPE_TEXTURE_CUBE_ARRAY:
1449 info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
1450 FALLTHROUGH;
1451 case PIPE_TEXTURE_2D:
1452 case PIPE_TEXTURE_2D_ARRAY:
1453 case PIPE_TEXTURE_RECT:
1454 info.type = VK_IMAGE_TYPE_2D;
1455 break;
1456
1457 case PIPE_TEXTURE_3D:
1458 info.type = VK_IMAGE_TYPE_3D;
1459 if (bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL))
1460 info.flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
1461 if (screen->info.have_EXT_image_2d_view_of_3d)
1462 info.flags |= VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT;
1463 break;
1464
1465 default:
1466 unreachable("unknown texture target");
1467 }
1468 u_foreach_bit(b, bind) {
1469 switch (1<<b) {
1470 case PIPE_BIND_RENDER_TARGET:
1471 info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1472 break;
1473 case PIPE_BIND_DEPTH_STENCIL:
1474 info.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1475 break;
1476 case PIPE_BIND_SAMPLER_VIEW:
1477 info.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
1478 break;
1479 }
1480 }
1481
1482 if (VKSCR(GetPhysicalDeviceImageFormatProperties2)) {
1483 ret = VKSCR(GetPhysicalDeviceImageFormatProperties2)(screen->pdev, &info, &props2);
1484 /* this is using VK_IMAGE_CREATE_EXTENDED_USAGE_BIT and can't be validated */
1485 if (vk_format_aspects(vkformat) & VK_IMAGE_ASPECT_PLANE_1_BIT)
1486 ret = VK_SUCCESS;
1487 image_props = props2.imageFormatProperties;
1488 } else {
1489 ret = VKSCR(GetPhysicalDeviceImageFormatProperties)(screen->pdev, vkformat, info.type,
1490 info.tiling, info.usage, info.flags, &image_props);
1491 }
1492 if (ret != VK_SUCCESS)
1493 return false;
1494 if (!(sample_count & image_props.sampleCounts))
1495 return false;
1496 }
1497
1498 struct zink_format_props props = screen->format_props[format];
1499
1500 if (target == PIPE_BUFFER) {
1501 if (bind & PIPE_BIND_VERTEX_BUFFER) {
1502 if (!(props.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)) {
1503 enum pipe_format new_format = zink_decompose_vertex_format(format);
1504 if (!new_format)
1505 return false;
1506 if (!(screen->format_props[new_format].bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))
1507 return false;
1508 }
1509 }
1510
1511 if (bind & PIPE_BIND_SAMPLER_VIEW &&
1512 !(props.bufferFeatures & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT))
1513 return false;
1514
1515 if (bind & PIPE_BIND_SHADER_IMAGE &&
1516 !(props.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1517 return false;
1518 } else {
1519 /* all other targets are texture-targets */
1520 if (bind & PIPE_BIND_RENDER_TARGET &&
1521 !(props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
1522 return false;
1523
1524 if (bind & PIPE_BIND_BLENDABLE &&
1525 !(props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT))
1526 return false;
1527
1528 if (bind & PIPE_BIND_SAMPLER_VIEW &&
1529 !(props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT))
1530 return false;
1531
1532 if (bind & PIPE_BIND_SAMPLER_REDUCTION_MINMAX &&
1533 !(props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT))
1534 return false;
1535
1536 if ((bind & PIPE_BIND_SAMPLER_VIEW) || (bind & PIPE_BIND_RENDER_TARGET)) {
1537 /* if this is a 3-component texture, force gallium to give us 4 components by rejecting this one */
1538 const struct util_format_description *desc = util_format_description(format);
1539 if (desc->nr_channels == 3 &&
1540 (desc->block.bits == 24 || desc->block.bits == 48 || desc->block.bits == 96))
1541 return false;
1542 }
1543
1544 if (bind & PIPE_BIND_DEPTH_STENCIL &&
1545 !(props.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT))
1546 return false;
1547
1548 if (bind & PIPE_BIND_SHADER_IMAGE &&
1549 !(props.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
1550 return false;
1551 }
1552
1553 return true;
1554 }
1555
1556 static void
zink_set_damage_region(struct pipe_screen * pscreen,struct pipe_resource * pres,unsigned int nrects,const struct pipe_box * rects)1557 zink_set_damage_region(struct pipe_screen *pscreen, struct pipe_resource *pres, unsigned int nrects, const struct pipe_box *rects)
1558 {
1559 struct zink_resource *res = zink_resource(pres);
1560
1561 for (unsigned i = 0; i < nrects; i++) {
1562 int y = pres->height0 - rects[i].y - rects[i].height;
1563 /* convert back to coord-based rects to use coordinate calcs */
1564 struct u_rect currect = {
1565 .x0 = res->damage.offset.x,
1566 .y0 = res->damage.offset.y,
1567 .x1 = res->damage.offset.x + res->damage.extent.width,
1568 .y1 = res->damage.offset.y + res->damage.extent.height,
1569 };
1570 struct u_rect newrect = {
1571 .x0 = rects[i].x,
1572 .y0 = y,
1573 .x1 = rects[i].x + rects[i].width,
1574 .y1 = y + rects[i].height,
1575 };
1576 struct u_rect u;
1577 u_rect_union(&u, &currect, &newrect);
1578 res->damage.extent.width = u.y1 - u.y0;
1579 res->damage.extent.height = u.x1 - u.x0;
1580 res->damage.offset.x = u.x0;
1581 res->damage.offset.y = u.y0;
1582 }
1583
1584 res->use_damage = nrects > 0;
1585 }
1586
1587 static void
zink_destroy_screen(struct pipe_screen * pscreen)1588 zink_destroy_screen(struct pipe_screen *pscreen)
1589 {
1590 struct zink_screen *screen = zink_screen(pscreen);
1591
1592 if (screen->renderdoc_capture_all && p_atomic_dec_zero(&num_screens))
1593 screen->renderdoc_api->EndFrameCapture(RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE(screen->instance), NULL);
1594
1595 hash_table_foreach(&screen->dts, entry)
1596 zink_kopper_deinit_displaytarget(screen, entry->data);
1597
1598 if (screen->copy_context)
1599 screen->copy_context->base.destroy(&screen->copy_context->base);
1600
1601 struct zink_batch_state *bs = screen->free_batch_states;
1602 while (bs) {
1603 struct zink_batch_state *bs_next = bs->next;
1604 zink_batch_state_destroy(screen, bs);
1605 bs = bs_next;
1606 }
1607
1608 if (VK_NULL_HANDLE != screen->debugUtilsCallbackHandle) {
1609 VKSCR(DestroyDebugUtilsMessengerEXT)(screen->instance, screen->debugUtilsCallbackHandle, NULL);
1610 }
1611
1612 util_vertex_state_cache_deinit(&screen->vertex_state_cache);
1613
1614 if (screen->gfx_push_constant_layout)
1615 VKSCR(DestroyPipelineLayout)(screen->dev, screen->gfx_push_constant_layout, NULL);
1616
1617 u_transfer_helper_destroy(pscreen->transfer_helper);
1618 if (util_queue_is_initialized(&screen->cache_get_thread)) {
1619 util_queue_finish(&screen->cache_get_thread);
1620 util_queue_destroy(&screen->cache_get_thread);
1621 }
1622 #ifdef ENABLE_SHADER_CACHE
1623 if (screen->disk_cache && util_queue_is_initialized(&screen->cache_put_thread)) {
1624 util_queue_finish(&screen->cache_put_thread);
1625 disk_cache_wait_for_idle(screen->disk_cache);
1626 util_queue_destroy(&screen->cache_put_thread);
1627 }
1628 #endif
1629 disk_cache_destroy(screen->disk_cache);
1630
1631 /* we don't have an API to check if a set is already initialized */
1632 for (unsigned i = 0; i < ARRAY_SIZE(screen->pipeline_libs); i++)
1633 if (screen->pipeline_libs[i].table)
1634 _mesa_set_clear(&screen->pipeline_libs[i], NULL);
1635
1636 zink_bo_deinit(screen);
1637 util_live_shader_cache_deinit(&screen->shaders);
1638
1639 zink_descriptor_layouts_deinit(screen);
1640
1641 if (screen->sem)
1642 VKSCR(DestroySemaphore)(screen->dev, screen->sem, NULL);
1643
1644 if (screen->fence)
1645 VKSCR(DestroyFence)(screen->dev, screen->fence, NULL);
1646
1647 if (util_queue_is_initialized(&screen->flush_queue))
1648 util_queue_destroy(&screen->flush_queue);
1649
1650 while (util_dynarray_contains(&screen->semaphores, VkSemaphore))
1651 VKSCR(DestroySemaphore)(screen->dev, util_dynarray_pop(&screen->semaphores, VkSemaphore), NULL);
1652 while (util_dynarray_contains(&screen->fd_semaphores, VkSemaphore))
1653 VKSCR(DestroySemaphore)(screen->dev, util_dynarray_pop(&screen->fd_semaphores, VkSemaphore), NULL);
1654 if (screen->bindless_layout)
1655 VKSCR(DestroyDescriptorSetLayout)(screen->dev, screen->bindless_layout, NULL);
1656
1657 if (screen->dev)
1658 VKSCR(DestroyDevice)(screen->dev, NULL);
1659
1660 if (screen->instance)
1661 VKSCR(DestroyInstance)(screen->instance, NULL);
1662
1663 util_idalloc_mt_fini(&screen->buffer_ids);
1664
1665 if (screen->loader_lib)
1666 util_dl_close(screen->loader_lib);
1667
1668 if (screen->drm_fd != -1)
1669 close(screen->drm_fd);
1670
1671 slab_destroy_parent(&screen->transfer_pool);
1672 ralloc_free(screen);
1673 glsl_type_singleton_decref();
1674 }
1675
1676 static int
zink_get_display_device(const struct zink_screen * screen,uint32_t pdev_count,const VkPhysicalDevice * pdevs,int64_t dev_major,int64_t dev_minor)1677 zink_get_display_device(const struct zink_screen *screen, uint32_t pdev_count,
1678 const VkPhysicalDevice *pdevs, int64_t dev_major,
1679 int64_t dev_minor)
1680 {
1681 VkPhysicalDeviceDrmPropertiesEXT drm_props = {
1682 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT,
1683 };
1684 VkPhysicalDeviceProperties2 props = {
1685 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
1686 .pNext = &drm_props,
1687 };
1688
1689 for (uint32_t i = 0; i < pdev_count; ++i) {
1690 VKSCR(GetPhysicalDeviceProperties2)(pdevs[i], &props);
1691 if (drm_props.renderMajor == dev_major &&
1692 drm_props.renderMinor == dev_minor)
1693 return i;
1694 }
1695
1696 return -1;
1697 }
1698
1699 static int
zink_get_cpu_device_type(const struct zink_screen * screen,uint32_t pdev_count,const VkPhysicalDevice * pdevs)1700 zink_get_cpu_device_type(const struct zink_screen *screen, uint32_t pdev_count,
1701 const VkPhysicalDevice *pdevs)
1702 {
1703 VkPhysicalDeviceProperties props;
1704
1705 for (uint32_t i = 0; i < pdev_count; ++i) {
1706 VKSCR(GetPhysicalDeviceProperties)(pdevs[i], &props);
1707
1708 /* if user wants cpu, only give them cpu */
1709 if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU)
1710 return i;
1711 }
1712
1713 mesa_loge("ZINK: CPU device requested but none found!");
1714
1715 return -1;
1716 }
1717
1718 static void
choose_pdev(struct zink_screen * screen,int64_t dev_major,int64_t dev_minor)1719 choose_pdev(struct zink_screen *screen, int64_t dev_major, int64_t dev_minor)
1720 {
1721 bool cpu = debug_get_bool_option("LIBGL_ALWAYS_SOFTWARE", false) ||
1722 debug_get_bool_option("D3D_ALWAYS_SOFTWARE", false);
1723
1724 if (cpu || (dev_major > 0 && dev_major < 255)) {
1725 uint32_t pdev_count;
1726 int idx;
1727 VkPhysicalDevice *pdevs;
1728 VkResult result = VKSCR(EnumeratePhysicalDevices)(screen->instance, &pdev_count, NULL);
1729 if (result != VK_SUCCESS) {
1730 if (!screen->driver_name_is_inferred)
1731 mesa_loge("ZINK: vkEnumeratePhysicalDevices failed (%s)", vk_Result_to_str(result));
1732 return;
1733 }
1734
1735 if (!pdev_count)
1736 return;
1737
1738 pdevs = malloc(sizeof(*pdevs) * pdev_count);
1739 if (!pdevs) {
1740 if (!screen->driver_name_is_inferred)
1741 mesa_loge("ZINK: failed to allocate pdevs!");
1742 return;
1743 }
1744 result = VKSCR(EnumeratePhysicalDevices)(screen->instance, &pdev_count, pdevs);
1745 assert(result == VK_SUCCESS);
1746 assert(pdev_count > 0);
1747
1748 if (cpu)
1749 idx = zink_get_cpu_device_type(screen, pdev_count, pdevs);
1750 else
1751 idx = zink_get_display_device(screen, pdev_count, pdevs, dev_major,
1752 dev_minor);
1753
1754 if (idx != -1)
1755 /* valid cpu device */
1756 screen->pdev = pdevs[idx];
1757
1758 free(pdevs);
1759
1760 if (idx == -1)
1761 return;
1762
1763 } else {
1764 VkPhysicalDevice pdev;
1765 unsigned pdev_count = 1;
1766 VkResult result = VKSCR(EnumeratePhysicalDevices)(screen->instance, &pdev_count, &pdev);
1767 if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
1768 if (!screen->driver_name_is_inferred)
1769 mesa_loge("ZINK: vkEnumeratePhysicalDevices failed (%s)", vk_Result_to_str(result));
1770 return;
1771 }
1772 if (!pdev_count)
1773 return;
1774 screen->pdev = pdev;
1775 }
1776 VKSCR(GetPhysicalDeviceProperties)(screen->pdev, &screen->info.props);
1777
1778 /* allow software rendering only if forced by the user */
1779 if (!cpu && screen->info.props.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU) {
1780 screen->pdev = VK_NULL_HANDLE;
1781 return;
1782 }
1783
1784 screen->info.device_version = screen->info.props.apiVersion;
1785
1786 /* runtime version is the lesser of the instance version and device version */
1787 screen->vk_version = MIN2(screen->info.device_version, screen->instance_info.loader_version);
1788
1789 /* calculate SPIR-V version based on VK version */
1790 if (screen->vk_version >= VK_MAKE_VERSION(1, 3, 0))
1791 screen->spirv_version = SPIRV_VERSION(1, 6);
1792 else if (screen->vk_version >= VK_MAKE_VERSION(1, 2, 0))
1793 screen->spirv_version = SPIRV_VERSION(1, 5);
1794 else if (screen->vk_version >= VK_MAKE_VERSION(1, 1, 0))
1795 screen->spirv_version = SPIRV_VERSION(1, 3);
1796 else
1797 screen->spirv_version = SPIRV_VERSION(1, 0);
1798 }
1799
1800 static void
update_queue_props(struct zink_screen * screen)1801 update_queue_props(struct zink_screen *screen)
1802 {
1803 uint32_t num_queues;
1804 VKSCR(GetPhysicalDeviceQueueFamilyProperties)(screen->pdev, &num_queues, NULL);
1805 assert(num_queues > 0);
1806
1807 VkQueueFamilyProperties *props = malloc(sizeof(*props) * num_queues);
1808 if (!props) {
1809 mesa_loge("ZINK: failed to allocate props!");
1810 return;
1811 }
1812
1813 VKSCR(GetPhysicalDeviceQueueFamilyProperties)(screen->pdev, &num_queues, props);
1814
1815 bool found_gfx = false;
1816 uint32_t sparse_only = UINT32_MAX;
1817 screen->sparse_queue = UINT32_MAX;
1818 for (uint32_t i = 0; i < num_queues; i++) {
1819 if (props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
1820 if (found_gfx)
1821 continue;
1822 screen->sparse_queue = screen->gfx_queue = i;
1823 screen->max_queues = props[i].queueCount;
1824 screen->timestamp_valid_bits = props[i].timestampValidBits;
1825 found_gfx = true;
1826 } else if (props[i].queueFlags & VK_QUEUE_SPARSE_BINDING_BIT)
1827 sparse_only = i;
1828 }
1829 if (sparse_only != UINT32_MAX)
1830 screen->sparse_queue = sparse_only;
1831 free(props);
1832 }
1833
1834 static void
init_queue(struct zink_screen * screen)1835 init_queue(struct zink_screen *screen)
1836 {
1837 simple_mtx_init(&screen->queue_lock, mtx_plain);
1838 VKSCR(GetDeviceQueue)(screen->dev, screen->gfx_queue, 0, &screen->queue);
1839 if (screen->sparse_queue != screen->gfx_queue)
1840 VKSCR(GetDeviceQueue)(screen->dev, screen->sparse_queue, 0, &screen->queue_sparse);
1841 else
1842 screen->queue_sparse = screen->queue;
1843 }
1844
1845 static void
zink_flush_frontbuffer(struct pipe_screen * pscreen,struct pipe_context * pctx,struct pipe_resource * pres,unsigned level,unsigned layer,void * winsys_drawable_handle,unsigned nboxes,struct pipe_box * sub_box)1846 zink_flush_frontbuffer(struct pipe_screen *pscreen,
1847 struct pipe_context *pctx,
1848 struct pipe_resource *pres,
1849 unsigned level, unsigned layer,
1850 void *winsys_drawable_handle,
1851 unsigned nboxes,
1852 struct pipe_box *sub_box)
1853 {
1854 struct zink_screen *screen = zink_screen(pscreen);
1855 struct zink_resource *res = zink_resource(pres);
1856 struct zink_context *ctx = zink_context(pctx);
1857
1858 /* if the surface is no longer a swapchain, this is a no-op */
1859 if (!zink_is_swapchain(res))
1860 return;
1861
1862 ctx = zink_tc_context_unwrap(pctx, screen->threaded);
1863
1864 if (!zink_kopper_acquired(res->obj->dt, res->obj->dt_idx)) {
1865 /* swapbuffers to an undefined surface: acquire and present garbage */
1866 zink_kopper_acquire(ctx, res, UINT64_MAX);
1867 ctx->needs_present = res;
1868 /* set batch usage to submit acquire semaphore */
1869 zink_batch_resource_usage_set(ctx->bs, res, true, false);
1870 /* ensure the resource is set up to present garbage */
1871 ctx->base.flush_resource(&ctx->base, pres);
1872 }
1873
1874 /* handle any outstanding acquire submits (not just from above) */
1875 if (ctx->swapchain || ctx->needs_present) {
1876 ctx->bs->has_work = true;
1877 pctx->flush(pctx, NULL, PIPE_FLUSH_END_OF_FRAME);
1878 if (ctx->last_batch_state && screen->threaded_submit) {
1879 struct zink_batch_state *bs = ctx->last_batch_state;
1880 util_queue_fence_wait(&bs->flush_completed);
1881 }
1882 }
1883 res->use_damage = false;
1884
1885 /* always verify that this was acquired */
1886 assert(zink_kopper_acquired(res->obj->dt, res->obj->dt_idx));
1887 zink_kopper_present_queue(screen, res, nboxes, sub_box);
1888 }
1889
1890 bool
zink_is_depth_format_supported(struct zink_screen * screen,VkFormat format)1891 zink_is_depth_format_supported(struct zink_screen *screen, VkFormat format)
1892 {
1893 VkFormatProperties props;
1894 VKSCR(GetPhysicalDeviceFormatProperties)(screen->pdev, format, &props);
1895 return (props.linearTilingFeatures | props.optimalTilingFeatures) &
1896 VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
1897 }
1898
1899 static enum pipe_format
emulate_x8(enum pipe_format format)1900 emulate_x8(enum pipe_format format)
1901 {
1902 /* convert missing Xn variants to An */
1903 switch (format) {
1904 case PIPE_FORMAT_B8G8R8X8_UNORM:
1905 return PIPE_FORMAT_B8G8R8A8_UNORM;
1906
1907 case PIPE_FORMAT_B8G8R8X8_SRGB:
1908 return PIPE_FORMAT_B8G8R8A8_SRGB;
1909 case PIPE_FORMAT_R8G8B8X8_SRGB:
1910 return PIPE_FORMAT_R8G8B8A8_SRGB;
1911
1912 case PIPE_FORMAT_R8G8B8X8_SINT:
1913 return PIPE_FORMAT_R8G8B8A8_SINT;
1914 case PIPE_FORMAT_R8G8B8X8_SNORM:
1915 return PIPE_FORMAT_R8G8B8A8_SNORM;
1916 case PIPE_FORMAT_R8G8B8X8_UNORM:
1917 return PIPE_FORMAT_R8G8B8A8_UNORM;
1918
1919 case PIPE_FORMAT_R16G16B16X16_FLOAT:
1920 return PIPE_FORMAT_R16G16B16A16_FLOAT;
1921 case PIPE_FORMAT_R16G16B16X16_SINT:
1922 return PIPE_FORMAT_R16G16B16A16_SINT;
1923 case PIPE_FORMAT_R16G16B16X16_SNORM:
1924 return PIPE_FORMAT_R16G16B16A16_SNORM;
1925 case PIPE_FORMAT_R16G16B16X16_UNORM:
1926 return PIPE_FORMAT_R16G16B16A16_UNORM;
1927
1928 case PIPE_FORMAT_R32G32B32X32_FLOAT:
1929 return PIPE_FORMAT_R32G32B32A32_FLOAT;
1930 case PIPE_FORMAT_R32G32B32X32_SINT:
1931 return PIPE_FORMAT_R32G32B32A32_SINT;
1932
1933 default:
1934 return format;
1935 }
1936 }
1937
1938 VkFormat
zink_get_format(struct zink_screen * screen,enum pipe_format format)1939 zink_get_format(struct zink_screen *screen, enum pipe_format format)
1940 {
1941 if (format == PIPE_FORMAT_A8_UNORM && !screen->driver_workarounds.missing_a8_unorm)
1942 return VK_FORMAT_A8_UNORM_KHR;
1943 else if (!screen->driver_workarounds.broken_l4a4 || format != PIPE_FORMAT_L4A4_UNORM)
1944 format = zink_format_get_emulated_alpha(format);
1945
1946 VkFormat ret = vk_format_from_pipe_format(emulate_x8(format));
1947
1948 if (format == PIPE_FORMAT_X32_S8X24_UINT &&
1949 screen->have_D32_SFLOAT_S8_UINT)
1950 return VK_FORMAT_D32_SFLOAT_S8_UINT;
1951
1952 if (format == PIPE_FORMAT_X24S8_UINT)
1953 /* valid when using aspects to extract stencil,
1954 * fails format test because it's emulated */
1955 ret = VK_FORMAT_D24_UNORM_S8_UINT;
1956
1957 if (ret == VK_FORMAT_X8_D24_UNORM_PACK32 &&
1958 !screen->have_X8_D24_UNORM_PACK32) {
1959 assert(zink_is_depth_format_supported(screen, VK_FORMAT_D32_SFLOAT));
1960 return VK_FORMAT_D32_SFLOAT;
1961 }
1962
1963 if (ret == VK_FORMAT_D24_UNORM_S8_UINT &&
1964 !screen->have_D24_UNORM_S8_UINT) {
1965 assert(screen->have_D32_SFLOAT_S8_UINT);
1966 return VK_FORMAT_D32_SFLOAT_S8_UINT;
1967 }
1968
1969 if ((ret == VK_FORMAT_A4B4G4R4_UNORM_PACK16 &&
1970 !screen->info.format_4444_feats.formatA4B4G4R4) ||
1971 (ret == VK_FORMAT_A4R4G4B4_UNORM_PACK16 &&
1972 !screen->info.format_4444_feats.formatA4R4G4B4))
1973 return VK_FORMAT_UNDEFINED;
1974
1975 if (format == PIPE_FORMAT_R4A4_UNORM)
1976 return VK_FORMAT_R4G4_UNORM_PACK8;
1977
1978 return ret;
1979 }
1980
1981 void
zink_convert_color(const struct zink_screen * screen,enum pipe_format format,union pipe_color_union * dst,const union pipe_color_union * src)1982 zink_convert_color(const struct zink_screen *screen, enum pipe_format format,
1983 union pipe_color_union *dst,
1984 const union pipe_color_union *src)
1985 {
1986 const struct util_format_description *desc = util_format_description(format);
1987 union pipe_color_union tmp = *src;
1988
1989 for (unsigned i = 0; i < 4; i++)
1990 zink_format_clamp_channel_color(desc, &tmp, src, i);
1991
1992 if (zink_format_is_emulated_alpha(format) &&
1993 /* Don't swizzle colors if the driver supports real A8_UNORM */
1994 (format != PIPE_FORMAT_A8_UNORM ||
1995 screen->driver_workarounds.missing_a8_unorm)) {
1996 if (util_format_is_alpha(format)) {
1997 tmp.ui[0] = tmp.ui[3];
1998 tmp.ui[1] = 0;
1999 tmp.ui[2] = 0;
2000 tmp.ui[3] = 0;
2001 } else if (util_format_is_luminance(format)) {
2002 tmp.ui[1] = 0;
2003 tmp.ui[2] = 0;
2004 tmp.f[3] = 1.0;
2005 } else if (util_format_is_luminance_alpha(format)) {
2006 tmp.ui[1] = tmp.ui[3];
2007 tmp.ui[2] = 0;
2008 tmp.f[3] = 1.0;
2009 } else /* zink_format_is_red_alpha */ {
2010 tmp.ui[1] = tmp.ui[3];
2011 tmp.ui[2] = 0;
2012 tmp.ui[3] = 0;
2013 }
2014 }
2015
2016 memcpy(dst, &tmp, sizeof(union pipe_color_union));
2017 }
2018
2019 static bool
check_have_device_time(struct zink_screen * screen)2020 check_have_device_time(struct zink_screen *screen)
2021 {
2022 uint32_t num_domains = 0;
2023 VkTimeDomainEXT domains[8]; //current max is 4
2024 VkResult result = VKSCR(GetPhysicalDeviceCalibrateableTimeDomainsEXT)(screen->pdev, &num_domains, NULL);
2025 if (result != VK_SUCCESS) {
2026 mesa_loge("ZINK: vkGetPhysicalDeviceCalibrateableTimeDomainsEXT failed (%s)", vk_Result_to_str(result));
2027 }
2028 assert(num_domains > 0);
2029 assert(num_domains < ARRAY_SIZE(domains));
2030
2031 result = VKSCR(GetPhysicalDeviceCalibrateableTimeDomainsEXT)(screen->pdev, &num_domains, domains);
2032 if (result != VK_SUCCESS) {
2033 mesa_loge("ZINK: vkGetPhysicalDeviceCalibrateableTimeDomainsEXT failed (%s)", vk_Result_to_str(result));
2034 }
2035
2036 /* VK_TIME_DOMAIN_DEVICE_EXT is used for the ctx->get_timestamp hook and is the only one we really need */
2037 for (unsigned i = 0; i < num_domains; i++) {
2038 if (domains[i] == VK_TIME_DOMAIN_DEVICE_EXT) {
2039 return true;
2040 }
2041 }
2042
2043 return false;
2044 }
2045
2046 static void
zink_error(const char * msg)2047 zink_error(const char *msg)
2048 {
2049 }
2050
2051 static void
zink_warn(const char * msg)2052 zink_warn(const char *msg)
2053 {
2054 }
2055
2056 static void
zink_info(const char * msg)2057 zink_info(const char *msg)
2058 {
2059 }
2060
2061 static void
zink_msg(const char * msg)2062 zink_msg(const char *msg)
2063 {
2064 }
2065
2066 static VKAPI_ATTR VkBool32 VKAPI_CALL
zink_debug_util_callback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,VkDebugUtilsMessageTypeFlagsEXT messageType,const VkDebugUtilsMessengerCallbackDataEXT * pCallbackData,void * pUserData)2067 zink_debug_util_callback(
2068 VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
2069 VkDebugUtilsMessageTypeFlagsEXT messageType,
2070 const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData,
2071 void *pUserData)
2072 {
2073 // Pick message prefix and color to use.
2074 // Only MacOS and Linux have been tested for color support
2075 if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
2076 zink_error(pCallbackData->pMessage);
2077 } else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
2078 zink_warn(pCallbackData->pMessage);
2079 } else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) {
2080 zink_info(pCallbackData->pMessage);
2081 } else
2082 zink_msg(pCallbackData->pMessage);
2083
2084 return VK_FALSE;
2085 }
2086
2087 static bool
create_debug(struct zink_screen * screen)2088 create_debug(struct zink_screen *screen)
2089 {
2090 VkDebugUtilsMessengerCreateInfoEXT vkDebugUtilsMessengerCreateInfoEXT = {
2091 VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
2092 NULL,
2093 0, // flags
2094 VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
2095 VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT |
2096 VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
2097 VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
2098 VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
2099 VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
2100 VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
2101 zink_debug_util_callback,
2102 NULL
2103 };
2104
2105 VkDebugUtilsMessengerEXT vkDebugUtilsCallbackEXT = VK_NULL_HANDLE;
2106
2107 VkResult result = VKSCR(CreateDebugUtilsMessengerEXT)(
2108 screen->instance,
2109 &vkDebugUtilsMessengerCreateInfoEXT,
2110 NULL,
2111 &vkDebugUtilsCallbackEXT);
2112 if (result != VK_SUCCESS) {
2113 mesa_loge("ZINK: vkCreateDebugUtilsMessengerEXT failed (%s)", vk_Result_to_str(result));
2114 }
2115
2116 screen->debugUtilsCallbackHandle = vkDebugUtilsCallbackEXT;
2117
2118 return true;
2119 }
2120
2121 static bool
zink_internal_setup_moltenvk(struct zink_screen * screen)2122 zink_internal_setup_moltenvk(struct zink_screen *screen)
2123 {
2124 #if defined(MVK_VERSION)
2125 if (!screen->instance_info.have_MVK_moltenvk)
2126 return true;
2127
2128 GET_PROC_ADDR_INSTANCE_LOCAL(screen, screen->instance, GetMoltenVKConfigurationMVK);
2129 GET_PROC_ADDR_INSTANCE_LOCAL(screen, screen->instance, SetMoltenVKConfigurationMVK);
2130 GET_PROC_ADDR_INSTANCE_LOCAL(screen, screen->instance, GetVersionStringsMVK);
2131
2132 if (vk_GetVersionStringsMVK) {
2133 char molten_version[64] = {0};
2134 char vulkan_version[64] = {0};
2135
2136 vk_GetVersionStringsMVK(molten_version, sizeof(molten_version) - 1, vulkan_version, sizeof(vulkan_version) - 1);
2137
2138 printf("zink: MoltenVK %s Vulkan %s \n", molten_version, vulkan_version);
2139 }
2140
2141 if (vk_GetMoltenVKConfigurationMVK && vk_SetMoltenVKConfigurationMVK) {
2142 MVKConfiguration molten_config = {0};
2143 size_t molten_config_size = sizeof(molten_config);
2144
2145 VkResult res = vk_GetMoltenVKConfigurationMVK(screen->instance, &molten_config, &molten_config_size);
2146 if (res == VK_SUCCESS || res == VK_INCOMPLETE) {
2147 // Needed to allow MoltenVK to accept VkImageView swizzles.
2148 // Encountered when using VK_FORMAT_R8G8_UNORM
2149 molten_config.fullImageViewSwizzle = VK_TRUE;
2150 vk_SetMoltenVKConfigurationMVK(screen->instance, &molten_config, &molten_config_size);
2151 }
2152 }
2153 #endif // MVK_VERSION
2154
2155 return true;
2156 }
2157
2158 static void
check_vertex_formats(struct zink_screen * screen)2159 check_vertex_formats(struct zink_screen *screen)
2160 {
2161 /* from vbuf */
2162 enum pipe_format format_list[] = {
2163 /* not supported by vk
2164 PIPE_FORMAT_R32_FIXED,
2165 PIPE_FORMAT_R32G32_FIXED,
2166 PIPE_FORMAT_R32G32B32_FIXED,
2167 PIPE_FORMAT_R32G32B32A32_FIXED,
2168 */
2169 PIPE_FORMAT_R16_FLOAT,
2170 PIPE_FORMAT_R16G16_FLOAT,
2171 PIPE_FORMAT_R16G16B16_FLOAT,
2172 PIPE_FORMAT_R16G16B16A16_FLOAT,
2173 /* not supported by vk
2174 PIPE_FORMAT_R64_FLOAT,
2175 PIPE_FORMAT_R64G64_FLOAT,
2176 PIPE_FORMAT_R64G64B64_FLOAT,
2177 PIPE_FORMAT_R64G64B64A64_FLOAT,
2178 PIPE_FORMAT_R32_UNORM,
2179 PIPE_FORMAT_R32G32_UNORM,
2180 PIPE_FORMAT_R32G32B32_UNORM,
2181 PIPE_FORMAT_R32G32B32A32_UNORM,
2182 PIPE_FORMAT_R32_SNORM,
2183 PIPE_FORMAT_R32G32_SNORM,
2184 PIPE_FORMAT_R32G32B32_SNORM,
2185 PIPE_FORMAT_R32G32B32A32_SNORM,
2186 PIPE_FORMAT_R32_USCALED,
2187 PIPE_FORMAT_R32G32_USCALED,
2188 PIPE_FORMAT_R32G32B32_USCALED,
2189 PIPE_FORMAT_R32G32B32A32_USCALED,
2190 PIPE_FORMAT_R32_SSCALED,
2191 PIPE_FORMAT_R32G32_SSCALED,
2192 PIPE_FORMAT_R32G32B32_SSCALED,
2193 PIPE_FORMAT_R32G32B32A32_SSCALED,
2194 */
2195 PIPE_FORMAT_R16_UNORM,
2196 PIPE_FORMAT_R16G16_UNORM,
2197 PIPE_FORMAT_R16G16B16_UNORM,
2198 PIPE_FORMAT_R16G16B16A16_UNORM,
2199 PIPE_FORMAT_R16_SNORM,
2200 PIPE_FORMAT_R16G16_SNORM,
2201 PIPE_FORMAT_R16G16B16_SNORM,
2202 PIPE_FORMAT_R16G16B16_SINT,
2203 PIPE_FORMAT_R16G16B16_UINT,
2204 PIPE_FORMAT_R16G16B16A16_SNORM,
2205 PIPE_FORMAT_R16_USCALED,
2206 PIPE_FORMAT_R16G16_USCALED,
2207 PIPE_FORMAT_R16G16B16_USCALED,
2208 PIPE_FORMAT_R16G16B16A16_USCALED,
2209 PIPE_FORMAT_R16_SSCALED,
2210 PIPE_FORMAT_R16G16_SSCALED,
2211 PIPE_FORMAT_R16G16B16_SSCALED,
2212 PIPE_FORMAT_R16G16B16A16_SSCALED,
2213 PIPE_FORMAT_R8_UNORM,
2214 PIPE_FORMAT_R8G8_UNORM,
2215 PIPE_FORMAT_R8G8B8_UNORM,
2216 PIPE_FORMAT_R8G8B8A8_UNORM,
2217 PIPE_FORMAT_R8_SNORM,
2218 PIPE_FORMAT_R8G8_SNORM,
2219 PIPE_FORMAT_R8G8B8_SNORM,
2220 PIPE_FORMAT_R8G8B8A8_SNORM,
2221 PIPE_FORMAT_R8_USCALED,
2222 PIPE_FORMAT_R8G8_USCALED,
2223 PIPE_FORMAT_R8G8B8_USCALED,
2224 PIPE_FORMAT_R8G8B8A8_USCALED,
2225 PIPE_FORMAT_R8_SSCALED,
2226 PIPE_FORMAT_R8G8_SSCALED,
2227 PIPE_FORMAT_R8G8B8_SSCALED,
2228 PIPE_FORMAT_R8G8B8A8_SSCALED,
2229 };
2230 for (unsigned i = 0; i < ARRAY_SIZE(format_list); i++) {
2231 if (zink_is_format_supported(&screen->base, format_list[i], PIPE_BUFFER, 0, 0, PIPE_BIND_VERTEX_BUFFER))
2232 continue;
2233 if (util_format_get_nr_components(format_list[i]) == 1)
2234 continue;
2235 enum pipe_format decomposed = zink_decompose_vertex_format(format_list[i]);
2236 if (zink_is_format_supported(&screen->base, decomposed, PIPE_BUFFER, 0, 0, PIPE_BIND_VERTEX_BUFFER)) {
2237 screen->need_decompose_attrs = true;
2238 mesa_logw("zink: this application would be much faster if %s supported vertex format %s", screen->info.props.deviceName, util_format_name(format_list[i]));
2239 }
2240 }
2241 }
2242
2243 static void
populate_format_props(struct zink_screen * screen)2244 populate_format_props(struct zink_screen *screen)
2245 {
2246 for (unsigned i = 0; i < PIPE_FORMAT_COUNT; i++) {
2247 VkFormat format;
2248 retry:
2249 format = zink_get_format(screen, i);
2250 if (!format)
2251 continue;
2252 if (VKSCR(GetPhysicalDeviceFormatProperties2)) {
2253 VkFormatProperties2 props = {0};
2254 props.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2;
2255
2256 VkDrmFormatModifierPropertiesListEXT mod_props;
2257 VkDrmFormatModifierPropertiesEXT mods[128];
2258 if (screen->info.have_EXT_image_drm_format_modifier) {
2259 mod_props.sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT;
2260 mod_props.pNext = NULL;
2261 mod_props.drmFormatModifierCount = ARRAY_SIZE(mods);
2262 mod_props.pDrmFormatModifierProperties = mods;
2263 props.pNext = &mod_props;
2264 }
2265 VkFormatProperties3 props3 = {0};
2266 if (screen->info.have_KHR_format_feature_flags2 || screen->info.have_vulkan13) {
2267 props3.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3;
2268 props3.pNext = props.pNext;
2269 props.pNext = &props3;
2270 }
2271
2272 VKSCR(GetPhysicalDeviceFormatProperties2)(screen->pdev, format, &props);
2273
2274 if (screen->info.have_KHR_format_feature_flags2 || screen->info.have_vulkan13) {
2275 screen->format_props[i].linearTilingFeatures = props3.linearTilingFeatures;
2276 screen->format_props[i].optimalTilingFeatures = props3.optimalTilingFeatures;
2277 screen->format_props[i].bufferFeatures = props3.bufferFeatures;
2278
2279 if (props3.linearTilingFeatures & VK_FORMAT_FEATURE_2_LINEAR_COLOR_ATTACHMENT_BIT_NV)
2280 screen->format_props[i].linearTilingFeatures |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
2281 } else {
2282 // MoltenVk is 1.2 API
2283 screen->format_props[i].linearTilingFeatures = props.formatProperties.linearTilingFeatures;
2284 screen->format_props[i].optimalTilingFeatures = props.formatProperties.optimalTilingFeatures;
2285 screen->format_props[i].bufferFeatures = props.formatProperties.bufferFeatures;
2286 }
2287
2288 if (screen->info.have_EXT_image_drm_format_modifier && mod_props.drmFormatModifierCount) {
2289 screen->modifier_props[i].drmFormatModifierCount = mod_props.drmFormatModifierCount;
2290 screen->modifier_props[i].pDrmFormatModifierProperties = ralloc_array(screen, VkDrmFormatModifierPropertiesEXT, mod_props.drmFormatModifierCount);
2291 if (mod_props.pDrmFormatModifierProperties) {
2292 for (unsigned j = 0; j < mod_props.drmFormatModifierCount; j++)
2293 screen->modifier_props[i].pDrmFormatModifierProperties[j] = mod_props.pDrmFormatModifierProperties[j];
2294 }
2295 }
2296 } else {
2297 VkFormatProperties props = {0};
2298 VKSCR(GetPhysicalDeviceFormatProperties)(screen->pdev, format, &props);
2299 screen->format_props[i].linearTilingFeatures = props.linearTilingFeatures;
2300 screen->format_props[i].optimalTilingFeatures = props.optimalTilingFeatures;
2301 screen->format_props[i].bufferFeatures = props.bufferFeatures;
2302 }
2303 if (i == PIPE_FORMAT_A8_UNORM && !screen->driver_workarounds.missing_a8_unorm) {
2304 if (!screen->format_props[i].linearTilingFeatures &&
2305 !screen->format_props[i].optimalTilingFeatures &&
2306 !screen->format_props[i].bufferFeatures) {
2307 screen->driver_workarounds.missing_a8_unorm = true;
2308 goto retry;
2309 }
2310 }
2311 if (zink_format_is_emulated_alpha(i)) {
2312 VkFormatFeatureFlags blocked = VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
2313 screen->format_props[i].linearTilingFeatures &= ~blocked;
2314 screen->format_props[i].optimalTilingFeatures &= ~blocked;
2315 screen->format_props[i].bufferFeatures = 0;
2316 }
2317 }
2318 check_vertex_formats(screen);
2319 VkImageFormatProperties image_props;
2320 VkResult ret = VKSCR(GetPhysicalDeviceImageFormatProperties)(screen->pdev, VK_FORMAT_D32_SFLOAT,
2321 VK_IMAGE_TYPE_1D,
2322 VK_IMAGE_TILING_OPTIMAL,
2323 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
2324 0, &image_props);
2325 if (ret != VK_SUCCESS && ret != VK_ERROR_FORMAT_NOT_SUPPORTED) {
2326 mesa_loge("ZINK: vkGetPhysicalDeviceImageFormatProperties failed (%s)", vk_Result_to_str(ret));
2327 }
2328 screen->need_2D_zs = ret != VK_SUCCESS;
2329
2330 if (screen->info.feats.features.sparseResidencyImage2D)
2331 screen->need_2D_sparse = !screen->base.get_sparse_texture_virtual_page_size(&screen->base, PIPE_TEXTURE_1D, false, PIPE_FORMAT_R32_FLOAT, 0, 16, NULL, NULL, NULL);
2332 }
2333
2334 static void
setup_renderdoc(struct zink_screen * screen)2335 setup_renderdoc(struct zink_screen *screen)
2336 {
2337 #ifndef _WIN32
2338 const char *capture_id = debug_get_option("ZINK_RENDERDOC", NULL);
2339 if (!capture_id)
2340 return;
2341 void *renderdoc = dlopen("librenderdoc.so", RTLD_NOW | RTLD_NOLOAD);
2342 /* not loaded */
2343 if (!renderdoc)
2344 return;
2345
2346 pRENDERDOC_GetAPI get_api = dlsym(renderdoc, "RENDERDOC_GetAPI");
2347 if (!get_api)
2348 return;
2349
2350 /* need synchronous dispatch for renderdoc coherency */
2351 screen->threaded_submit = false;
2352 get_api(eRENDERDOC_API_Version_1_0_0, (void*)&screen->renderdoc_api);
2353 screen->renderdoc_api->SetActiveWindow(RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE(screen->instance), NULL);
2354
2355 int count = sscanf(capture_id, "%u:%u", &screen->renderdoc_capture_start, &screen->renderdoc_capture_end);
2356 if (count != 2) {
2357 count = sscanf(capture_id, "%u", &screen->renderdoc_capture_start);
2358 if (!count) {
2359 if (!strcmp(capture_id, "all")) {
2360 screen->renderdoc_capture_all = true;
2361 } else {
2362 printf("`ZINK_RENDERDOC` usage: ZINK_RENDERDOC=all|frame_no[:end_frame_no]\n");
2363 abort();
2364 }
2365 }
2366 screen->renderdoc_capture_end = screen->renderdoc_capture_start;
2367 }
2368 p_atomic_set(&screen->renderdoc_frame, 1);
2369 #endif
2370 }
2371
2372 bool
zink_screen_init_semaphore(struct zink_screen * screen)2373 zink_screen_init_semaphore(struct zink_screen *screen)
2374 {
2375 VkSemaphoreCreateInfo sci = {0};
2376 VkSemaphoreTypeCreateInfo tci = {0};
2377 sci.pNext = &tci;
2378 sci.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
2379 tci.sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO;
2380 tci.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE;
2381
2382 return VKSCR(CreateSemaphore)(screen->dev, &sci, NULL, &screen->sem) == VK_SUCCESS;
2383 }
2384
2385 VkSemaphore
zink_create_exportable_semaphore(struct zink_screen * screen)2386 zink_create_exportable_semaphore(struct zink_screen *screen)
2387 {
2388 VkExportSemaphoreCreateInfo eci = {
2389 VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
2390 NULL,
2391 VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
2392 };
2393 VkSemaphoreCreateInfo sci = {
2394 VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
2395 &eci,
2396 0
2397 };
2398
2399 VkSemaphore sem = VK_NULL_HANDLE;
2400 if (util_dynarray_contains(&screen->fd_semaphores, VkSemaphore)) {
2401 simple_mtx_lock(&screen->semaphores_lock);
2402 if (util_dynarray_contains(&screen->fd_semaphores, VkSemaphore))
2403 sem = util_dynarray_pop(&screen->fd_semaphores, VkSemaphore);
2404 simple_mtx_unlock(&screen->semaphores_lock);
2405 }
2406 if (sem)
2407 return sem;
2408 VkResult ret = VKSCR(CreateSemaphore)(screen->dev, &sci, NULL, &sem);
2409 return ret == VK_SUCCESS ? sem : VK_NULL_HANDLE;
2410 }
2411
2412 VkSemaphore
zink_screen_export_dmabuf_semaphore(struct zink_screen * screen,struct zink_resource * res)2413 zink_screen_export_dmabuf_semaphore(struct zink_screen *screen, struct zink_resource *res)
2414 {
2415 VkSemaphore sem = VK_NULL_HANDLE;
2416 #if defined(HAVE_LIBDRM) && (DETECT_OS_LINUX || DETECT_OS_BSD)
2417 struct dma_buf_export_sync_file export = {
2418 .flags = DMA_BUF_SYNC_RW,
2419 .fd = -1,
2420 };
2421
2422 int fd = -1;
2423 if (res->obj->is_aux) {
2424 fd = os_dupfd_cloexec(res->obj->handle);
2425 } else {
2426 VkMemoryGetFdInfoKHR fd_info = {0};
2427 fd_info.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR;
2428 fd_info.memory = zink_bo_get_mem(res->obj->bo);
2429 fd_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
2430 VKSCR(GetMemoryFdKHR)(screen->dev, &fd_info, &fd);
2431 }
2432
2433 if (unlikely(fd < 0)) {
2434 mesa_loge("MESA: Unable to get a valid memory fd");
2435 return VK_NULL_HANDLE;
2436 }
2437
2438 int ret = drmIoctl(fd, DMA_BUF_IOCTL_EXPORT_SYNC_FILE, &export);
2439 if (ret) {
2440 if (errno == ENOTTY || errno == EBADF || errno == ENOSYS) {
2441 assert(!"how did this fail?");
2442 return VK_NULL_HANDLE;
2443 } else {
2444 mesa_loge("MESA: failed to import sync file '%s'", strerror(errno));
2445 return VK_NULL_HANDLE;
2446 }
2447 }
2448
2449 sem = zink_create_exportable_semaphore(screen);
2450
2451 const VkImportSemaphoreFdInfoKHR sdi = {
2452 .sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR,
2453 .semaphore = sem,
2454 .flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT,
2455 .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
2456 .fd = export.fd,
2457 };
2458 bool success = VKSCR(ImportSemaphoreFdKHR)(screen->dev, &sdi) == VK_SUCCESS;
2459 close(fd);
2460 if (!success) {
2461 VKSCR(DestroySemaphore)(screen->dev, sem, NULL);
2462 return VK_NULL_HANDLE;
2463 }
2464 #endif
2465 return sem;
2466 }
2467
2468 bool
zink_screen_import_dmabuf_semaphore(struct zink_screen * screen,struct zink_resource * res,VkSemaphore sem)2469 zink_screen_import_dmabuf_semaphore(struct zink_screen *screen, struct zink_resource *res, VkSemaphore sem)
2470 {
2471 #if defined(HAVE_LIBDRM) && (DETECT_OS_LINUX || DETECT_OS_BSD)
2472 const VkSemaphoreGetFdInfoKHR get_fd_info = {
2473 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
2474 .semaphore = sem,
2475 .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
2476 };
2477 int sync_file_fd = -1;
2478 VkResult result = VKSCR(GetSemaphoreFdKHR)(screen->dev, &get_fd_info, &sync_file_fd);
2479 if (result != VK_SUCCESS) {
2480 return false;
2481 }
2482
2483 bool ret = false;
2484 int fd;
2485 if (res->obj->is_aux) {
2486 fd = os_dupfd_cloexec(res->obj->handle);
2487 } else {
2488 VkMemoryGetFdInfoKHR fd_info = {0};
2489 fd_info.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR;
2490 fd_info.memory = zink_bo_get_mem(res->obj->bo);
2491 fd_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
2492 if (VKSCR(GetMemoryFdKHR)(screen->dev, &fd_info, &fd) != VK_SUCCESS)
2493 fd = -1;
2494 }
2495 if (fd != -1) {
2496 struct dma_buf_import_sync_file import = {
2497 .flags = DMA_BUF_SYNC_RW,
2498 .fd = sync_file_fd,
2499 };
2500 int ioctl_ret = drmIoctl(fd, DMA_BUF_IOCTL_IMPORT_SYNC_FILE, &import);
2501 if (ioctl_ret) {
2502 if (errno == ENOTTY || errno == EBADF || errno == ENOSYS) {
2503 assert(!"how did this fail?");
2504 } else {
2505 ret = true;
2506 }
2507 }
2508 close(fd);
2509 }
2510 close(sync_file_fd);
2511 return ret;
2512 #else
2513 return true;
2514 #endif
2515 }
2516
2517 bool
zink_screen_timeline_wait(struct zink_screen * screen,uint64_t batch_id,uint64_t timeout)2518 zink_screen_timeline_wait(struct zink_screen *screen, uint64_t batch_id, uint64_t timeout)
2519 {
2520 VkSemaphoreWaitInfo wi = {0};
2521
2522 if (zink_screen_check_last_finished(screen, batch_id))
2523 return true;
2524
2525 wi.sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO;
2526 wi.semaphoreCount = 1;
2527 wi.pSemaphores = &screen->sem;
2528 wi.pValues = &batch_id;
2529 bool success = false;
2530 if (screen->device_lost)
2531 return true;
2532 VkResult ret = VKSCR(WaitSemaphores)(screen->dev, &wi, timeout);
2533 success = zink_screen_handle_vkresult(screen, ret);
2534
2535 if (success)
2536 zink_screen_update_last_finished(screen, batch_id);
2537
2538 return success;
2539 }
2540
2541 static uint32_t
zink_get_loader_version(struct zink_screen * screen)2542 zink_get_loader_version(struct zink_screen *screen)
2543 {
2544
2545 uint32_t loader_version = VK_API_VERSION_1_0;
2546
2547 // Get the Loader version
2548 GET_PROC_ADDR_INSTANCE_LOCAL(screen, NULL, EnumerateInstanceVersion);
2549 if (vk_EnumerateInstanceVersion) {
2550 uint32_t loader_version_temp = VK_API_VERSION_1_0;
2551 VkResult result = (*vk_EnumerateInstanceVersion)(&loader_version_temp);
2552 if (VK_SUCCESS == result) {
2553 loader_version = loader_version_temp;
2554 } else {
2555 mesa_loge("ZINK: vkEnumerateInstanceVersion failed (%s)", vk_Result_to_str(result));
2556 }
2557 }
2558
2559 return loader_version;
2560 }
2561
2562 static void
zink_query_memory_info(struct pipe_screen * pscreen,struct pipe_memory_info * info)2563 zink_query_memory_info(struct pipe_screen *pscreen, struct pipe_memory_info *info)
2564 {
2565 struct zink_screen *screen = zink_screen(pscreen);
2566 memset(info, 0, sizeof(struct pipe_memory_info));
2567 if (screen->info.have_EXT_memory_budget && VKSCR(GetPhysicalDeviceMemoryProperties2)) {
2568 VkPhysicalDeviceMemoryProperties2 mem = {0};
2569 mem.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
2570
2571 VkPhysicalDeviceMemoryBudgetPropertiesEXT budget = {0};
2572 budget.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT;
2573 mem.pNext = &budget;
2574 VKSCR(GetPhysicalDeviceMemoryProperties2)(screen->pdev, &mem);
2575
2576 for (unsigned i = 0; i < mem.memoryProperties.memoryHeapCount; i++) {
2577 if (mem.memoryProperties.memoryHeaps[i].flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
2578 /* VRAM */
2579 info->total_device_memory += mem.memoryProperties.memoryHeaps[i].size / 1024;
2580 info->avail_device_memory += (mem.memoryProperties.memoryHeaps[i].size - budget.heapUsage[i]) / 1024;
2581 } else {
2582 /* GART */
2583 info->total_staging_memory += mem.memoryProperties.memoryHeaps[i].size / 1024;
2584 info->avail_staging_memory += (mem.memoryProperties.memoryHeaps[i].size - budget.heapUsage[i]) / 1024;
2585 }
2586 }
2587 /* evictions not yet supported in vulkan */
2588 } else {
2589 for (unsigned i = 0; i < screen->info.mem_props.memoryHeapCount; i++) {
2590 if (screen->info.mem_props.memoryHeaps[i].flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
2591 /* VRAM */
2592 info->total_device_memory += screen->info.mem_props.memoryHeaps[i].size / 1024;
2593 /* free real estate! */
2594 info->avail_device_memory += info->total_device_memory;
2595 } else {
2596 /* GART */
2597 info->total_staging_memory += screen->info.mem_props.memoryHeaps[i].size / 1024;
2598 /* free real estate! */
2599 info->avail_staging_memory += info->total_staging_memory;
2600 }
2601 }
2602 }
2603 }
2604
2605 static void
zink_query_dmabuf_modifiers(struct pipe_screen * pscreen,enum pipe_format format,int max,uint64_t * modifiers,unsigned int * external_only,int * count)2606 zink_query_dmabuf_modifiers(struct pipe_screen *pscreen, enum pipe_format format, int max, uint64_t *modifiers, unsigned int *external_only, int *count)
2607 {
2608 struct zink_screen *screen = zink_screen(pscreen);
2609 *count = screen->modifier_props[format].drmFormatModifierCount;
2610 for (int i = 0; i < MIN2(max, *count); i++) {
2611 if (external_only)
2612 external_only[i] = 0;
2613
2614 modifiers[i] = screen->modifier_props[format].pDrmFormatModifierProperties[i].drmFormatModifier;
2615 }
2616 }
2617
2618 static bool
zink_is_dmabuf_modifier_supported(struct pipe_screen * pscreen,uint64_t modifier,enum pipe_format format,bool * external_only)2619 zink_is_dmabuf_modifier_supported(struct pipe_screen *pscreen, uint64_t modifier, enum pipe_format format, bool *external_only)
2620 {
2621 struct zink_screen *screen = zink_screen(pscreen);
2622 for (unsigned i = 0; i < screen->modifier_props[format].drmFormatModifierCount; i++)
2623 if (screen->modifier_props[format].pDrmFormatModifierProperties[i].drmFormatModifier == modifier)
2624 return true;
2625 return false;
2626 }
2627
2628 static unsigned
zink_get_dmabuf_modifier_planes(struct pipe_screen * pscreen,uint64_t modifier,enum pipe_format format)2629 zink_get_dmabuf_modifier_planes(struct pipe_screen *pscreen, uint64_t modifier, enum pipe_format format)
2630 {
2631 struct zink_screen *screen = zink_screen(pscreen);
2632 for (unsigned i = 0; i < screen->modifier_props[format].drmFormatModifierCount; i++)
2633 if (screen->modifier_props[format].pDrmFormatModifierProperties[i].drmFormatModifier == modifier)
2634 return screen->modifier_props[format].pDrmFormatModifierProperties[i].drmFormatModifierPlaneCount;
2635 return util_format_get_num_planes(format);
2636 }
2637
2638 static int
zink_get_sparse_texture_virtual_page_size(struct pipe_screen * pscreen,enum pipe_texture_target target,bool multi_sample,enum pipe_format pformat,unsigned offset,unsigned size,int * x,int * y,int * z)2639 zink_get_sparse_texture_virtual_page_size(struct pipe_screen *pscreen,
2640 enum pipe_texture_target target,
2641 bool multi_sample,
2642 enum pipe_format pformat,
2643 unsigned offset, unsigned size,
2644 int *x, int *y, int *z)
2645 {
2646 struct zink_screen *screen = zink_screen(pscreen);
2647 static const int page_size_2d[][3] = {
2648 { 256, 256, 1 }, /* 8bpp */
2649 { 256, 128, 1 }, /* 16bpp */
2650 { 128, 128, 1 }, /* 32bpp */
2651 { 128, 64, 1 }, /* 64bpp */
2652 { 64, 64, 1 }, /* 128bpp */
2653 };
2654 static const int page_size_3d[][3] = {
2655 { 64, 32, 32 }, /* 8bpp */
2656 { 32, 32, 32 }, /* 16bpp */
2657 { 32, 32, 16 }, /* 32bpp */
2658 { 32, 16, 16 }, /* 64bpp */
2659 { 16, 16, 16 }, /* 128bpp */
2660 };
2661 /* Only support one type of page size. */
2662 if (offset != 0)
2663 return 0;
2664
2665 /* reject multisample if 2x isn't supported; assume none are */
2666 if (multi_sample && !screen->info.feats.features.sparseResidency2Samples)
2667 return 0;
2668
2669 VkFormat format = zink_get_format(screen, pformat);
2670 bool is_zs = util_format_is_depth_or_stencil(pformat);
2671 VkImageType type;
2672 switch (target) {
2673 case PIPE_TEXTURE_1D:
2674 case PIPE_TEXTURE_1D_ARRAY:
2675 type = (screen->need_2D_sparse || (screen->need_2D_zs && is_zs)) ? VK_IMAGE_TYPE_2D : VK_IMAGE_TYPE_1D;
2676 break;
2677
2678 case PIPE_TEXTURE_2D:
2679 case PIPE_TEXTURE_CUBE:
2680 case PIPE_TEXTURE_RECT:
2681 case PIPE_TEXTURE_2D_ARRAY:
2682 case PIPE_TEXTURE_CUBE_ARRAY:
2683 type = VK_IMAGE_TYPE_2D;
2684 break;
2685
2686 case PIPE_TEXTURE_3D:
2687 type = VK_IMAGE_TYPE_3D;
2688 break;
2689
2690 case PIPE_BUFFER:
2691 goto hack_it_up;
2692
2693 default:
2694 return 0;
2695 }
2696
2697 VkImageUsageFlags use_flags = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
2698 VK_IMAGE_USAGE_STORAGE_BIT;
2699 use_flags |= is_zs ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
2700 VkImageUsageFlags flags = screen->format_props[pformat].optimalTilingFeatures & use_flags;
2701 VkSparseImageFormatProperties props[4]; //planar?
2702 unsigned prop_count = ARRAY_SIZE(props);
2703 VKSCR(GetPhysicalDeviceSparseImageFormatProperties)(screen->pdev, format, type,
2704 multi_sample ? VK_SAMPLE_COUNT_2_BIT : VK_SAMPLE_COUNT_1_BIT,
2705 flags,
2706 VK_IMAGE_TILING_OPTIMAL,
2707 &prop_count, props);
2708 if (!prop_count) {
2709 /* format may not support storage; try without */
2710 flags &= ~VK_IMAGE_USAGE_STORAGE_BIT;
2711 prop_count = ARRAY_SIZE(props);
2712 VKSCR(GetPhysicalDeviceSparseImageFormatProperties)(screen->pdev, format, type,
2713 multi_sample ? VK_SAMPLE_COUNT_2_BIT : VK_SAMPLE_COUNT_1_BIT,
2714 flags,
2715 VK_IMAGE_TILING_OPTIMAL,
2716 &prop_count, props);
2717 if (!prop_count)
2718 return 0;
2719 }
2720
2721 if (size) {
2722 if (x)
2723 *x = props[0].imageGranularity.width;
2724 if (y)
2725 *y = props[0].imageGranularity.height;
2726 if (z)
2727 *z = props[0].imageGranularity.depth;
2728 }
2729
2730 return 1;
2731 hack_it_up:
2732 {
2733 const int (*page_sizes)[3] = target == PIPE_TEXTURE_3D ? page_size_3d : page_size_2d;
2734 int blk_size = util_format_get_blocksize(pformat);
2735
2736 if (size) {
2737 unsigned index = util_logbase2(blk_size);
2738 if (x) *x = page_sizes[index][0];
2739 if (y) *y = page_sizes[index][1];
2740 if (z) *z = page_sizes[index][2];
2741 }
2742 }
2743 return 1;
2744 }
2745
2746 static VkDevice
zink_create_logical_device(struct zink_screen * screen)2747 zink_create_logical_device(struct zink_screen *screen)
2748 {
2749 VkDevice dev = VK_NULL_HANDLE;
2750
2751 VkDeviceQueueCreateInfo qci[2] = {0};
2752 uint32_t queues[3] = {
2753 screen->gfx_queue,
2754 screen->sparse_queue,
2755 };
2756 float dummy = 0.0f;
2757 for (unsigned i = 0; i < ARRAY_SIZE(qci); i++) {
2758 qci[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
2759 qci[i].queueFamilyIndex = queues[i];
2760 qci[i].queueCount = 1;
2761 qci[i].pQueuePriorities = &dummy;
2762 }
2763
2764 unsigned num_queues = 1;
2765 if (screen->sparse_queue != screen->gfx_queue)
2766 num_queues++;
2767
2768 VkDeviceCreateInfo dci = {0};
2769 dci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
2770 dci.queueCreateInfoCount = num_queues;
2771 dci.pQueueCreateInfos = qci;
2772 /* extensions don't have bool members in pEnabledFeatures.
2773 * this requires us to pass the whole VkPhysicalDeviceFeatures2 struct
2774 */
2775 if (screen->info.feats.sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2) {
2776 dci.pNext = &screen->info.feats;
2777 } else {
2778 dci.pEnabledFeatures = &screen->info.feats.features;
2779 }
2780
2781 dci.ppEnabledExtensionNames = screen->info.extensions;
2782 dci.enabledExtensionCount = screen->info.num_extensions;
2783
2784 VkResult result = VKSCR(CreateDevice)(screen->pdev, &dci, NULL, &dev);
2785 if (result != VK_SUCCESS)
2786 mesa_loge("ZINK: vkCreateDevice failed (%s)", vk_Result_to_str(result));
2787
2788 return dev;
2789 }
2790
2791 static void
check_base_requirements(struct zink_screen * screen)2792 check_base_requirements(struct zink_screen *screen)
2793 {
2794 if (zink_debug & ZINK_DEBUG_QUIET)
2795 return;
2796 if (zink_driverid(screen) == VK_DRIVER_ID_MESA_V3DV) {
2797 /* v3dv doesn't support straddling i/o, but zink doesn't do that so this is effectively supported:
2798 * don't spam errors in this case
2799 */
2800 screen->info.feats12.scalarBlockLayout = true;
2801 screen->info.have_EXT_scalar_block_layout = true;
2802 }
2803 if (!screen->info.feats.features.logicOp ||
2804 !screen->info.feats.features.fillModeNonSolid ||
2805 !screen->info.feats.features.shaderClipDistance ||
2806 !(screen->info.feats12.scalarBlockLayout ||
2807 screen->info.have_EXT_scalar_block_layout) ||
2808 !screen->info.have_KHR_maintenance1 ||
2809 !screen->info.have_EXT_custom_border_color ||
2810 !screen->info.have_EXT_line_rasterization) {
2811 fprintf(stderr, "WARNING: Some incorrect rendering "
2812 "might occur because the selected Vulkan device (%s) doesn't support "
2813 "base Zink requirements: ", screen->info.props.deviceName);
2814 #define CHECK_OR_PRINT(X) \
2815 if (!screen->info.X) \
2816 fprintf(stderr, "%s ", #X)
2817 CHECK_OR_PRINT(feats.features.logicOp);
2818 CHECK_OR_PRINT(feats.features.fillModeNonSolid);
2819 CHECK_OR_PRINT(feats.features.shaderClipDistance);
2820 if (!screen->info.feats12.scalarBlockLayout && !screen->info.have_EXT_scalar_block_layout)
2821 fprintf(stderr, "scalarBlockLayout OR EXT_scalar_block_layout ");
2822 CHECK_OR_PRINT(have_KHR_maintenance1);
2823 CHECK_OR_PRINT(have_EXT_custom_border_color);
2824 CHECK_OR_PRINT(have_EXT_line_rasterization);
2825 fprintf(stderr, "\n");
2826 }
2827 if (zink_driverid(screen) == VK_DRIVER_ID_MESA_V3DV) {
2828 screen->info.feats12.scalarBlockLayout = false;
2829 screen->info.have_EXT_scalar_block_layout = false;
2830 }
2831 }
2832
2833 static void
zink_get_sample_pixel_grid(struct pipe_screen * pscreen,unsigned sample_count,unsigned * width,unsigned * height)2834 zink_get_sample_pixel_grid(struct pipe_screen *pscreen, unsigned sample_count,
2835 unsigned *width, unsigned *height)
2836 {
2837 struct zink_screen *screen = zink_screen(pscreen);
2838 unsigned idx = util_logbase2_ceil(MAX2(sample_count, 1));
2839 assert(idx < ARRAY_SIZE(screen->maxSampleLocationGridSize));
2840 *width = screen->maxSampleLocationGridSize[idx].width;
2841 *height = screen->maxSampleLocationGridSize[idx].height;
2842 }
2843
2844 static void
init_driver_workarounds(struct zink_screen * screen)2845 init_driver_workarounds(struct zink_screen *screen)
2846 {
2847 /* enable implicit sync for all non-mesa drivers */
2848 screen->driver_workarounds.implicit_sync = screen->info.driver_props.driverID != VK_DRIVER_ID_MESA_VENUS;
2849 switch (zink_driverid(screen)) {
2850 case VK_DRIVER_ID_MESA_RADV:
2851 case VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA:
2852 case VK_DRIVER_ID_MESA_LLVMPIPE:
2853 case VK_DRIVER_ID_MESA_TURNIP:
2854 case VK_DRIVER_ID_MESA_V3DV:
2855 case VK_DRIVER_ID_MESA_PANVK:
2856 screen->driver_workarounds.implicit_sync = false;
2857 break;
2858 default:
2859 break;
2860 }
2861 /* TODO: maybe compile multiple variants for different set counts for compact mode? */
2862 if (screen->info.props.limits.maxBoundDescriptorSets < ZINK_DESCRIPTOR_ALL_TYPES ||
2863 zink_debug & (ZINK_DEBUG_COMPACT | ZINK_DEBUG_NOSHOBJ))
2864 screen->info.have_EXT_shader_object = false;
2865 /* EDS2 is only used with EDS1 */
2866 if (!screen->info.have_EXT_extended_dynamic_state) {
2867 screen->info.have_EXT_extended_dynamic_state2 = false;
2868 /* CWE usage needs EDS1 */
2869 screen->info.have_EXT_color_write_enable = false;
2870 }
2871 if (zink_driverid(screen) == VK_DRIVER_ID_AMD_PROPRIETARY)
2872 /* this completely breaks xfb somehow */
2873 screen->info.have_EXT_extended_dynamic_state2 = false;
2874 /* EDS3 is only used with EDS2 */
2875 if (!screen->info.have_EXT_extended_dynamic_state2)
2876 screen->info.have_EXT_extended_dynamic_state3 = false;
2877 /* EXT_vertex_input_dynamic_state is only used with EDS2 and above */
2878 if (!screen->info.have_EXT_extended_dynamic_state2)
2879 screen->info.have_EXT_vertex_input_dynamic_state = false;
2880 if (screen->info.line_rast_feats.stippledRectangularLines &&
2881 screen->info.line_rast_feats.stippledBresenhamLines &&
2882 screen->info.line_rast_feats.stippledSmoothLines &&
2883 !screen->info.dynamic_state3_feats.extendedDynamicState3LineStippleEnable)
2884 screen->info.have_EXT_extended_dynamic_state3 = false;
2885 if (!screen->info.dynamic_state3_feats.extendedDynamicState3PolygonMode ||
2886 !screen->info.dynamic_state3_feats.extendedDynamicState3DepthClampEnable ||
2887 !screen->info.dynamic_state3_feats.extendedDynamicState3DepthClipNegativeOneToOne ||
2888 !screen->info.dynamic_state3_feats.extendedDynamicState3DepthClipEnable ||
2889 !screen->info.dynamic_state3_feats.extendedDynamicState3ProvokingVertexMode ||
2890 !screen->info.dynamic_state3_feats.extendedDynamicState3LineRasterizationMode)
2891 screen->info.have_EXT_extended_dynamic_state3 = false;
2892 else if (screen->info.dynamic_state3_feats.extendedDynamicState3SampleMask &&
2893 screen->info.dynamic_state3_feats.extendedDynamicState3AlphaToCoverageEnable &&
2894 (!screen->info.feats.features.alphaToOne || screen->info.dynamic_state3_feats.extendedDynamicState3AlphaToOneEnable) &&
2895 screen->info.dynamic_state3_feats.extendedDynamicState3ColorBlendEnable &&
2896 screen->info.dynamic_state3_feats.extendedDynamicState3RasterizationSamples &&
2897 screen->info.dynamic_state3_feats.extendedDynamicState3ColorWriteMask &&
2898 screen->info.dynamic_state3_feats.extendedDynamicState3ColorBlendEquation &&
2899 screen->info.dynamic_state3_feats.extendedDynamicState3LogicOpEnable &&
2900 screen->info.dynamic_state2_feats.extendedDynamicState2LogicOp)
2901 screen->have_full_ds3 = true;
2902 if (screen->info.have_EXT_graphics_pipeline_library)
2903 screen->info.have_EXT_graphics_pipeline_library = screen->info.have_EXT_extended_dynamic_state &&
2904 screen->info.have_EXT_extended_dynamic_state2 &&
2905 ((zink_debug & ZINK_DEBUG_GPL) ||
2906 screen->info.dynamic_state2_feats.extendedDynamicState2PatchControlPoints) &&
2907 screen->info.have_EXT_extended_dynamic_state3 &&
2908 screen->info.have_KHR_dynamic_rendering &&
2909 screen->info.have_EXT_non_seamless_cube_map &&
2910 (!(zink_debug & ZINK_DEBUG_GPL) ||
2911 screen->info.gpl_props.graphicsPipelineLibraryFastLinking ||
2912 screen->is_cpu);
2913 screen->driver_workarounds.broken_l4a4 = zink_driverid(screen) == VK_DRIVER_ID_NVIDIA_PROPRIETARY;
2914 if (zink_driverid(screen) == VK_DRIVER_ID_MESA_TURNIP) {
2915 /* performance */
2916 screen->info.border_color_feats.customBorderColorWithoutFormat = VK_FALSE;
2917 }
2918 if (!screen->info.have_KHR_maintenance5)
2919 screen->driver_workarounds.missing_a8_unorm = true;
2920
2921 if ((!screen->info.have_EXT_line_rasterization ||
2922 !screen->info.line_rast_feats.stippledBresenhamLines) &&
2923 screen->info.feats.features.geometryShader &&
2924 screen->info.feats.features.sampleRateShading) {
2925 /* we're using stippledBresenhamLines as a proxy for all of these, to
2926 * avoid accidentally changing behavior on VK-drivers where we don't
2927 * want to add emulation.
2928 */
2929 screen->driver_workarounds.no_linestipple = true;
2930 }
2931
2932 if (zink_driverid(screen) ==
2933 VK_DRIVER_ID_IMAGINATION_PROPRIETARY) {
2934 assert(screen->info.feats.features.geometryShader);
2935 screen->driver_workarounds.no_linesmooth = true;
2936 }
2937
2938 /* This is a workarround for the lack of
2939 * gl_PointSize + glPolygonMode(..., GL_LINE), in the imagination
2940 * proprietary driver.
2941 */
2942 switch (zink_driverid(screen)) {
2943 case VK_DRIVER_ID_IMAGINATION_PROPRIETARY:
2944 screen->driver_workarounds.no_hw_gl_point = true;
2945 break;
2946 default:
2947 screen->driver_workarounds.no_hw_gl_point = false;
2948 break;
2949 }
2950
2951 if (zink_driverid(screen) == VK_DRIVER_ID_AMD_OPEN_SOURCE ||
2952 zink_driverid(screen) == VK_DRIVER_ID_AMD_PROPRIETARY ||
2953 zink_driverid(screen) == VK_DRIVER_ID_NVIDIA_PROPRIETARY ||
2954 zink_driverid(screen) == VK_DRIVER_ID_MESA_RADV)
2955 screen->driver_workarounds.z24_unscaled_bias = 1<<23;
2956 else
2957 screen->driver_workarounds.z24_unscaled_bias = 1<<24;
2958 if (zink_driverid(screen) == VK_DRIVER_ID_NVIDIA_PROPRIETARY)
2959 screen->driver_workarounds.z16_unscaled_bias = 1<<15;
2960 else
2961 screen->driver_workarounds.z16_unscaled_bias = 1<<16;
2962 /* these drivers don't use VK_PIPELINE_CREATE_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT, so it can always be set */
2963 switch (zink_driverid(screen)) {
2964 case VK_DRIVER_ID_MESA_RADV:
2965 case VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA:
2966 case VK_DRIVER_ID_MESA_LLVMPIPE:
2967 case VK_DRIVER_ID_NVIDIA_PROPRIETARY:
2968 case VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS:
2969 case VK_DRIVER_ID_IMAGINATION_PROPRIETARY:
2970 screen->driver_workarounds.always_feedback_loop = screen->info.have_EXT_attachment_feedback_loop_layout;
2971 break;
2972 default:
2973 break;
2974 }
2975 /* these drivers don't use VK_PIPELINE_CREATE_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT, so it can always be set */
2976 switch (zink_driverid(screen)) {
2977 case VK_DRIVER_ID_MESA_LLVMPIPE:
2978 case VK_DRIVER_ID_NVIDIA_PROPRIETARY:
2979 case VK_DRIVER_ID_IMAGINATION_PROPRIETARY:
2980 screen->driver_workarounds.always_feedback_loop_zs = screen->info.have_EXT_attachment_feedback_loop_layout;
2981 break;
2982 default:
2983 break;
2984 }
2985 /* use same mechanics if dynamic state is supported */
2986 screen->driver_workarounds.always_feedback_loop |= screen->info.have_EXT_attachment_feedback_loop_dynamic_state;
2987 screen->driver_workarounds.always_feedback_loop_zs |= screen->info.have_EXT_attachment_feedback_loop_dynamic_state;
2988
2989 /* these drivers cannot handle OOB gl_Layer values, and therefore need clamping in shader.
2990 * TODO: Vulkan extension that details whether vulkan driver can handle OOB layer values
2991 */
2992 switch (zink_driverid(screen)) {
2993 case VK_DRIVER_ID_IMAGINATION_PROPRIETARY:
2994 screen->driver_compiler_workarounds.needs_sanitised_layer = true;
2995 break;
2996 default:
2997 screen->driver_compiler_workarounds.needs_sanitised_layer = false;
2998 break;
2999 }
3000 /* these drivers will produce undefined results when using swizzle 1 with combined z/s textures
3001 * TODO: use a future device property when available
3002 */
3003 switch (zink_driverid(screen)) {
3004 case VK_DRIVER_ID_IMAGINATION_PROPRIETARY:
3005 case VK_DRIVER_ID_IMAGINATION_OPEN_SOURCE_MESA:
3006 screen->driver_compiler_workarounds.needs_zs_shader_swizzle = true;
3007 break;
3008 default:
3009 screen->driver_compiler_workarounds.needs_zs_shader_swizzle = false;
3010 break;
3011 }
3012
3013 /* When robust contexts are advertised but robustImageAccess2 is not available */
3014 screen->driver_compiler_workarounds.lower_robustImageAccess2 =
3015 !screen->info.rb2_feats.robustImageAccess2 &&
3016 screen->info.feats.features.robustBufferAccess &&
3017 screen->info.rb_image_feats.robustImageAccess;
3018
3019 /* once more testing has been done, use the #if 0 block */
3020 unsigned illegal = ZINK_DEBUG_RP | ZINK_DEBUG_NORP;
3021 if ((zink_debug & illegal) == illegal) {
3022 mesa_loge("Cannot specify ZINK_DEBUG=rp and ZINK_DEBUG=norp");
3023 abort();
3024 }
3025
3026 /* these drivers benefit from renderpass optimization */
3027 switch (zink_driverid(screen)) {
3028 case VK_DRIVER_ID_MESA_LLVMPIPE:
3029 case VK_DRIVER_ID_MESA_TURNIP:
3030 case VK_DRIVER_ID_MESA_PANVK:
3031 case VK_DRIVER_ID_MESA_V3DV:
3032 case VK_DRIVER_ID_IMAGINATION_PROPRIETARY:
3033 case VK_DRIVER_ID_QUALCOMM_PROPRIETARY:
3034 case VK_DRIVER_ID_BROADCOM_PROPRIETARY:
3035 case VK_DRIVER_ID_ARM_PROPRIETARY:
3036 case VK_DRIVER_ID_MESA_HONEYKRISP:
3037 screen->driver_workarounds.track_renderpasses = true; //screen->info.primgen_feats.primitivesGeneratedQueryWithRasterizerDiscard
3038 break;
3039 default:
3040 break;
3041 }
3042 if (zink_debug & ZINK_DEBUG_RP)
3043 screen->driver_workarounds.track_renderpasses = true;
3044 else if (zink_debug & ZINK_DEBUG_NORP)
3045 screen->driver_workarounds.track_renderpasses = false;
3046
3047 /* these drivers can successfully do INVALID <-> LINEAR dri3 modifier swap */
3048 switch (zink_driverid(screen)) {
3049 case VK_DRIVER_ID_MESA_TURNIP:
3050 case VK_DRIVER_ID_MESA_NVK:
3051 case VK_DRIVER_ID_MESA_LLVMPIPE:
3052 screen->driver_workarounds.can_do_invalid_linear_modifier = true;
3053 break;
3054 default:
3055 break;
3056 }
3057
3058 /* these drivers have no difference between unoptimized and optimized shader compilation */
3059 switch (zink_driverid(screen)) {
3060 case VK_DRIVER_ID_MESA_LLVMPIPE:
3061 screen->driver_workarounds.disable_optimized_compile = true;
3062 break;
3063 default:
3064 if (zink_debug & ZINK_DEBUG_NOOPT)
3065 screen->driver_workarounds.disable_optimized_compile = true;
3066 break;
3067 }
3068
3069 switch (zink_driverid(screen)) {
3070 case VK_DRIVER_ID_MESA_RADV:
3071 case VK_DRIVER_ID_AMD_OPEN_SOURCE:
3072 case VK_DRIVER_ID_AMD_PROPRIETARY:
3073 /* this has bad perf on AMD */
3074 screen->info.have_KHR_push_descriptor = false;
3075 /* Interpolation is not consistent between two triangles of a rectangle. */
3076 screen->driver_workarounds.inconsistent_interpolation = true;
3077 break;
3078 default:
3079 break;
3080 }
3081
3082 screen->driver_workarounds.can_2d_view_sparse = true;
3083 switch (zink_driverid(screen)) {
3084 case VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA:
3085 case VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS:
3086 /* this does wild things to block shapes */
3087 screen->driver_workarounds.can_2d_view_sparse = false;
3088 break;
3089 default:
3090 break;
3091 }
3092
3093 switch (zink_driverid(screen)) {
3094 case VK_DRIVER_ID_MESA_RADV:
3095 case VK_DRIVER_ID_MESA_NVK:
3096 case VK_DRIVER_ID_NVIDIA_PROPRIETARY:
3097 screen->driver_workarounds.general_depth_layout = true;
3098 break;
3099 default:
3100 break;
3101 }
3102
3103 if (!screen->resizable_bar)
3104 screen->info.have_EXT_host_image_copy = false;
3105 }
3106
3107 static void
fixup_driver_props(struct zink_screen * screen)3108 fixup_driver_props(struct zink_screen *screen)
3109 {
3110 VkPhysicalDeviceProperties2 props = {
3111 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2
3112 };
3113 if (screen->info.have_EXT_host_image_copy) {
3114 /* fill in layouts */
3115 screen->info.hic_props.pNext = props.pNext;
3116 props.pNext = &screen->info.hic_props;
3117 screen->info.hic_props.pCopySrcLayouts = ralloc_array(screen, VkImageLayout, screen->info.hic_props.copySrcLayoutCount);
3118 screen->info.hic_props.pCopyDstLayouts = ralloc_array(screen, VkImageLayout, screen->info.hic_props.copyDstLayoutCount);
3119 }
3120 if (props.pNext)
3121 screen->vk.GetPhysicalDeviceProperties2(screen->pdev, &props);
3122
3123 if (screen->info.have_EXT_host_image_copy) {
3124 for (unsigned i = 0; i < screen->info.hic_props.copyDstLayoutCount; i++) {
3125 if (screen->info.hic_props.pCopyDstLayouts[i] == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
3126 screen->can_hic_shader_read = true;
3127 break;
3128 }
3129 }
3130 }
3131 }
3132
3133 static void
init_optimal_keys(struct zink_screen * screen)3134 init_optimal_keys(struct zink_screen *screen)
3135 {
3136 /* assume that anyone who knows enough to enable optimal_keys on turnip doesn't care about missing line stipple */
3137 if (zink_debug & ZINK_DEBUG_OPTIMAL_KEYS && zink_driverid(screen) == VK_DRIVER_ID_MESA_TURNIP)
3138 zink_debug |= ZINK_DEBUG_QUIET;
3139 screen->optimal_keys = !screen->need_decompose_attrs &&
3140 screen->info.have_EXT_non_seamless_cube_map &&
3141 screen->info.have_EXT_provoking_vertex &&
3142 !screen->driconf.inline_uniforms &&
3143 !screen->driver_workarounds.no_linestipple &&
3144 !screen->driver_workarounds.no_linesmooth &&
3145 !screen->driver_workarounds.no_hw_gl_point &&
3146 !screen->driver_compiler_workarounds.lower_robustImageAccess2 &&
3147 !screen->driconf.emulate_point_smooth &&
3148 !screen->driver_compiler_workarounds.needs_zs_shader_swizzle;
3149 if (!screen->optimal_keys && zink_debug & ZINK_DEBUG_OPTIMAL_KEYS && !(zink_debug & ZINK_DEBUG_QUIET)) {
3150 fprintf(stderr, "The following criteria are preventing optimal_keys enablement:\n");
3151 if (screen->need_decompose_attrs)
3152 fprintf(stderr, "missing vertex attribute formats\n");
3153 if (screen->driconf.inline_uniforms)
3154 fprintf(stderr, "uniform inlining must be disabled (set ZINK_INLINE_UNIFORMS=0 in your env)\n");
3155 if (screen->driconf.emulate_point_smooth)
3156 fprintf(stderr, "smooth point emulation is enabled\n");
3157 if (screen->driver_compiler_workarounds.needs_zs_shader_swizzle)
3158 fprintf(stderr, "Z/S shader swizzle workaround is enabled\n");
3159 CHECK_OR_PRINT(have_EXT_line_rasterization);
3160 CHECK_OR_PRINT(line_rast_feats.stippledBresenhamLines);
3161 CHECK_OR_PRINT(feats.features.geometryShader);
3162 CHECK_OR_PRINT(feats.features.sampleRateShading);
3163 CHECK_OR_PRINT(have_EXT_non_seamless_cube_map);
3164 CHECK_OR_PRINT(have_EXT_provoking_vertex);
3165 if (screen->driver_workarounds.no_linesmooth)
3166 fprintf(stderr, "driver does not support smooth lines\n");
3167 if (screen->driver_workarounds.no_hw_gl_point)
3168 fprintf(stderr, "driver does not support hardware GL_POINT\n");
3169 CHECK_OR_PRINT(rb2_feats.robustImageAccess2);
3170 CHECK_OR_PRINT(feats.features.robustBufferAccess);
3171 CHECK_OR_PRINT(rb_image_feats.robustImageAccess);
3172 printf("\n");
3173 mesa_logw("zink: force-enabling optimal_keys despite missing features. Good luck!");
3174 }
3175 if (zink_debug & ZINK_DEBUG_OPTIMAL_KEYS)
3176 screen->optimal_keys = true;
3177 if (!screen->optimal_keys)
3178 screen->info.have_EXT_graphics_pipeline_library = false;
3179
3180 if (!screen->optimal_keys ||
3181 !screen->info.have_KHR_maintenance5 ||
3182 /* EXT_shader_object needs either dynamic feedback loop or per-app enablement */
3183 (!screen->driconf.zink_shader_object_enable && !screen->info.have_EXT_attachment_feedback_loop_dynamic_state))
3184 screen->info.have_EXT_shader_object = false;
3185 if (screen->info.have_EXT_shader_object)
3186 screen->have_full_ds3 = true;
3187 }
3188
3189 static struct disk_cache *
zink_get_disk_shader_cache(struct pipe_screen * _screen)3190 zink_get_disk_shader_cache(struct pipe_screen *_screen)
3191 {
3192 struct zink_screen *screen = zink_screen(_screen);
3193
3194 return screen->disk_cache;
3195 }
3196
3197 VkSemaphore
zink_create_semaphore(struct zink_screen * screen)3198 zink_create_semaphore(struct zink_screen *screen)
3199 {
3200 VkSemaphoreCreateInfo sci = {
3201 VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
3202 NULL,
3203 0
3204 };
3205 VkSemaphore sem = VK_NULL_HANDLE;
3206 if (util_dynarray_contains(&screen->semaphores, VkSemaphore)) {
3207 simple_mtx_lock(&screen->semaphores_lock);
3208 if (util_dynarray_contains(&screen->semaphores, VkSemaphore))
3209 sem = util_dynarray_pop(&screen->semaphores, VkSemaphore);
3210 simple_mtx_unlock(&screen->semaphores_lock);
3211 }
3212 if (sem)
3213 return sem;
3214 VkResult ret = VKSCR(CreateSemaphore)(screen->dev, &sci, NULL, &sem);
3215 return ret == VK_SUCCESS ? sem : VK_NULL_HANDLE;
3216 }
3217
3218 void
zink_screen_lock_context(struct zink_screen * screen)3219 zink_screen_lock_context(struct zink_screen *screen)
3220 {
3221 simple_mtx_lock(&screen->copy_context_lock);
3222 if (!screen->copy_context)
3223 screen->copy_context = zink_context(screen->base.context_create(&screen->base, NULL, ZINK_CONTEXT_COPY_ONLY));
3224 if (!screen->copy_context) {
3225 mesa_loge("zink: failed to create copy context");
3226 /* realistically there's nothing that can be done here */
3227 }
3228 }
3229
3230 void
zink_screen_unlock_context(struct zink_screen * screen)3231 zink_screen_unlock_context(struct zink_screen *screen)
3232 {
3233 simple_mtx_unlock(&screen->copy_context_lock);
3234 }
3235
3236 static bool
init_layouts(struct zink_screen * screen)3237 init_layouts(struct zink_screen *screen)
3238 {
3239 if (screen->info.have_EXT_descriptor_indexing) {
3240 VkDescriptorSetLayoutBinding bindings[4];
3241 const unsigned num_bindings = 4;
3242 VkDescriptorSetLayoutCreateInfo dcslci = {0};
3243 dcslci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
3244 dcslci.pNext = NULL;
3245 VkDescriptorSetLayoutBindingFlagsCreateInfo fci = {0};
3246 VkDescriptorBindingFlags flags[4];
3247 dcslci.pNext = &fci;
3248 if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB)
3249 dcslci.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT;
3250 else
3251 dcslci.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT;
3252 fci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO;
3253 fci.bindingCount = num_bindings;
3254 fci.pBindingFlags = flags;
3255 for (unsigned i = 0; i < num_bindings; i++) {
3256 flags[i] = VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT | VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT;
3257 if (zink_descriptor_mode != ZINK_DESCRIPTOR_MODE_DB)
3258 flags[i] |= VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT;
3259 }
3260 /* there is exactly 1 bindless descriptor set per context, and it has 4 bindings, 1 for each descriptor type */
3261 for (unsigned i = 0; i < num_bindings; i++) {
3262 bindings[i].binding = i;
3263 bindings[i].descriptorType = zink_descriptor_type_from_bindless_index(i);
3264 bindings[i].descriptorCount = ZINK_MAX_BINDLESS_HANDLES;
3265 bindings[i].stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_COMPUTE_BIT;
3266 bindings[i].pImmutableSamplers = NULL;
3267 }
3268
3269 dcslci.bindingCount = num_bindings;
3270 dcslci.pBindings = bindings;
3271 VkResult result = VKSCR(CreateDescriptorSetLayout)(screen->dev, &dcslci, 0, &screen->bindless_layout);
3272 if (result != VK_SUCCESS) {
3273 mesa_loge("ZINK: vkCreateDescriptorSetLayout failed (%s)", vk_Result_to_str(result));
3274 return false;
3275 }
3276 }
3277
3278 screen->gfx_push_constant_layout = zink_pipeline_layout_create(screen, NULL, 0, false, 0);
3279 return !!screen->gfx_push_constant_layout;
3280 }
3281
3282 static int
zink_screen_get_fd(struct pipe_screen * pscreen)3283 zink_screen_get_fd(struct pipe_screen *pscreen)
3284 {
3285 struct zink_screen *screen = zink_screen(pscreen);
3286
3287 return screen->drm_fd;
3288 }
3289
3290 static struct zink_screen *
zink_internal_create_screen(const struct pipe_screen_config * config,int64_t dev_major,int64_t dev_minor)3291 zink_internal_create_screen(const struct pipe_screen_config *config, int64_t dev_major, int64_t dev_minor)
3292 {
3293 if (getenv("ZINK_USE_LAVAPIPE")) {
3294 mesa_loge("ZINK_USE_LAVAPIPE is obsolete. Use LIBGL_ALWAYS_SOFTWARE\n");
3295 return NULL;
3296 }
3297
3298 struct zink_screen *screen = rzalloc(NULL, struct zink_screen);
3299 if (!screen) {
3300 if (!config || !config->driver_name_is_inferred)
3301 mesa_loge("ZINK: failed to allocate screen");
3302 return NULL;
3303 }
3304
3305 screen->driver_name_is_inferred = config && config->driver_name_is_inferred;
3306 screen->drm_fd = -1;
3307
3308 glsl_type_singleton_init_or_ref();
3309 zink_debug = debug_get_option_zink_debug();
3310 if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_AUTO)
3311 zink_descriptor_mode = debug_get_option_zink_descriptor_mode();
3312
3313 screen->threaded = util_get_cpu_caps()->nr_cpus > 1 && debug_get_bool_option("GALLIUM_THREAD", util_get_cpu_caps()->nr_cpus > 1);
3314 if (zink_debug & ZINK_DEBUG_FLUSHSYNC)
3315 screen->threaded_submit = false;
3316 else
3317 screen->threaded_submit = screen->threaded;
3318 screen->abort_on_hang = debug_get_bool_option("ZINK_HANG_ABORT", false);
3319
3320
3321 u_trace_state_init();
3322
3323 screen->loader_lib = util_dl_open(VK_LIBNAME);
3324 if (!screen->loader_lib) {
3325 if (!screen->driver_name_is_inferred)
3326 mesa_loge("ZINK: failed to load "VK_LIBNAME);
3327 goto fail;
3328 }
3329
3330 screen->vk_GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)util_dl_get_proc_address(screen->loader_lib, "vkGetInstanceProcAddr");
3331 screen->vk_GetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)util_dl_get_proc_address(screen->loader_lib, "vkGetDeviceProcAddr");
3332 if (!screen->vk_GetInstanceProcAddr ||
3333 !screen->vk_GetDeviceProcAddr) {
3334 if (!screen->driver_name_is_inferred)
3335 mesa_loge("ZINK: failed to get proc address");
3336 goto fail;
3337 }
3338
3339 screen->instance_info.loader_version = zink_get_loader_version(screen);
3340 if (config) {
3341 driParseConfigFiles(config->options, config->options_info, 0, "zink",
3342 NULL, NULL, NULL, 0, NULL, 0);
3343 screen->driconf.dual_color_blend_by_location = driQueryOptionb(config->options, "dual_color_blend_by_location");
3344 //screen->driconf.inline_uniforms = driQueryOptionb(config->options, "radeonsi_inline_uniforms");
3345 screen->driconf.emulate_point_smooth = driQueryOptionb(config->options, "zink_emulate_point_smooth");
3346 screen->driconf.zink_shader_object_enable = driQueryOptionb(config->options, "zink_shader_object_enable");
3347 }
3348
3349 if (!zink_create_instance(screen))
3350 goto fail;
3351
3352 if (zink_debug & ZINK_DEBUG_VALIDATION) {
3353 if (!screen->instance_info.have_layer_KHRONOS_validation &&
3354 !screen->instance_info.have_layer_LUNARG_standard_validation) {
3355 if (!screen->driver_name_is_inferred)
3356 mesa_loge("Failed to load validation layer");
3357 goto fail;
3358 }
3359 }
3360
3361 vk_instance_uncompacted_dispatch_table_load(&screen->vk.instance,
3362 screen->vk_GetInstanceProcAddr,
3363 screen->instance);
3364 vk_physical_device_uncompacted_dispatch_table_load(&screen->vk.physical_device,
3365 screen->vk_GetInstanceProcAddr,
3366 screen->instance);
3367
3368 zink_verify_instance_extensions(screen);
3369
3370 if (screen->instance_info.have_EXT_debug_utils &&
3371 (zink_debug & ZINK_DEBUG_VALIDATION) && !create_debug(screen)) {
3372 if (!screen->driver_name_is_inferred)
3373 debug_printf("ZINK: failed to setup debug utils\n");
3374 }
3375
3376 choose_pdev(screen, dev_major, dev_minor);
3377 if (screen->pdev == VK_NULL_HANDLE) {
3378 if (!screen->driver_name_is_inferred)
3379 mesa_loge("ZINK: failed to choose pdev");
3380 goto fail;
3381 }
3382 screen->is_cpu = screen->info.props.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU;
3383
3384 update_queue_props(screen);
3385
3386 screen->have_X8_D24_UNORM_PACK32 = zink_is_depth_format_supported(screen,
3387 VK_FORMAT_X8_D24_UNORM_PACK32);
3388 screen->have_D24_UNORM_S8_UINT = zink_is_depth_format_supported(screen,
3389 VK_FORMAT_D24_UNORM_S8_UINT);
3390 screen->have_D32_SFLOAT_S8_UINT = zink_is_depth_format_supported(screen,
3391 VK_FORMAT_D32_SFLOAT_S8_UINT);
3392
3393 if (!zink_get_physical_device_info(screen)) {
3394 if (!screen->driver_name_is_inferred)
3395 debug_printf("ZINK: failed to detect features\n");
3396 goto fail;
3397 }
3398
3399 if (zink_set_driver_strings(screen)) {
3400 mesa_loge("ZINK: failed to set driver strings\n");
3401 goto fail;
3402 }
3403
3404 memset(&screen->heap_map, UINT8_MAX, sizeof(screen->heap_map));
3405 for (enum zink_heap i = 0; i < ZINK_HEAP_MAX; i++) {
3406 for (unsigned j = 0; j < screen->info.mem_props.memoryTypeCount; j++) {
3407 VkMemoryPropertyFlags domains = vk_domain_from_heap(i);
3408 if ((screen->info.mem_props.memoryTypes[j].propertyFlags & domains) == domains) {
3409 screen->heap_map[i][screen->heap_count[i]++] = j;
3410 }
3411 }
3412 }
3413 /* iterate again to check for missing heaps */
3414 for (enum zink_heap i = 0; i < ZINK_HEAP_MAX; i++) {
3415 /* not found: use compatible heap */
3416 if (screen->heap_map[i][0] == UINT8_MAX) {
3417 /* only cached mem has a failure case for now */
3418 assert(i == ZINK_HEAP_HOST_VISIBLE_COHERENT_CACHED || i == ZINK_HEAP_DEVICE_LOCAL_LAZY ||
3419 i == ZINK_HEAP_DEVICE_LOCAL_VISIBLE);
3420 if (i == ZINK_HEAP_HOST_VISIBLE_COHERENT_CACHED) {
3421 memcpy(screen->heap_map[i], screen->heap_map[ZINK_HEAP_HOST_VISIBLE_COHERENT], screen->heap_count[ZINK_HEAP_HOST_VISIBLE_COHERENT]);
3422 screen->heap_count[i] = screen->heap_count[ZINK_HEAP_HOST_VISIBLE_COHERENT];
3423 } else {
3424 memcpy(screen->heap_map[i], screen->heap_map[ZINK_HEAP_DEVICE_LOCAL], screen->heap_count[ZINK_HEAP_DEVICE_LOCAL]);
3425 screen->heap_count[i] = screen->heap_count[ZINK_HEAP_DEVICE_LOCAL];
3426 }
3427 }
3428 }
3429 {
3430 uint64_t biggest_vis_vram = 0;
3431 for (unsigned i = 0; i < screen->heap_count[ZINK_HEAP_DEVICE_LOCAL_VISIBLE]; i++)
3432 biggest_vis_vram = MAX2(biggest_vis_vram, screen->info.mem_props.memoryHeaps[screen->info.mem_props.memoryTypes[screen->heap_map[ZINK_HEAP_DEVICE_LOCAL_VISIBLE][i]].heapIndex].size);
3433 uint64_t biggest_vram = 0;
3434 for (unsigned i = 0; i < screen->heap_count[ZINK_HEAP_DEVICE_LOCAL]; i++)
3435 biggest_vram = MAX2(biggest_vram, screen->info.mem_props.memoryHeaps[screen->info.mem_props.memoryTypes[screen->heap_map[ZINK_HEAP_DEVICE_LOCAL][i]].heapIndex].size);
3436 /* determine if vis vram is roughly equal to total vram */
3437 if (biggest_vis_vram > biggest_vram * 0.9)
3438 screen->resizable_bar = true;
3439 }
3440
3441 setup_renderdoc(screen);
3442 if (screen->threaded_submit && !util_queue_init(&screen->flush_queue, "zfq", 8, 1, UTIL_QUEUE_INIT_RESIZE_IF_FULL, screen)) {
3443 if (!screen->driver_name_is_inferred)
3444 mesa_loge("zink: Failed to create flush queue.\n");
3445 goto fail;
3446 }
3447
3448 zink_internal_setup_moltenvk(screen);
3449 if (!screen->info.have_KHR_timeline_semaphore && !screen->info.feats12.timelineSemaphore) {
3450 if (!screen->driver_name_is_inferred)
3451 mesa_loge("zink: KHR_timeline_semaphore is required");
3452 goto fail;
3453 }
3454
3455 if (zink_driverid(screen) == VK_DRIVER_ID_IMAGINATION_PROPRIETARY && !screen->info.feats.features.geometryShader) {
3456 if (!screen->driver_name_is_inferred)
3457 mesa_loge("zink: Imagination proprietary driver w/o geometryShader is unsupported");
3458 goto fail;
3459 }
3460
3461 if (zink_debug & ZINK_DEBUG_MEM) {
3462 simple_mtx_init(&screen->debug_mem_lock, mtx_plain);
3463 screen->debug_mem_sizes = _mesa_hash_table_create(screen, _mesa_hash_string, _mesa_key_string_equal);
3464 }
3465
3466 fixup_driver_props(screen);
3467
3468 init_driver_workarounds(screen);
3469
3470 screen->dev = zink_create_logical_device(screen);
3471 if (!screen->dev)
3472 goto fail;
3473
3474 vk_device_uncompacted_dispatch_table_load(&screen->vk.device,
3475 screen->vk_GetDeviceProcAddr,
3476 screen->dev);
3477
3478 init_queue(screen);
3479
3480 zink_verify_device_extensions(screen);
3481
3482 /* descriptor set indexing is determined by 'compact' descriptor mode:
3483 * by default, 6 sets are used to provide more granular updating
3484 * in compact mode, a maximum of 4 sets are used, with like-types combined
3485 */
3486 if ((zink_debug & ZINK_DEBUG_COMPACT) ||
3487 screen->info.props.limits.maxBoundDescriptorSets < ZINK_MAX_DESCRIPTOR_SETS) {
3488 screen->desc_set_id[ZINK_DESCRIPTOR_TYPE_UNIFORMS] = 0;
3489 screen->desc_set_id[ZINK_DESCRIPTOR_TYPE_UBO] = 1;
3490 screen->desc_set_id[ZINK_DESCRIPTOR_TYPE_SSBO] = 1;
3491 screen->desc_set_id[ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW] = 2;
3492 screen->desc_set_id[ZINK_DESCRIPTOR_TYPE_IMAGE] = 2;
3493 screen->desc_set_id[ZINK_DESCRIPTOR_BINDLESS] = 3;
3494 screen->compact_descriptors = true;
3495 } else {
3496 screen->desc_set_id[ZINK_DESCRIPTOR_TYPE_UNIFORMS] = 0;
3497 screen->desc_set_id[ZINK_DESCRIPTOR_TYPE_UBO] = 1;
3498 screen->desc_set_id[ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW] = 2;
3499 screen->desc_set_id[ZINK_DESCRIPTOR_TYPE_SSBO] = 3;
3500 screen->desc_set_id[ZINK_DESCRIPTOR_TYPE_IMAGE] = 4;
3501 screen->desc_set_id[ZINK_DESCRIPTOR_BINDLESS] = 5;
3502 }
3503
3504 if (screen->info.have_EXT_calibrated_timestamps && !check_have_device_time(screen))
3505 goto fail;
3506
3507 screen->have_triangle_fans = true;
3508 #if defined(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME)
3509 if (screen->info.have_KHR_portability_subset) {
3510 screen->have_triangle_fans = (VK_TRUE == screen->info.portability_subset_feats.triangleFans);
3511 }
3512 #endif // VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME
3513
3514 check_base_requirements(screen);
3515 util_live_shader_cache_init(&screen->shaders, zink_create_gfx_shader_state, zink_delete_shader_state);
3516
3517 screen->base.get_name = zink_get_name;
3518 if (screen->instance_info.have_KHR_external_memory_capabilities) {
3519 screen->base.get_device_uuid = zink_get_device_uuid;
3520 screen->base.get_driver_uuid = zink_get_driver_uuid;
3521 }
3522 if (screen->info.have_KHR_external_memory_win32) {
3523 screen->base.get_device_luid = zink_get_device_luid;
3524 screen->base.get_device_node_mask = zink_get_device_node_mask;
3525 }
3526 screen->base.set_max_shader_compiler_threads = zink_set_max_shader_compiler_threads;
3527 screen->base.is_parallel_shader_compilation_finished = zink_is_parallel_shader_compilation_finished;
3528 screen->base.get_vendor = zink_get_vendor;
3529 screen->base.get_device_vendor = zink_get_device_vendor;
3530 screen->base.get_compute_param = zink_get_compute_param;
3531 screen->base.get_timestamp = zink_get_timestamp;
3532 screen->base.query_memory_info = zink_query_memory_info;
3533 screen->base.get_param = zink_get_param;
3534 screen->base.get_paramf = zink_get_paramf;
3535 screen->base.get_shader_param = zink_get_shader_param;
3536 screen->base.get_compiler_options = zink_get_compiler_options;
3537 screen->base.get_sample_pixel_grid = zink_get_sample_pixel_grid;
3538 screen->base.is_compute_copy_faster = zink_is_compute_copy_faster;
3539 screen->base.is_format_supported = zink_is_format_supported;
3540 screen->base.driver_thread_add_job = zink_driver_thread_add_job;
3541 if (screen->info.have_EXT_image_drm_format_modifier && screen->info.have_EXT_external_memory_dma_buf) {
3542 screen->base.query_dmabuf_modifiers = zink_query_dmabuf_modifiers;
3543 screen->base.is_dmabuf_modifier_supported = zink_is_dmabuf_modifier_supported;
3544 screen->base.get_dmabuf_modifier_planes = zink_get_dmabuf_modifier_planes;
3545 }
3546 #if defined(_WIN32)
3547 if (screen->info.have_KHR_external_memory_win32)
3548 screen->base.create_fence_win32 = zink_create_fence_win32;
3549 #endif
3550 screen->base.context_create = zink_context_create;
3551 screen->base.flush_frontbuffer = zink_flush_frontbuffer;
3552 screen->base.destroy = zink_destroy_screen;
3553 screen->base.finalize_nir = zink_shader_finalize;
3554 screen->base.get_disk_shader_cache = zink_get_disk_shader_cache;
3555 screen->base.get_sparse_texture_virtual_page_size = zink_get_sparse_texture_virtual_page_size;
3556 screen->base.get_driver_query_group_info = zink_get_driver_query_group_info;
3557 screen->base.get_driver_query_info = zink_get_driver_query_info;
3558 screen->base.set_damage_region = zink_set_damage_region;
3559
3560 if (screen->info.have_EXT_sample_locations) {
3561 VkMultisamplePropertiesEXT prop;
3562 prop.sType = VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT;
3563 prop.pNext = NULL;
3564 for (unsigned i = 0; i < ARRAY_SIZE(screen->maxSampleLocationGridSize); i++) {
3565 if (screen->info.sample_locations_props.sampleLocationSampleCounts & (1 << i)) {
3566 VKSCR(GetPhysicalDeviceMultisamplePropertiesEXT)(screen->pdev, 1 << i, &prop);
3567 screen->maxSampleLocationGridSize[i] = prop.maxSampleLocationGridSize;
3568 }
3569 }
3570 }
3571
3572 if (!zink_screen_resource_init(&screen->base))
3573 goto fail;
3574 if (!zink_bo_init(screen)) {
3575 if (!screen->driver_name_is_inferred)
3576 mesa_loge("ZINK: failed to initialize suballocator");
3577 goto fail;
3578 }
3579 zink_screen_fence_init(&screen->base);
3580
3581 if (zink_debug & ZINK_DEBUG_IOOPT)
3582 screen->driver_compiler_workarounds.io_opt = true;
3583 zink_screen_init_compiler(screen);
3584 if (!disk_cache_init(screen)) {
3585 if (!screen->driver_name_is_inferred)
3586 mesa_loge("ZINK: failed to initialize disk cache");
3587 goto fail;
3588 }
3589 if (!util_queue_init(&screen->cache_get_thread, "zcfq", 8, 4,
3590 UTIL_QUEUE_INIT_RESIZE_IF_FULL, screen))
3591 goto fail;
3592 populate_format_props(screen);
3593
3594 slab_create_parent(&screen->transfer_pool, sizeof(struct zink_transfer), 16);
3595
3596 screen->driconf.inline_uniforms = debug_get_bool_option("ZINK_INLINE_UNIFORMS", screen->is_cpu);
3597
3598 screen->total_video_mem = get_video_mem(screen);
3599 screen->clamp_video_mem = screen->total_video_mem * 0.8;
3600 if (!os_get_total_physical_memory(&screen->total_mem)) {
3601 if (!screen->driver_name_is_inferred)
3602 mesa_loge("ZINK: failed to get total physical memory");
3603 goto fail;
3604 }
3605
3606 if (!zink_screen_init_semaphore(screen)) {
3607 if (!screen->driver_name_is_inferred)
3608 mesa_loge("zink: failed to create timeline semaphore");
3609 goto fail;
3610 }
3611
3612 bool can_db = true;
3613 {
3614 if (!screen->info.have_EXT_descriptor_buffer) {
3615 if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
3616 if (!screen->driver_name_is_inferred)
3617 mesa_loge("Cannot use db descriptor mode without EXT_descriptor_buffer");
3618 goto fail;
3619 }
3620 can_db = false;
3621 }
3622 if (!screen->resizable_bar) {
3623 if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
3624 if (!screen->driver_name_is_inferred)
3625 mesa_loge("Cannot use db descriptor mode without resizable bar");
3626 goto fail;
3627 }
3628 can_db = false;
3629 }
3630 if (!screen->info.have_EXT_non_seamless_cube_map) {
3631 if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
3632 if (!screen->driver_name_is_inferred)
3633 mesa_loge("Cannot use db descriptor mode without EXT_non_seamless_cube_map");
3634 goto fail;
3635 }
3636 can_db = false;
3637 }
3638 if (!screen->info.rb2_feats.nullDescriptor) {
3639 if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
3640 if (!screen->driver_name_is_inferred)
3641 mesa_loge("Cannot use db descriptor mode without robustness2.nullDescriptor");
3642 goto fail;
3643 }
3644 can_db = false;
3645 }
3646 if (ZINK_FBFETCH_DESCRIPTOR_SIZE < screen->info.db_props.inputAttachmentDescriptorSize) {
3647 if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
3648 if (!screen->driver_name_is_inferred)
3649 mesa_loge("Cannot use db descriptor mode with inputAttachmentDescriptorSize(%u) > %u", (unsigned)screen->info.db_props.inputAttachmentDescriptorSize, ZINK_FBFETCH_DESCRIPTOR_SIZE);
3650 goto fail;
3651 }
3652 mesa_logw("zink: bug detected: inputAttachmentDescriptorSize(%u) > %u", (unsigned)screen->info.db_props.inputAttachmentDescriptorSize, ZINK_FBFETCH_DESCRIPTOR_SIZE);
3653 can_db = false;
3654 }
3655 if (screen->info.db_props.maxDescriptorBufferBindings < 2 || screen->info.db_props.maxSamplerDescriptorBufferBindings < 2) {
3656 if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
3657 /* allow for testing, but disable bindless */
3658 mesa_logw("Cannot use bindless and db descriptor mode with (maxDescriptorBufferBindings||maxSamplerDescriptorBufferBindings) < 2");
3659 } else {
3660 can_db = false;
3661 }
3662 }
3663 }
3664 if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_AUTO) {
3665 /* descriptor buffer is not performant with virt yet */
3666 if (screen->info.driver_props.driverID == VK_DRIVER_ID_MESA_VENUS)
3667 zink_descriptor_mode = ZINK_DESCRIPTOR_MODE_LAZY;
3668 else
3669 zink_descriptor_mode = can_db ? ZINK_DESCRIPTOR_MODE_DB : ZINK_DESCRIPTOR_MODE_LAZY;
3670 }
3671 if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
3672 const uint32_t sampler_size = MAX2(screen->info.db_props.combinedImageSamplerDescriptorSize, screen->info.db_props.robustUniformTexelBufferDescriptorSize);
3673 const uint32_t image_size = MAX2(screen->info.db_props.storageImageDescriptorSize, screen->info.db_props.robustStorageTexelBufferDescriptorSize);
3674 if (screen->compact_descriptors) {
3675 screen->db_size[ZINK_DESCRIPTOR_TYPE_UBO] = screen->info.db_props.robustUniformBufferDescriptorSize +
3676 screen->info.db_props.robustStorageBufferDescriptorSize;
3677 screen->db_size[ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW] = sampler_size + image_size;
3678 } else {
3679 screen->db_size[ZINK_DESCRIPTOR_TYPE_UBO] = screen->info.db_props.robustUniformBufferDescriptorSize;
3680 screen->db_size[ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW] = sampler_size;
3681 screen->db_size[ZINK_DESCRIPTOR_TYPE_SSBO] = screen->info.db_props.robustStorageBufferDescriptorSize;
3682 screen->db_size[ZINK_DESCRIPTOR_TYPE_IMAGE] = image_size;
3683 }
3684 screen->db_size[ZINK_DESCRIPTOR_TYPE_UNIFORMS] = screen->info.db_props.robustUniformBufferDescriptorSize;
3685 screen->info.have_KHR_push_descriptor = false;
3686 screen->base_descriptor_size = MAX4(screen->db_size[0], screen->db_size[1], screen->db_size[2], screen->db_size[3]);
3687 }
3688
3689 simple_mtx_init(&screen->free_batch_states_lock, mtx_plain);
3690 simple_mtx_init(&screen->dt_lock, mtx_plain);
3691
3692 util_idalloc_mt_init_tc(&screen->buffer_ids);
3693
3694 simple_mtx_init(&screen->semaphores_lock, mtx_plain);
3695 util_dynarray_init(&screen->semaphores, screen);
3696 util_dynarray_init(&screen->fd_semaphores, screen);
3697
3698 util_vertex_state_cache_init(&screen->vertex_state_cache,
3699 zink_create_vertex_state, zink_vertex_state_destroy);
3700 screen->base.create_vertex_state = zink_cache_create_vertex_state;
3701 screen->base.vertex_state_destroy = zink_cache_vertex_state_destroy;
3702
3703 zink_synchronization_init(screen);
3704
3705 zink_init_screen_pipeline_libs(screen);
3706
3707 if (!init_layouts(screen)) {
3708 if (!screen->driver_name_is_inferred)
3709 mesa_loge("ZINK: failed to initialize layouts");
3710 goto fail;
3711 }
3712
3713 if (!zink_descriptor_layouts_init(screen)) {
3714 if (!screen->driver_name_is_inferred)
3715 mesa_loge("ZINK: failed to initialize descriptor layouts");
3716 goto fail;
3717 }
3718
3719 simple_mtx_init(&screen->copy_context_lock, mtx_plain);
3720
3721 init_optimal_keys(screen);
3722
3723 screen->screen_id = p_atomic_inc_return(&num_screens);
3724 zink_tracing = screen->instance_info.have_EXT_debug_utils &&
3725 (u_trace_is_enabled(U_TRACE_TYPE_PERFETTO) || u_trace_is_enabled(U_TRACE_TYPE_MARKERS));
3726
3727 screen->frame_marker_emitted = zink_screen_debug_marker_begin(screen, "frame");
3728
3729 return screen;
3730
3731 fail:
3732 zink_destroy_screen(&screen->base);
3733 return NULL;
3734 }
3735
3736 struct pipe_screen *
zink_create_screen(struct sw_winsys * winsys,const struct pipe_screen_config * config)3737 zink_create_screen(struct sw_winsys *winsys, const struct pipe_screen_config *config)
3738 {
3739 struct zink_screen *ret = zink_internal_create_screen(config, -1, -1);
3740 if (ret) {
3741 ret->drm_fd = -1;
3742 }
3743
3744 return &ret->base;
3745 }
3746
3747 static inline int
zink_render_rdev(int fd,int64_t * dev_major,int64_t * dev_minor)3748 zink_render_rdev(int fd, int64_t *dev_major, int64_t *dev_minor)
3749 {
3750 int ret = 0;
3751 *dev_major = *dev_minor = -1;
3752 #ifdef HAVE_LIBDRM
3753 struct stat stx;
3754 drmDevicePtr dev;
3755
3756 if (fd == -1)
3757 return 0;
3758
3759 if (drmGetDevice2(fd, 0, &dev))
3760 return -1;
3761
3762 if(!(dev->available_nodes & (1 << DRM_NODE_RENDER))) {
3763 ret = -1;
3764 goto free_device;
3765 }
3766
3767 if(stat(dev->nodes[DRM_NODE_RENDER], &stx)) {
3768 ret = -1;
3769 goto free_device;
3770 }
3771
3772 *dev_major = major(stx.st_rdev);
3773 *dev_minor = minor(stx.st_rdev);
3774
3775 free_device:
3776 drmFreeDevice(&dev);
3777 #endif //HAVE_LIBDRM
3778
3779 return ret;
3780 }
3781
3782 struct pipe_screen *
zink_drm_create_screen(int fd,const struct pipe_screen_config * config)3783 zink_drm_create_screen(int fd, const struct pipe_screen_config *config)
3784 {
3785 int64_t dev_major, dev_minor;
3786 struct zink_screen *ret;
3787
3788 if (zink_render_rdev(fd, &dev_major, &dev_minor))
3789 return NULL;
3790
3791 ret = zink_internal_create_screen(config, dev_major, dev_minor);
3792
3793 if (ret)
3794 ret->drm_fd = os_dupfd_cloexec(fd);
3795 if (ret && !ret->info.have_KHR_external_memory_fd) {
3796 debug_printf("ZINK: KHR_external_memory_fd required!\n");
3797 zink_destroy_screen(&ret->base);
3798 return NULL;
3799 }
3800
3801 return &ret->base;
3802 }
3803
zink_stub_function_not_loaded()3804 void VKAPI_PTR zink_stub_function_not_loaded()
3805 {
3806 /* this will be used by the zink_verify_*_extensions() functions on a
3807 * release build
3808 */
3809 mesa_loge("ZINK: a Vulkan function was called without being loaded");
3810 abort();
3811 }
3812
3813 bool
zink_screen_debug_marker_begin(struct zink_screen * screen,const char * fmt,...)3814 zink_screen_debug_marker_begin(struct zink_screen *screen, const char *fmt, ...)
3815 {
3816 if (!zink_tracing)
3817 return false;
3818
3819 char *name;
3820 va_list va;
3821 va_start(va, fmt);
3822 int ret = vasprintf(&name, fmt, va);
3823 va_end(va);
3824
3825 if (ret == -1)
3826 return false;
3827
3828 VkDebugUtilsLabelEXT info = { 0 };
3829 info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
3830 info.pLabelName = name;
3831
3832 VKSCR(QueueBeginDebugUtilsLabelEXT)(screen->queue, &info);
3833
3834 free(name);
3835 return true;
3836 }
3837
3838 void
zink_screen_debug_marker_end(struct zink_screen * screen,bool emitted)3839 zink_screen_debug_marker_end(struct zink_screen *screen, bool emitted)
3840 {
3841 if (emitted)
3842 VKSCR(QueueEndDebugUtilsLabelEXT)(screen->queue);
3843 }
3844