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