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