17ec681f3Smrg/*
27ec681f3Smrg * Copyright © 2021 Collabora Ltd.
37ec681f3Smrg *
47ec681f3Smrg * Derived from tu_device.c which is:
57ec681f3Smrg * Copyright © 2016 Red Hat.
67ec681f3Smrg * Copyright © 2016 Bas Nieuwenhuizen
77ec681f3Smrg * Copyright © 2015 Intel Corporation
87ec681f3Smrg *
97ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
107ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
117ec681f3Smrg * to deal in the Software without restriction, including without limitation
127ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
137ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the
147ec681f3Smrg * Software is furnished to do so, subject to the following conditions:
157ec681f3Smrg *
167ec681f3Smrg * The above copyright notice and this permission notice (including the next
177ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
187ec681f3Smrg * Software.
197ec681f3Smrg *
207ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
217ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
227ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
237ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
247ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
257ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
267ec681f3Smrg * DEALINGS IN THE SOFTWARE.
277ec681f3Smrg */
287ec681f3Smrg
297ec681f3Smrg#include "panvk_private.h"
307ec681f3Smrg
317ec681f3Smrg#include "panfrost-quirks.h"
327ec681f3Smrg#include "pan_bo.h"
337ec681f3Smrg#include "pan_encoder.h"
347ec681f3Smrg#include "pan_util.h"
357ec681f3Smrg
367ec681f3Smrg#include <fcntl.h>
377ec681f3Smrg#include <libsync.h>
387ec681f3Smrg#include <stdbool.h>
397ec681f3Smrg#include <string.h>
407ec681f3Smrg#include <sys/mman.h>
417ec681f3Smrg#include <sys/sysinfo.h>
427ec681f3Smrg#include <unistd.h>
437ec681f3Smrg#include <xf86drm.h>
447ec681f3Smrg
457ec681f3Smrg#include "drm-uapi/panfrost_drm.h"
467ec681f3Smrg
477ec681f3Smrg#include "util/debug.h"
487ec681f3Smrg#include "util/disk_cache.h"
497ec681f3Smrg#include "util/strtod.h"
507ec681f3Smrg#include "vk_format.h"
517ec681f3Smrg#include "vk_util.h"
527ec681f3Smrg
537ec681f3Smrg#ifdef VK_USE_PLATFORM_WAYLAND_KHR
547ec681f3Smrg#include <wayland-client.h>
557ec681f3Smrg#include "wayland-drm-client-protocol.h"
567ec681f3Smrg#endif
577ec681f3Smrg
587ec681f3Smrg#include "panvk_cs.h"
597ec681f3Smrg
607ec681f3SmrgVkResult
617ec681f3Smrg_panvk_device_set_lost(struct panvk_device *device,
627ec681f3Smrg                       const char *file, int line,
637ec681f3Smrg                       const char *msg, ...)
647ec681f3Smrg{
657ec681f3Smrg   /* Set the flag indicating that waits should return in finite time even
667ec681f3Smrg    * after device loss.
677ec681f3Smrg    */
687ec681f3Smrg   p_atomic_inc(&device->_lost);
697ec681f3Smrg
707ec681f3Smrg   /* TODO: Report the log message through VkDebugReportCallbackEXT instead */
717ec681f3Smrg   fprintf(stderr, "%s:%d: ", file, line);
727ec681f3Smrg   va_list ap;
737ec681f3Smrg   va_start(ap, msg);
747ec681f3Smrg   vfprintf(stderr, msg, ap);
757ec681f3Smrg   va_end(ap);
767ec681f3Smrg
777ec681f3Smrg   if (env_var_as_boolean("PANVK_ABORT_ON_DEVICE_LOSS", false))
787ec681f3Smrg      abort();
797ec681f3Smrg
807ec681f3Smrg   return VK_ERROR_DEVICE_LOST;
817ec681f3Smrg}
827ec681f3Smrg
837ec681f3Smrgstatic int
847ec681f3Smrgpanvk_device_get_cache_uuid(uint16_t family, void *uuid)
857ec681f3Smrg{
867ec681f3Smrg   uint32_t mesa_timestamp;
877ec681f3Smrg   uint16_t f = family;
887ec681f3Smrg
897ec681f3Smrg   if (!disk_cache_get_function_timestamp(panvk_device_get_cache_uuid,
907ec681f3Smrg                                          &mesa_timestamp))
917ec681f3Smrg      return -1;
927ec681f3Smrg
937ec681f3Smrg   memset(uuid, 0, VK_UUID_SIZE);
947ec681f3Smrg   memcpy(uuid, &mesa_timestamp, 4);
957ec681f3Smrg   memcpy((char *) uuid + 4, &f, 2);
967ec681f3Smrg   snprintf((char *) uuid + 6, VK_UUID_SIZE - 10, "pan");
977ec681f3Smrg   return 0;
987ec681f3Smrg}
997ec681f3Smrg
1007ec681f3Smrgstatic void
1017ec681f3Smrgpanvk_get_driver_uuid(void *uuid)
1027ec681f3Smrg{
1037ec681f3Smrg   memset(uuid, 0, VK_UUID_SIZE);
1047ec681f3Smrg   snprintf(uuid, VK_UUID_SIZE, "panfrost");
1057ec681f3Smrg}
1067ec681f3Smrg
1077ec681f3Smrgstatic void
1087ec681f3Smrgpanvk_get_device_uuid(void *uuid)
1097ec681f3Smrg{
1107ec681f3Smrg   memset(uuid, 0, VK_UUID_SIZE);
1117ec681f3Smrg}
1127ec681f3Smrg
1137ec681f3Smrgstatic const struct debug_control panvk_debug_options[] = {
1147ec681f3Smrg   { "startup", PANVK_DEBUG_STARTUP },
1157ec681f3Smrg   { "nir", PANVK_DEBUG_NIR },
1167ec681f3Smrg   { "trace", PANVK_DEBUG_TRACE },
1177ec681f3Smrg   { "sync", PANVK_DEBUG_SYNC },
1187ec681f3Smrg   { "afbc", PANVK_DEBUG_AFBC },
1197ec681f3Smrg   { "linear", PANVK_DEBUG_LINEAR },
1207ec681f3Smrg   { NULL, 0 }
1217ec681f3Smrg};
1227ec681f3Smrg
1237ec681f3Smrg#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
1247ec681f3Smrg#define PANVK_USE_WSI_PLATFORM
1257ec681f3Smrg#endif
1267ec681f3Smrg
1277ec681f3Smrg#define PANVK_API_VERSION VK_MAKE_VERSION(1, 1, VK_HEADER_VERSION)
1287ec681f3Smrg
1297ec681f3SmrgVkResult
1307ec681f3Smrgpanvk_EnumerateInstanceVersion(uint32_t *pApiVersion)
1317ec681f3Smrg{
1327ec681f3Smrg    *pApiVersion = PANVK_API_VERSION;
1337ec681f3Smrg    return VK_SUCCESS;
1347ec681f3Smrg}
1357ec681f3Smrg
1367ec681f3Smrgstatic const struct vk_instance_extension_table panvk_instance_extensions = {
1377ec681f3Smrg#ifdef PANVK_USE_WSI_PLATFORM
1387ec681f3Smrg   .KHR_surface = true,
1397ec681f3Smrg#endif
1407ec681f3Smrg#ifdef VK_USE_PLATFORM_WAYLAND_KHR
1417ec681f3Smrg   .KHR_wayland_surface = true,
1427ec681f3Smrg#endif
1437ec681f3Smrg};
1447ec681f3Smrg
1457ec681f3Smrgstatic void
1467ec681f3Smrgpanvk_get_device_extensions(const struct panvk_physical_device *device,
1477ec681f3Smrg                            struct vk_device_extension_table *ext)
1487ec681f3Smrg{
1497ec681f3Smrg   *ext = (struct vk_device_extension_table) {
1507ec681f3Smrg#ifdef PANVK_USE_WSI_PLATFORM
1517ec681f3Smrg      .KHR_swapchain = true,
1527ec681f3Smrg#endif
1537ec681f3Smrg      .EXT_custom_border_color = true,
1547ec681f3Smrg   };
1557ec681f3Smrg}
1567ec681f3Smrg
1577ec681f3SmrgVkResult
1587ec681f3Smrgpanvk_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
1597ec681f3Smrg                     const VkAllocationCallbacks *pAllocator,
1607ec681f3Smrg                     VkInstance *pInstance)
1617ec681f3Smrg{
1627ec681f3Smrg   struct panvk_instance *instance;
1637ec681f3Smrg   VkResult result;
1647ec681f3Smrg
1657ec681f3Smrg   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO);
1667ec681f3Smrg
1677ec681f3Smrg   pAllocator = pAllocator ? : vk_default_allocator();
1687ec681f3Smrg   instance = vk_zalloc(pAllocator, sizeof(*instance), 8,
1697ec681f3Smrg                        VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
1707ec681f3Smrg   if (!instance)
1717ec681f3Smrg      return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
1727ec681f3Smrg
1737ec681f3Smrg   struct vk_instance_dispatch_table dispatch_table;
1747ec681f3Smrg
1757ec681f3Smrg   vk_instance_dispatch_table_from_entrypoints(&dispatch_table,
1767ec681f3Smrg                                               &panvk_instance_entrypoints,
1777ec681f3Smrg                                               true);
1787ec681f3Smrg   vk_instance_dispatch_table_from_entrypoints(&dispatch_table,
1797ec681f3Smrg                                               &wsi_instance_entrypoints,
1807ec681f3Smrg                                               false);
1817ec681f3Smrg   result = vk_instance_init(&instance->vk,
1827ec681f3Smrg                             &panvk_instance_extensions,
1837ec681f3Smrg                             &dispatch_table,
1847ec681f3Smrg                             pCreateInfo,
1857ec681f3Smrg                             pAllocator);
1867ec681f3Smrg   if (result != VK_SUCCESS) {
1877ec681f3Smrg      vk_free(pAllocator, instance);
1887ec681f3Smrg      return vk_error(NULL, result);
1897ec681f3Smrg   }
1907ec681f3Smrg
1917ec681f3Smrg   instance->physical_device_count = -1;
1927ec681f3Smrg   instance->debug_flags = parse_debug_string(getenv("PANVK_DEBUG"),
1937ec681f3Smrg                                              panvk_debug_options);
1947ec681f3Smrg
1957ec681f3Smrg   if (instance->debug_flags & PANVK_DEBUG_STARTUP)
1967ec681f3Smrg      panvk_logi("Created an instance");
1977ec681f3Smrg
1987ec681f3Smrg   VG(VALGRIND_CREATE_MEMPOOL(instance, 0, false));
1997ec681f3Smrg
2007ec681f3Smrg   *pInstance = panvk_instance_to_handle(instance);
2017ec681f3Smrg
2027ec681f3Smrg   return VK_SUCCESS;
2037ec681f3Smrg}
2047ec681f3Smrg
2057ec681f3Smrgstatic void
2067ec681f3Smrgpanvk_physical_device_finish(struct panvk_physical_device *device)
2077ec681f3Smrg{
2087ec681f3Smrg   panvk_wsi_finish(device);
2097ec681f3Smrg
2107ec681f3Smrg   panvk_arch_dispatch(device->pdev.arch, meta_cleanup, device);
2117ec681f3Smrg   panfrost_close_device(&device->pdev);
2127ec681f3Smrg   if (device->master_fd != -1)
2137ec681f3Smrg      close(device->master_fd);
2147ec681f3Smrg
2157ec681f3Smrg   vk_physical_device_finish(&device->vk);
2167ec681f3Smrg}
2177ec681f3Smrg
2187ec681f3Smrgvoid
2197ec681f3Smrgpanvk_DestroyInstance(VkInstance _instance,
2207ec681f3Smrg                      const VkAllocationCallbacks *pAllocator)
2217ec681f3Smrg{
2227ec681f3Smrg   VK_FROM_HANDLE(panvk_instance, instance, _instance);
2237ec681f3Smrg
2247ec681f3Smrg   if (!instance)
2257ec681f3Smrg      return;
2267ec681f3Smrg
2277ec681f3Smrg   for (int i = 0; i < instance->physical_device_count; ++i) {
2287ec681f3Smrg      panvk_physical_device_finish(instance->physical_devices + i);
2297ec681f3Smrg   }
2307ec681f3Smrg
2317ec681f3Smrg   vk_instance_finish(&instance->vk);
2327ec681f3Smrg   vk_free(&instance->vk.alloc, instance);
2337ec681f3Smrg}
2347ec681f3Smrg
2357ec681f3Smrgstatic VkResult
2367ec681f3Smrgpanvk_physical_device_init(struct panvk_physical_device *device,
2377ec681f3Smrg                           struct panvk_instance *instance,
2387ec681f3Smrg                           drmDevicePtr drm_device)
2397ec681f3Smrg{
2407ec681f3Smrg   const char *path = drm_device->nodes[DRM_NODE_RENDER];
2417ec681f3Smrg   VkResult result = VK_SUCCESS;
2427ec681f3Smrg   drmVersionPtr version;
2437ec681f3Smrg   int fd;
2447ec681f3Smrg   int master_fd = -1;
2457ec681f3Smrg
2467ec681f3Smrg   if (!getenv("PAN_I_WANT_A_BROKEN_VULKAN_DRIVER")) {
2477ec681f3Smrg      return vk_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER,
2487ec681f3Smrg                       "WARNING: panvk is not a conformant vulkan implementation, "
2497ec681f3Smrg                       "pass PAN_I_WANT_A_BROKEN_VULKAN_DRIVER=1 if you know what you're doing.");
2507ec681f3Smrg   }
2517ec681f3Smrg
2527ec681f3Smrg   fd = open(path, O_RDWR | O_CLOEXEC);
2537ec681f3Smrg   if (fd < 0) {
2547ec681f3Smrg      return vk_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER,
2557ec681f3Smrg                       "failed to open device %s", path);
2567ec681f3Smrg   }
2577ec681f3Smrg
2587ec681f3Smrg   version = drmGetVersion(fd);
2597ec681f3Smrg   if (!version) {
2607ec681f3Smrg      close(fd);
2617ec681f3Smrg      return vk_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER,
2627ec681f3Smrg                       "failed to query kernel driver version for device %s",
2637ec681f3Smrg                       path);
2647ec681f3Smrg   }
2657ec681f3Smrg
2667ec681f3Smrg   if (strcmp(version->name, "panfrost")) {
2677ec681f3Smrg      drmFreeVersion(version);
2687ec681f3Smrg      close(fd);
2697ec681f3Smrg      return vk_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER,
2707ec681f3Smrg                       "device %s does not use the panfrost kernel driver", path);
2717ec681f3Smrg   }
2727ec681f3Smrg
2737ec681f3Smrg   drmFreeVersion(version);
2747ec681f3Smrg
2757ec681f3Smrg   if (instance->debug_flags & PANVK_DEBUG_STARTUP)
2767ec681f3Smrg      panvk_logi("Found compatible device '%s'.", path);
2777ec681f3Smrg
2787ec681f3Smrg   struct vk_device_extension_table supported_extensions;
2797ec681f3Smrg   panvk_get_device_extensions(device, &supported_extensions);
2807ec681f3Smrg
2817ec681f3Smrg   struct vk_physical_device_dispatch_table dispatch_table;
2827ec681f3Smrg   vk_physical_device_dispatch_table_from_entrypoints(&dispatch_table,
2837ec681f3Smrg                                                      &panvk_physical_device_entrypoints,
2847ec681f3Smrg                                                      true);
2857ec681f3Smrg   vk_physical_device_dispatch_table_from_entrypoints(&dispatch_table,
2867ec681f3Smrg                                                      &wsi_physical_device_entrypoints,
2877ec681f3Smrg                                                      false);
2887ec681f3Smrg
2897ec681f3Smrg   result = vk_physical_device_init(&device->vk, &instance->vk,
2907ec681f3Smrg                                    &supported_extensions,
2917ec681f3Smrg                                    &dispatch_table);
2927ec681f3Smrg
2937ec681f3Smrg   if (result != VK_SUCCESS) {
2947ec681f3Smrg      vk_error(instance, result);
2957ec681f3Smrg      goto fail;
2967ec681f3Smrg   }
2977ec681f3Smrg
2987ec681f3Smrg   device->instance = instance;
2997ec681f3Smrg   assert(strlen(path) < ARRAY_SIZE(device->path));
3007ec681f3Smrg   strncpy(device->path, path, ARRAY_SIZE(device->path));
3017ec681f3Smrg
3027ec681f3Smrg   if (instance->vk.enabled_extensions.KHR_display) {
3037ec681f3Smrg      master_fd = open(drm_device->nodes[DRM_NODE_PRIMARY], O_RDWR | O_CLOEXEC);
3047ec681f3Smrg      if (master_fd >= 0) {
3057ec681f3Smrg         /* TODO: free master_fd is accel is not working? */
3067ec681f3Smrg      }
3077ec681f3Smrg   }
3087ec681f3Smrg
3097ec681f3Smrg   device->master_fd = master_fd;
3107ec681f3Smrg   if (instance->debug_flags & PANVK_DEBUG_TRACE)
3117ec681f3Smrg      device->pdev.debug |= PAN_DBG_TRACE;
3127ec681f3Smrg
3137ec681f3Smrg   device->pdev.debug |= PAN_DBG_NO_CACHE;
3147ec681f3Smrg   panfrost_open_device(NULL, fd, &device->pdev);
3157ec681f3Smrg   fd = -1;
3167ec681f3Smrg
3177ec681f3Smrg   if (device->pdev.quirks & MIDGARD_SFBD) {
3187ec681f3Smrg      result = vk_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER,
3197ec681f3Smrg                         "%s not supported",
3207ec681f3Smrg                         panfrost_model_name(device->pdev.gpu_id));
3217ec681f3Smrg      goto fail;
3227ec681f3Smrg   }
3237ec681f3Smrg
3247ec681f3Smrg   panvk_arch_dispatch(device->pdev.arch, meta_init, device);
3257ec681f3Smrg
3267ec681f3Smrg   memset(device->name, 0, sizeof(device->name));
3277ec681f3Smrg   sprintf(device->name, "%s", panfrost_model_name(device->pdev.gpu_id));
3287ec681f3Smrg
3297ec681f3Smrg   if (panvk_device_get_cache_uuid(device->pdev.gpu_id, device->cache_uuid)) {
3307ec681f3Smrg      result = vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
3317ec681f3Smrg                         "cannot generate UUID");
3327ec681f3Smrg      goto fail_close_device;
3337ec681f3Smrg   }
3347ec681f3Smrg
3357ec681f3Smrg   fprintf(stderr, "WARNING: panvk is not a conformant vulkan implementation, "
3367ec681f3Smrg                   "testing use only.\n");
3377ec681f3Smrg
3387ec681f3Smrg   panvk_get_driver_uuid(&device->device_uuid);
3397ec681f3Smrg   panvk_get_device_uuid(&device->device_uuid);
3407ec681f3Smrg
3417ec681f3Smrg   result = panvk_wsi_init(device);
3427ec681f3Smrg   if (result != VK_SUCCESS) {
3437ec681f3Smrg      vk_error(instance, result);
3447ec681f3Smrg      goto fail_close_device;
3457ec681f3Smrg   }
3467ec681f3Smrg
3477ec681f3Smrg   return VK_SUCCESS;
3487ec681f3Smrg
3497ec681f3Smrgfail_close_device:
3507ec681f3Smrg   panfrost_close_device(&device->pdev);
3517ec681f3Smrgfail:
3527ec681f3Smrg   if (fd != -1)
3537ec681f3Smrg      close(fd);
3547ec681f3Smrg   if (master_fd != -1)
3557ec681f3Smrg      close(master_fd);
3567ec681f3Smrg   return result;
3577ec681f3Smrg}
3587ec681f3Smrg
3597ec681f3Smrgstatic VkResult
3607ec681f3Smrgpanvk_enumerate_devices(struct panvk_instance *instance)
3617ec681f3Smrg{
3627ec681f3Smrg   /* TODO: Check for more devices ? */
3637ec681f3Smrg   drmDevicePtr devices[8];
3647ec681f3Smrg   VkResult result = VK_ERROR_INCOMPATIBLE_DRIVER;
3657ec681f3Smrg   int max_devices;
3667ec681f3Smrg
3677ec681f3Smrg   instance->physical_device_count = 0;
3687ec681f3Smrg
3697ec681f3Smrg   max_devices = drmGetDevices2(0, devices, ARRAY_SIZE(devices));
3707ec681f3Smrg
3717ec681f3Smrg   if (instance->debug_flags & PANVK_DEBUG_STARTUP)
3727ec681f3Smrg      panvk_logi("Found %d drm nodes", max_devices);
3737ec681f3Smrg
3747ec681f3Smrg   if (max_devices < 1)
3757ec681f3Smrg      return vk_error(instance, VK_ERROR_INCOMPATIBLE_DRIVER);
3767ec681f3Smrg
3777ec681f3Smrg   for (unsigned i = 0; i < (unsigned) max_devices; i++) {
3787ec681f3Smrg      if ((devices[i]->available_nodes & (1 << DRM_NODE_RENDER)) &&
3797ec681f3Smrg          devices[i]->bustype == DRM_BUS_PLATFORM) {
3807ec681f3Smrg
3817ec681f3Smrg         result = panvk_physical_device_init(instance->physical_devices +
3827ec681f3Smrg                                           instance->physical_device_count,
3837ec681f3Smrg                                           instance, devices[i]);
3847ec681f3Smrg         if (result == VK_SUCCESS)
3857ec681f3Smrg            ++instance->physical_device_count;
3867ec681f3Smrg         else if (result != VK_ERROR_INCOMPATIBLE_DRIVER)
3877ec681f3Smrg            break;
3887ec681f3Smrg      }
3897ec681f3Smrg   }
3907ec681f3Smrg   drmFreeDevices(devices, max_devices);
3917ec681f3Smrg
3927ec681f3Smrg   return result;
3937ec681f3Smrg}
3947ec681f3Smrg
3957ec681f3SmrgVkResult
3967ec681f3Smrgpanvk_EnumeratePhysicalDevices(VkInstance _instance,
3977ec681f3Smrg                               uint32_t *pPhysicalDeviceCount,
3987ec681f3Smrg                               VkPhysicalDevice *pPhysicalDevices)
3997ec681f3Smrg{
4007ec681f3Smrg   VK_FROM_HANDLE(panvk_instance, instance, _instance);
4017ec681f3Smrg   VK_OUTARRAY_MAKE(out, pPhysicalDevices, pPhysicalDeviceCount);
4027ec681f3Smrg
4037ec681f3Smrg   VkResult result;
4047ec681f3Smrg
4057ec681f3Smrg   if (instance->physical_device_count < 0) {
4067ec681f3Smrg      result = panvk_enumerate_devices(instance);
4077ec681f3Smrg      if (result != VK_SUCCESS && result != VK_ERROR_INCOMPATIBLE_DRIVER)
4087ec681f3Smrg         return result;
4097ec681f3Smrg   }
4107ec681f3Smrg
4117ec681f3Smrg   for (uint32_t i = 0; i < instance->physical_device_count; ++i) {
4127ec681f3Smrg      vk_outarray_append(&out, p)
4137ec681f3Smrg      {
4147ec681f3Smrg         *p = panvk_physical_device_to_handle(instance->physical_devices + i);
4157ec681f3Smrg      }
4167ec681f3Smrg   }
4177ec681f3Smrg
4187ec681f3Smrg   return vk_outarray_status(&out);
4197ec681f3Smrg}
4207ec681f3Smrg
4217ec681f3SmrgVkResult
4227ec681f3Smrgpanvk_EnumeratePhysicalDeviceGroups(VkInstance _instance,
4237ec681f3Smrg                                    uint32_t *pPhysicalDeviceGroupCount,
4247ec681f3Smrg                                    VkPhysicalDeviceGroupProperties *pPhysicalDeviceGroupProperties)
4257ec681f3Smrg{
4267ec681f3Smrg   VK_FROM_HANDLE(panvk_instance, instance, _instance);
4277ec681f3Smrg   VK_OUTARRAY_MAKE(out, pPhysicalDeviceGroupProperties,
4287ec681f3Smrg                    pPhysicalDeviceGroupCount);
4297ec681f3Smrg   VkResult result;
4307ec681f3Smrg
4317ec681f3Smrg   if (instance->physical_device_count < 0) {
4327ec681f3Smrg      result = panvk_enumerate_devices(instance);
4337ec681f3Smrg      if (result != VK_SUCCESS && result != VK_ERROR_INCOMPATIBLE_DRIVER)
4347ec681f3Smrg         return result;
4357ec681f3Smrg   }
4367ec681f3Smrg
4377ec681f3Smrg   for (uint32_t i = 0; i < instance->physical_device_count; ++i) {
4387ec681f3Smrg      vk_outarray_append(&out, p)
4397ec681f3Smrg      {
4407ec681f3Smrg         p->physicalDeviceCount = 1;
4417ec681f3Smrg         p->physicalDevices[0] =
4427ec681f3Smrg            panvk_physical_device_to_handle(instance->physical_devices + i);
4437ec681f3Smrg         p->subsetAllocation = false;
4447ec681f3Smrg      }
4457ec681f3Smrg   }
4467ec681f3Smrg
4477ec681f3Smrg   return VK_SUCCESS;
4487ec681f3Smrg}
4497ec681f3Smrg
4507ec681f3Smrgvoid
4517ec681f3Smrgpanvk_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,
4527ec681f3Smrg                                 VkPhysicalDeviceFeatures2 *pFeatures)
4537ec681f3Smrg{
4547ec681f3Smrg   vk_foreach_struct(ext, pFeatures->pNext)
4557ec681f3Smrg   {
4567ec681f3Smrg      switch (ext->sType) {
4577ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES: {
4587ec681f3Smrg         VkPhysicalDeviceVulkan11Features *features = (void *) ext;
4597ec681f3Smrg         features->storageBuffer16BitAccess            = false;
4607ec681f3Smrg         features->uniformAndStorageBuffer16BitAccess  = false;
4617ec681f3Smrg         features->storagePushConstant16               = false;
4627ec681f3Smrg         features->storageInputOutput16                = false;
4637ec681f3Smrg         features->multiview                           = false;
4647ec681f3Smrg         features->multiviewGeometryShader             = false;
4657ec681f3Smrg         features->multiviewTessellationShader         = false;
4667ec681f3Smrg         features->variablePointersStorageBuffer       = true;
4677ec681f3Smrg         features->variablePointers                    = true;
4687ec681f3Smrg         features->protectedMemory                     = false;
4697ec681f3Smrg         features->samplerYcbcrConversion              = false;
4707ec681f3Smrg         features->shaderDrawParameters                = false;
4717ec681f3Smrg         break;
4727ec681f3Smrg      }
4737ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES: {
4747ec681f3Smrg         VkPhysicalDeviceVulkan12Features *features = (void *) ext;
4757ec681f3Smrg         features->samplerMirrorClampToEdge            = false;
4767ec681f3Smrg         features->drawIndirectCount                   = false;
4777ec681f3Smrg         features->storageBuffer8BitAccess             = false;
4787ec681f3Smrg         features->uniformAndStorageBuffer8BitAccess   = false;
4797ec681f3Smrg         features->storagePushConstant8                = false;
4807ec681f3Smrg         features->shaderBufferInt64Atomics            = false;
4817ec681f3Smrg         features->shaderSharedInt64Atomics            = false;
4827ec681f3Smrg         features->shaderFloat16                       = false;
4837ec681f3Smrg         features->shaderInt8                          = false;
4847ec681f3Smrg
4857ec681f3Smrg         features->descriptorIndexing                                 = false;
4867ec681f3Smrg         features->shaderInputAttachmentArrayDynamicIndexing          = false;
4877ec681f3Smrg         features->shaderUniformTexelBufferArrayDynamicIndexing       = false;
4887ec681f3Smrg         features->shaderStorageTexelBufferArrayDynamicIndexing       = false;
4897ec681f3Smrg         features->shaderUniformBufferArrayNonUniformIndexing         = false;
4907ec681f3Smrg         features->shaderSampledImageArrayNonUniformIndexing          = false;
4917ec681f3Smrg         features->shaderStorageBufferArrayNonUniformIndexing         = false;
4927ec681f3Smrg         features->shaderStorageImageArrayNonUniformIndexing          = false;
4937ec681f3Smrg         features->shaderInputAttachmentArrayNonUniformIndexing       = false;
4947ec681f3Smrg         features->shaderUniformTexelBufferArrayNonUniformIndexing    = false;
4957ec681f3Smrg         features->shaderStorageTexelBufferArrayNonUniformIndexing    = false;
4967ec681f3Smrg         features->descriptorBindingUniformBufferUpdateAfterBind      = false;
4977ec681f3Smrg         features->descriptorBindingSampledImageUpdateAfterBind       = false;
4987ec681f3Smrg         features->descriptorBindingStorageImageUpdateAfterBind       = false;
4997ec681f3Smrg         features->descriptorBindingStorageBufferUpdateAfterBind      = false;
5007ec681f3Smrg         features->descriptorBindingUniformTexelBufferUpdateAfterBind = false;
5017ec681f3Smrg         features->descriptorBindingStorageTexelBufferUpdateAfterBind = false;
5027ec681f3Smrg         features->descriptorBindingUpdateUnusedWhilePending          = false;
5037ec681f3Smrg         features->descriptorBindingPartiallyBound                    = false;
5047ec681f3Smrg         features->descriptorBindingVariableDescriptorCount           = false;
5057ec681f3Smrg         features->runtimeDescriptorArray                             = false;
5067ec681f3Smrg
5077ec681f3Smrg         features->samplerFilterMinmax                 = false;
5087ec681f3Smrg         features->scalarBlockLayout                   = false;
5097ec681f3Smrg         features->imagelessFramebuffer                = false;
5107ec681f3Smrg         features->uniformBufferStandardLayout         = false;
5117ec681f3Smrg         features->shaderSubgroupExtendedTypes         = false;
5127ec681f3Smrg         features->separateDepthStencilLayouts         = false;
5137ec681f3Smrg         features->hostQueryReset                      = false;
5147ec681f3Smrg         features->timelineSemaphore                   = false;
5157ec681f3Smrg         features->bufferDeviceAddress                 = false;
5167ec681f3Smrg         features->bufferDeviceAddressCaptureReplay    = false;
5177ec681f3Smrg         features->bufferDeviceAddressMultiDevice      = false;
5187ec681f3Smrg         features->vulkanMemoryModel                   = false;
5197ec681f3Smrg         features->vulkanMemoryModelDeviceScope        = false;
5207ec681f3Smrg         features->vulkanMemoryModelAvailabilityVisibilityChains = false;
5217ec681f3Smrg         features->shaderOutputViewportIndex           = false;
5227ec681f3Smrg         features->shaderOutputLayer                   = false;
5237ec681f3Smrg         features->subgroupBroadcastDynamicId          = false;
5247ec681f3Smrg         break;
5257ec681f3Smrg      }
5267ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES: {
5277ec681f3Smrg         VkPhysicalDeviceVariablePointersFeatures *features = (void *) ext;
5287ec681f3Smrg         features->variablePointersStorageBuffer = true;
5297ec681f3Smrg         features->variablePointers = true;
5307ec681f3Smrg         break;
5317ec681f3Smrg      }
5327ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES: {
5337ec681f3Smrg         VkPhysicalDeviceMultiviewFeatures *features =
5347ec681f3Smrg            (VkPhysicalDeviceMultiviewFeatures *) ext;
5357ec681f3Smrg         features->multiview = false;
5367ec681f3Smrg         features->multiviewGeometryShader = false;
5377ec681f3Smrg         features->multiviewTessellationShader = false;
5387ec681f3Smrg         break;
5397ec681f3Smrg      }
5407ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES: {
5417ec681f3Smrg         VkPhysicalDeviceShaderDrawParametersFeatures *features =
5427ec681f3Smrg            (VkPhysicalDeviceShaderDrawParametersFeatures *) ext;
5437ec681f3Smrg         features->shaderDrawParameters = false;
5447ec681f3Smrg         break;
5457ec681f3Smrg      }
5467ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES: {
5477ec681f3Smrg         VkPhysicalDeviceProtectedMemoryFeatures *features =
5487ec681f3Smrg            (VkPhysicalDeviceProtectedMemoryFeatures *) ext;
5497ec681f3Smrg         features->protectedMemory = false;
5507ec681f3Smrg         break;
5517ec681f3Smrg      }
5527ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES: {
5537ec681f3Smrg         VkPhysicalDevice16BitStorageFeatures *features =
5547ec681f3Smrg            (VkPhysicalDevice16BitStorageFeatures *) ext;
5557ec681f3Smrg         features->storageBuffer16BitAccess = false;
5567ec681f3Smrg         features->uniformAndStorageBuffer16BitAccess = false;
5577ec681f3Smrg         features->storagePushConstant16 = false;
5587ec681f3Smrg         features->storageInputOutput16 = false;
5597ec681f3Smrg         break;
5607ec681f3Smrg      }
5617ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES: {
5627ec681f3Smrg         VkPhysicalDeviceSamplerYcbcrConversionFeatures *features =
5637ec681f3Smrg            (VkPhysicalDeviceSamplerYcbcrConversionFeatures *) ext;
5647ec681f3Smrg         features->samplerYcbcrConversion = false;
5657ec681f3Smrg         break;
5667ec681f3Smrg      }
5677ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT: {
5687ec681f3Smrg         VkPhysicalDeviceDescriptorIndexingFeaturesEXT *features =
5697ec681f3Smrg            (VkPhysicalDeviceDescriptorIndexingFeaturesEXT *) ext;
5707ec681f3Smrg         features->shaderInputAttachmentArrayDynamicIndexing = false;
5717ec681f3Smrg         features->shaderUniformTexelBufferArrayDynamicIndexing = false;
5727ec681f3Smrg         features->shaderStorageTexelBufferArrayDynamicIndexing = false;
5737ec681f3Smrg         features->shaderUniformBufferArrayNonUniformIndexing = false;
5747ec681f3Smrg         features->shaderSampledImageArrayNonUniformIndexing = false;
5757ec681f3Smrg         features->shaderStorageBufferArrayNonUniformIndexing = false;
5767ec681f3Smrg         features->shaderStorageImageArrayNonUniformIndexing = false;
5777ec681f3Smrg         features->shaderInputAttachmentArrayNonUniformIndexing = false;
5787ec681f3Smrg         features->shaderUniformTexelBufferArrayNonUniformIndexing = false;
5797ec681f3Smrg         features->shaderStorageTexelBufferArrayNonUniformIndexing = false;
5807ec681f3Smrg         features->descriptorBindingUniformBufferUpdateAfterBind = false;
5817ec681f3Smrg         features->descriptorBindingSampledImageUpdateAfterBind = false;
5827ec681f3Smrg         features->descriptorBindingStorageImageUpdateAfterBind = false;
5837ec681f3Smrg         features->descriptorBindingStorageBufferUpdateAfterBind = false;
5847ec681f3Smrg         features->descriptorBindingUniformTexelBufferUpdateAfterBind = false;
5857ec681f3Smrg         features->descriptorBindingStorageTexelBufferUpdateAfterBind = false;
5867ec681f3Smrg         features->descriptorBindingUpdateUnusedWhilePending = false;
5877ec681f3Smrg         features->descriptorBindingPartiallyBound = false;
5887ec681f3Smrg         features->descriptorBindingVariableDescriptorCount = false;
5897ec681f3Smrg         features->runtimeDescriptorArray = false;
5907ec681f3Smrg         break;
5917ec681f3Smrg      }
5927ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT: {
5937ec681f3Smrg         VkPhysicalDeviceConditionalRenderingFeaturesEXT *features =
5947ec681f3Smrg            (VkPhysicalDeviceConditionalRenderingFeaturesEXT *) ext;
5957ec681f3Smrg         features->conditionalRendering = false;
5967ec681f3Smrg         features->inheritedConditionalRendering = false;
5977ec681f3Smrg         break;
5987ec681f3Smrg      }
5997ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT: {
6007ec681f3Smrg         VkPhysicalDeviceTransformFeedbackFeaturesEXT *features =
6017ec681f3Smrg            (VkPhysicalDeviceTransformFeedbackFeaturesEXT *) ext;
6027ec681f3Smrg         features->transformFeedback = false;
6037ec681f3Smrg         features->geometryStreams = false;
6047ec681f3Smrg         break;
6057ec681f3Smrg      }
6067ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT: {
6077ec681f3Smrg         VkPhysicalDeviceIndexTypeUint8FeaturesEXT *features =
6087ec681f3Smrg            (VkPhysicalDeviceIndexTypeUint8FeaturesEXT *)ext;
6097ec681f3Smrg         features->indexTypeUint8 = true;
6107ec681f3Smrg         break;
6117ec681f3Smrg      }
6127ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: {
6137ec681f3Smrg         VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *features =
6147ec681f3Smrg            (VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *)ext;
6157ec681f3Smrg         features->vertexAttributeInstanceRateDivisor = true;
6167ec681f3Smrg         features->vertexAttributeInstanceRateZeroDivisor = true;
6177ec681f3Smrg         break;
6187ec681f3Smrg      }
6197ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT: {
6207ec681f3Smrg         VkPhysicalDevicePrivateDataFeaturesEXT *features =
6217ec681f3Smrg            (VkPhysicalDevicePrivateDataFeaturesEXT *)ext;
6227ec681f3Smrg         features->privateData = true;
6237ec681f3Smrg         break;
6247ec681f3Smrg      }
6257ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT: {
6267ec681f3Smrg         VkPhysicalDeviceDepthClipEnableFeaturesEXT *features =
6277ec681f3Smrg            (VkPhysicalDeviceDepthClipEnableFeaturesEXT *)ext;
6287ec681f3Smrg         features->depthClipEnable = true;
6297ec681f3Smrg         break;
6307ec681f3Smrg      }
6317ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT: {
6327ec681f3Smrg         VkPhysicalDevice4444FormatsFeaturesEXT *features = (void *)ext;
6337ec681f3Smrg         features->formatA4R4G4B4 = true;
6347ec681f3Smrg         features->formatA4B4G4R4 = true;
6357ec681f3Smrg         break;
6367ec681f3Smrg      }
6377ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT: {
6387ec681f3Smrg         VkPhysicalDeviceCustomBorderColorFeaturesEXT *features = (void *) ext;
6397ec681f3Smrg         features->customBorderColors = true;
6407ec681f3Smrg         features->customBorderColorWithoutFormat = true;
6417ec681f3Smrg         break;
6427ec681f3Smrg      }
6437ec681f3Smrg      default:
6447ec681f3Smrg         break;
6457ec681f3Smrg      }
6467ec681f3Smrg   }
6477ec681f3Smrg
6487ec681f3Smrg   pFeatures->features = (VkPhysicalDeviceFeatures) {
6497ec681f3Smrg      .fullDrawIndexUint32 = true,
6507ec681f3Smrg      .independentBlend = true,
6517ec681f3Smrg      .wideLines = true,
6527ec681f3Smrg      .largePoints = true,
6537ec681f3Smrg      .textureCompressionETC2 = true,
6547ec681f3Smrg      .textureCompressionASTC_LDR = true,
6557ec681f3Smrg      .shaderUniformBufferArrayDynamicIndexing = true,
6567ec681f3Smrg      .shaderSampledImageArrayDynamicIndexing = true,
6577ec681f3Smrg      .shaderStorageBufferArrayDynamicIndexing = true,
6587ec681f3Smrg      .shaderStorageImageArrayDynamicIndexing = true,
6597ec681f3Smrg   };
6607ec681f3Smrg}
6617ec681f3Smrg
6627ec681f3Smrgvoid
6637ec681f3Smrgpanvk_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
6647ec681f3Smrg                                   VkPhysicalDeviceProperties2 *pProperties)
6657ec681f3Smrg{
6667ec681f3Smrg   VK_FROM_HANDLE(panvk_physical_device, pdevice, physicalDevice);
6677ec681f3Smrg
6687ec681f3Smrg   vk_foreach_struct(ext, pProperties->pNext)
6697ec681f3Smrg   {
6707ec681f3Smrg      switch (ext->sType) {
6717ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: {
6727ec681f3Smrg         VkPhysicalDevicePushDescriptorPropertiesKHR *properties = (VkPhysicalDevicePushDescriptorPropertiesKHR *)ext;
6737ec681f3Smrg         properties->maxPushDescriptors = MAX_PUSH_DESCRIPTORS;
6747ec681f3Smrg         break;
6757ec681f3Smrg      }
6767ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES: {
6777ec681f3Smrg         VkPhysicalDeviceIDProperties *properties = (VkPhysicalDeviceIDProperties *)ext;
6787ec681f3Smrg         memcpy(properties->driverUUID, pdevice->driver_uuid, VK_UUID_SIZE);
6797ec681f3Smrg         memcpy(properties->deviceUUID, pdevice->device_uuid, VK_UUID_SIZE);
6807ec681f3Smrg         properties->deviceLUIDValid = false;
6817ec681f3Smrg         break;
6827ec681f3Smrg      }
6837ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES: {
6847ec681f3Smrg         VkPhysicalDeviceMultiviewProperties *properties = (VkPhysicalDeviceMultiviewProperties *)ext;
6857ec681f3Smrg         properties->maxMultiviewViewCount = 0;
6867ec681f3Smrg         properties->maxMultiviewInstanceIndex = 0;
6877ec681f3Smrg         break;
6887ec681f3Smrg      }
6897ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES: {
6907ec681f3Smrg         VkPhysicalDevicePointClippingProperties *properties = (VkPhysicalDevicePointClippingProperties *)ext;
6917ec681f3Smrg         properties->pointClippingBehavior =
6927ec681f3Smrg            VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES;
6937ec681f3Smrg         break;
6947ec681f3Smrg      }
6957ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES: {
6967ec681f3Smrg         VkPhysicalDeviceMaintenance3Properties *properties = (VkPhysicalDeviceMaintenance3Properties *)ext;
6977ec681f3Smrg         /* Make sure everything is addressable by a signed 32-bit int, and
6987ec681f3Smrg          * our largest descriptors are 96 bytes. */
6997ec681f3Smrg         properties->maxPerSetDescriptors = (1ull << 31) / 96;
7007ec681f3Smrg         /* Our buffer size fields allow only this much */
7017ec681f3Smrg         properties->maxMemoryAllocationSize = 0xFFFFFFFFull;
7027ec681f3Smrg         break;
7037ec681f3Smrg      }
7047ec681f3Smrg      default:
7057ec681f3Smrg         break;
7067ec681f3Smrg      }
7077ec681f3Smrg   }
7087ec681f3Smrg
7097ec681f3Smrg   VkSampleCountFlags sample_counts =
7107ec681f3Smrg      VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT;
7117ec681f3Smrg
7127ec681f3Smrg   /* make sure that the entire descriptor set is addressable with a signed
7137ec681f3Smrg    * 32-bit int. So the sum of all limits scaled by descriptor size has to
7147ec681f3Smrg    * be at most 2 GiB. the combined image & samples object count as one of
7157ec681f3Smrg    * both. This limit is for the pipeline layout, not for the set layout, but
7167ec681f3Smrg    * there is no set limit, so we just set a pipeline limit. I don't think
7177ec681f3Smrg    * any app is going to hit this soon. */
7187ec681f3Smrg   size_t max_descriptor_set_size =
7197ec681f3Smrg      ((1ull << 31) - 16 * MAX_DYNAMIC_BUFFERS) /
7207ec681f3Smrg      (32 /* uniform buffer, 32 due to potential space wasted on alignment */ +
7217ec681f3Smrg       32 /* storage buffer, 32 due to potential space wasted on alignment */ +
7227ec681f3Smrg       32 /* sampler, largest when combined with image */ +
7237ec681f3Smrg       64 /* sampled image */ + 64 /* storage image */);
7247ec681f3Smrg
7257ec681f3Smrg   VkPhysicalDeviceLimits limits = {
7267ec681f3Smrg      .maxImageDimension1D = (1 << 14),
7277ec681f3Smrg      .maxImageDimension2D = (1 << 14),
7287ec681f3Smrg      .maxImageDimension3D = (1 << 11),
7297ec681f3Smrg      .maxImageDimensionCube = (1 << 14),
7307ec681f3Smrg      .maxImageArrayLayers = (1 << 11),
7317ec681f3Smrg      .maxTexelBufferElements = 128 * 1024 * 1024,
7327ec681f3Smrg      .maxUniformBufferRange = UINT32_MAX,
7337ec681f3Smrg      .maxStorageBufferRange = UINT32_MAX,
7347ec681f3Smrg      .maxPushConstantsSize = MAX_PUSH_CONSTANTS_SIZE,
7357ec681f3Smrg      .maxMemoryAllocationCount = UINT32_MAX,
7367ec681f3Smrg      .maxSamplerAllocationCount = 64 * 1024,
7377ec681f3Smrg      .bufferImageGranularity = 64,          /* A cache line */
7387ec681f3Smrg      .sparseAddressSpaceSize = 0xffffffffu, /* buffer max size */
7397ec681f3Smrg      .maxBoundDescriptorSets = MAX_SETS,
7407ec681f3Smrg      .maxPerStageDescriptorSamplers = max_descriptor_set_size,
7417ec681f3Smrg      .maxPerStageDescriptorUniformBuffers = max_descriptor_set_size,
7427ec681f3Smrg      .maxPerStageDescriptorStorageBuffers = max_descriptor_set_size,
7437ec681f3Smrg      .maxPerStageDescriptorSampledImages = max_descriptor_set_size,
7447ec681f3Smrg      .maxPerStageDescriptorStorageImages = max_descriptor_set_size,
7457ec681f3Smrg      .maxPerStageDescriptorInputAttachments = max_descriptor_set_size,
7467ec681f3Smrg      .maxPerStageResources = max_descriptor_set_size,
7477ec681f3Smrg      .maxDescriptorSetSamplers = max_descriptor_set_size,
7487ec681f3Smrg      .maxDescriptorSetUniformBuffers = max_descriptor_set_size,
7497ec681f3Smrg      .maxDescriptorSetUniformBuffersDynamic = MAX_DYNAMIC_UNIFORM_BUFFERS,
7507ec681f3Smrg      .maxDescriptorSetStorageBuffers = max_descriptor_set_size,
7517ec681f3Smrg      .maxDescriptorSetStorageBuffersDynamic = MAX_DYNAMIC_STORAGE_BUFFERS,
7527ec681f3Smrg      .maxDescriptorSetSampledImages = max_descriptor_set_size,
7537ec681f3Smrg      .maxDescriptorSetStorageImages = max_descriptor_set_size,
7547ec681f3Smrg      .maxDescriptorSetInputAttachments = max_descriptor_set_size,
7557ec681f3Smrg      .maxVertexInputAttributes = 32,
7567ec681f3Smrg      .maxVertexInputBindings = 32,
7577ec681f3Smrg      .maxVertexInputAttributeOffset = 2047,
7587ec681f3Smrg      .maxVertexInputBindingStride = 2048,
7597ec681f3Smrg      .maxVertexOutputComponents = 128,
7607ec681f3Smrg      .maxTessellationGenerationLevel = 64,
7617ec681f3Smrg      .maxTessellationPatchSize = 32,
7627ec681f3Smrg      .maxTessellationControlPerVertexInputComponents = 128,
7637ec681f3Smrg      .maxTessellationControlPerVertexOutputComponents = 128,
7647ec681f3Smrg      .maxTessellationControlPerPatchOutputComponents = 120,
7657ec681f3Smrg      .maxTessellationControlTotalOutputComponents = 4096,
7667ec681f3Smrg      .maxTessellationEvaluationInputComponents = 128,
7677ec681f3Smrg      .maxTessellationEvaluationOutputComponents = 128,
7687ec681f3Smrg      .maxGeometryShaderInvocations = 127,
7697ec681f3Smrg      .maxGeometryInputComponents = 64,
7707ec681f3Smrg      .maxGeometryOutputComponents = 128,
7717ec681f3Smrg      .maxGeometryOutputVertices = 256,
7727ec681f3Smrg      .maxGeometryTotalOutputComponents = 1024,
7737ec681f3Smrg      .maxFragmentInputComponents = 128,
7747ec681f3Smrg      .maxFragmentOutputAttachments = 8,
7757ec681f3Smrg      .maxFragmentDualSrcAttachments = 1,
7767ec681f3Smrg      .maxFragmentCombinedOutputResources = 8,
7777ec681f3Smrg      .maxComputeSharedMemorySize = 32768,
7787ec681f3Smrg      .maxComputeWorkGroupCount = { 65535, 65535, 65535 },
7797ec681f3Smrg      .maxComputeWorkGroupInvocations = 2048,
7807ec681f3Smrg      .maxComputeWorkGroupSize = { 2048, 2048, 2048 },
7817ec681f3Smrg      .subPixelPrecisionBits = 4 /* FIXME */,
7827ec681f3Smrg      .subTexelPrecisionBits = 4 /* FIXME */,
7837ec681f3Smrg      .mipmapPrecisionBits = 4 /* FIXME */,
7847ec681f3Smrg      .maxDrawIndexedIndexValue = UINT32_MAX,
7857ec681f3Smrg      .maxDrawIndirectCount = UINT32_MAX,
7867ec681f3Smrg      .maxSamplerLodBias = 16,
7877ec681f3Smrg      .maxSamplerAnisotropy = 16,
7887ec681f3Smrg      .maxViewports = MAX_VIEWPORTS,
7897ec681f3Smrg      .maxViewportDimensions = { (1 << 14), (1 << 14) },
7907ec681f3Smrg      .viewportBoundsRange = { INT16_MIN, INT16_MAX },
7917ec681f3Smrg      .viewportSubPixelBits = 8,
7927ec681f3Smrg      .minMemoryMapAlignment = 4096, /* A page */
7937ec681f3Smrg      .minTexelBufferOffsetAlignment = 1,
7947ec681f3Smrg      .minUniformBufferOffsetAlignment = 4,
7957ec681f3Smrg      .minStorageBufferOffsetAlignment = 4,
7967ec681f3Smrg      .minTexelOffset = -32,
7977ec681f3Smrg      .maxTexelOffset = 31,
7987ec681f3Smrg      .minTexelGatherOffset = -32,
7997ec681f3Smrg      .maxTexelGatherOffset = 31,
8007ec681f3Smrg      .minInterpolationOffset = -2,
8017ec681f3Smrg      .maxInterpolationOffset = 2,
8027ec681f3Smrg      .subPixelInterpolationOffsetBits = 8,
8037ec681f3Smrg      .maxFramebufferWidth = (1 << 14),
8047ec681f3Smrg      .maxFramebufferHeight = (1 << 14),
8057ec681f3Smrg      .maxFramebufferLayers = (1 << 10),
8067ec681f3Smrg      .framebufferColorSampleCounts = sample_counts,
8077ec681f3Smrg      .framebufferDepthSampleCounts = sample_counts,
8087ec681f3Smrg      .framebufferStencilSampleCounts = sample_counts,
8097ec681f3Smrg      .framebufferNoAttachmentsSampleCounts = sample_counts,
8107ec681f3Smrg      .maxColorAttachments = MAX_RTS,
8117ec681f3Smrg      .sampledImageColorSampleCounts = sample_counts,
8127ec681f3Smrg      .sampledImageIntegerSampleCounts = VK_SAMPLE_COUNT_1_BIT,
8137ec681f3Smrg      .sampledImageDepthSampleCounts = sample_counts,
8147ec681f3Smrg      .sampledImageStencilSampleCounts = sample_counts,
8157ec681f3Smrg      .storageImageSampleCounts = VK_SAMPLE_COUNT_1_BIT,
8167ec681f3Smrg      .maxSampleMaskWords = 1,
8177ec681f3Smrg      .timestampComputeAndGraphics = true,
8187ec681f3Smrg      .timestampPeriod = 1,
8197ec681f3Smrg      .maxClipDistances = 8,
8207ec681f3Smrg      .maxCullDistances = 8,
8217ec681f3Smrg      .maxCombinedClipAndCullDistances = 8,
8227ec681f3Smrg      .discreteQueuePriorities = 1,
8237ec681f3Smrg      .pointSizeRange = { 0.125, 255.875 },
8247ec681f3Smrg      .lineWidthRange = { 0.0, 7.9921875 },
8257ec681f3Smrg      .pointSizeGranularity = (1.0 / 8.0),
8267ec681f3Smrg      .lineWidthGranularity = (1.0 / 128.0),
8277ec681f3Smrg      .strictLines = false, /* FINISHME */
8287ec681f3Smrg      .standardSampleLocations = true,
8297ec681f3Smrg      .optimalBufferCopyOffsetAlignment = 128,
8307ec681f3Smrg      .optimalBufferCopyRowPitchAlignment = 128,
8317ec681f3Smrg      .nonCoherentAtomSize = 64,
8327ec681f3Smrg   };
8337ec681f3Smrg
8347ec681f3Smrg   pProperties->properties = (VkPhysicalDeviceProperties) {
8357ec681f3Smrg      .apiVersion = PANVK_API_VERSION,
8367ec681f3Smrg      .driverVersion = vk_get_driver_version(),
8377ec681f3Smrg      .vendorID = 0, /* TODO */
8387ec681f3Smrg      .deviceID = 0,
8397ec681f3Smrg      .deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
8407ec681f3Smrg      .limits = limits,
8417ec681f3Smrg      .sparseProperties = { 0 },
8427ec681f3Smrg   };
8437ec681f3Smrg
8447ec681f3Smrg   strcpy(pProperties->properties.deviceName, pdevice->name);
8457ec681f3Smrg   memcpy(pProperties->properties.pipelineCacheUUID, pdevice->cache_uuid, VK_UUID_SIZE);
8467ec681f3Smrg}
8477ec681f3Smrg
8487ec681f3Smrgstatic const VkQueueFamilyProperties panvk_queue_family_properties = {
8497ec681f3Smrg   .queueFlags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT,
8507ec681f3Smrg   .queueCount = 1,
8517ec681f3Smrg   .timestampValidBits = 64,
8527ec681f3Smrg   .minImageTransferGranularity = { 1, 1, 1 },
8537ec681f3Smrg};
8547ec681f3Smrg
8557ec681f3Smrgvoid
8567ec681f3Smrgpanvk_GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,
8577ec681f3Smrg                                             uint32_t *pQueueFamilyPropertyCount,
8587ec681f3Smrg                                             VkQueueFamilyProperties *pQueueFamilyProperties)
8597ec681f3Smrg{
8607ec681f3Smrg   VK_OUTARRAY_MAKE(out, pQueueFamilyProperties, pQueueFamilyPropertyCount);
8617ec681f3Smrg
8627ec681f3Smrg   vk_outarray_append(&out, p) { *p = panvk_queue_family_properties; }
8637ec681f3Smrg}
8647ec681f3Smrg
8657ec681f3Smrgvoid
8667ec681f3Smrgpanvk_GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice,
8677ec681f3Smrg                                              uint32_t *pQueueFamilyPropertyCount,
8687ec681f3Smrg                                              VkQueueFamilyProperties2 *pQueueFamilyProperties)
8697ec681f3Smrg{
8707ec681f3Smrg   VK_OUTARRAY_MAKE(out, pQueueFamilyProperties, pQueueFamilyPropertyCount);
8717ec681f3Smrg
8727ec681f3Smrg   vk_outarray_append(&out, p)
8737ec681f3Smrg   {
8747ec681f3Smrg      p->queueFamilyProperties = panvk_queue_family_properties;
8757ec681f3Smrg   }
8767ec681f3Smrg}
8777ec681f3Smrg
8787ec681f3Smrgstatic uint64_t
8797ec681f3Smrgpanvk_get_system_heap_size()
8807ec681f3Smrg{
8817ec681f3Smrg   struct sysinfo info;
8827ec681f3Smrg   sysinfo(&info);
8837ec681f3Smrg
8847ec681f3Smrg   uint64_t total_ram = (uint64_t)info.totalram * info.mem_unit;
8857ec681f3Smrg
8867ec681f3Smrg   /* We don't want to burn too much ram with the GPU.  If the user has 4GiB
8877ec681f3Smrg    * or less, we use at most half.  If they have more than 4GiB, we use 3/4.
8887ec681f3Smrg    */
8897ec681f3Smrg   uint64_t available_ram;
8907ec681f3Smrg   if (total_ram <= 4ull * 1024 * 1024 * 1024)
8917ec681f3Smrg      available_ram = total_ram / 2;
8927ec681f3Smrg   else
8937ec681f3Smrg      available_ram = total_ram * 3 / 4;
8947ec681f3Smrg
8957ec681f3Smrg   return available_ram;
8967ec681f3Smrg}
8977ec681f3Smrg
8987ec681f3Smrgvoid
8997ec681f3Smrgpanvk_GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice,
9007ec681f3Smrg                                         VkPhysicalDeviceMemoryProperties2 *pMemoryProperties)
9017ec681f3Smrg{
9027ec681f3Smrg   pMemoryProperties->memoryProperties = (VkPhysicalDeviceMemoryProperties) {
9037ec681f3Smrg      .memoryHeapCount = 1,
9047ec681f3Smrg      .memoryHeaps[0].size = panvk_get_system_heap_size(),
9057ec681f3Smrg      .memoryHeaps[0].flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
9067ec681f3Smrg      .memoryTypeCount = 1,
9077ec681f3Smrg      .memoryTypes[0].propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
9087ec681f3Smrg                                      VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
9097ec681f3Smrg                                      VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
9107ec681f3Smrg      .memoryTypes[0].heapIndex = 0,
9117ec681f3Smrg   };
9127ec681f3Smrg}
9137ec681f3Smrg
9147ec681f3Smrgstatic VkResult
9157ec681f3Smrgpanvk_queue_init(struct panvk_device *device,
9167ec681f3Smrg                 struct panvk_queue *queue,
9177ec681f3Smrg                 int idx,
9187ec681f3Smrg                 const VkDeviceQueueCreateInfo *create_info)
9197ec681f3Smrg{
9207ec681f3Smrg   const struct panfrost_device *pdev = &device->physical_device->pdev;
9217ec681f3Smrg
9227ec681f3Smrg   VkResult result = vk_queue_init(&queue->vk, &device->vk, create_info, idx);
9237ec681f3Smrg   if (result != VK_SUCCESS)
9247ec681f3Smrg      return result;
9257ec681f3Smrg   queue->device = device;
9267ec681f3Smrg
9277ec681f3Smrg   struct drm_syncobj_create create = {
9287ec681f3Smrg      .flags = DRM_SYNCOBJ_CREATE_SIGNALED,
9297ec681f3Smrg   };
9307ec681f3Smrg
9317ec681f3Smrg   int ret = drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_CREATE, &create);
9327ec681f3Smrg   if (ret) {
9337ec681f3Smrg      vk_queue_finish(&queue->vk);
9347ec681f3Smrg      return VK_ERROR_OUT_OF_HOST_MEMORY;
9357ec681f3Smrg   }
9367ec681f3Smrg
9377ec681f3Smrg   queue->sync = create.handle;
9387ec681f3Smrg   return VK_SUCCESS;
9397ec681f3Smrg}
9407ec681f3Smrg
9417ec681f3Smrgstatic void
9427ec681f3Smrgpanvk_queue_finish(struct panvk_queue *queue)
9437ec681f3Smrg{
9447ec681f3Smrg   vk_queue_finish(&queue->vk);
9457ec681f3Smrg}
9467ec681f3Smrg
9477ec681f3SmrgVkResult
9487ec681f3Smrgpanvk_CreateDevice(VkPhysicalDevice physicalDevice,
9497ec681f3Smrg                   const VkDeviceCreateInfo *pCreateInfo,
9507ec681f3Smrg                   const VkAllocationCallbacks *pAllocator,
9517ec681f3Smrg                   VkDevice *pDevice)
9527ec681f3Smrg{
9537ec681f3Smrg   VK_FROM_HANDLE(panvk_physical_device, physical_device, physicalDevice);
9547ec681f3Smrg   VkResult result;
9557ec681f3Smrg   struct panvk_device *device;
9567ec681f3Smrg
9577ec681f3Smrg   device = vk_zalloc2(&physical_device->instance->vk.alloc, pAllocator,
9587ec681f3Smrg                       sizeof(*device), 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
9597ec681f3Smrg   if (!device)
9607ec681f3Smrg      return vk_error(physical_device, VK_ERROR_OUT_OF_HOST_MEMORY);
9617ec681f3Smrg
9627ec681f3Smrg   const struct vk_device_entrypoint_table *dev_entrypoints;
9637ec681f3Smrg   struct vk_device_dispatch_table dispatch_table;
9647ec681f3Smrg
9657ec681f3Smrg   switch (physical_device->pdev.arch) {
9667ec681f3Smrg   case 5:
9677ec681f3Smrg      dev_entrypoints = &panvk_v5_device_entrypoints;
9687ec681f3Smrg      break;
9697ec681f3Smrg   case 6:
9707ec681f3Smrg      dev_entrypoints = &panvk_v6_device_entrypoints;
9717ec681f3Smrg      break;
9727ec681f3Smrg   case 7:
9737ec681f3Smrg      dev_entrypoints = &panvk_v7_device_entrypoints;
9747ec681f3Smrg      break;
9757ec681f3Smrg   default:
9767ec681f3Smrg      unreachable("Unsupported architecture");
9777ec681f3Smrg   }
9787ec681f3Smrg
9797ec681f3Smrg   vk_device_dispatch_table_from_entrypoints(&dispatch_table,
9807ec681f3Smrg                                             dev_entrypoints,
9817ec681f3Smrg                                             true);
9827ec681f3Smrg   vk_device_dispatch_table_from_entrypoints(&dispatch_table,
9837ec681f3Smrg                                             &panvk_device_entrypoints,
9847ec681f3Smrg                                             false);
9857ec681f3Smrg   vk_device_dispatch_table_from_entrypoints(&dispatch_table,
9867ec681f3Smrg                                             &wsi_device_entrypoints,
9877ec681f3Smrg                                             false);
9887ec681f3Smrg   result = vk_device_init(&device->vk, &physical_device->vk, &dispatch_table,
9897ec681f3Smrg                           pCreateInfo, pAllocator);
9907ec681f3Smrg   if (result != VK_SUCCESS) {
9917ec681f3Smrg      vk_free(&device->vk.alloc, device);
9927ec681f3Smrg      return result;
9937ec681f3Smrg   }
9947ec681f3Smrg
9957ec681f3Smrg   device->instance = physical_device->instance;
9967ec681f3Smrg   device->physical_device = physical_device;
9977ec681f3Smrg
9987ec681f3Smrg   for (unsigned i = 0; i < pCreateInfo->queueCreateInfoCount; i++) {
9997ec681f3Smrg      const VkDeviceQueueCreateInfo *queue_create =
10007ec681f3Smrg         &pCreateInfo->pQueueCreateInfos[i];
10017ec681f3Smrg      uint32_t qfi = queue_create->queueFamilyIndex;
10027ec681f3Smrg      device->queues[qfi] =
10037ec681f3Smrg         vk_alloc(&device->vk.alloc,
10047ec681f3Smrg                  queue_create->queueCount * sizeof(struct panvk_queue),
10057ec681f3Smrg                  8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
10067ec681f3Smrg      if (!device->queues[qfi]) {
10077ec681f3Smrg         result = VK_ERROR_OUT_OF_HOST_MEMORY;
10087ec681f3Smrg         goto fail;
10097ec681f3Smrg      }
10107ec681f3Smrg
10117ec681f3Smrg      memset(device->queues[qfi], 0,
10127ec681f3Smrg             queue_create->queueCount * sizeof(struct panvk_queue));
10137ec681f3Smrg
10147ec681f3Smrg      device->queue_count[qfi] = queue_create->queueCount;
10157ec681f3Smrg
10167ec681f3Smrg      for (unsigned q = 0; q < queue_create->queueCount; q++) {
10177ec681f3Smrg         result = panvk_queue_init(device, &device->queues[qfi][q], q,
10187ec681f3Smrg                                   queue_create);
10197ec681f3Smrg         if (result != VK_SUCCESS)
10207ec681f3Smrg            goto fail;
10217ec681f3Smrg      }
10227ec681f3Smrg   }
10237ec681f3Smrg
10247ec681f3Smrg   *pDevice = panvk_device_to_handle(device);
10257ec681f3Smrg   return VK_SUCCESS;
10267ec681f3Smrg
10277ec681f3Smrgfail:
10287ec681f3Smrg   for (unsigned i = 0; i < PANVK_MAX_QUEUE_FAMILIES; i++) {
10297ec681f3Smrg      for (unsigned q = 0; q < device->queue_count[i]; q++)
10307ec681f3Smrg         panvk_queue_finish(&device->queues[i][q]);
10317ec681f3Smrg      if (device->queue_count[i])
10327ec681f3Smrg         vk_object_free(&device->vk, NULL, device->queues[i]);
10337ec681f3Smrg   }
10347ec681f3Smrg
10357ec681f3Smrg   vk_free(&device->vk.alloc, device);
10367ec681f3Smrg   return result;
10377ec681f3Smrg}
10387ec681f3Smrg
10397ec681f3Smrgvoid
10407ec681f3Smrgpanvk_DestroyDevice(VkDevice _device, const VkAllocationCallbacks *pAllocator)
10417ec681f3Smrg{
10427ec681f3Smrg   VK_FROM_HANDLE(panvk_device, device, _device);
10437ec681f3Smrg
10447ec681f3Smrg   if (!device)
10457ec681f3Smrg      return;
10467ec681f3Smrg
10477ec681f3Smrg   for (unsigned i = 0; i < PANVK_MAX_QUEUE_FAMILIES; i++) {
10487ec681f3Smrg      for (unsigned q = 0; q < device->queue_count[i]; q++)
10497ec681f3Smrg         panvk_queue_finish(&device->queues[i][q]);
10507ec681f3Smrg      if (device->queue_count[i])
10517ec681f3Smrg         vk_object_free(&device->vk, NULL, device->queues[i]);
10527ec681f3Smrg   }
10537ec681f3Smrg
10547ec681f3Smrg   vk_free(&device->vk.alloc, device);
10557ec681f3Smrg}
10567ec681f3Smrg
10577ec681f3SmrgVkResult
10587ec681f3Smrgpanvk_EnumerateInstanceLayerProperties(uint32_t *pPropertyCount,
10597ec681f3Smrg                                       VkLayerProperties *pProperties)
10607ec681f3Smrg{
10617ec681f3Smrg   *pPropertyCount = 0;
10627ec681f3Smrg   return VK_SUCCESS;
10637ec681f3Smrg}
10647ec681f3Smrg
10657ec681f3SmrgVkResult
10667ec681f3Smrgpanvk_QueueWaitIdle(VkQueue _queue)
10677ec681f3Smrg{
10687ec681f3Smrg   VK_FROM_HANDLE(panvk_queue, queue, _queue);
10697ec681f3Smrg
10707ec681f3Smrg   if (panvk_device_is_lost(queue->device))
10717ec681f3Smrg      return VK_ERROR_DEVICE_LOST;
10727ec681f3Smrg
10737ec681f3Smrg   const struct panfrost_device *pdev = &queue->device->physical_device->pdev;
10747ec681f3Smrg   struct drm_syncobj_wait wait = {
10757ec681f3Smrg      .handles = (uint64_t) (uintptr_t)(&queue->sync),
10767ec681f3Smrg      .count_handles = 1,
10777ec681f3Smrg      .timeout_nsec = INT64_MAX,
10787ec681f3Smrg      .flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL,
10797ec681f3Smrg   };
10807ec681f3Smrg   int ret;
10817ec681f3Smrg
10827ec681f3Smrg   ret = drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_WAIT, &wait);
10837ec681f3Smrg   assert(!ret);
10847ec681f3Smrg
10857ec681f3Smrg   return VK_SUCCESS;
10867ec681f3Smrg}
10877ec681f3Smrg
10887ec681f3SmrgVkResult
10897ec681f3Smrgpanvk_EnumerateInstanceExtensionProperties(const char *pLayerName,
10907ec681f3Smrg                                           uint32_t *pPropertyCount,
10917ec681f3Smrg                                           VkExtensionProperties *pProperties)
10927ec681f3Smrg{
10937ec681f3Smrg   if (pLayerName)
10947ec681f3Smrg      return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
10957ec681f3Smrg
10967ec681f3Smrg   return vk_enumerate_instance_extension_properties(&panvk_instance_extensions,
10977ec681f3Smrg                                                     pPropertyCount, pProperties);
10987ec681f3Smrg}
10997ec681f3Smrg
11007ec681f3SmrgPFN_vkVoidFunction
11017ec681f3Smrgpanvk_GetInstanceProcAddr(VkInstance _instance, const char *pName)
11027ec681f3Smrg{
11037ec681f3Smrg   VK_FROM_HANDLE(panvk_instance, instance, _instance);
11047ec681f3Smrg   return vk_instance_get_proc_addr(&instance->vk,
11057ec681f3Smrg                                    &panvk_instance_entrypoints,
11067ec681f3Smrg                                    pName);
11077ec681f3Smrg}
11087ec681f3Smrg
11097ec681f3Smrg/* The loader wants us to expose a second GetInstanceProcAddr function
11107ec681f3Smrg * to work around certain LD_PRELOAD issues seen in apps.
11117ec681f3Smrg */
11127ec681f3SmrgPUBLIC
11137ec681f3SmrgVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
11147ec681f3Smrgvk_icdGetInstanceProcAddr(VkInstance instance, const char *pName);
11157ec681f3Smrg
11167ec681f3SmrgPUBLIC
11177ec681f3SmrgVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
11187ec681f3Smrgvk_icdGetInstanceProcAddr(VkInstance instance, const char *pName)
11197ec681f3Smrg{
11207ec681f3Smrg   return panvk_GetInstanceProcAddr(instance, pName);
11217ec681f3Smrg}
11227ec681f3Smrg
11237ec681f3SmrgVkResult
11247ec681f3Smrgpanvk_AllocateMemory(VkDevice _device,
11257ec681f3Smrg                     const VkMemoryAllocateInfo *pAllocateInfo,
11267ec681f3Smrg                     const VkAllocationCallbacks *pAllocator,
11277ec681f3Smrg                     VkDeviceMemory *pMem)
11287ec681f3Smrg{
11297ec681f3Smrg   VK_FROM_HANDLE(panvk_device, device, _device);
11307ec681f3Smrg   struct panvk_device_memory *mem;
11317ec681f3Smrg
11327ec681f3Smrg   assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
11337ec681f3Smrg
11347ec681f3Smrg   if (pAllocateInfo->allocationSize == 0) {
11357ec681f3Smrg      /* Apparently, this is allowed */
11367ec681f3Smrg      *pMem = VK_NULL_HANDLE;
11377ec681f3Smrg      return VK_SUCCESS;
11387ec681f3Smrg   }
11397ec681f3Smrg
11407ec681f3Smrg   mem = vk_object_alloc(&device->vk, pAllocator, sizeof(*mem),
11417ec681f3Smrg                         VK_OBJECT_TYPE_DEVICE_MEMORY);
11427ec681f3Smrg   if (mem == NULL)
11437ec681f3Smrg      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
11447ec681f3Smrg
11457ec681f3Smrg   const VkImportMemoryFdInfoKHR *fd_info =
11467ec681f3Smrg      vk_find_struct_const(pAllocateInfo->pNext,
11477ec681f3Smrg                           IMPORT_MEMORY_FD_INFO_KHR);
11487ec681f3Smrg
11497ec681f3Smrg   if (fd_info && !fd_info->handleType)
11507ec681f3Smrg      fd_info = NULL;
11517ec681f3Smrg
11527ec681f3Smrg   if (fd_info) {
11537ec681f3Smrg      assert(fd_info->handleType ==
11547ec681f3Smrg                VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
11557ec681f3Smrg             fd_info->handleType ==
11567ec681f3Smrg                VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
11577ec681f3Smrg
11587ec681f3Smrg      /*
11597ec681f3Smrg       * TODO Importing the same fd twice gives us the same handle without
11607ec681f3Smrg       * reference counting.  We need to maintain a per-instance handle-to-bo
11617ec681f3Smrg       * table and add reference count to panvk_bo.
11627ec681f3Smrg       */
11637ec681f3Smrg      mem->bo = panfrost_bo_import(&device->physical_device->pdev, fd_info->fd);
11647ec681f3Smrg      /* take ownership and close the fd */
11657ec681f3Smrg      close(fd_info->fd);
11667ec681f3Smrg   } else {
11677ec681f3Smrg      mem->bo = panfrost_bo_create(&device->physical_device->pdev,
11687ec681f3Smrg                                   pAllocateInfo->allocationSize, 0,
11697ec681f3Smrg                                   "User-requested memory");
11707ec681f3Smrg   }
11717ec681f3Smrg
11727ec681f3Smrg   assert(mem->bo);
11737ec681f3Smrg
11747ec681f3Smrg   *pMem = panvk_device_memory_to_handle(mem);
11757ec681f3Smrg
11767ec681f3Smrg   return VK_SUCCESS;
11777ec681f3Smrg}
11787ec681f3Smrg
11797ec681f3Smrgvoid
11807ec681f3Smrgpanvk_FreeMemory(VkDevice _device,
11817ec681f3Smrg                 VkDeviceMemory _mem,
11827ec681f3Smrg                 const VkAllocationCallbacks *pAllocator)
11837ec681f3Smrg{
11847ec681f3Smrg   VK_FROM_HANDLE(panvk_device, device, _device);
11857ec681f3Smrg   VK_FROM_HANDLE(panvk_device_memory, mem, _mem);
11867ec681f3Smrg
11877ec681f3Smrg   if (mem == NULL)
11887ec681f3Smrg      return;
11897ec681f3Smrg
11907ec681f3Smrg   panfrost_bo_unreference(mem->bo);
11917ec681f3Smrg   vk_object_free(&device->vk, pAllocator, mem);
11927ec681f3Smrg}
11937ec681f3Smrg
11947ec681f3SmrgVkResult
11957ec681f3Smrgpanvk_MapMemory(VkDevice _device,
11967ec681f3Smrg                VkDeviceMemory _memory,
11977ec681f3Smrg                VkDeviceSize offset,
11987ec681f3Smrg                VkDeviceSize size,
11997ec681f3Smrg                VkMemoryMapFlags flags,
12007ec681f3Smrg                void **ppData)
12017ec681f3Smrg{
12027ec681f3Smrg   VK_FROM_HANDLE(panvk_device, device, _device);
12037ec681f3Smrg   VK_FROM_HANDLE(panvk_device_memory, mem, _memory);
12047ec681f3Smrg
12057ec681f3Smrg   if (mem == NULL) {
12067ec681f3Smrg      *ppData = NULL;
12077ec681f3Smrg      return VK_SUCCESS;
12087ec681f3Smrg   }
12097ec681f3Smrg
12107ec681f3Smrg   if (!mem->bo->ptr.cpu)
12117ec681f3Smrg      panfrost_bo_mmap(mem->bo);
12127ec681f3Smrg
12137ec681f3Smrg   *ppData = mem->bo->ptr.cpu;
12147ec681f3Smrg
12157ec681f3Smrg   if (*ppData) {
12167ec681f3Smrg      *ppData += offset;
12177ec681f3Smrg      return VK_SUCCESS;
12187ec681f3Smrg   }
12197ec681f3Smrg
12207ec681f3Smrg   return vk_error(device, VK_ERROR_MEMORY_MAP_FAILED);
12217ec681f3Smrg}
12227ec681f3Smrg
12237ec681f3Smrgvoid
12247ec681f3Smrgpanvk_UnmapMemory(VkDevice _device, VkDeviceMemory _memory)
12257ec681f3Smrg{
12267ec681f3Smrg}
12277ec681f3Smrg
12287ec681f3SmrgVkResult
12297ec681f3Smrgpanvk_FlushMappedMemoryRanges(VkDevice _device,
12307ec681f3Smrg                              uint32_t memoryRangeCount,
12317ec681f3Smrg                              const VkMappedMemoryRange *pMemoryRanges)
12327ec681f3Smrg{
12337ec681f3Smrg   return VK_SUCCESS;
12347ec681f3Smrg}
12357ec681f3Smrg
12367ec681f3SmrgVkResult
12377ec681f3Smrgpanvk_InvalidateMappedMemoryRanges(VkDevice _device,
12387ec681f3Smrg                                   uint32_t memoryRangeCount,
12397ec681f3Smrg                                   const VkMappedMemoryRange *pMemoryRanges)
12407ec681f3Smrg{
12417ec681f3Smrg   return VK_SUCCESS;
12427ec681f3Smrg}
12437ec681f3Smrg
12447ec681f3Smrgvoid
12457ec681f3Smrgpanvk_GetBufferMemoryRequirements(VkDevice _device,
12467ec681f3Smrg                                  VkBuffer _buffer,
12477ec681f3Smrg                                  VkMemoryRequirements *pMemoryRequirements)
12487ec681f3Smrg{
12497ec681f3Smrg   VK_FROM_HANDLE(panvk_buffer, buffer, _buffer);
12507ec681f3Smrg
12517ec681f3Smrg   pMemoryRequirements->memoryTypeBits = 1;
12527ec681f3Smrg   pMemoryRequirements->alignment = 64;
12537ec681f3Smrg   pMemoryRequirements->size =
12547ec681f3Smrg      MAX2(align64(buffer->size, pMemoryRequirements->alignment), buffer->size);
12557ec681f3Smrg}
12567ec681f3Smrg
12577ec681f3Smrgvoid
12587ec681f3Smrgpanvk_GetBufferMemoryRequirements2(VkDevice device,
12597ec681f3Smrg                                   const VkBufferMemoryRequirementsInfo2 *pInfo,
12607ec681f3Smrg                                   VkMemoryRequirements2 *pMemoryRequirements)
12617ec681f3Smrg{
12627ec681f3Smrg   panvk_GetBufferMemoryRequirements(device, pInfo->buffer,
12637ec681f3Smrg                                     &pMemoryRequirements->memoryRequirements);
12647ec681f3Smrg}
12657ec681f3Smrg
12667ec681f3Smrgvoid
12677ec681f3Smrgpanvk_GetImageMemoryRequirements(VkDevice _device,
12687ec681f3Smrg                                 VkImage _image,
12697ec681f3Smrg                                 VkMemoryRequirements *pMemoryRequirements)
12707ec681f3Smrg{
12717ec681f3Smrg   VK_FROM_HANDLE(panvk_image, image, _image);
12727ec681f3Smrg
12737ec681f3Smrg   pMemoryRequirements->memoryTypeBits = 1;
12747ec681f3Smrg   pMemoryRequirements->size = panvk_image_get_total_size(image);
12757ec681f3Smrg   pMemoryRequirements->alignment = 4096;
12767ec681f3Smrg}
12777ec681f3Smrg
12787ec681f3Smrgvoid
12797ec681f3Smrgpanvk_GetImageMemoryRequirements2(VkDevice device,
12807ec681f3Smrg                                 const VkImageMemoryRequirementsInfo2 *pInfo,
12817ec681f3Smrg                                 VkMemoryRequirements2 *pMemoryRequirements)
12827ec681f3Smrg{
12837ec681f3Smrg   panvk_GetImageMemoryRequirements(device, pInfo->image,
12847ec681f3Smrg                                    &pMemoryRequirements->memoryRequirements);
12857ec681f3Smrg}
12867ec681f3Smrg
12877ec681f3Smrgvoid
12887ec681f3Smrgpanvk_GetImageSparseMemoryRequirements(VkDevice device, VkImage image,
12897ec681f3Smrg                                       uint32_t *pSparseMemoryRequirementCount,
12907ec681f3Smrg                                       VkSparseImageMemoryRequirements *pSparseMemoryRequirements)
12917ec681f3Smrg{
12927ec681f3Smrg   panvk_stub();
12937ec681f3Smrg}
12947ec681f3Smrg
12957ec681f3Smrgvoid
12967ec681f3Smrgpanvk_GetImageSparseMemoryRequirements2(VkDevice device,
12977ec681f3Smrg                                        const VkImageSparseMemoryRequirementsInfo2 *pInfo,
12987ec681f3Smrg                                        uint32_t *pSparseMemoryRequirementCount,
12997ec681f3Smrg                                        VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
13007ec681f3Smrg{
13017ec681f3Smrg   panvk_stub();
13027ec681f3Smrg}
13037ec681f3Smrg
13047ec681f3Smrgvoid
13057ec681f3Smrgpanvk_GetDeviceMemoryCommitment(VkDevice device,
13067ec681f3Smrg                                VkDeviceMemory memory,
13077ec681f3Smrg                                VkDeviceSize *pCommittedMemoryInBytes)
13087ec681f3Smrg{
13097ec681f3Smrg   *pCommittedMemoryInBytes = 0;
13107ec681f3Smrg}
13117ec681f3Smrg
13127ec681f3SmrgVkResult
13137ec681f3Smrgpanvk_BindBufferMemory2(VkDevice device,
13147ec681f3Smrg                        uint32_t bindInfoCount,
13157ec681f3Smrg                        const VkBindBufferMemoryInfo *pBindInfos)
13167ec681f3Smrg{
13177ec681f3Smrg   for (uint32_t i = 0; i < bindInfoCount; ++i) {
13187ec681f3Smrg      VK_FROM_HANDLE(panvk_device_memory, mem, pBindInfos[i].memory);
13197ec681f3Smrg      VK_FROM_HANDLE(panvk_buffer, buffer, pBindInfos[i].buffer);
13207ec681f3Smrg
13217ec681f3Smrg      if (mem) {
13227ec681f3Smrg         buffer->bo = mem->bo;
13237ec681f3Smrg         buffer->bo_offset = pBindInfos[i].memoryOffset;
13247ec681f3Smrg      } else {
13257ec681f3Smrg         buffer->bo = NULL;
13267ec681f3Smrg      }
13277ec681f3Smrg   }
13287ec681f3Smrg   return VK_SUCCESS;
13297ec681f3Smrg}
13307ec681f3Smrg
13317ec681f3SmrgVkResult
13327ec681f3Smrgpanvk_BindBufferMemory(VkDevice device,
13337ec681f3Smrg                       VkBuffer buffer,
13347ec681f3Smrg                       VkDeviceMemory memory,
13357ec681f3Smrg                       VkDeviceSize memoryOffset)
13367ec681f3Smrg{
13377ec681f3Smrg   const VkBindBufferMemoryInfo info = {
13387ec681f3Smrg      .sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,
13397ec681f3Smrg      .buffer = buffer,
13407ec681f3Smrg      .memory = memory,
13417ec681f3Smrg      .memoryOffset = memoryOffset
13427ec681f3Smrg   };
13437ec681f3Smrg
13447ec681f3Smrg   return panvk_BindBufferMemory2(device, 1, &info);
13457ec681f3Smrg}
13467ec681f3Smrg
13477ec681f3SmrgVkResult
13487ec681f3Smrgpanvk_BindImageMemory2(VkDevice device,
13497ec681f3Smrg                       uint32_t bindInfoCount,
13507ec681f3Smrg                       const VkBindImageMemoryInfo *pBindInfos)
13517ec681f3Smrg{
13527ec681f3Smrg   for (uint32_t i = 0; i < bindInfoCount; ++i) {
13537ec681f3Smrg      VK_FROM_HANDLE(panvk_image, image, pBindInfos[i].image);
13547ec681f3Smrg      VK_FROM_HANDLE(panvk_device_memory, mem, pBindInfos[i].memory);
13557ec681f3Smrg
13567ec681f3Smrg      if (mem) {
13577ec681f3Smrg         image->pimage.data.bo = mem->bo;
13587ec681f3Smrg         image->pimage.data.offset = pBindInfos[i].memoryOffset;
13597ec681f3Smrg         /* Reset the AFBC headers */
13607ec681f3Smrg         if (drm_is_afbc(image->pimage.layout.modifier)) {
13617ec681f3Smrg            void *base = image->pimage.data.bo->ptr.cpu + image->pimage.data.offset;
13627ec681f3Smrg
13637ec681f3Smrg            for (unsigned layer = 0; layer < image->pimage.layout.array_size; layer++) {
13647ec681f3Smrg               for (unsigned level = 0; level < image->pimage.layout.nr_slices; level++) {
13657ec681f3Smrg                  void *header = base +
13667ec681f3Smrg                                 (layer * image->pimage.layout.array_stride) +
13677ec681f3Smrg                                 image->pimage.layout.slices[level].offset;
13687ec681f3Smrg                  memset(header, 0, image->pimage.layout.slices[level].afbc.header_size);
13697ec681f3Smrg               }
13707ec681f3Smrg            }
13717ec681f3Smrg         }
13727ec681f3Smrg      } else {
13737ec681f3Smrg         image->pimage.data.bo = NULL;
13747ec681f3Smrg         image->pimage.data.offset = pBindInfos[i].memoryOffset;
13757ec681f3Smrg      }
13767ec681f3Smrg   }
13777ec681f3Smrg
13787ec681f3Smrg   return VK_SUCCESS;
13797ec681f3Smrg}
13807ec681f3Smrg
13817ec681f3SmrgVkResult
13827ec681f3Smrgpanvk_BindImageMemory(VkDevice device,
13837ec681f3Smrg                      VkImage image,
13847ec681f3Smrg                      VkDeviceMemory memory,
13857ec681f3Smrg                      VkDeviceSize memoryOffset)
13867ec681f3Smrg{
13877ec681f3Smrg   const VkBindImageMemoryInfo info = {
13887ec681f3Smrg      .sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,
13897ec681f3Smrg      .image = image,
13907ec681f3Smrg      .memory = memory,
13917ec681f3Smrg      .memoryOffset = memoryOffset
13927ec681f3Smrg   };
13937ec681f3Smrg
13947ec681f3Smrg   return panvk_BindImageMemory2(device, 1, &info);
13957ec681f3Smrg}
13967ec681f3Smrg
13977ec681f3SmrgVkResult
13987ec681f3Smrgpanvk_QueueBindSparse(VkQueue _queue,
13997ec681f3Smrg                      uint32_t bindInfoCount,
14007ec681f3Smrg                      const VkBindSparseInfo *pBindInfo,
14017ec681f3Smrg                      VkFence _fence)
14027ec681f3Smrg{
14037ec681f3Smrg   return VK_SUCCESS;
14047ec681f3Smrg}
14057ec681f3Smrg
14067ec681f3SmrgVkResult
14077ec681f3Smrgpanvk_CreateEvent(VkDevice _device,
14087ec681f3Smrg                  const VkEventCreateInfo *pCreateInfo,
14097ec681f3Smrg                  const VkAllocationCallbacks *pAllocator,
14107ec681f3Smrg                  VkEvent *pEvent)
14117ec681f3Smrg{
14127ec681f3Smrg   VK_FROM_HANDLE(panvk_device, device, _device);
14137ec681f3Smrg   const struct panfrost_device *pdev = &device->physical_device->pdev;
14147ec681f3Smrg   struct panvk_event *event =
14157ec681f3Smrg      vk_object_zalloc(&device->vk, pAllocator, sizeof(*event),
14167ec681f3Smrg                       VK_OBJECT_TYPE_EVENT);
14177ec681f3Smrg   if (!event)
14187ec681f3Smrg      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
14197ec681f3Smrg
14207ec681f3Smrg   struct drm_syncobj_create create = {
14217ec681f3Smrg      .flags = 0,
14227ec681f3Smrg   };
14237ec681f3Smrg
14247ec681f3Smrg   int ret = drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_CREATE, &create);
14257ec681f3Smrg   if (ret)
14267ec681f3Smrg      return VK_ERROR_OUT_OF_HOST_MEMORY;
14277ec681f3Smrg
14287ec681f3Smrg   event->syncobj = create.handle;
14297ec681f3Smrg   *pEvent = panvk_event_to_handle(event);
14307ec681f3Smrg
14317ec681f3Smrg   return VK_SUCCESS;
14327ec681f3Smrg}
14337ec681f3Smrg
14347ec681f3Smrgvoid
14357ec681f3Smrgpanvk_DestroyEvent(VkDevice _device,
14367ec681f3Smrg                   VkEvent _event,
14377ec681f3Smrg                   const VkAllocationCallbacks *pAllocator)
14387ec681f3Smrg{
14397ec681f3Smrg   VK_FROM_HANDLE(panvk_device, device, _device);
14407ec681f3Smrg   VK_FROM_HANDLE(panvk_event, event, _event);
14417ec681f3Smrg   const struct panfrost_device *pdev = &device->physical_device->pdev;
14427ec681f3Smrg
14437ec681f3Smrg   if (!event)
14447ec681f3Smrg      return;
14457ec681f3Smrg
14467ec681f3Smrg   struct drm_syncobj_destroy destroy = { .handle = event->syncobj };
14477ec681f3Smrg   drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_DESTROY, &destroy);
14487ec681f3Smrg
14497ec681f3Smrg   vk_object_free(&device->vk, pAllocator, event);
14507ec681f3Smrg}
14517ec681f3Smrg
14527ec681f3SmrgVkResult
14537ec681f3Smrgpanvk_GetEventStatus(VkDevice _device, VkEvent _event)
14547ec681f3Smrg{
14557ec681f3Smrg   VK_FROM_HANDLE(panvk_device, device, _device);
14567ec681f3Smrg   VK_FROM_HANDLE(panvk_event, event, _event);
14577ec681f3Smrg   const struct panfrost_device *pdev = &device->physical_device->pdev;
14587ec681f3Smrg   bool signaled;
14597ec681f3Smrg
14607ec681f3Smrg   struct drm_syncobj_wait wait = {
14617ec681f3Smrg      .handles = (uintptr_t) &event->syncobj,
14627ec681f3Smrg      .count_handles = 1,
14637ec681f3Smrg      .timeout_nsec = 0,
14647ec681f3Smrg      .flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,
14657ec681f3Smrg   };
14667ec681f3Smrg
14677ec681f3Smrg   int ret = drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_WAIT, &wait);
14687ec681f3Smrg   if (ret) {
14697ec681f3Smrg      if (errno == ETIME)
14707ec681f3Smrg         signaled = false;
14717ec681f3Smrg      else {
14727ec681f3Smrg         assert(0);
14737ec681f3Smrg         return VK_ERROR_DEVICE_LOST; /* TODO */
14747ec681f3Smrg      }
14757ec681f3Smrg   } else
14767ec681f3Smrg      signaled = true;
14777ec681f3Smrg
14787ec681f3Smrg   return signaled ? VK_EVENT_SET : VK_EVENT_RESET;
14797ec681f3Smrg}
14807ec681f3Smrg
14817ec681f3SmrgVkResult
14827ec681f3Smrgpanvk_SetEvent(VkDevice _device, VkEvent _event)
14837ec681f3Smrg{
14847ec681f3Smrg   VK_FROM_HANDLE(panvk_device, device, _device);
14857ec681f3Smrg   VK_FROM_HANDLE(panvk_event, event, _event);
14867ec681f3Smrg   const struct panfrost_device *pdev = &device->physical_device->pdev;
14877ec681f3Smrg
14887ec681f3Smrg   struct drm_syncobj_array objs = {
14897ec681f3Smrg      .handles = (uint64_t) (uintptr_t) &event->syncobj,
14907ec681f3Smrg      .count_handles = 1
14917ec681f3Smrg   };
14927ec681f3Smrg
14937ec681f3Smrg   /* This is going to just replace the fence for this syncobj with one that
14947ec681f3Smrg    * is already in signaled state. This won't be a problem because the spec
14957ec681f3Smrg    * mandates that the event will have been set before the vkCmdWaitEvents
14967ec681f3Smrg    * command executes.
14977ec681f3Smrg    * https://www.khronos.org/registry/vulkan/specs/1.2/html/chap6.html#commandbuffers-submission-progress
14987ec681f3Smrg    */
14997ec681f3Smrg   if (drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_SIGNAL, &objs))
15007ec681f3Smrg      return VK_ERROR_DEVICE_LOST;
15017ec681f3Smrg
15027ec681f3Smrg  return VK_SUCCESS;
15037ec681f3Smrg}
15047ec681f3Smrg
15057ec681f3SmrgVkResult
15067ec681f3Smrgpanvk_ResetEvent(VkDevice _device, VkEvent _event)
15077ec681f3Smrg{
15087ec681f3Smrg   VK_FROM_HANDLE(panvk_device, device, _device);
15097ec681f3Smrg   VK_FROM_HANDLE(panvk_event, event, _event);
15107ec681f3Smrg   const struct panfrost_device *pdev = &device->physical_device->pdev;
15117ec681f3Smrg
15127ec681f3Smrg   struct drm_syncobj_array objs = {
15137ec681f3Smrg      .handles = (uint64_t) (uintptr_t) &event->syncobj,
15147ec681f3Smrg      .count_handles = 1
15157ec681f3Smrg   };
15167ec681f3Smrg
15177ec681f3Smrg   if (drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_RESET, &objs))
15187ec681f3Smrg      return VK_ERROR_DEVICE_LOST;
15197ec681f3Smrg
15207ec681f3Smrg  return VK_SUCCESS;
15217ec681f3Smrg}
15227ec681f3Smrg
15237ec681f3SmrgVkResult
15247ec681f3Smrgpanvk_CreateBuffer(VkDevice _device,
15257ec681f3Smrg                   const VkBufferCreateInfo *pCreateInfo,
15267ec681f3Smrg                   const VkAllocationCallbacks *pAllocator,
15277ec681f3Smrg                   VkBuffer *pBuffer)
15287ec681f3Smrg{
15297ec681f3Smrg   VK_FROM_HANDLE(panvk_device, device, _device);
15307ec681f3Smrg   struct panvk_buffer *buffer;
15317ec681f3Smrg
15327ec681f3Smrg   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);
15337ec681f3Smrg
15347ec681f3Smrg   buffer = vk_object_alloc(&device->vk, pAllocator, sizeof(*buffer),
15357ec681f3Smrg                            VK_OBJECT_TYPE_BUFFER);
15367ec681f3Smrg   if (buffer == NULL)
15377ec681f3Smrg      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
15387ec681f3Smrg
15397ec681f3Smrg   buffer->size = pCreateInfo->size;
15407ec681f3Smrg   buffer->usage = pCreateInfo->usage;
15417ec681f3Smrg   buffer->flags = pCreateInfo->flags;
15427ec681f3Smrg
15437ec681f3Smrg   *pBuffer = panvk_buffer_to_handle(buffer);
15447ec681f3Smrg
15457ec681f3Smrg   return VK_SUCCESS;
15467ec681f3Smrg}
15477ec681f3Smrg
15487ec681f3Smrgvoid
15497ec681f3Smrgpanvk_DestroyBuffer(VkDevice _device,
15507ec681f3Smrg                    VkBuffer _buffer,
15517ec681f3Smrg                    const VkAllocationCallbacks *pAllocator)
15527ec681f3Smrg{
15537ec681f3Smrg   VK_FROM_HANDLE(panvk_device, device, _device);
15547ec681f3Smrg   VK_FROM_HANDLE(panvk_buffer, buffer, _buffer);
15557ec681f3Smrg
15567ec681f3Smrg   if (!buffer)
15577ec681f3Smrg      return;
15587ec681f3Smrg
15597ec681f3Smrg   vk_object_free(&device->vk, pAllocator, buffer);
15607ec681f3Smrg}
15617ec681f3Smrg
15627ec681f3SmrgVkResult
15637ec681f3Smrgpanvk_CreateFramebuffer(VkDevice _device,
15647ec681f3Smrg                        const VkFramebufferCreateInfo *pCreateInfo,
15657ec681f3Smrg                        const VkAllocationCallbacks *pAllocator,
15667ec681f3Smrg                        VkFramebuffer *pFramebuffer)
15677ec681f3Smrg{
15687ec681f3Smrg   VK_FROM_HANDLE(panvk_device, device, _device);
15697ec681f3Smrg   struct panvk_framebuffer *framebuffer;
15707ec681f3Smrg
15717ec681f3Smrg   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO);
15727ec681f3Smrg
15737ec681f3Smrg   size_t size = sizeof(*framebuffer) + sizeof(struct panvk_attachment_info) *
15747ec681f3Smrg                                           pCreateInfo->attachmentCount;
15757ec681f3Smrg   framebuffer = vk_object_alloc(&device->vk, pAllocator, size,
15767ec681f3Smrg                                 VK_OBJECT_TYPE_FRAMEBUFFER);
15777ec681f3Smrg   if (framebuffer == NULL)
15787ec681f3Smrg      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
15797ec681f3Smrg
15807ec681f3Smrg   framebuffer->attachment_count = pCreateInfo->attachmentCount;
15817ec681f3Smrg   framebuffer->width = pCreateInfo->width;
15827ec681f3Smrg   framebuffer->height = pCreateInfo->height;
15837ec681f3Smrg   framebuffer->layers = pCreateInfo->layers;
15847ec681f3Smrg   for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
15857ec681f3Smrg      VkImageView _iview = pCreateInfo->pAttachments[i];
15867ec681f3Smrg      struct panvk_image_view *iview = panvk_image_view_from_handle(_iview);
15877ec681f3Smrg      framebuffer->attachments[i].iview = iview;
15887ec681f3Smrg   }
15897ec681f3Smrg
15907ec681f3Smrg   *pFramebuffer = panvk_framebuffer_to_handle(framebuffer);
15917ec681f3Smrg   return VK_SUCCESS;
15927ec681f3Smrg}
15937ec681f3Smrg
15947ec681f3Smrgvoid
15957ec681f3Smrgpanvk_DestroyFramebuffer(VkDevice _device,
15967ec681f3Smrg                         VkFramebuffer _fb,
15977ec681f3Smrg                         const VkAllocationCallbacks *pAllocator)
15987ec681f3Smrg{
15997ec681f3Smrg   VK_FROM_HANDLE(panvk_device, device, _device);
16007ec681f3Smrg   VK_FROM_HANDLE(panvk_framebuffer, fb, _fb);
16017ec681f3Smrg
16027ec681f3Smrg   if (fb)
16037ec681f3Smrg      vk_object_free(&device->vk, pAllocator, fb);
16047ec681f3Smrg}
16057ec681f3Smrg
16067ec681f3Smrgvoid
16077ec681f3Smrgpanvk_DestroySampler(VkDevice _device,
16087ec681f3Smrg                     VkSampler _sampler,
16097ec681f3Smrg                     const VkAllocationCallbacks *pAllocator)
16107ec681f3Smrg{
16117ec681f3Smrg   VK_FROM_HANDLE(panvk_device, device, _device);
16127ec681f3Smrg   VK_FROM_HANDLE(panvk_sampler, sampler, _sampler);
16137ec681f3Smrg
16147ec681f3Smrg   if (!sampler)
16157ec681f3Smrg      return;
16167ec681f3Smrg
16177ec681f3Smrg   vk_object_free(&device->vk, pAllocator, sampler);
16187ec681f3Smrg}
16197ec681f3Smrg
16207ec681f3Smrg/* vk_icd.h does not declare this function, so we declare it here to
16217ec681f3Smrg * suppress Wmissing-prototypes.
16227ec681f3Smrg */
16237ec681f3SmrgPUBLIC VKAPI_ATTR VkResult VKAPI_CALL
16247ec681f3Smrgvk_icdNegotiateLoaderICDInterfaceVersion(uint32_t *pSupportedVersion);
16257ec681f3Smrg
16267ec681f3SmrgPUBLIC VKAPI_ATTR VkResult VKAPI_CALL
16277ec681f3Smrgvk_icdNegotiateLoaderICDInterfaceVersion(uint32_t *pSupportedVersion)
16287ec681f3Smrg{
16297ec681f3Smrg   /* For the full details on loader interface versioning, see
16307ec681f3Smrg    * <https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/loader/LoaderAndLayerInterface.md>.
16317ec681f3Smrg    * What follows is a condensed summary, to help you navigate the large and
16327ec681f3Smrg    * confusing official doc.
16337ec681f3Smrg    *
16347ec681f3Smrg    *   - Loader interface v0 is incompatible with later versions. We don't
16357ec681f3Smrg    *     support it.
16367ec681f3Smrg    *
16377ec681f3Smrg    *   - In loader interface v1:
16387ec681f3Smrg    *       - The first ICD entrypoint called by the loader is
16397ec681f3Smrg    *         vk_icdGetInstanceProcAddr(). The ICD must statically expose this
16407ec681f3Smrg    *         entrypoint.
16417ec681f3Smrg    *       - The ICD must statically expose no other Vulkan symbol unless it
16427ec681f3Smrg    * is linked with -Bsymbolic.
16437ec681f3Smrg    *       - Each dispatchable Vulkan handle created by the ICD must be
16447ec681f3Smrg    *         a pointer to a struct whose first member is VK_LOADER_DATA. The
16457ec681f3Smrg    *         ICD must initialize VK_LOADER_DATA.loadMagic to
16467ec681f3Smrg    * ICD_LOADER_MAGIC.
16477ec681f3Smrg    *       - The loader implements vkCreate{PLATFORM}SurfaceKHR() and
16487ec681f3Smrg    *         vkDestroySurfaceKHR(). The ICD must be capable of working with
16497ec681f3Smrg    *         such loader-managed surfaces.
16507ec681f3Smrg    *
16517ec681f3Smrg    *    - Loader interface v2 differs from v1 in:
16527ec681f3Smrg    *       - The first ICD entrypoint called by the loader is
16537ec681f3Smrg    *         vk_icdNegotiateLoaderICDInterfaceVersion(). The ICD must
16547ec681f3Smrg    *         statically expose this entrypoint.
16557ec681f3Smrg    *
16567ec681f3Smrg    *    - Loader interface v3 differs from v2 in:
16577ec681f3Smrg    *        - The ICD must implement vkCreate{PLATFORM}SurfaceKHR(),
16587ec681f3Smrg    *          vkDestroySurfaceKHR(), and other API which uses VKSurfaceKHR,
16597ec681f3Smrg    *          because the loader no longer does so.
16607ec681f3Smrg    */
16617ec681f3Smrg   *pSupportedVersion = MIN2(*pSupportedVersion, 3u);
16627ec681f3Smrg   return VK_SUCCESS;
16637ec681f3Smrg}
16647ec681f3Smrg
16657ec681f3SmrgVkResult
16667ec681f3Smrgpanvk_GetMemoryFdKHR(VkDevice _device,
16677ec681f3Smrg                     const VkMemoryGetFdInfoKHR *pGetFdInfo,
16687ec681f3Smrg                     int *pFd)
16697ec681f3Smrg{
16707ec681f3Smrg   VK_FROM_HANDLE(panvk_device, device, _device);
16717ec681f3Smrg   VK_FROM_HANDLE(panvk_device_memory, memory, pGetFdInfo->memory);
16727ec681f3Smrg
16737ec681f3Smrg   assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR);
16747ec681f3Smrg
16757ec681f3Smrg   /* At the moment, we support only the below handle types. */
16767ec681f3Smrg   assert(pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
16777ec681f3Smrg          pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
16787ec681f3Smrg
16797ec681f3Smrg   int prime_fd = panfrost_bo_export(memory->bo);
16807ec681f3Smrg   if (prime_fd < 0)
16817ec681f3Smrg      return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
16827ec681f3Smrg
16837ec681f3Smrg   *pFd = prime_fd;
16847ec681f3Smrg   return VK_SUCCESS;
16857ec681f3Smrg}
16867ec681f3Smrg
16877ec681f3SmrgVkResult
16887ec681f3Smrgpanvk_GetMemoryFdPropertiesKHR(VkDevice _device,
16897ec681f3Smrg                               VkExternalMemoryHandleTypeFlagBits handleType,
16907ec681f3Smrg                               int fd,
16917ec681f3Smrg                               VkMemoryFdPropertiesKHR *pMemoryFdProperties)
16927ec681f3Smrg{
16937ec681f3Smrg   assert(handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
16947ec681f3Smrg   pMemoryFdProperties->memoryTypeBits = 1;
16957ec681f3Smrg   return VK_SUCCESS;
16967ec681f3Smrg}
16977ec681f3Smrg
16987ec681f3Smrgvoid
16997ec681f3Smrgpanvk_GetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice,
17007ec681f3Smrg                                                   const VkPhysicalDeviceExternalSemaphoreInfo *pExternalSemaphoreInfo,
17017ec681f3Smrg                                                   VkExternalSemaphoreProperties *pExternalSemaphoreProperties)
17027ec681f3Smrg{
17037ec681f3Smrg   if ((pExternalSemaphoreInfo->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT ||
17047ec681f3Smrg        pExternalSemaphoreInfo->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)) {
17057ec681f3Smrg      pExternalSemaphoreProperties->exportFromImportedHandleTypes =
17067ec681f3Smrg         VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT |
17077ec681f3Smrg         VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
17087ec681f3Smrg      pExternalSemaphoreProperties->compatibleHandleTypes =
17097ec681f3Smrg         VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT |
17107ec681f3Smrg         VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
17117ec681f3Smrg      pExternalSemaphoreProperties->externalSemaphoreFeatures =
17127ec681f3Smrg         VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT |
17137ec681f3Smrg         VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT;
17147ec681f3Smrg   } else {
17157ec681f3Smrg      pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0;
17167ec681f3Smrg      pExternalSemaphoreProperties->compatibleHandleTypes = 0;
17177ec681f3Smrg      pExternalSemaphoreProperties->externalSemaphoreFeatures = 0;
17187ec681f3Smrg   }
17197ec681f3Smrg}
17207ec681f3Smrg
17217ec681f3Smrgvoid
17227ec681f3Smrgpanvk_GetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice,
17237ec681f3Smrg                                               const VkPhysicalDeviceExternalFenceInfo *pExternalFenceInfo,
17247ec681f3Smrg                                               VkExternalFenceProperties *pExternalFenceProperties)
17257ec681f3Smrg{
17267ec681f3Smrg   pExternalFenceProperties->exportFromImportedHandleTypes = 0;
17277ec681f3Smrg   pExternalFenceProperties->compatibleHandleTypes = 0;
17287ec681f3Smrg   pExternalFenceProperties->externalFenceFeatures = 0;
17297ec681f3Smrg}
17307ec681f3Smrg
17317ec681f3Smrgvoid
17327ec681f3Smrgpanvk_GetDeviceGroupPeerMemoryFeatures(VkDevice device,
17337ec681f3Smrg                                       uint32_t heapIndex,
17347ec681f3Smrg                                       uint32_t localDeviceIndex,
17357ec681f3Smrg                                       uint32_t remoteDeviceIndex,
17367ec681f3Smrg                                       VkPeerMemoryFeatureFlags *pPeerMemoryFeatures)
17377ec681f3Smrg{
17387ec681f3Smrg   assert(localDeviceIndex == remoteDeviceIndex);
17397ec681f3Smrg
17407ec681f3Smrg   *pPeerMemoryFeatures = VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT |
17417ec681f3Smrg                          VK_PEER_MEMORY_FEATURE_COPY_DST_BIT |
17427ec681f3Smrg                          VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT |
17437ec681f3Smrg                          VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT;
17447ec681f3Smrg}
1745