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