panvk_device.c revision 7ec681f3
1/*
2 * Copyright © 2021 Collabora Ltd.
3 *
4 * Derived from tu_device.c which is:
5 * Copyright © 2016 Red Hat.
6 * Copyright © 2016 Bas Nieuwenhuizen
7 * Copyright © 2015 Intel Corporation
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the next
17 * paragraph) shall be included in all copies or substantial portions of the
18 * Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 */
28
29#include "panvk_private.h"
30
31#include "panfrost-quirks.h"
32#include "pan_bo.h"
33#include "pan_encoder.h"
34#include "pan_util.h"
35
36#include <fcntl.h>
37#include <libsync.h>
38#include <stdbool.h>
39#include <string.h>
40#include <sys/mman.h>
41#include <sys/sysinfo.h>
42#include <unistd.h>
43#include <xf86drm.h>
44
45#include "drm-uapi/panfrost_drm.h"
46
47#include "util/debug.h"
48#include "util/disk_cache.h"
49#include "util/strtod.h"
50#include "vk_format.h"
51#include "vk_util.h"
52
53#ifdef VK_USE_PLATFORM_WAYLAND_KHR
54#include <wayland-client.h>
55#include "wayland-drm-client-protocol.h"
56#endif
57
58#include "panvk_cs.h"
59
60VkResult
61_panvk_device_set_lost(struct panvk_device *device,
62                       const char *file, int line,
63                       const char *msg, ...)
64{
65   /* Set the flag indicating that waits should return in finite time even
66    * after device loss.
67    */
68   p_atomic_inc(&device->_lost);
69
70   /* TODO: Report the log message through VkDebugReportCallbackEXT instead */
71   fprintf(stderr, "%s:%d: ", file, line);
72   va_list ap;
73   va_start(ap, msg);
74   vfprintf(stderr, msg, ap);
75   va_end(ap);
76
77   if (env_var_as_boolean("PANVK_ABORT_ON_DEVICE_LOSS", false))
78      abort();
79
80   return VK_ERROR_DEVICE_LOST;
81}
82
83static int
84panvk_device_get_cache_uuid(uint16_t family, void *uuid)
85{
86   uint32_t mesa_timestamp;
87   uint16_t f = family;
88
89   if (!disk_cache_get_function_timestamp(panvk_device_get_cache_uuid,
90                                          &mesa_timestamp))
91      return -1;
92
93   memset(uuid, 0, VK_UUID_SIZE);
94   memcpy(uuid, &mesa_timestamp, 4);
95   memcpy((char *) uuid + 4, &f, 2);
96   snprintf((char *) uuid + 6, VK_UUID_SIZE - 10, "pan");
97   return 0;
98}
99
100static void
101panvk_get_driver_uuid(void *uuid)
102{
103   memset(uuid, 0, VK_UUID_SIZE);
104   snprintf(uuid, VK_UUID_SIZE, "panfrost");
105}
106
107static void
108panvk_get_device_uuid(void *uuid)
109{
110   memset(uuid, 0, VK_UUID_SIZE);
111}
112
113static const struct debug_control panvk_debug_options[] = {
114   { "startup", PANVK_DEBUG_STARTUP },
115   { "nir", PANVK_DEBUG_NIR },
116   { "trace", PANVK_DEBUG_TRACE },
117   { "sync", PANVK_DEBUG_SYNC },
118   { "afbc", PANVK_DEBUG_AFBC },
119   { "linear", PANVK_DEBUG_LINEAR },
120   { NULL, 0 }
121};
122
123#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
124#define PANVK_USE_WSI_PLATFORM
125#endif
126
127#define PANVK_API_VERSION VK_MAKE_VERSION(1, 1, VK_HEADER_VERSION)
128
129VkResult
130panvk_EnumerateInstanceVersion(uint32_t *pApiVersion)
131{
132    *pApiVersion = PANVK_API_VERSION;
133    return VK_SUCCESS;
134}
135
136static const struct vk_instance_extension_table panvk_instance_extensions = {
137#ifdef PANVK_USE_WSI_PLATFORM
138   .KHR_surface = true,
139#endif
140#ifdef VK_USE_PLATFORM_WAYLAND_KHR
141   .KHR_wayland_surface = true,
142#endif
143};
144
145static void
146panvk_get_device_extensions(const struct panvk_physical_device *device,
147                            struct vk_device_extension_table *ext)
148{
149   *ext = (struct vk_device_extension_table) {
150#ifdef PANVK_USE_WSI_PLATFORM
151      .KHR_swapchain = true,
152#endif
153      .EXT_custom_border_color = true,
154   };
155}
156
157VkResult
158panvk_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
159                     const VkAllocationCallbacks *pAllocator,
160                     VkInstance *pInstance)
161{
162   struct panvk_instance *instance;
163   VkResult result;
164
165   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO);
166
167   pAllocator = pAllocator ? : vk_default_allocator();
168   instance = vk_zalloc(pAllocator, sizeof(*instance), 8,
169                        VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
170   if (!instance)
171      return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
172
173   struct vk_instance_dispatch_table dispatch_table;
174
175   vk_instance_dispatch_table_from_entrypoints(&dispatch_table,
176                                               &panvk_instance_entrypoints,
177                                               true);
178   vk_instance_dispatch_table_from_entrypoints(&dispatch_table,
179                                               &wsi_instance_entrypoints,
180                                               false);
181   result = vk_instance_init(&instance->vk,
182                             &panvk_instance_extensions,
183                             &dispatch_table,
184                             pCreateInfo,
185                             pAllocator);
186   if (result != VK_SUCCESS) {
187      vk_free(pAllocator, instance);
188      return vk_error(NULL, result);
189   }
190
191   instance->physical_device_count = -1;
192   instance->debug_flags = parse_debug_string(getenv("PANVK_DEBUG"),
193                                              panvk_debug_options);
194
195   if (instance->debug_flags & PANVK_DEBUG_STARTUP)
196      panvk_logi("Created an instance");
197
198   VG(VALGRIND_CREATE_MEMPOOL(instance, 0, false));
199
200   *pInstance = panvk_instance_to_handle(instance);
201
202   return VK_SUCCESS;
203}
204
205static void
206panvk_physical_device_finish(struct panvk_physical_device *device)
207{
208   panvk_wsi_finish(device);
209
210   panvk_arch_dispatch(device->pdev.arch, meta_cleanup, device);
211   panfrost_close_device(&device->pdev);
212   if (device->master_fd != -1)
213      close(device->master_fd);
214
215   vk_physical_device_finish(&device->vk);
216}
217
218void
219panvk_DestroyInstance(VkInstance _instance,
220                      const VkAllocationCallbacks *pAllocator)
221{
222   VK_FROM_HANDLE(panvk_instance, instance, _instance);
223
224   if (!instance)
225      return;
226
227   for (int i = 0; i < instance->physical_device_count; ++i) {
228      panvk_physical_device_finish(instance->physical_devices + i);
229   }
230
231   vk_instance_finish(&instance->vk);
232   vk_free(&instance->vk.alloc, instance);
233}
234
235static VkResult
236panvk_physical_device_init(struct panvk_physical_device *device,
237                           struct panvk_instance *instance,
238                           drmDevicePtr drm_device)
239{
240   const char *path = drm_device->nodes[DRM_NODE_RENDER];
241   VkResult result = VK_SUCCESS;
242   drmVersionPtr version;
243   int fd;
244   int master_fd = -1;
245
246   if (!getenv("PAN_I_WANT_A_BROKEN_VULKAN_DRIVER")) {
247      return vk_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER,
248                       "WARNING: panvk is not a conformant vulkan implementation, "
249                       "pass PAN_I_WANT_A_BROKEN_VULKAN_DRIVER=1 if you know what you're doing.");
250   }
251
252   fd = open(path, O_RDWR | O_CLOEXEC);
253   if (fd < 0) {
254      return vk_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER,
255                       "failed to open device %s", path);
256   }
257
258   version = drmGetVersion(fd);
259   if (!version) {
260      close(fd);
261      return vk_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER,
262                       "failed to query kernel driver version for device %s",
263                       path);
264   }
265
266   if (strcmp(version->name, "panfrost")) {
267      drmFreeVersion(version);
268      close(fd);
269      return vk_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER,
270                       "device %s does not use the panfrost kernel driver", path);
271   }
272
273   drmFreeVersion(version);
274
275   if (instance->debug_flags & PANVK_DEBUG_STARTUP)
276      panvk_logi("Found compatible device '%s'.", path);
277
278   struct vk_device_extension_table supported_extensions;
279   panvk_get_device_extensions(device, &supported_extensions);
280
281   struct vk_physical_device_dispatch_table dispatch_table;
282   vk_physical_device_dispatch_table_from_entrypoints(&dispatch_table,
283                                                      &panvk_physical_device_entrypoints,
284                                                      true);
285   vk_physical_device_dispatch_table_from_entrypoints(&dispatch_table,
286                                                      &wsi_physical_device_entrypoints,
287                                                      false);
288
289   result = vk_physical_device_init(&device->vk, &instance->vk,
290                                    &supported_extensions,
291                                    &dispatch_table);
292
293   if (result != VK_SUCCESS) {
294      vk_error(instance, result);
295      goto fail;
296   }
297
298   device->instance = instance;
299   assert(strlen(path) < ARRAY_SIZE(device->path));
300   strncpy(device->path, path, ARRAY_SIZE(device->path));
301
302   if (instance->vk.enabled_extensions.KHR_display) {
303      master_fd = open(drm_device->nodes[DRM_NODE_PRIMARY], O_RDWR | O_CLOEXEC);
304      if (master_fd >= 0) {
305         /* TODO: free master_fd is accel is not working? */
306      }
307   }
308
309   device->master_fd = master_fd;
310   if (instance->debug_flags & PANVK_DEBUG_TRACE)
311      device->pdev.debug |= PAN_DBG_TRACE;
312
313   device->pdev.debug |= PAN_DBG_NO_CACHE;
314   panfrost_open_device(NULL, fd, &device->pdev);
315   fd = -1;
316
317   if (device->pdev.quirks & MIDGARD_SFBD) {
318      result = vk_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER,
319                         "%s not supported",
320                         panfrost_model_name(device->pdev.gpu_id));
321      goto fail;
322   }
323
324   panvk_arch_dispatch(device->pdev.arch, meta_init, device);
325
326   memset(device->name, 0, sizeof(device->name));
327   sprintf(device->name, "%s", panfrost_model_name(device->pdev.gpu_id));
328
329   if (panvk_device_get_cache_uuid(device->pdev.gpu_id, device->cache_uuid)) {
330      result = vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
331                         "cannot generate UUID");
332      goto fail_close_device;
333   }
334
335   fprintf(stderr, "WARNING: panvk is not a conformant vulkan implementation, "
336                   "testing use only.\n");
337
338   panvk_get_driver_uuid(&device->device_uuid);
339   panvk_get_device_uuid(&device->device_uuid);
340
341   result = panvk_wsi_init(device);
342   if (result != VK_SUCCESS) {
343      vk_error(instance, result);
344      goto fail_close_device;
345   }
346
347   return VK_SUCCESS;
348
349fail_close_device:
350   panfrost_close_device(&device->pdev);
351fail:
352   if (fd != -1)
353      close(fd);
354   if (master_fd != -1)
355      close(master_fd);
356   return result;
357}
358
359static VkResult
360panvk_enumerate_devices(struct panvk_instance *instance)
361{
362   /* TODO: Check for more devices ? */
363   drmDevicePtr devices[8];
364   VkResult result = VK_ERROR_INCOMPATIBLE_DRIVER;
365   int max_devices;
366
367   instance->physical_device_count = 0;
368
369   max_devices = drmGetDevices2(0, devices, ARRAY_SIZE(devices));
370
371   if (instance->debug_flags & PANVK_DEBUG_STARTUP)
372      panvk_logi("Found %d drm nodes", max_devices);
373
374   if (max_devices < 1)
375      return vk_error(instance, VK_ERROR_INCOMPATIBLE_DRIVER);
376
377   for (unsigned i = 0; i < (unsigned) max_devices; i++) {
378      if ((devices[i]->available_nodes & (1 << DRM_NODE_RENDER)) &&
379          devices[i]->bustype == DRM_BUS_PLATFORM) {
380
381         result = panvk_physical_device_init(instance->physical_devices +
382                                           instance->physical_device_count,
383                                           instance, devices[i]);
384         if (result == VK_SUCCESS)
385            ++instance->physical_device_count;
386         else if (result != VK_ERROR_INCOMPATIBLE_DRIVER)
387            break;
388      }
389   }
390   drmFreeDevices(devices, max_devices);
391
392   return result;
393}
394
395VkResult
396panvk_EnumeratePhysicalDevices(VkInstance _instance,
397                               uint32_t *pPhysicalDeviceCount,
398                               VkPhysicalDevice *pPhysicalDevices)
399{
400   VK_FROM_HANDLE(panvk_instance, instance, _instance);
401   VK_OUTARRAY_MAKE(out, pPhysicalDevices, pPhysicalDeviceCount);
402
403   VkResult result;
404
405   if (instance->physical_device_count < 0) {
406      result = panvk_enumerate_devices(instance);
407      if (result != VK_SUCCESS && result != VK_ERROR_INCOMPATIBLE_DRIVER)
408         return result;
409   }
410
411   for (uint32_t i = 0; i < instance->physical_device_count; ++i) {
412      vk_outarray_append(&out, p)
413      {
414         *p = panvk_physical_device_to_handle(instance->physical_devices + i);
415      }
416   }
417
418   return vk_outarray_status(&out);
419}
420
421VkResult
422panvk_EnumeratePhysicalDeviceGroups(VkInstance _instance,
423                                    uint32_t *pPhysicalDeviceGroupCount,
424                                    VkPhysicalDeviceGroupProperties *pPhysicalDeviceGroupProperties)
425{
426   VK_FROM_HANDLE(panvk_instance, instance, _instance);
427   VK_OUTARRAY_MAKE(out, pPhysicalDeviceGroupProperties,
428                    pPhysicalDeviceGroupCount);
429   VkResult result;
430
431   if (instance->physical_device_count < 0) {
432      result = panvk_enumerate_devices(instance);
433      if (result != VK_SUCCESS && result != VK_ERROR_INCOMPATIBLE_DRIVER)
434         return result;
435   }
436
437   for (uint32_t i = 0; i < instance->physical_device_count; ++i) {
438      vk_outarray_append(&out, p)
439      {
440         p->physicalDeviceCount = 1;
441         p->physicalDevices[0] =
442            panvk_physical_device_to_handle(instance->physical_devices + i);
443         p->subsetAllocation = false;
444      }
445   }
446
447   return VK_SUCCESS;
448}
449
450void
451panvk_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,
452                                 VkPhysicalDeviceFeatures2 *pFeatures)
453{
454   vk_foreach_struct(ext, pFeatures->pNext)
455   {
456      switch (ext->sType) {
457      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES: {
458         VkPhysicalDeviceVulkan11Features *features = (void *) ext;
459         features->storageBuffer16BitAccess            = false;
460         features->uniformAndStorageBuffer16BitAccess  = false;
461         features->storagePushConstant16               = false;
462         features->storageInputOutput16                = false;
463         features->multiview                           = false;
464         features->multiviewGeometryShader             = false;
465         features->multiviewTessellationShader         = false;
466         features->variablePointersStorageBuffer       = true;
467         features->variablePointers                    = true;
468         features->protectedMemory                     = false;
469         features->samplerYcbcrConversion              = false;
470         features->shaderDrawParameters                = false;
471         break;
472      }
473      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES: {
474         VkPhysicalDeviceVulkan12Features *features = (void *) ext;
475         features->samplerMirrorClampToEdge            = false;
476         features->drawIndirectCount                   = false;
477         features->storageBuffer8BitAccess             = false;
478         features->uniformAndStorageBuffer8BitAccess   = false;
479         features->storagePushConstant8                = false;
480         features->shaderBufferInt64Atomics            = false;
481         features->shaderSharedInt64Atomics            = false;
482         features->shaderFloat16                       = false;
483         features->shaderInt8                          = false;
484
485         features->descriptorIndexing                                 = false;
486         features->shaderInputAttachmentArrayDynamicIndexing          = false;
487         features->shaderUniformTexelBufferArrayDynamicIndexing       = false;
488         features->shaderStorageTexelBufferArrayDynamicIndexing       = false;
489         features->shaderUniformBufferArrayNonUniformIndexing         = false;
490         features->shaderSampledImageArrayNonUniformIndexing          = false;
491         features->shaderStorageBufferArrayNonUniformIndexing         = false;
492         features->shaderStorageImageArrayNonUniformIndexing          = false;
493         features->shaderInputAttachmentArrayNonUniformIndexing       = false;
494         features->shaderUniformTexelBufferArrayNonUniformIndexing    = false;
495         features->shaderStorageTexelBufferArrayNonUniformIndexing    = false;
496         features->descriptorBindingUniformBufferUpdateAfterBind      = false;
497         features->descriptorBindingSampledImageUpdateAfterBind       = false;
498         features->descriptorBindingStorageImageUpdateAfterBind       = false;
499         features->descriptorBindingStorageBufferUpdateAfterBind      = false;
500         features->descriptorBindingUniformTexelBufferUpdateAfterBind = false;
501         features->descriptorBindingStorageTexelBufferUpdateAfterBind = false;
502         features->descriptorBindingUpdateUnusedWhilePending          = false;
503         features->descriptorBindingPartiallyBound                    = false;
504         features->descriptorBindingVariableDescriptorCount           = false;
505         features->runtimeDescriptorArray                             = false;
506
507         features->samplerFilterMinmax                 = false;
508         features->scalarBlockLayout                   = false;
509         features->imagelessFramebuffer                = false;
510         features->uniformBufferStandardLayout         = false;
511         features->shaderSubgroupExtendedTypes         = false;
512         features->separateDepthStencilLayouts         = false;
513         features->hostQueryReset                      = false;
514         features->timelineSemaphore                   = false;
515         features->bufferDeviceAddress                 = false;
516         features->bufferDeviceAddressCaptureReplay    = false;
517         features->bufferDeviceAddressMultiDevice      = false;
518         features->vulkanMemoryModel                   = false;
519         features->vulkanMemoryModelDeviceScope        = false;
520         features->vulkanMemoryModelAvailabilityVisibilityChains = false;
521         features->shaderOutputViewportIndex           = false;
522         features->shaderOutputLayer                   = false;
523         features->subgroupBroadcastDynamicId          = false;
524         break;
525      }
526      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES: {
527         VkPhysicalDeviceVariablePointersFeatures *features = (void *) ext;
528         features->variablePointersStorageBuffer = true;
529         features->variablePointers = true;
530         break;
531      }
532      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES: {
533         VkPhysicalDeviceMultiviewFeatures *features =
534            (VkPhysicalDeviceMultiviewFeatures *) ext;
535         features->multiview = false;
536         features->multiviewGeometryShader = false;
537         features->multiviewTessellationShader = false;
538         break;
539      }
540      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES: {
541         VkPhysicalDeviceShaderDrawParametersFeatures *features =
542            (VkPhysicalDeviceShaderDrawParametersFeatures *) ext;
543         features->shaderDrawParameters = false;
544         break;
545      }
546      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES: {
547         VkPhysicalDeviceProtectedMemoryFeatures *features =
548            (VkPhysicalDeviceProtectedMemoryFeatures *) ext;
549         features->protectedMemory = false;
550         break;
551      }
552      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES: {
553         VkPhysicalDevice16BitStorageFeatures *features =
554            (VkPhysicalDevice16BitStorageFeatures *) ext;
555         features->storageBuffer16BitAccess = false;
556         features->uniformAndStorageBuffer16BitAccess = false;
557         features->storagePushConstant16 = false;
558         features->storageInputOutput16 = false;
559         break;
560      }
561      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES: {
562         VkPhysicalDeviceSamplerYcbcrConversionFeatures *features =
563            (VkPhysicalDeviceSamplerYcbcrConversionFeatures *) ext;
564         features->samplerYcbcrConversion = false;
565         break;
566      }
567      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT: {
568         VkPhysicalDeviceDescriptorIndexingFeaturesEXT *features =
569            (VkPhysicalDeviceDescriptorIndexingFeaturesEXT *) ext;
570         features->shaderInputAttachmentArrayDynamicIndexing = false;
571         features->shaderUniformTexelBufferArrayDynamicIndexing = false;
572         features->shaderStorageTexelBufferArrayDynamicIndexing = false;
573         features->shaderUniformBufferArrayNonUniformIndexing = false;
574         features->shaderSampledImageArrayNonUniformIndexing = false;
575         features->shaderStorageBufferArrayNonUniformIndexing = false;
576         features->shaderStorageImageArrayNonUniformIndexing = false;
577         features->shaderInputAttachmentArrayNonUniformIndexing = false;
578         features->shaderUniformTexelBufferArrayNonUniformIndexing = false;
579         features->shaderStorageTexelBufferArrayNonUniformIndexing = false;
580         features->descriptorBindingUniformBufferUpdateAfterBind = false;
581         features->descriptorBindingSampledImageUpdateAfterBind = false;
582         features->descriptorBindingStorageImageUpdateAfterBind = false;
583         features->descriptorBindingStorageBufferUpdateAfterBind = false;
584         features->descriptorBindingUniformTexelBufferUpdateAfterBind = false;
585         features->descriptorBindingStorageTexelBufferUpdateAfterBind = false;
586         features->descriptorBindingUpdateUnusedWhilePending = false;
587         features->descriptorBindingPartiallyBound = false;
588         features->descriptorBindingVariableDescriptorCount = false;
589         features->runtimeDescriptorArray = false;
590         break;
591      }
592      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT: {
593         VkPhysicalDeviceConditionalRenderingFeaturesEXT *features =
594            (VkPhysicalDeviceConditionalRenderingFeaturesEXT *) ext;
595         features->conditionalRendering = false;
596         features->inheritedConditionalRendering = false;
597         break;
598      }
599      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT: {
600         VkPhysicalDeviceTransformFeedbackFeaturesEXT *features =
601            (VkPhysicalDeviceTransformFeedbackFeaturesEXT *) ext;
602         features->transformFeedback = false;
603         features->geometryStreams = false;
604         break;
605      }
606      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT: {
607         VkPhysicalDeviceIndexTypeUint8FeaturesEXT *features =
608            (VkPhysicalDeviceIndexTypeUint8FeaturesEXT *)ext;
609         features->indexTypeUint8 = true;
610         break;
611      }
612      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: {
613         VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *features =
614            (VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *)ext;
615         features->vertexAttributeInstanceRateDivisor = true;
616         features->vertexAttributeInstanceRateZeroDivisor = true;
617         break;
618      }
619      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT: {
620         VkPhysicalDevicePrivateDataFeaturesEXT *features =
621            (VkPhysicalDevicePrivateDataFeaturesEXT *)ext;
622         features->privateData = true;
623         break;
624      }
625      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT: {
626         VkPhysicalDeviceDepthClipEnableFeaturesEXT *features =
627            (VkPhysicalDeviceDepthClipEnableFeaturesEXT *)ext;
628         features->depthClipEnable = true;
629         break;
630      }
631      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT: {
632         VkPhysicalDevice4444FormatsFeaturesEXT *features = (void *)ext;
633         features->formatA4R4G4B4 = true;
634         features->formatA4B4G4R4 = true;
635         break;
636      }
637      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT: {
638         VkPhysicalDeviceCustomBorderColorFeaturesEXT *features = (void *) ext;
639         features->customBorderColors = true;
640         features->customBorderColorWithoutFormat = true;
641         break;
642      }
643      default:
644         break;
645      }
646   }
647
648   pFeatures->features = (VkPhysicalDeviceFeatures) {
649      .fullDrawIndexUint32 = true,
650      .independentBlend = true,
651      .wideLines = true,
652      .largePoints = true,
653      .textureCompressionETC2 = true,
654      .textureCompressionASTC_LDR = true,
655      .shaderUniformBufferArrayDynamicIndexing = true,
656      .shaderSampledImageArrayDynamicIndexing = true,
657      .shaderStorageBufferArrayDynamicIndexing = true,
658      .shaderStorageImageArrayDynamicIndexing = true,
659   };
660}
661
662void
663panvk_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
664                                   VkPhysicalDeviceProperties2 *pProperties)
665{
666   VK_FROM_HANDLE(panvk_physical_device, pdevice, physicalDevice);
667
668   vk_foreach_struct(ext, pProperties->pNext)
669   {
670      switch (ext->sType) {
671      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: {
672         VkPhysicalDevicePushDescriptorPropertiesKHR *properties = (VkPhysicalDevicePushDescriptorPropertiesKHR *)ext;
673         properties->maxPushDescriptors = MAX_PUSH_DESCRIPTORS;
674         break;
675      }
676      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES: {
677         VkPhysicalDeviceIDProperties *properties = (VkPhysicalDeviceIDProperties *)ext;
678         memcpy(properties->driverUUID, pdevice->driver_uuid, VK_UUID_SIZE);
679         memcpy(properties->deviceUUID, pdevice->device_uuid, VK_UUID_SIZE);
680         properties->deviceLUIDValid = false;
681         break;
682      }
683      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES: {
684         VkPhysicalDeviceMultiviewProperties *properties = (VkPhysicalDeviceMultiviewProperties *)ext;
685         properties->maxMultiviewViewCount = 0;
686         properties->maxMultiviewInstanceIndex = 0;
687         break;
688      }
689      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES: {
690         VkPhysicalDevicePointClippingProperties *properties = (VkPhysicalDevicePointClippingProperties *)ext;
691         properties->pointClippingBehavior =
692            VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES;
693         break;
694      }
695      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES: {
696         VkPhysicalDeviceMaintenance3Properties *properties = (VkPhysicalDeviceMaintenance3Properties *)ext;
697         /* Make sure everything is addressable by a signed 32-bit int, and
698          * our largest descriptors are 96 bytes. */
699         properties->maxPerSetDescriptors = (1ull << 31) / 96;
700         /* Our buffer size fields allow only this much */
701         properties->maxMemoryAllocationSize = 0xFFFFFFFFull;
702         break;
703      }
704      default:
705         break;
706      }
707   }
708
709   VkSampleCountFlags sample_counts =
710      VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT;
711
712   /* make sure that the entire descriptor set is addressable with a signed
713    * 32-bit int. So the sum of all limits scaled by descriptor size has to
714    * be at most 2 GiB. the combined image & samples object count as one of
715    * both. This limit is for the pipeline layout, not for the set layout, but
716    * there is no set limit, so we just set a pipeline limit. I don't think
717    * any app is going to hit this soon. */
718   size_t max_descriptor_set_size =
719      ((1ull << 31) - 16 * MAX_DYNAMIC_BUFFERS) /
720      (32 /* uniform buffer, 32 due to potential space wasted on alignment */ +
721       32 /* storage buffer, 32 due to potential space wasted on alignment */ +
722       32 /* sampler, largest when combined with image */ +
723       64 /* sampled image */ + 64 /* storage image */);
724
725   VkPhysicalDeviceLimits limits = {
726      .maxImageDimension1D = (1 << 14),
727      .maxImageDimension2D = (1 << 14),
728      .maxImageDimension3D = (1 << 11),
729      .maxImageDimensionCube = (1 << 14),
730      .maxImageArrayLayers = (1 << 11),
731      .maxTexelBufferElements = 128 * 1024 * 1024,
732      .maxUniformBufferRange = UINT32_MAX,
733      .maxStorageBufferRange = UINT32_MAX,
734      .maxPushConstantsSize = MAX_PUSH_CONSTANTS_SIZE,
735      .maxMemoryAllocationCount = UINT32_MAX,
736      .maxSamplerAllocationCount = 64 * 1024,
737      .bufferImageGranularity = 64,          /* A cache line */
738      .sparseAddressSpaceSize = 0xffffffffu, /* buffer max size */
739      .maxBoundDescriptorSets = MAX_SETS,
740      .maxPerStageDescriptorSamplers = max_descriptor_set_size,
741      .maxPerStageDescriptorUniformBuffers = max_descriptor_set_size,
742      .maxPerStageDescriptorStorageBuffers = max_descriptor_set_size,
743      .maxPerStageDescriptorSampledImages = max_descriptor_set_size,
744      .maxPerStageDescriptorStorageImages = max_descriptor_set_size,
745      .maxPerStageDescriptorInputAttachments = max_descriptor_set_size,
746      .maxPerStageResources = max_descriptor_set_size,
747      .maxDescriptorSetSamplers = max_descriptor_set_size,
748      .maxDescriptorSetUniformBuffers = max_descriptor_set_size,
749      .maxDescriptorSetUniformBuffersDynamic = MAX_DYNAMIC_UNIFORM_BUFFERS,
750      .maxDescriptorSetStorageBuffers = max_descriptor_set_size,
751      .maxDescriptorSetStorageBuffersDynamic = MAX_DYNAMIC_STORAGE_BUFFERS,
752      .maxDescriptorSetSampledImages = max_descriptor_set_size,
753      .maxDescriptorSetStorageImages = max_descriptor_set_size,
754      .maxDescriptorSetInputAttachments = max_descriptor_set_size,
755      .maxVertexInputAttributes = 32,
756      .maxVertexInputBindings = 32,
757      .maxVertexInputAttributeOffset = 2047,
758      .maxVertexInputBindingStride = 2048,
759      .maxVertexOutputComponents = 128,
760      .maxTessellationGenerationLevel = 64,
761      .maxTessellationPatchSize = 32,
762      .maxTessellationControlPerVertexInputComponents = 128,
763      .maxTessellationControlPerVertexOutputComponents = 128,
764      .maxTessellationControlPerPatchOutputComponents = 120,
765      .maxTessellationControlTotalOutputComponents = 4096,
766      .maxTessellationEvaluationInputComponents = 128,
767      .maxTessellationEvaluationOutputComponents = 128,
768      .maxGeometryShaderInvocations = 127,
769      .maxGeometryInputComponents = 64,
770      .maxGeometryOutputComponents = 128,
771      .maxGeometryOutputVertices = 256,
772      .maxGeometryTotalOutputComponents = 1024,
773      .maxFragmentInputComponents = 128,
774      .maxFragmentOutputAttachments = 8,
775      .maxFragmentDualSrcAttachments = 1,
776      .maxFragmentCombinedOutputResources = 8,
777      .maxComputeSharedMemorySize = 32768,
778      .maxComputeWorkGroupCount = { 65535, 65535, 65535 },
779      .maxComputeWorkGroupInvocations = 2048,
780      .maxComputeWorkGroupSize = { 2048, 2048, 2048 },
781      .subPixelPrecisionBits = 4 /* FIXME */,
782      .subTexelPrecisionBits = 4 /* FIXME */,
783      .mipmapPrecisionBits = 4 /* FIXME */,
784      .maxDrawIndexedIndexValue = UINT32_MAX,
785      .maxDrawIndirectCount = UINT32_MAX,
786      .maxSamplerLodBias = 16,
787      .maxSamplerAnisotropy = 16,
788      .maxViewports = MAX_VIEWPORTS,
789      .maxViewportDimensions = { (1 << 14), (1 << 14) },
790      .viewportBoundsRange = { INT16_MIN, INT16_MAX },
791      .viewportSubPixelBits = 8,
792      .minMemoryMapAlignment = 4096, /* A page */
793      .minTexelBufferOffsetAlignment = 1,
794      .minUniformBufferOffsetAlignment = 4,
795      .minStorageBufferOffsetAlignment = 4,
796      .minTexelOffset = -32,
797      .maxTexelOffset = 31,
798      .minTexelGatherOffset = -32,
799      .maxTexelGatherOffset = 31,
800      .minInterpolationOffset = -2,
801      .maxInterpolationOffset = 2,
802      .subPixelInterpolationOffsetBits = 8,
803      .maxFramebufferWidth = (1 << 14),
804      .maxFramebufferHeight = (1 << 14),
805      .maxFramebufferLayers = (1 << 10),
806      .framebufferColorSampleCounts = sample_counts,
807      .framebufferDepthSampleCounts = sample_counts,
808      .framebufferStencilSampleCounts = sample_counts,
809      .framebufferNoAttachmentsSampleCounts = sample_counts,
810      .maxColorAttachments = MAX_RTS,
811      .sampledImageColorSampleCounts = sample_counts,
812      .sampledImageIntegerSampleCounts = VK_SAMPLE_COUNT_1_BIT,
813      .sampledImageDepthSampleCounts = sample_counts,
814      .sampledImageStencilSampleCounts = sample_counts,
815      .storageImageSampleCounts = VK_SAMPLE_COUNT_1_BIT,
816      .maxSampleMaskWords = 1,
817      .timestampComputeAndGraphics = true,
818      .timestampPeriod = 1,
819      .maxClipDistances = 8,
820      .maxCullDistances = 8,
821      .maxCombinedClipAndCullDistances = 8,
822      .discreteQueuePriorities = 1,
823      .pointSizeRange = { 0.125, 255.875 },
824      .lineWidthRange = { 0.0, 7.9921875 },
825      .pointSizeGranularity = (1.0 / 8.0),
826      .lineWidthGranularity = (1.0 / 128.0),
827      .strictLines = false, /* FINISHME */
828      .standardSampleLocations = true,
829      .optimalBufferCopyOffsetAlignment = 128,
830      .optimalBufferCopyRowPitchAlignment = 128,
831      .nonCoherentAtomSize = 64,
832   };
833
834   pProperties->properties = (VkPhysicalDeviceProperties) {
835      .apiVersion = PANVK_API_VERSION,
836      .driverVersion = vk_get_driver_version(),
837      .vendorID = 0, /* TODO */
838      .deviceID = 0,
839      .deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
840      .limits = limits,
841      .sparseProperties = { 0 },
842   };
843
844   strcpy(pProperties->properties.deviceName, pdevice->name);
845   memcpy(pProperties->properties.pipelineCacheUUID, pdevice->cache_uuid, VK_UUID_SIZE);
846}
847
848static const VkQueueFamilyProperties panvk_queue_family_properties = {
849   .queueFlags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT,
850   .queueCount = 1,
851   .timestampValidBits = 64,
852   .minImageTransferGranularity = { 1, 1, 1 },
853};
854
855void
856panvk_GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,
857                                             uint32_t *pQueueFamilyPropertyCount,
858                                             VkQueueFamilyProperties *pQueueFamilyProperties)
859{
860   VK_OUTARRAY_MAKE(out, pQueueFamilyProperties, pQueueFamilyPropertyCount);
861
862   vk_outarray_append(&out, p) { *p = panvk_queue_family_properties; }
863}
864
865void
866panvk_GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice,
867                                              uint32_t *pQueueFamilyPropertyCount,
868                                              VkQueueFamilyProperties2 *pQueueFamilyProperties)
869{
870   VK_OUTARRAY_MAKE(out, pQueueFamilyProperties, pQueueFamilyPropertyCount);
871
872   vk_outarray_append(&out, p)
873   {
874      p->queueFamilyProperties = panvk_queue_family_properties;
875   }
876}
877
878static uint64_t
879panvk_get_system_heap_size()
880{
881   struct sysinfo info;
882   sysinfo(&info);
883
884   uint64_t total_ram = (uint64_t)info.totalram * info.mem_unit;
885
886   /* We don't want to burn too much ram with the GPU.  If the user has 4GiB
887    * or less, we use at most half.  If they have more than 4GiB, we use 3/4.
888    */
889   uint64_t available_ram;
890   if (total_ram <= 4ull * 1024 * 1024 * 1024)
891      available_ram = total_ram / 2;
892   else
893      available_ram = total_ram * 3 / 4;
894
895   return available_ram;
896}
897
898void
899panvk_GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice,
900                                         VkPhysicalDeviceMemoryProperties2 *pMemoryProperties)
901{
902   pMemoryProperties->memoryProperties = (VkPhysicalDeviceMemoryProperties) {
903      .memoryHeapCount = 1,
904      .memoryHeaps[0].size = panvk_get_system_heap_size(),
905      .memoryHeaps[0].flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
906      .memoryTypeCount = 1,
907      .memoryTypes[0].propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
908                                      VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
909                                      VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
910      .memoryTypes[0].heapIndex = 0,
911   };
912}
913
914static VkResult
915panvk_queue_init(struct panvk_device *device,
916                 struct panvk_queue *queue,
917                 int idx,
918                 const VkDeviceQueueCreateInfo *create_info)
919{
920   const struct panfrost_device *pdev = &device->physical_device->pdev;
921
922   VkResult result = vk_queue_init(&queue->vk, &device->vk, create_info, idx);
923   if (result != VK_SUCCESS)
924      return result;
925   queue->device = device;
926
927   struct drm_syncobj_create create = {
928      .flags = DRM_SYNCOBJ_CREATE_SIGNALED,
929   };
930
931   int ret = drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_CREATE, &create);
932   if (ret) {
933      vk_queue_finish(&queue->vk);
934      return VK_ERROR_OUT_OF_HOST_MEMORY;
935   }
936
937   queue->sync = create.handle;
938   return VK_SUCCESS;
939}
940
941static void
942panvk_queue_finish(struct panvk_queue *queue)
943{
944   vk_queue_finish(&queue->vk);
945}
946
947VkResult
948panvk_CreateDevice(VkPhysicalDevice physicalDevice,
949                   const VkDeviceCreateInfo *pCreateInfo,
950                   const VkAllocationCallbacks *pAllocator,
951                   VkDevice *pDevice)
952{
953   VK_FROM_HANDLE(panvk_physical_device, physical_device, physicalDevice);
954   VkResult result;
955   struct panvk_device *device;
956
957   device = vk_zalloc2(&physical_device->instance->vk.alloc, pAllocator,
958                       sizeof(*device), 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
959   if (!device)
960      return vk_error(physical_device, VK_ERROR_OUT_OF_HOST_MEMORY);
961
962   const struct vk_device_entrypoint_table *dev_entrypoints;
963   struct vk_device_dispatch_table dispatch_table;
964
965   switch (physical_device->pdev.arch) {
966   case 5:
967      dev_entrypoints = &panvk_v5_device_entrypoints;
968      break;
969   case 6:
970      dev_entrypoints = &panvk_v6_device_entrypoints;
971      break;
972   case 7:
973      dev_entrypoints = &panvk_v7_device_entrypoints;
974      break;
975   default:
976      unreachable("Unsupported architecture");
977   }
978
979   vk_device_dispatch_table_from_entrypoints(&dispatch_table,
980                                             dev_entrypoints,
981                                             true);
982   vk_device_dispatch_table_from_entrypoints(&dispatch_table,
983                                             &panvk_device_entrypoints,
984                                             false);
985   vk_device_dispatch_table_from_entrypoints(&dispatch_table,
986                                             &wsi_device_entrypoints,
987                                             false);
988   result = vk_device_init(&device->vk, &physical_device->vk, &dispatch_table,
989                           pCreateInfo, pAllocator);
990   if (result != VK_SUCCESS) {
991      vk_free(&device->vk.alloc, device);
992      return result;
993   }
994
995   device->instance = physical_device->instance;
996   device->physical_device = physical_device;
997
998   for (unsigned i = 0; i < pCreateInfo->queueCreateInfoCount; i++) {
999      const VkDeviceQueueCreateInfo *queue_create =
1000         &pCreateInfo->pQueueCreateInfos[i];
1001      uint32_t qfi = queue_create->queueFamilyIndex;
1002      device->queues[qfi] =
1003         vk_alloc(&device->vk.alloc,
1004                  queue_create->queueCount * sizeof(struct panvk_queue),
1005                  8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
1006      if (!device->queues[qfi]) {
1007         result = VK_ERROR_OUT_OF_HOST_MEMORY;
1008         goto fail;
1009      }
1010
1011      memset(device->queues[qfi], 0,
1012             queue_create->queueCount * sizeof(struct panvk_queue));
1013
1014      device->queue_count[qfi] = queue_create->queueCount;
1015
1016      for (unsigned q = 0; q < queue_create->queueCount; q++) {
1017         result = panvk_queue_init(device, &device->queues[qfi][q], q,
1018                                   queue_create);
1019         if (result != VK_SUCCESS)
1020            goto fail;
1021      }
1022   }
1023
1024   *pDevice = panvk_device_to_handle(device);
1025   return VK_SUCCESS;
1026
1027fail:
1028   for (unsigned i = 0; i < PANVK_MAX_QUEUE_FAMILIES; i++) {
1029      for (unsigned q = 0; q < device->queue_count[i]; q++)
1030         panvk_queue_finish(&device->queues[i][q]);
1031      if (device->queue_count[i])
1032         vk_object_free(&device->vk, NULL, device->queues[i]);
1033   }
1034
1035   vk_free(&device->vk.alloc, device);
1036   return result;
1037}
1038
1039void
1040panvk_DestroyDevice(VkDevice _device, const VkAllocationCallbacks *pAllocator)
1041{
1042   VK_FROM_HANDLE(panvk_device, device, _device);
1043
1044   if (!device)
1045      return;
1046
1047   for (unsigned i = 0; i < PANVK_MAX_QUEUE_FAMILIES; i++) {
1048      for (unsigned q = 0; q < device->queue_count[i]; q++)
1049         panvk_queue_finish(&device->queues[i][q]);
1050      if (device->queue_count[i])
1051         vk_object_free(&device->vk, NULL, device->queues[i]);
1052   }
1053
1054   vk_free(&device->vk.alloc, device);
1055}
1056
1057VkResult
1058panvk_EnumerateInstanceLayerProperties(uint32_t *pPropertyCount,
1059                                       VkLayerProperties *pProperties)
1060{
1061   *pPropertyCount = 0;
1062   return VK_SUCCESS;
1063}
1064
1065VkResult
1066panvk_QueueWaitIdle(VkQueue _queue)
1067{
1068   VK_FROM_HANDLE(panvk_queue, queue, _queue);
1069
1070   if (panvk_device_is_lost(queue->device))
1071      return VK_ERROR_DEVICE_LOST;
1072
1073   const struct panfrost_device *pdev = &queue->device->physical_device->pdev;
1074   struct drm_syncobj_wait wait = {
1075      .handles = (uint64_t) (uintptr_t)(&queue->sync),
1076      .count_handles = 1,
1077      .timeout_nsec = INT64_MAX,
1078      .flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL,
1079   };
1080   int ret;
1081
1082   ret = drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_WAIT, &wait);
1083   assert(!ret);
1084
1085   return VK_SUCCESS;
1086}
1087
1088VkResult
1089panvk_EnumerateInstanceExtensionProperties(const char *pLayerName,
1090                                           uint32_t *pPropertyCount,
1091                                           VkExtensionProperties *pProperties)
1092{
1093   if (pLayerName)
1094      return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
1095
1096   return vk_enumerate_instance_extension_properties(&panvk_instance_extensions,
1097                                                     pPropertyCount, pProperties);
1098}
1099
1100PFN_vkVoidFunction
1101panvk_GetInstanceProcAddr(VkInstance _instance, const char *pName)
1102{
1103   VK_FROM_HANDLE(panvk_instance, instance, _instance);
1104   return vk_instance_get_proc_addr(&instance->vk,
1105                                    &panvk_instance_entrypoints,
1106                                    pName);
1107}
1108
1109/* The loader wants us to expose a second GetInstanceProcAddr function
1110 * to work around certain LD_PRELOAD issues seen in apps.
1111 */
1112PUBLIC
1113VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1114vk_icdGetInstanceProcAddr(VkInstance instance, const char *pName);
1115
1116PUBLIC
1117VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1118vk_icdGetInstanceProcAddr(VkInstance instance, const char *pName)
1119{
1120   return panvk_GetInstanceProcAddr(instance, pName);
1121}
1122
1123VkResult
1124panvk_AllocateMemory(VkDevice _device,
1125                     const VkMemoryAllocateInfo *pAllocateInfo,
1126                     const VkAllocationCallbacks *pAllocator,
1127                     VkDeviceMemory *pMem)
1128{
1129   VK_FROM_HANDLE(panvk_device, device, _device);
1130   struct panvk_device_memory *mem;
1131
1132   assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
1133
1134   if (pAllocateInfo->allocationSize == 0) {
1135      /* Apparently, this is allowed */
1136      *pMem = VK_NULL_HANDLE;
1137      return VK_SUCCESS;
1138   }
1139
1140   mem = vk_object_alloc(&device->vk, pAllocator, sizeof(*mem),
1141                         VK_OBJECT_TYPE_DEVICE_MEMORY);
1142   if (mem == NULL)
1143      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1144
1145   const VkImportMemoryFdInfoKHR *fd_info =
1146      vk_find_struct_const(pAllocateInfo->pNext,
1147                           IMPORT_MEMORY_FD_INFO_KHR);
1148
1149   if (fd_info && !fd_info->handleType)
1150      fd_info = NULL;
1151
1152   if (fd_info) {
1153      assert(fd_info->handleType ==
1154                VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
1155             fd_info->handleType ==
1156                VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
1157
1158      /*
1159       * TODO Importing the same fd twice gives us the same handle without
1160       * reference counting.  We need to maintain a per-instance handle-to-bo
1161       * table and add reference count to panvk_bo.
1162       */
1163      mem->bo = panfrost_bo_import(&device->physical_device->pdev, fd_info->fd);
1164      /* take ownership and close the fd */
1165      close(fd_info->fd);
1166   } else {
1167      mem->bo = panfrost_bo_create(&device->physical_device->pdev,
1168                                   pAllocateInfo->allocationSize, 0,
1169                                   "User-requested memory");
1170   }
1171
1172   assert(mem->bo);
1173
1174   *pMem = panvk_device_memory_to_handle(mem);
1175
1176   return VK_SUCCESS;
1177}
1178
1179void
1180panvk_FreeMemory(VkDevice _device,
1181                 VkDeviceMemory _mem,
1182                 const VkAllocationCallbacks *pAllocator)
1183{
1184   VK_FROM_HANDLE(panvk_device, device, _device);
1185   VK_FROM_HANDLE(panvk_device_memory, mem, _mem);
1186
1187   if (mem == NULL)
1188      return;
1189
1190   panfrost_bo_unreference(mem->bo);
1191   vk_object_free(&device->vk, pAllocator, mem);
1192}
1193
1194VkResult
1195panvk_MapMemory(VkDevice _device,
1196                VkDeviceMemory _memory,
1197                VkDeviceSize offset,
1198                VkDeviceSize size,
1199                VkMemoryMapFlags flags,
1200                void **ppData)
1201{
1202   VK_FROM_HANDLE(panvk_device, device, _device);
1203   VK_FROM_HANDLE(panvk_device_memory, mem, _memory);
1204
1205   if (mem == NULL) {
1206      *ppData = NULL;
1207      return VK_SUCCESS;
1208   }
1209
1210   if (!mem->bo->ptr.cpu)
1211      panfrost_bo_mmap(mem->bo);
1212
1213   *ppData = mem->bo->ptr.cpu;
1214
1215   if (*ppData) {
1216      *ppData += offset;
1217      return VK_SUCCESS;
1218   }
1219
1220   return vk_error(device, VK_ERROR_MEMORY_MAP_FAILED);
1221}
1222
1223void
1224panvk_UnmapMemory(VkDevice _device, VkDeviceMemory _memory)
1225{
1226}
1227
1228VkResult
1229panvk_FlushMappedMemoryRanges(VkDevice _device,
1230                              uint32_t memoryRangeCount,
1231                              const VkMappedMemoryRange *pMemoryRanges)
1232{
1233   return VK_SUCCESS;
1234}
1235
1236VkResult
1237panvk_InvalidateMappedMemoryRanges(VkDevice _device,
1238                                   uint32_t memoryRangeCount,
1239                                   const VkMappedMemoryRange *pMemoryRanges)
1240{
1241   return VK_SUCCESS;
1242}
1243
1244void
1245panvk_GetBufferMemoryRequirements(VkDevice _device,
1246                                  VkBuffer _buffer,
1247                                  VkMemoryRequirements *pMemoryRequirements)
1248{
1249   VK_FROM_HANDLE(panvk_buffer, buffer, _buffer);
1250
1251   pMemoryRequirements->memoryTypeBits = 1;
1252   pMemoryRequirements->alignment = 64;
1253   pMemoryRequirements->size =
1254      MAX2(align64(buffer->size, pMemoryRequirements->alignment), buffer->size);
1255}
1256
1257void
1258panvk_GetBufferMemoryRequirements2(VkDevice device,
1259                                   const VkBufferMemoryRequirementsInfo2 *pInfo,
1260                                   VkMemoryRequirements2 *pMemoryRequirements)
1261{
1262   panvk_GetBufferMemoryRequirements(device, pInfo->buffer,
1263                                     &pMemoryRequirements->memoryRequirements);
1264}
1265
1266void
1267panvk_GetImageMemoryRequirements(VkDevice _device,
1268                                 VkImage _image,
1269                                 VkMemoryRequirements *pMemoryRequirements)
1270{
1271   VK_FROM_HANDLE(panvk_image, image, _image);
1272
1273   pMemoryRequirements->memoryTypeBits = 1;
1274   pMemoryRequirements->size = panvk_image_get_total_size(image);
1275   pMemoryRequirements->alignment = 4096;
1276}
1277
1278void
1279panvk_GetImageMemoryRequirements2(VkDevice device,
1280                                 const VkImageMemoryRequirementsInfo2 *pInfo,
1281                                 VkMemoryRequirements2 *pMemoryRequirements)
1282{
1283   panvk_GetImageMemoryRequirements(device, pInfo->image,
1284                                    &pMemoryRequirements->memoryRequirements);
1285}
1286
1287void
1288panvk_GetImageSparseMemoryRequirements(VkDevice device, VkImage image,
1289                                       uint32_t *pSparseMemoryRequirementCount,
1290                                       VkSparseImageMemoryRequirements *pSparseMemoryRequirements)
1291{
1292   panvk_stub();
1293}
1294
1295void
1296panvk_GetImageSparseMemoryRequirements2(VkDevice device,
1297                                        const VkImageSparseMemoryRequirementsInfo2 *pInfo,
1298                                        uint32_t *pSparseMemoryRequirementCount,
1299                                        VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
1300{
1301   panvk_stub();
1302}
1303
1304void
1305panvk_GetDeviceMemoryCommitment(VkDevice device,
1306                                VkDeviceMemory memory,
1307                                VkDeviceSize *pCommittedMemoryInBytes)
1308{
1309   *pCommittedMemoryInBytes = 0;
1310}
1311
1312VkResult
1313panvk_BindBufferMemory2(VkDevice device,
1314                        uint32_t bindInfoCount,
1315                        const VkBindBufferMemoryInfo *pBindInfos)
1316{
1317   for (uint32_t i = 0; i < bindInfoCount; ++i) {
1318      VK_FROM_HANDLE(panvk_device_memory, mem, pBindInfos[i].memory);
1319      VK_FROM_HANDLE(panvk_buffer, buffer, pBindInfos[i].buffer);
1320
1321      if (mem) {
1322         buffer->bo = mem->bo;
1323         buffer->bo_offset = pBindInfos[i].memoryOffset;
1324      } else {
1325         buffer->bo = NULL;
1326      }
1327   }
1328   return VK_SUCCESS;
1329}
1330
1331VkResult
1332panvk_BindBufferMemory(VkDevice device,
1333                       VkBuffer buffer,
1334                       VkDeviceMemory memory,
1335                       VkDeviceSize memoryOffset)
1336{
1337   const VkBindBufferMemoryInfo info = {
1338      .sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,
1339      .buffer = buffer,
1340      .memory = memory,
1341      .memoryOffset = memoryOffset
1342   };
1343
1344   return panvk_BindBufferMemory2(device, 1, &info);
1345}
1346
1347VkResult
1348panvk_BindImageMemory2(VkDevice device,
1349                       uint32_t bindInfoCount,
1350                       const VkBindImageMemoryInfo *pBindInfos)
1351{
1352   for (uint32_t i = 0; i < bindInfoCount; ++i) {
1353      VK_FROM_HANDLE(panvk_image, image, pBindInfos[i].image);
1354      VK_FROM_HANDLE(panvk_device_memory, mem, pBindInfos[i].memory);
1355
1356      if (mem) {
1357         image->pimage.data.bo = mem->bo;
1358         image->pimage.data.offset = pBindInfos[i].memoryOffset;
1359         /* Reset the AFBC headers */
1360         if (drm_is_afbc(image->pimage.layout.modifier)) {
1361            void *base = image->pimage.data.bo->ptr.cpu + image->pimage.data.offset;
1362
1363            for (unsigned layer = 0; layer < image->pimage.layout.array_size; layer++) {
1364               for (unsigned level = 0; level < image->pimage.layout.nr_slices; level++) {
1365                  void *header = base +
1366                                 (layer * image->pimage.layout.array_stride) +
1367                                 image->pimage.layout.slices[level].offset;
1368                  memset(header, 0, image->pimage.layout.slices[level].afbc.header_size);
1369               }
1370            }
1371         }
1372      } else {
1373         image->pimage.data.bo = NULL;
1374         image->pimage.data.offset = pBindInfos[i].memoryOffset;
1375      }
1376   }
1377
1378   return VK_SUCCESS;
1379}
1380
1381VkResult
1382panvk_BindImageMemory(VkDevice device,
1383                      VkImage image,
1384                      VkDeviceMemory memory,
1385                      VkDeviceSize memoryOffset)
1386{
1387   const VkBindImageMemoryInfo info = {
1388      .sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,
1389      .image = image,
1390      .memory = memory,
1391      .memoryOffset = memoryOffset
1392   };
1393
1394   return panvk_BindImageMemory2(device, 1, &info);
1395}
1396
1397VkResult
1398panvk_QueueBindSparse(VkQueue _queue,
1399                      uint32_t bindInfoCount,
1400                      const VkBindSparseInfo *pBindInfo,
1401                      VkFence _fence)
1402{
1403   return VK_SUCCESS;
1404}
1405
1406VkResult
1407panvk_CreateEvent(VkDevice _device,
1408                  const VkEventCreateInfo *pCreateInfo,
1409                  const VkAllocationCallbacks *pAllocator,
1410                  VkEvent *pEvent)
1411{
1412   VK_FROM_HANDLE(panvk_device, device, _device);
1413   const struct panfrost_device *pdev = &device->physical_device->pdev;
1414   struct panvk_event *event =
1415      vk_object_zalloc(&device->vk, pAllocator, sizeof(*event),
1416                       VK_OBJECT_TYPE_EVENT);
1417   if (!event)
1418      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1419
1420   struct drm_syncobj_create create = {
1421      .flags = 0,
1422   };
1423
1424   int ret = drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_CREATE, &create);
1425   if (ret)
1426      return VK_ERROR_OUT_OF_HOST_MEMORY;
1427
1428   event->syncobj = create.handle;
1429   *pEvent = panvk_event_to_handle(event);
1430
1431   return VK_SUCCESS;
1432}
1433
1434void
1435panvk_DestroyEvent(VkDevice _device,
1436                   VkEvent _event,
1437                   const VkAllocationCallbacks *pAllocator)
1438{
1439   VK_FROM_HANDLE(panvk_device, device, _device);
1440   VK_FROM_HANDLE(panvk_event, event, _event);
1441   const struct panfrost_device *pdev = &device->physical_device->pdev;
1442
1443   if (!event)
1444      return;
1445
1446   struct drm_syncobj_destroy destroy = { .handle = event->syncobj };
1447   drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_DESTROY, &destroy);
1448
1449   vk_object_free(&device->vk, pAllocator, event);
1450}
1451
1452VkResult
1453panvk_GetEventStatus(VkDevice _device, VkEvent _event)
1454{
1455   VK_FROM_HANDLE(panvk_device, device, _device);
1456   VK_FROM_HANDLE(panvk_event, event, _event);
1457   const struct panfrost_device *pdev = &device->physical_device->pdev;
1458   bool signaled;
1459
1460   struct drm_syncobj_wait wait = {
1461      .handles = (uintptr_t) &event->syncobj,
1462      .count_handles = 1,
1463      .timeout_nsec = 0,
1464      .flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,
1465   };
1466
1467   int ret = drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_WAIT, &wait);
1468   if (ret) {
1469      if (errno == ETIME)
1470         signaled = false;
1471      else {
1472         assert(0);
1473         return VK_ERROR_DEVICE_LOST; /* TODO */
1474      }
1475   } else
1476      signaled = true;
1477
1478   return signaled ? VK_EVENT_SET : VK_EVENT_RESET;
1479}
1480
1481VkResult
1482panvk_SetEvent(VkDevice _device, VkEvent _event)
1483{
1484   VK_FROM_HANDLE(panvk_device, device, _device);
1485   VK_FROM_HANDLE(panvk_event, event, _event);
1486   const struct panfrost_device *pdev = &device->physical_device->pdev;
1487
1488   struct drm_syncobj_array objs = {
1489      .handles = (uint64_t) (uintptr_t) &event->syncobj,
1490      .count_handles = 1
1491   };
1492
1493   /* This is going to just replace the fence for this syncobj with one that
1494    * is already in signaled state. This won't be a problem because the spec
1495    * mandates that the event will have been set before the vkCmdWaitEvents
1496    * command executes.
1497    * https://www.khronos.org/registry/vulkan/specs/1.2/html/chap6.html#commandbuffers-submission-progress
1498    */
1499   if (drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_SIGNAL, &objs))
1500      return VK_ERROR_DEVICE_LOST;
1501
1502  return VK_SUCCESS;
1503}
1504
1505VkResult
1506panvk_ResetEvent(VkDevice _device, VkEvent _event)
1507{
1508   VK_FROM_HANDLE(panvk_device, device, _device);
1509   VK_FROM_HANDLE(panvk_event, event, _event);
1510   const struct panfrost_device *pdev = &device->physical_device->pdev;
1511
1512   struct drm_syncobj_array objs = {
1513      .handles = (uint64_t) (uintptr_t) &event->syncobj,
1514      .count_handles = 1
1515   };
1516
1517   if (drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_RESET, &objs))
1518      return VK_ERROR_DEVICE_LOST;
1519
1520  return VK_SUCCESS;
1521}
1522
1523VkResult
1524panvk_CreateBuffer(VkDevice _device,
1525                   const VkBufferCreateInfo *pCreateInfo,
1526                   const VkAllocationCallbacks *pAllocator,
1527                   VkBuffer *pBuffer)
1528{
1529   VK_FROM_HANDLE(panvk_device, device, _device);
1530   struct panvk_buffer *buffer;
1531
1532   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);
1533
1534   buffer = vk_object_alloc(&device->vk, pAllocator, sizeof(*buffer),
1535                            VK_OBJECT_TYPE_BUFFER);
1536   if (buffer == NULL)
1537      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1538
1539   buffer->size = pCreateInfo->size;
1540   buffer->usage = pCreateInfo->usage;
1541   buffer->flags = pCreateInfo->flags;
1542
1543   *pBuffer = panvk_buffer_to_handle(buffer);
1544
1545   return VK_SUCCESS;
1546}
1547
1548void
1549panvk_DestroyBuffer(VkDevice _device,
1550                    VkBuffer _buffer,
1551                    const VkAllocationCallbacks *pAllocator)
1552{
1553   VK_FROM_HANDLE(panvk_device, device, _device);
1554   VK_FROM_HANDLE(panvk_buffer, buffer, _buffer);
1555
1556   if (!buffer)
1557      return;
1558
1559   vk_object_free(&device->vk, pAllocator, buffer);
1560}
1561
1562VkResult
1563panvk_CreateFramebuffer(VkDevice _device,
1564                        const VkFramebufferCreateInfo *pCreateInfo,
1565                        const VkAllocationCallbacks *pAllocator,
1566                        VkFramebuffer *pFramebuffer)
1567{
1568   VK_FROM_HANDLE(panvk_device, device, _device);
1569   struct panvk_framebuffer *framebuffer;
1570
1571   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO);
1572
1573   size_t size = sizeof(*framebuffer) + sizeof(struct panvk_attachment_info) *
1574                                           pCreateInfo->attachmentCount;
1575   framebuffer = vk_object_alloc(&device->vk, pAllocator, size,
1576                                 VK_OBJECT_TYPE_FRAMEBUFFER);
1577   if (framebuffer == NULL)
1578      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1579
1580   framebuffer->attachment_count = pCreateInfo->attachmentCount;
1581   framebuffer->width = pCreateInfo->width;
1582   framebuffer->height = pCreateInfo->height;
1583   framebuffer->layers = pCreateInfo->layers;
1584   for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
1585      VkImageView _iview = pCreateInfo->pAttachments[i];
1586      struct panvk_image_view *iview = panvk_image_view_from_handle(_iview);
1587      framebuffer->attachments[i].iview = iview;
1588   }
1589
1590   *pFramebuffer = panvk_framebuffer_to_handle(framebuffer);
1591   return VK_SUCCESS;
1592}
1593
1594void
1595panvk_DestroyFramebuffer(VkDevice _device,
1596                         VkFramebuffer _fb,
1597                         const VkAllocationCallbacks *pAllocator)
1598{
1599   VK_FROM_HANDLE(panvk_device, device, _device);
1600   VK_FROM_HANDLE(panvk_framebuffer, fb, _fb);
1601
1602   if (fb)
1603      vk_object_free(&device->vk, pAllocator, fb);
1604}
1605
1606void
1607panvk_DestroySampler(VkDevice _device,
1608                     VkSampler _sampler,
1609                     const VkAllocationCallbacks *pAllocator)
1610{
1611   VK_FROM_HANDLE(panvk_device, device, _device);
1612   VK_FROM_HANDLE(panvk_sampler, sampler, _sampler);
1613
1614   if (!sampler)
1615      return;
1616
1617   vk_object_free(&device->vk, pAllocator, sampler);
1618}
1619
1620/* vk_icd.h does not declare this function, so we declare it here to
1621 * suppress Wmissing-prototypes.
1622 */
1623PUBLIC VKAPI_ATTR VkResult VKAPI_CALL
1624vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t *pSupportedVersion);
1625
1626PUBLIC VKAPI_ATTR VkResult VKAPI_CALL
1627vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t *pSupportedVersion)
1628{
1629   /* For the full details on loader interface versioning, see
1630    * <https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/loader/LoaderAndLayerInterface.md>.
1631    * What follows is a condensed summary, to help you navigate the large and
1632    * confusing official doc.
1633    *
1634    *   - Loader interface v0 is incompatible with later versions. We don't
1635    *     support it.
1636    *
1637    *   - In loader interface v1:
1638    *       - The first ICD entrypoint called by the loader is
1639    *         vk_icdGetInstanceProcAddr(). The ICD must statically expose this
1640    *         entrypoint.
1641    *       - The ICD must statically expose no other Vulkan symbol unless it
1642    * is linked with -Bsymbolic.
1643    *       - Each dispatchable Vulkan handle created by the ICD must be
1644    *         a pointer to a struct whose first member is VK_LOADER_DATA. The
1645    *         ICD must initialize VK_LOADER_DATA.loadMagic to
1646    * ICD_LOADER_MAGIC.
1647    *       - The loader implements vkCreate{PLATFORM}SurfaceKHR() and
1648    *         vkDestroySurfaceKHR(). The ICD must be capable of working with
1649    *         such loader-managed surfaces.
1650    *
1651    *    - Loader interface v2 differs from v1 in:
1652    *       - The first ICD entrypoint called by the loader is
1653    *         vk_icdNegotiateLoaderICDInterfaceVersion(). The ICD must
1654    *         statically expose this entrypoint.
1655    *
1656    *    - Loader interface v3 differs from v2 in:
1657    *        - The ICD must implement vkCreate{PLATFORM}SurfaceKHR(),
1658    *          vkDestroySurfaceKHR(), and other API which uses VKSurfaceKHR,
1659    *          because the loader no longer does so.
1660    */
1661   *pSupportedVersion = MIN2(*pSupportedVersion, 3u);
1662   return VK_SUCCESS;
1663}
1664
1665VkResult
1666panvk_GetMemoryFdKHR(VkDevice _device,
1667                     const VkMemoryGetFdInfoKHR *pGetFdInfo,
1668                     int *pFd)
1669{
1670   VK_FROM_HANDLE(panvk_device, device, _device);
1671   VK_FROM_HANDLE(panvk_device_memory, memory, pGetFdInfo->memory);
1672
1673   assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR);
1674
1675   /* At the moment, we support only the below handle types. */
1676   assert(pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
1677          pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
1678
1679   int prime_fd = panfrost_bo_export(memory->bo);
1680   if (prime_fd < 0)
1681      return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
1682
1683   *pFd = prime_fd;
1684   return VK_SUCCESS;
1685}
1686
1687VkResult
1688panvk_GetMemoryFdPropertiesKHR(VkDevice _device,
1689                               VkExternalMemoryHandleTypeFlagBits handleType,
1690                               int fd,
1691                               VkMemoryFdPropertiesKHR *pMemoryFdProperties)
1692{
1693   assert(handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
1694   pMemoryFdProperties->memoryTypeBits = 1;
1695   return VK_SUCCESS;
1696}
1697
1698void
1699panvk_GetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice,
1700                                                   const VkPhysicalDeviceExternalSemaphoreInfo *pExternalSemaphoreInfo,
1701                                                   VkExternalSemaphoreProperties *pExternalSemaphoreProperties)
1702{
1703   if ((pExternalSemaphoreInfo->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT ||
1704        pExternalSemaphoreInfo->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)) {
1705      pExternalSemaphoreProperties->exportFromImportedHandleTypes =
1706         VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT |
1707         VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
1708      pExternalSemaphoreProperties->compatibleHandleTypes =
1709         VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT |
1710         VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
1711      pExternalSemaphoreProperties->externalSemaphoreFeatures =
1712         VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT |
1713         VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT;
1714   } else {
1715      pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0;
1716      pExternalSemaphoreProperties->compatibleHandleTypes = 0;
1717      pExternalSemaphoreProperties->externalSemaphoreFeatures = 0;
1718   }
1719}
1720
1721void
1722panvk_GetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice,
1723                                               const VkPhysicalDeviceExternalFenceInfo *pExternalFenceInfo,
1724                                               VkExternalFenceProperties *pExternalFenceProperties)
1725{
1726   pExternalFenceProperties->exportFromImportedHandleTypes = 0;
1727   pExternalFenceProperties->compatibleHandleTypes = 0;
1728   pExternalFenceProperties->externalFenceFeatures = 0;
1729}
1730
1731void
1732panvk_GetDeviceGroupPeerMemoryFeatures(VkDevice device,
1733                                       uint32_t heapIndex,
1734                                       uint32_t localDeviceIndex,
1735                                       uint32_t remoteDeviceIndex,
1736                                       VkPeerMemoryFeatureFlags *pPeerMemoryFeatures)
1737{
1738   assert(localDeviceIndex == remoteDeviceIndex);
1739
1740   *pPeerMemoryFeatures = VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT |
1741                          VK_PEER_MEMORY_FEATURE_COPY_DST_BIT |
1742                          VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT |
1743                          VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT;
1744}
1745