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