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