Path: blob/21.2-virgl/src/panfrost/vulkan/panvk_device.c
4560 views
/*1* Copyright © 2021 Collabora Ltd.2*3* Derived from tu_device.c which is:4* Copyright © 2016 Red Hat.5* Copyright © 2016 Bas Nieuwenhuizen6* Copyright © 2015 Intel Corporation7*8* Permission is hereby granted, free of charge, to any person obtaining a9* copy of this software and associated documentation files (the "Software"),10* to deal in the Software without restriction, including without limitation11* the rights to use, copy, modify, merge, publish, distribute, sublicense,12* and/or sell copies of the Software, and to permit persons to whom the13* Software is furnished to do so, subject to the following conditions:14*15* The above copyright notice and this permission notice (including the next16* paragraph) shall be included in all copies or substantial portions of the17* Software.18*19* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR20* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,21* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL22* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER23* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING24* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER25* DEALINGS IN THE SOFTWARE.26*/2728#include "panvk_private.h"2930#include "panfrost-quirks.h"31#include "pan_bo.h"32#include "pan_encoder.h"33#include "pan_util.h"34#include "decode.h"3536#include <fcntl.h>37#include <libsync.h>38#include <stdbool.h>39#include <string.h>40#include <sys/mman.h>41#include <sys/sysinfo.h>42#include <unistd.h>43#include <xf86drm.h>4445#include "drm-uapi/panfrost_drm.h"4647#include "util/debug.h"48#include "util/strtod.h"49#include "vk_format.h"50#include "vk_util.h"5152#ifdef VK_USE_PLATFORM_WAYLAND_KHR53#include <wayland-client.h>54#include "wayland-drm-client-protocol.h"55#endif5657#include "panvk_cs.h"5859VkResult60_panvk_device_set_lost(struct panvk_device *device,61const char *file, int line,62const char *msg, ...)63{64/* Set the flag indicating that waits should return in finite time even65* after device loss.66*/67p_atomic_inc(&device->_lost);6869/* TODO: Report the log message through VkDebugReportCallbackEXT instead */70fprintf(stderr, "%s:%d: ", file, line);71va_list ap;72va_start(ap, msg);73vfprintf(stderr, msg, ap);74va_end(ap);7576if (env_var_as_boolean("PANVK_ABORT_ON_DEVICE_LOSS", false))77abort();7879return VK_ERROR_DEVICE_LOST;80}8182static int83panvk_device_get_cache_uuid(uint16_t family, void *uuid)84{85uint32_t mesa_timestamp;86uint16_t f = family;87memset(uuid, 0, VK_UUID_SIZE);88memcpy(uuid, &mesa_timestamp, 4);89memcpy((char *) uuid + 4, &f, 2);90snprintf((char *) uuid + 6, VK_UUID_SIZE - 10, "pan");91return 0;92}9394static void95panvk_get_driver_uuid(void *uuid)96{97memset(uuid, 0, VK_UUID_SIZE);98snprintf(uuid, VK_UUID_SIZE, "panfrost");99}100101static void102panvk_get_device_uuid(void *uuid)103{104memset(uuid, 0, VK_UUID_SIZE);105}106107static const struct debug_control panvk_debug_options[] = {108{ "startup", PANVK_DEBUG_STARTUP },109{ "nir", PANVK_DEBUG_NIR },110{ "trace", PANVK_DEBUG_TRACE },111{ "sync", PANVK_DEBUG_SYNC },112{ "afbc", PANVK_DEBUG_AFBC },113{ "linear", PANVK_DEBUG_LINEAR },114{ NULL, 0 }115};116117#if defined(VK_USE_PLATFORM_WAYLAND_KHR)118#define PANVK_USE_WSI_PLATFORM119#endif120121#define PANVK_API_VERSION VK_MAKE_VERSION(1, 1, VK_HEADER_VERSION)122123VkResult124panvk_EnumerateInstanceVersion(uint32_t *pApiVersion)125{126*pApiVersion = PANVK_API_VERSION;127return VK_SUCCESS;128}129130static const struct vk_instance_extension_table panvk_instance_extensions = {131#ifdef PANVK_USE_WSI_PLATFORM132.KHR_surface = true,133#endif134#ifdef VK_USE_PLATFORM_WAYLAND_KHR135.KHR_wayland_surface = true,136#endif137};138139static void140panvk_get_device_extensions(const struct panvk_physical_device *device,141struct vk_device_extension_table *ext)142{143*ext = (struct vk_device_extension_table) {144#ifdef PANVK_USE_WSI_PLATFORM145.KHR_swapchain = true,146#endif147.EXT_custom_border_color = true,148};149}150151VkResult152panvk_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,153const VkAllocationCallbacks *pAllocator,154VkInstance *pInstance)155{156struct panvk_instance *instance;157VkResult result;158159assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO);160161pAllocator = pAllocator ? : vk_default_allocator();162instance = vk_zalloc(pAllocator, sizeof(*instance), 8,163VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);164if (!instance)165return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);166167struct vk_instance_dispatch_table dispatch_table;168169vk_instance_dispatch_table_from_entrypoints(&dispatch_table,170&panvk_instance_entrypoints,171true);172result = vk_instance_init(&instance->vk,173&panvk_instance_extensions,174&dispatch_table,175pCreateInfo,176pAllocator);177if (result != VK_SUCCESS) {178vk_free(pAllocator, instance);179return vk_error(NULL, result);180}181182instance->physical_device_count = -1;183instance->debug_flags = parse_debug_string(getenv("PANVK_DEBUG"),184panvk_debug_options);185186if (instance->debug_flags & PANVK_DEBUG_STARTUP)187panvk_logi("Created an instance");188189VG(VALGRIND_CREATE_MEMPOOL(instance, 0, false));190191*pInstance = panvk_instance_to_handle(instance);192193return VK_SUCCESS;194}195196static void197panvk_physical_device_finish(struct panvk_physical_device *device)198{199panvk_wsi_finish(device);200201panvk_meta_cleanup(device);202panfrost_close_device(&device->pdev);203if (device->master_fd != -1)204close(device->master_fd);205206vk_physical_device_finish(&device->vk);207}208209void210panvk_DestroyInstance(VkInstance _instance,211const VkAllocationCallbacks *pAllocator)212{213VK_FROM_HANDLE(panvk_instance, instance, _instance);214215if (!instance)216return;217218for (int i = 0; i < instance->physical_device_count; ++i) {219panvk_physical_device_finish(instance->physical_devices + i);220}221222vk_instance_finish(&instance->vk);223vk_free(&instance->vk.alloc, instance);224}225226static VkResult227panvk_physical_device_init(struct panvk_physical_device *device,228struct panvk_instance *instance,229drmDevicePtr drm_device)230{231const char *path = drm_device->nodes[DRM_NODE_RENDER];232VkResult result = VK_SUCCESS;233drmVersionPtr version;234int fd;235int master_fd = -1;236237if (!getenv("PAN_I_WANT_A_BROKEN_VULKAN_DRIVER")) {238return vk_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER,239"WARNING: panvk is not a conformant vulkan implementation, "240"pass PAN_I_WANT_A_BROKEN_VULKAN_DRIVER=1 if you know what you're doing.");241}242243fd = open(path, O_RDWR | O_CLOEXEC);244if (fd < 0) {245return vk_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER,246"failed to open device %s", path);247}248249version = drmGetVersion(fd);250if (!version) {251close(fd);252return vk_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER,253"failed to query kernel driver version for device %s",254path);255}256257if (strcmp(version->name, "panfrost")) {258drmFreeVersion(version);259close(fd);260return vk_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER,261"device %s does not use the panfrost kernel driver", path);262}263264drmFreeVersion(version);265266if (instance->debug_flags & PANVK_DEBUG_STARTUP)267panvk_logi("Found compatible device '%s'.", path);268269struct vk_device_extension_table supported_extensions;270panvk_get_device_extensions(device, &supported_extensions);271272struct vk_physical_device_dispatch_table dispatch_table;273vk_physical_device_dispatch_table_from_entrypoints(&dispatch_table,274&panvk_physical_device_entrypoints,275true);276277result = vk_physical_device_init(&device->vk, &instance->vk,278&supported_extensions,279&dispatch_table);280281if (result != VK_SUCCESS) {282vk_error(instance, result);283goto fail;284}285286device->instance = instance;287assert(strlen(path) < ARRAY_SIZE(device->path));288strncpy(device->path, path, ARRAY_SIZE(device->path));289290if (instance->vk.enabled_extensions.KHR_display) {291master_fd = open(drm_device->nodes[DRM_NODE_PRIMARY], O_RDWR | O_CLOEXEC);292if (master_fd >= 0) {293/* TODO: free master_fd is accel is not working? */294}295}296297device->master_fd = master_fd;298device->pdev.debug = PAN_DBG_TRACE;299panfrost_open_device(NULL, fd, &device->pdev);300301if (device->pdev.quirks & MIDGARD_SFBD) {302result = vk_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER,303"%s not supported",304panfrost_model_name(device->pdev.gpu_id));305goto fail;306}307308panvk_meta_init(device);309310memset(device->name, 0, sizeof(device->name));311sprintf(device->name, "%s", panfrost_model_name(device->pdev.gpu_id));312313if (panvk_device_get_cache_uuid(device->pdev.gpu_id, device->cache_uuid)) {314result = vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,315"cannot generate UUID");316goto fail;317}318319fprintf(stderr, "WARNING: panvk is not a conformant vulkan implementation, "320"testing use only.\n");321322panvk_get_driver_uuid(&device->device_uuid);323panvk_get_device_uuid(&device->device_uuid);324325result = panvk_wsi_init(device);326if (result != VK_SUCCESS) {327vk_error(instance, result);328goto fail;329}330331return VK_SUCCESS;332333fail:334close(fd);335if (master_fd != -1)336close(master_fd);337return result;338}339340static VkResult341panvk_enumerate_devices(struct panvk_instance *instance)342{343/* TODO: Check for more devices ? */344drmDevicePtr devices[8];345VkResult result = VK_ERROR_INCOMPATIBLE_DRIVER;346int max_devices;347348instance->physical_device_count = 0;349350max_devices = drmGetDevices2(0, devices, ARRAY_SIZE(devices));351352if (instance->debug_flags & PANVK_DEBUG_STARTUP)353panvk_logi("Found %d drm nodes", max_devices);354355if (max_devices < 1)356return vk_error(instance, VK_ERROR_INCOMPATIBLE_DRIVER);357358for (unsigned i = 0; i < (unsigned) max_devices; i++) {359if ((devices[i]->available_nodes & (1 << DRM_NODE_RENDER)) &&360devices[i]->bustype == DRM_BUS_PLATFORM) {361362result = panvk_physical_device_init(instance->physical_devices +363instance->physical_device_count,364instance, devices[i]);365if (result == VK_SUCCESS)366++instance->physical_device_count;367else if (result != VK_ERROR_INCOMPATIBLE_DRIVER)368break;369}370}371drmFreeDevices(devices, max_devices);372373return result;374}375376VkResult377panvk_EnumeratePhysicalDevices(VkInstance _instance,378uint32_t *pPhysicalDeviceCount,379VkPhysicalDevice *pPhysicalDevices)380{381VK_FROM_HANDLE(panvk_instance, instance, _instance);382VK_OUTARRAY_MAKE(out, pPhysicalDevices, pPhysicalDeviceCount);383384VkResult result;385386if (instance->physical_device_count < 0) {387result = panvk_enumerate_devices(instance);388if (result != VK_SUCCESS && result != VK_ERROR_INCOMPATIBLE_DRIVER)389return result;390}391392for (uint32_t i = 0; i < instance->physical_device_count; ++i) {393vk_outarray_append(&out, p)394{395*p = panvk_physical_device_to_handle(instance->physical_devices + i);396}397}398399return vk_outarray_status(&out);400}401402VkResult403panvk_EnumeratePhysicalDeviceGroups(VkInstance _instance,404uint32_t *pPhysicalDeviceGroupCount,405VkPhysicalDeviceGroupProperties *pPhysicalDeviceGroupProperties)406{407VK_FROM_HANDLE(panvk_instance, instance, _instance);408VK_OUTARRAY_MAKE(out, pPhysicalDeviceGroupProperties,409pPhysicalDeviceGroupCount);410VkResult result;411412if (instance->physical_device_count < 0) {413result = panvk_enumerate_devices(instance);414if (result != VK_SUCCESS && result != VK_ERROR_INCOMPATIBLE_DRIVER)415return result;416}417418for (uint32_t i = 0; i < instance->physical_device_count; ++i) {419vk_outarray_append(&out, p)420{421p->physicalDeviceCount = 1;422p->physicalDevices[0] =423panvk_physical_device_to_handle(instance->physical_devices + i);424p->subsetAllocation = false;425}426}427428return VK_SUCCESS;429}430431void432panvk_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,433VkPhysicalDeviceFeatures2 *pFeatures)434{435vk_foreach_struct(ext, pFeatures->pNext)436{437switch (ext->sType) {438case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES: {439VkPhysicalDeviceVulkan11Features *features = (void *) ext;440features->storageBuffer16BitAccess = false;441features->uniformAndStorageBuffer16BitAccess = false;442features->storagePushConstant16 = false;443features->storageInputOutput16 = false;444features->multiview = false;445features->multiviewGeometryShader = false;446features->multiviewTessellationShader = false;447features->variablePointersStorageBuffer = true;448features->variablePointers = true;449features->protectedMemory = false;450features->samplerYcbcrConversion = false;451features->shaderDrawParameters = false;452break;453}454case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES: {455VkPhysicalDeviceVulkan12Features *features = (void *) ext;456features->samplerMirrorClampToEdge = false;457features->drawIndirectCount = false;458features->storageBuffer8BitAccess = false;459features->uniformAndStorageBuffer8BitAccess = false;460features->storagePushConstant8 = false;461features->shaderBufferInt64Atomics = false;462features->shaderSharedInt64Atomics = false;463features->shaderFloat16 = false;464features->shaderInt8 = false;465466features->descriptorIndexing = false;467features->shaderInputAttachmentArrayDynamicIndexing = false;468features->shaderUniformTexelBufferArrayDynamicIndexing = false;469features->shaderStorageTexelBufferArrayDynamicIndexing = false;470features->shaderUniformBufferArrayNonUniformIndexing = false;471features->shaderSampledImageArrayNonUniformIndexing = false;472features->shaderStorageBufferArrayNonUniformIndexing = false;473features->shaderStorageImageArrayNonUniformIndexing = false;474features->shaderInputAttachmentArrayNonUniformIndexing = false;475features->shaderUniformTexelBufferArrayNonUniformIndexing = false;476features->shaderStorageTexelBufferArrayNonUniformIndexing = false;477features->descriptorBindingUniformBufferUpdateAfterBind = false;478features->descriptorBindingSampledImageUpdateAfterBind = false;479features->descriptorBindingStorageImageUpdateAfterBind = false;480features->descriptorBindingStorageBufferUpdateAfterBind = false;481features->descriptorBindingUniformTexelBufferUpdateAfterBind = false;482features->descriptorBindingStorageTexelBufferUpdateAfterBind = false;483features->descriptorBindingUpdateUnusedWhilePending = false;484features->descriptorBindingPartiallyBound = false;485features->descriptorBindingVariableDescriptorCount = false;486features->runtimeDescriptorArray = false;487488features->samplerFilterMinmax = false;489features->scalarBlockLayout = false;490features->imagelessFramebuffer = false;491features->uniformBufferStandardLayout = false;492features->shaderSubgroupExtendedTypes = false;493features->separateDepthStencilLayouts = false;494features->hostQueryReset = false;495features->timelineSemaphore = false;496features->bufferDeviceAddress = false;497features->bufferDeviceAddressCaptureReplay = false;498features->bufferDeviceAddressMultiDevice = false;499features->vulkanMemoryModel = false;500features->vulkanMemoryModelDeviceScope = false;501features->vulkanMemoryModelAvailabilityVisibilityChains = false;502features->shaderOutputViewportIndex = false;503features->shaderOutputLayer = false;504features->subgroupBroadcastDynamicId = false;505break;506}507case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES: {508VkPhysicalDeviceVariablePointersFeatures *features = (void *) ext;509features->variablePointersStorageBuffer = true;510features->variablePointers = true;511break;512}513case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES: {514VkPhysicalDeviceMultiviewFeatures *features =515(VkPhysicalDeviceMultiviewFeatures *) ext;516features->multiview = false;517features->multiviewGeometryShader = false;518features->multiviewTessellationShader = false;519break;520}521case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES: {522VkPhysicalDeviceShaderDrawParametersFeatures *features =523(VkPhysicalDeviceShaderDrawParametersFeatures *) ext;524features->shaderDrawParameters = false;525break;526}527case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES: {528VkPhysicalDeviceProtectedMemoryFeatures *features =529(VkPhysicalDeviceProtectedMemoryFeatures *) ext;530features->protectedMemory = false;531break;532}533case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES: {534VkPhysicalDevice16BitStorageFeatures *features =535(VkPhysicalDevice16BitStorageFeatures *) ext;536features->storageBuffer16BitAccess = false;537features->uniformAndStorageBuffer16BitAccess = false;538features->storagePushConstant16 = false;539features->storageInputOutput16 = false;540break;541}542case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES: {543VkPhysicalDeviceSamplerYcbcrConversionFeatures *features =544(VkPhysicalDeviceSamplerYcbcrConversionFeatures *) ext;545features->samplerYcbcrConversion = false;546break;547}548case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT: {549VkPhysicalDeviceDescriptorIndexingFeaturesEXT *features =550(VkPhysicalDeviceDescriptorIndexingFeaturesEXT *) ext;551features->shaderInputAttachmentArrayDynamicIndexing = false;552features->shaderUniformTexelBufferArrayDynamicIndexing = false;553features->shaderStorageTexelBufferArrayDynamicIndexing = false;554features->shaderUniformBufferArrayNonUniformIndexing = false;555features->shaderSampledImageArrayNonUniformIndexing = false;556features->shaderStorageBufferArrayNonUniformIndexing = false;557features->shaderStorageImageArrayNonUniformIndexing = false;558features->shaderInputAttachmentArrayNonUniformIndexing = false;559features->shaderUniformTexelBufferArrayNonUniformIndexing = false;560features->shaderStorageTexelBufferArrayNonUniformIndexing = false;561features->descriptorBindingUniformBufferUpdateAfterBind = false;562features->descriptorBindingSampledImageUpdateAfterBind = false;563features->descriptorBindingStorageImageUpdateAfterBind = false;564features->descriptorBindingStorageBufferUpdateAfterBind = false;565features->descriptorBindingUniformTexelBufferUpdateAfterBind = false;566features->descriptorBindingStorageTexelBufferUpdateAfterBind = false;567features->descriptorBindingUpdateUnusedWhilePending = false;568features->descriptorBindingPartiallyBound = false;569features->descriptorBindingVariableDescriptorCount = false;570features->runtimeDescriptorArray = false;571break;572}573case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT: {574VkPhysicalDeviceConditionalRenderingFeaturesEXT *features =575(VkPhysicalDeviceConditionalRenderingFeaturesEXT *) ext;576features->conditionalRendering = false;577features->inheritedConditionalRendering = false;578break;579}580case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT: {581VkPhysicalDeviceTransformFeedbackFeaturesEXT *features =582(VkPhysicalDeviceTransformFeedbackFeaturesEXT *) ext;583features->transformFeedback = false;584features->geometryStreams = false;585break;586}587case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT: {588VkPhysicalDeviceIndexTypeUint8FeaturesEXT *features =589(VkPhysicalDeviceIndexTypeUint8FeaturesEXT *)ext;590features->indexTypeUint8 = true;591break;592}593case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: {594VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *features =595(VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *)ext;596features->vertexAttributeInstanceRateDivisor = true;597features->vertexAttributeInstanceRateZeroDivisor = true;598break;599}600case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT: {601VkPhysicalDevicePrivateDataFeaturesEXT *features =602(VkPhysicalDevicePrivateDataFeaturesEXT *)ext;603features->privateData = true;604break;605}606case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT: {607VkPhysicalDeviceDepthClipEnableFeaturesEXT *features =608(VkPhysicalDeviceDepthClipEnableFeaturesEXT *)ext;609features->depthClipEnable = true;610break;611}612case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT: {613VkPhysicalDevice4444FormatsFeaturesEXT *features = (void *)ext;614features->formatA4R4G4B4 = true;615features->formatA4B4G4R4 = true;616break;617}618case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT: {619VkPhysicalDeviceCustomBorderColorFeaturesEXT *features = (void *) ext;620features->customBorderColors = true;621features->customBorderColorWithoutFormat = true;622break;623}624default:625break;626}627}628629pFeatures->features = (VkPhysicalDeviceFeatures) {630.fullDrawIndexUint32 = true,631.independentBlend = true,632.wideLines = true,633.largePoints = true,634.textureCompressionETC2 = true,635.textureCompressionASTC_LDR = true,636.shaderUniformBufferArrayDynamicIndexing = true,637.shaderSampledImageArrayDynamicIndexing = true,638.shaderStorageBufferArrayDynamicIndexing = true,639.shaderStorageImageArrayDynamicIndexing = true,640};641}642643void644panvk_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,645VkPhysicalDeviceProperties2 *pProperties)646{647VK_FROM_HANDLE(panvk_physical_device, pdevice, physicalDevice);648649vk_foreach_struct(ext, pProperties->pNext)650{651switch (ext->sType) {652case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: {653VkPhysicalDevicePushDescriptorPropertiesKHR *properties = (VkPhysicalDevicePushDescriptorPropertiesKHR *)ext;654properties->maxPushDescriptors = MAX_PUSH_DESCRIPTORS;655break;656}657case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES: {658VkPhysicalDeviceIDProperties *properties = (VkPhysicalDeviceIDProperties *)ext;659memcpy(properties->driverUUID, pdevice->driver_uuid, VK_UUID_SIZE);660memcpy(properties->deviceUUID, pdevice->device_uuid, VK_UUID_SIZE);661properties->deviceLUIDValid = false;662break;663}664case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES: {665VkPhysicalDeviceMultiviewProperties *properties = (VkPhysicalDeviceMultiviewProperties *)ext;666properties->maxMultiviewViewCount = 0;667properties->maxMultiviewInstanceIndex = 0;668break;669}670case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES: {671VkPhysicalDevicePointClippingProperties *properties = (VkPhysicalDevicePointClippingProperties *)ext;672properties->pointClippingBehavior =673VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES;674break;675}676case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES: {677VkPhysicalDeviceMaintenance3Properties *properties = (VkPhysicalDeviceMaintenance3Properties *)ext;678/* Make sure everything is addressable by a signed 32-bit int, and679* our largest descriptors are 96 bytes. */680properties->maxPerSetDescriptors = (1ull << 31) / 96;681/* Our buffer size fields allow only this much */682properties->maxMemoryAllocationSize = 0xFFFFFFFFull;683break;684}685default:686break;687}688}689690VkSampleCountFlags sample_counts = 0xf;691692/* make sure that the entire descriptor set is addressable with a signed693* 32-bit int. So the sum of all limits scaled by descriptor size has to694* be at most 2 GiB. the combined image & samples object count as one of695* both. This limit is for the pipeline layout, not for the set layout, but696* there is no set limit, so we just set a pipeline limit. I don't think697* any app is going to hit this soon. */698size_t max_descriptor_set_size =699((1ull << 31) - 16 * MAX_DYNAMIC_BUFFERS) /700(32 /* uniform buffer, 32 due to potential space wasted on alignment */ +70132 /* storage buffer, 32 due to potential space wasted on alignment */ +70232 /* sampler, largest when combined with image */ +70364 /* sampled image */ + 64 /* storage image */);704705VkPhysicalDeviceLimits limits = {706.maxImageDimension1D = (1 << 14),707.maxImageDimension2D = (1 << 14),708.maxImageDimension3D = (1 << 11),709.maxImageDimensionCube = (1 << 14),710.maxImageArrayLayers = (1 << 11),711.maxTexelBufferElements = 128 * 1024 * 1024,712.maxUniformBufferRange = UINT32_MAX,713.maxStorageBufferRange = UINT32_MAX,714.maxPushConstantsSize = MAX_PUSH_CONSTANTS_SIZE,715.maxMemoryAllocationCount = UINT32_MAX,716.maxSamplerAllocationCount = 64 * 1024,717.bufferImageGranularity = 64, /* A cache line */718.sparseAddressSpaceSize = 0xffffffffu, /* buffer max size */719.maxBoundDescriptorSets = MAX_SETS,720.maxPerStageDescriptorSamplers = max_descriptor_set_size,721.maxPerStageDescriptorUniformBuffers = max_descriptor_set_size,722.maxPerStageDescriptorStorageBuffers = max_descriptor_set_size,723.maxPerStageDescriptorSampledImages = max_descriptor_set_size,724.maxPerStageDescriptorStorageImages = max_descriptor_set_size,725.maxPerStageDescriptorInputAttachments = max_descriptor_set_size,726.maxPerStageResources = max_descriptor_set_size,727.maxDescriptorSetSamplers = max_descriptor_set_size,728.maxDescriptorSetUniformBuffers = max_descriptor_set_size,729.maxDescriptorSetUniformBuffersDynamic = MAX_DYNAMIC_UNIFORM_BUFFERS,730.maxDescriptorSetStorageBuffers = max_descriptor_set_size,731.maxDescriptorSetStorageBuffersDynamic = MAX_DYNAMIC_STORAGE_BUFFERS,732.maxDescriptorSetSampledImages = max_descriptor_set_size,733.maxDescriptorSetStorageImages = max_descriptor_set_size,734.maxDescriptorSetInputAttachments = max_descriptor_set_size,735.maxVertexInputAttributes = 32,736.maxVertexInputBindings = 32,737.maxVertexInputAttributeOffset = 2047,738.maxVertexInputBindingStride = 2048,739.maxVertexOutputComponents = 128,740.maxTessellationGenerationLevel = 64,741.maxTessellationPatchSize = 32,742.maxTessellationControlPerVertexInputComponents = 128,743.maxTessellationControlPerVertexOutputComponents = 128,744.maxTessellationControlPerPatchOutputComponents = 120,745.maxTessellationControlTotalOutputComponents = 4096,746.maxTessellationEvaluationInputComponents = 128,747.maxTessellationEvaluationOutputComponents = 128,748.maxGeometryShaderInvocations = 127,749.maxGeometryInputComponents = 64,750.maxGeometryOutputComponents = 128,751.maxGeometryOutputVertices = 256,752.maxGeometryTotalOutputComponents = 1024,753.maxFragmentInputComponents = 128,754.maxFragmentOutputAttachments = 8,755.maxFragmentDualSrcAttachments = 1,756.maxFragmentCombinedOutputResources = 8,757.maxComputeSharedMemorySize = 32768,758.maxComputeWorkGroupCount = { 65535, 65535, 65535 },759.maxComputeWorkGroupInvocations = 2048,760.maxComputeWorkGroupSize = { 2048, 2048, 2048 },761.subPixelPrecisionBits = 4 /* FIXME */,762.subTexelPrecisionBits = 4 /* FIXME */,763.mipmapPrecisionBits = 4 /* FIXME */,764.maxDrawIndexedIndexValue = UINT32_MAX,765.maxDrawIndirectCount = UINT32_MAX,766.maxSamplerLodBias = 16,767.maxSamplerAnisotropy = 16,768.maxViewports = MAX_VIEWPORTS,769.maxViewportDimensions = { (1 << 14), (1 << 14) },770.viewportBoundsRange = { INT16_MIN, INT16_MAX },771.viewportSubPixelBits = 8,772.minMemoryMapAlignment = 4096, /* A page */773.minTexelBufferOffsetAlignment = 1,774.minUniformBufferOffsetAlignment = 4,775.minStorageBufferOffsetAlignment = 4,776.minTexelOffset = -32,777.maxTexelOffset = 31,778.minTexelGatherOffset = -32,779.maxTexelGatherOffset = 31,780.minInterpolationOffset = -2,781.maxInterpolationOffset = 2,782.subPixelInterpolationOffsetBits = 8,783.maxFramebufferWidth = (1 << 14),784.maxFramebufferHeight = (1 << 14),785.maxFramebufferLayers = (1 << 10),786.framebufferColorSampleCounts = sample_counts,787.framebufferDepthSampleCounts = sample_counts,788.framebufferStencilSampleCounts = sample_counts,789.framebufferNoAttachmentsSampleCounts = sample_counts,790.maxColorAttachments = MAX_RTS,791.sampledImageColorSampleCounts = sample_counts,792.sampledImageIntegerSampleCounts = VK_SAMPLE_COUNT_1_BIT,793.sampledImageDepthSampleCounts = sample_counts,794.sampledImageStencilSampleCounts = sample_counts,795.storageImageSampleCounts = VK_SAMPLE_COUNT_1_BIT,796.maxSampleMaskWords = 1,797.timestampComputeAndGraphics = true,798.timestampPeriod = 1,799.maxClipDistances = 8,800.maxCullDistances = 8,801.maxCombinedClipAndCullDistances = 8,802.discreteQueuePriorities = 1,803.pointSizeRange = { 0.125, 255.875 },804.lineWidthRange = { 0.0, 7.9921875 },805.pointSizeGranularity = (1.0 / 8.0),806.lineWidthGranularity = (1.0 / 128.0),807.strictLines = false, /* FINISHME */808.standardSampleLocations = true,809.optimalBufferCopyOffsetAlignment = 128,810.optimalBufferCopyRowPitchAlignment = 128,811.nonCoherentAtomSize = 64,812};813814pProperties->properties = (VkPhysicalDeviceProperties) {815.apiVersion = PANVK_API_VERSION,816.driverVersion = vk_get_driver_version(),817.vendorID = 0, /* TODO */818.deviceID = 0,819.deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,820.limits = limits,821.sparseProperties = { 0 },822};823824strcpy(pProperties->properties.deviceName, pdevice->name);825memcpy(pProperties->properties.pipelineCacheUUID, pdevice->cache_uuid, VK_UUID_SIZE);826}827828static const VkQueueFamilyProperties panvk_queue_family_properties = {829.queueFlags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT,830.queueCount = 1,831.timestampValidBits = 64,832.minImageTransferGranularity = { 1, 1, 1 },833};834835void836panvk_GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,837uint32_t *pQueueFamilyPropertyCount,838VkQueueFamilyProperties *pQueueFamilyProperties)839{840VK_OUTARRAY_MAKE(out, pQueueFamilyProperties, pQueueFamilyPropertyCount);841842vk_outarray_append(&out, p) { *p = panvk_queue_family_properties; }843}844845void846panvk_GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice,847uint32_t *pQueueFamilyPropertyCount,848VkQueueFamilyProperties2 *pQueueFamilyProperties)849{850VK_OUTARRAY_MAKE(out, pQueueFamilyProperties, pQueueFamilyPropertyCount);851852vk_outarray_append(&out, p)853{854p->queueFamilyProperties = panvk_queue_family_properties;855}856}857858static uint64_t859panvk_get_system_heap_size()860{861struct sysinfo info;862sysinfo(&info);863864uint64_t total_ram = (uint64_t)info.totalram * info.mem_unit;865866/* We don't want to burn too much ram with the GPU. If the user has 4GiB867* or less, we use at most half. If they have more than 4GiB, we use 3/4.868*/869uint64_t available_ram;870if (total_ram <= 4ull * 1024 * 1024 * 1024)871available_ram = total_ram / 2;872else873available_ram = total_ram * 3 / 4;874875return available_ram;876}877878void879panvk_GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice,880VkPhysicalDeviceMemoryProperties2 *pMemoryProperties)881{882pMemoryProperties->memoryProperties = (VkPhysicalDeviceMemoryProperties) {883.memoryHeapCount = 1,884.memoryHeaps[0].size = panvk_get_system_heap_size(),885.memoryHeaps[0].flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,886.memoryTypeCount = 1,887.memoryTypes[0].propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |888VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |889VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,890.memoryTypes[0].heapIndex = 0,891};892}893894static VkResult895panvk_queue_init(struct panvk_device *device,896struct panvk_queue *queue,897uint32_t queue_family_index,898int idx,899VkDeviceQueueCreateFlags flags)900{901const struct panfrost_device *pdev = &device->physical_device->pdev;902903vk_object_base_init(&device->vk, &queue->base, VK_OBJECT_TYPE_QUEUE);904queue->device = device;905queue->queue_family_index = queue_family_index;906queue->flags = flags;907908struct drm_syncobj_create create = {909.flags = DRM_SYNCOBJ_CREATE_SIGNALED,910};911912int ret = drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_CREATE, &create);913if (ret)914return VK_ERROR_OUT_OF_HOST_MEMORY;915916queue->sync = create.handle;917return VK_SUCCESS;918}919920static void921panvk_queue_finish(struct panvk_queue *queue)922{923}924925VkResult926panvk_CreateDevice(VkPhysicalDevice physicalDevice,927const VkDeviceCreateInfo *pCreateInfo,928const VkAllocationCallbacks *pAllocator,929VkDevice *pDevice)930{931VK_FROM_HANDLE(panvk_physical_device, physical_device, physicalDevice);932VkResult result;933struct panvk_device *device;934935/* Check enabled features */936if (pCreateInfo->pEnabledFeatures) {937VkPhysicalDeviceFeatures2 supported_features = {938.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,939};940panvk_GetPhysicalDeviceFeatures2(physicalDevice, &supported_features);941VkBool32 *supported_feature = (VkBool32 *) &supported_features.features;942VkBool32 *enabled_feature = (VkBool32 *) pCreateInfo->pEnabledFeatures;943unsigned num_features =944sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);945for (uint32_t i = 0; i < num_features; i++) {946if (enabled_feature[i] && !supported_feature[i])947return vk_error(physical_device->instance,948VK_ERROR_FEATURE_NOT_PRESENT);949}950}951952device = vk_zalloc2(&physical_device->instance->vk.alloc, pAllocator,953sizeof(*device), 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);954if (!device)955return vk_error(physical_device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);956957struct vk_device_dispatch_table dispatch_table;958vk_device_dispatch_table_from_entrypoints(&dispatch_table,959&panvk_device_entrypoints,960true);961result = vk_device_init(&device->vk, &physical_device->vk, &dispatch_table,962pCreateInfo, pAllocator);963if (result != VK_SUCCESS) {964vk_free(&device->vk.alloc, device);965return vk_errorf(physical_device->instance, result, "vk_device_init failed");966}967968device->instance = physical_device->instance;969device->physical_device = physical_device;970971for (unsigned i = 0; i < pCreateInfo->queueCreateInfoCount; i++) {972const VkDeviceQueueCreateInfo *queue_create =973&pCreateInfo->pQueueCreateInfos[i];974uint32_t qfi = queue_create->queueFamilyIndex;975device->queues[qfi] =976vk_alloc(&device->vk.alloc,977queue_create->queueCount * sizeof(struct panvk_queue),9788, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);979if (!device->queues[qfi]) {980result = VK_ERROR_OUT_OF_HOST_MEMORY;981goto fail;982}983984memset(device->queues[qfi], 0,985queue_create->queueCount * sizeof(struct panvk_queue));986987device->queue_count[qfi] = queue_create->queueCount;988989for (unsigned q = 0; q < queue_create->queueCount; q++) {990result = panvk_queue_init(device, &device->queues[qfi][q], qfi, q,991queue_create->flags);992if (result != VK_SUCCESS)993goto fail;994}995}996997*pDevice = panvk_device_to_handle(device);998return VK_SUCCESS;9991000fail:1001for (unsigned i = 0; i < PANVK_MAX_QUEUE_FAMILIES; i++) {1002for (unsigned q = 0; q < device->queue_count[i]; q++)1003panvk_queue_finish(&device->queues[i][q]);1004if (device->queue_count[i])1005vk_object_free(&device->vk, NULL, device->queues[i]);1006}10071008vk_free(&device->vk.alloc, device);1009return result;1010}10111012void1013panvk_DestroyDevice(VkDevice _device, const VkAllocationCallbacks *pAllocator)1014{1015VK_FROM_HANDLE(panvk_device, device, _device);10161017if (!device)1018return;10191020for (unsigned i = 0; i < PANVK_MAX_QUEUE_FAMILIES; i++) {1021for (unsigned q = 0; q < device->queue_count[i]; q++)1022panvk_queue_finish(&device->queues[i][q]);1023if (device->queue_count[i])1024vk_object_free(&device->vk, NULL, device->queues[i]);1025}10261027vk_free(&device->vk.alloc, device);1028}10291030VkResult1031panvk_EnumerateInstanceLayerProperties(uint32_t *pPropertyCount,1032VkLayerProperties *pProperties)1033{1034*pPropertyCount = 0;1035return VK_SUCCESS;1036}10371038void1039panvk_GetDeviceQueue2(VkDevice _device,1040const VkDeviceQueueInfo2 *pQueueInfo,1041VkQueue *pQueue)1042{1043VK_FROM_HANDLE(panvk_device, device, _device);1044struct panvk_queue *queue;10451046queue = &device->queues[pQueueInfo->queueFamilyIndex][pQueueInfo->queueIndex];1047if (pQueueInfo->flags != queue->flags) {1048/* From the Vulkan 1.1.70 spec:1049*1050* "The queue returned by vkGetDeviceQueue2 must have the same1051* flags value from this structure as that used at device1052* creation time in a VkDeviceQueueCreateInfo instance. If no1053* matching flags were specified at device creation time then1054* pQueue will return VK_NULL_HANDLE."1055*/1056*pQueue = VK_NULL_HANDLE;1057return;1058}10591060*pQueue = panvk_queue_to_handle(queue);1061}10621063void1064panvk_GetDeviceQueue(VkDevice _device,1065uint32_t queueFamilyIndex,1066uint32_t queueIndex,1067VkQueue *pQueue)1068{1069const VkDeviceQueueInfo2 info = (VkDeviceQueueInfo2) {1070.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2,1071.queueFamilyIndex = queueFamilyIndex,1072.queueIndex = queueIndex1073};10741075panvk_GetDeviceQueue2(_device, &info, pQueue);1076}10771078static void1079panvk_queue_submit_batch(struct panvk_queue *queue,1080struct panvk_batch *batch,1081uint32_t *bos, unsigned nr_bos,1082uint32_t *in_fences,1083unsigned nr_in_fences)1084{1085const struct panvk_device *dev = queue->device;1086unsigned debug = dev->physical_device->instance->debug_flags;1087const struct panfrost_device *pdev = &dev->physical_device->pdev;1088int ret;10891090/* Reset the batch if it's already been issued */1091if (batch->issued) {1092util_dynarray_foreach(&batch->jobs, void *, job)1093memset((*job), 0, 4 * 4);10941095/* Reset the tiler before re-issuing the batch */1096if (pan_is_bifrost(pdev) && batch->tiler.bifrost_descs.cpu) {1097memcpy(batch->tiler.bifrost_descs.cpu, &batch->tiler.templ.bifrost,1098sizeof(batch->tiler.templ.bifrost));1099} else if (!pan_is_bifrost(pdev) && batch->fb.desc.cpu) {1100void *tiler = pan_section_ptr(batch->fb.desc.cpu, MULTI_TARGET_FRAMEBUFFER, TILER);1101memcpy(tiler, &batch->tiler.templ.midgard, sizeof(batch->tiler.templ.midgard));1102/* All weights set to 0, nothing to do here */1103pan_section_pack(batch->fb.desc.cpu, MULTI_TARGET_FRAMEBUFFER, TILER_WEIGHTS, w);1104}1105}11061107if (batch->scoreboard.first_job) {1108struct drm_panfrost_submit submit = {1109.bo_handles = (uintptr_t)bos,1110.bo_handle_count = nr_bos,1111.in_syncs = (uintptr_t)in_fences,1112.in_sync_count = nr_in_fences,1113.out_sync = queue->sync,1114.jc = batch->scoreboard.first_job,1115};11161117ret = drmIoctl(pdev->fd, DRM_IOCTL_PANFROST_SUBMIT, &submit);1118assert(!ret);11191120if (debug & (PANVK_DEBUG_TRACE | PANVK_DEBUG_SYNC)) {1121ret = drmSyncobjWait(pdev->fd, &submit.out_sync, 1, INT64_MAX, 0, NULL);1122assert(!ret);1123}11241125if (debug & PANVK_DEBUG_TRACE)1126pandecode_jc(batch->scoreboard.first_job, pan_is_bifrost(pdev), pdev->gpu_id);1127}11281129if (batch->fragment_job) {1130struct drm_panfrost_submit submit = {1131.bo_handles = (uintptr_t)bos,1132.bo_handle_count = nr_bos,1133.out_sync = queue->sync,1134.jc = batch->fragment_job,1135.requirements = PANFROST_JD_REQ_FS,1136};11371138if (batch->scoreboard.first_job) {1139submit.in_syncs = (uintptr_t)(&queue->sync);1140submit.in_sync_count = 1;1141} else {1142submit.in_syncs = (uintptr_t)in_fences;1143submit.in_sync_count = nr_in_fences;1144}11451146ret = drmIoctl(pdev->fd, DRM_IOCTL_PANFROST_SUBMIT, &submit);1147assert(!ret);1148if (debug & (PANVK_DEBUG_TRACE | PANVK_DEBUG_SYNC)) {1149ret = drmSyncobjWait(pdev->fd, &submit.out_sync, 1, INT64_MAX, 0, NULL);1150assert(!ret);1151}11521153if (debug & PANVK_DEBUG_TRACE)1154pandecode_jc(batch->fragment_job, pan_is_bifrost(pdev), pdev->gpu_id);1155}11561157if (debug & PANVK_DEBUG_TRACE)1158pandecode_next_frame();11591160batch->issued = true;1161}11621163static void1164panvk_queue_transfer_sync(struct panvk_queue *queue, uint32_t syncobj)1165{1166const struct panfrost_device *pdev = &queue->device->physical_device->pdev;1167int ret;11681169struct drm_syncobj_handle handle = {1170.handle = queue->sync,1171.flags = DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE,1172.fd = -1,1173};11741175ret = drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &handle);1176assert(!ret);1177assert(handle.fd >= 0);11781179handle.handle = syncobj;1180ret = drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, &handle);1181assert(!ret);11821183close(handle.fd);1184}11851186static void1187panvk_add_wait_event_syncobjs(struct panvk_batch *batch, uint32_t *in_fences, unsigned *nr_in_fences)1188{1189util_dynarray_foreach(&batch->event_ops, struct panvk_event_op, op) {1190switch (op->type) {1191case PANVK_EVENT_OP_SET:1192/* Nothing to do yet */1193break;1194case PANVK_EVENT_OP_RESET:1195/* Nothing to do yet */1196break;1197case PANVK_EVENT_OP_WAIT:1198in_fences[*nr_in_fences++] = op->event->syncobj;1199break;1200default:1201unreachable("bad panvk_event_op type\n");1202}1203}1204}12051206static void1207panvk_signal_event_syncobjs(struct panvk_queue *queue, struct panvk_batch *batch)1208{1209const struct panfrost_device *pdev = &queue->device->physical_device->pdev;12101211util_dynarray_foreach(&batch->event_ops, struct panvk_event_op, op) {1212switch (op->type) {1213case PANVK_EVENT_OP_SET: {1214panvk_queue_transfer_sync(queue, op->event->syncobj);1215break;1216}1217case PANVK_EVENT_OP_RESET: {1218struct panvk_event *event = op->event;12191220struct drm_syncobj_array objs = {1221.handles = (uint64_t) (uintptr_t) &event->syncobj,1222.count_handles = 11223};12241225int ret = drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_RESET, &objs);1226assert(!ret);1227break;1228}1229case PANVK_EVENT_OP_WAIT:1230/* Nothing left to do */1231break;1232default:1233unreachable("bad panvk_event_op type\n");1234}1235}1236}12371238VkResult1239panvk_QueueSubmit(VkQueue _queue,1240uint32_t submitCount,1241const VkSubmitInfo *pSubmits,1242VkFence _fence)1243{1244VK_FROM_HANDLE(panvk_queue, queue, _queue);1245VK_FROM_HANDLE(panvk_fence, fence, _fence);1246const struct panfrost_device *pdev = &queue->device->physical_device->pdev;12471248for (uint32_t i = 0; i < submitCount; ++i) {1249const VkSubmitInfo *submit = pSubmits + i;1250unsigned nr_semaphores = submit->waitSemaphoreCount + 1;1251uint32_t semaphores[nr_semaphores];12521253semaphores[0] = queue->sync;1254for (unsigned i = 0; i < submit->waitSemaphoreCount; i++) {1255VK_FROM_HANDLE(panvk_semaphore, sem, submit->pWaitSemaphores[i]);12561257semaphores[i + 1] = sem->syncobj.temporary ? : sem->syncobj.permanent;1258}12591260for (uint32_t j = 0; j < submit->commandBufferCount; ++j) {1261VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, (submit->pCommandBuffers[j]));12621263list_for_each_entry(struct panvk_batch, batch, &cmdbuf->batches, node) {1264/* FIXME: should be done at the batch level */1265unsigned nr_bos =1266panvk_pool_num_bos(&cmdbuf->desc_pool) +1267panvk_pool_num_bos(&cmdbuf->varying_pool) +1268panvk_pool_num_bos(&cmdbuf->tls_pool) +1269(batch->fb.info ? batch->fb.info->attachment_count : 0) +1270(batch->blit.src ? 1 : 0) +1271(batch->blit.dst ? 1 : 0) +1272(batch->scoreboard.first_tiler ? 1 : 0) + 1;1273unsigned bo_idx = 0;1274uint32_t bos[nr_bos];12751276panvk_pool_get_bo_handles(&cmdbuf->desc_pool, &bos[bo_idx]);1277bo_idx += panvk_pool_num_bos(&cmdbuf->desc_pool);12781279panvk_pool_get_bo_handles(&cmdbuf->varying_pool, &bos[bo_idx]);1280bo_idx += panvk_pool_num_bos(&cmdbuf->varying_pool);12811282panvk_pool_get_bo_handles(&cmdbuf->tls_pool, &bos[bo_idx]);1283bo_idx += panvk_pool_num_bos(&cmdbuf->tls_pool);12841285if (batch->fb.info) {1286for (unsigned i = 0; i < batch->fb.info->attachment_count; i++) {1287bos[bo_idx++] = batch->fb.info->attachments[i].iview->pview.image->data.bo->gem_handle;1288}1289}12901291if (batch->blit.src)1292bos[bo_idx++] = batch->blit.src->gem_handle;12931294if (batch->blit.dst)1295bos[bo_idx++] = batch->blit.dst->gem_handle;12961297if (batch->scoreboard.first_tiler)1298bos[bo_idx++] = pdev->tiler_heap->gem_handle;12991300bos[bo_idx++] = pdev->sample_positions->gem_handle;1301assert(bo_idx == nr_bos);13021303unsigned nr_in_fences = 0;1304unsigned max_wait_event_syncobjs =1305util_dynarray_num_elements(&batch->event_ops,1306struct panvk_event_op);1307uint32_t in_fences[nr_semaphores + max_wait_event_syncobjs];1308memcpy(in_fences, semaphores, nr_semaphores * sizeof(*in_fences));1309nr_in_fences += nr_semaphores;13101311panvk_add_wait_event_syncobjs(batch, in_fences, &nr_in_fences);13121313panvk_queue_submit_batch(queue, batch, bos, nr_bos, in_fences, nr_in_fences);13141315panvk_signal_event_syncobjs(queue, batch);1316}1317}13181319/* Transfer the out fence to signal semaphores */1320for (unsigned i = 0; i < submit->signalSemaphoreCount; i++) {1321VK_FROM_HANDLE(panvk_semaphore, sem, submit->pSignalSemaphores[i]);1322panvk_queue_transfer_sync(queue, sem->syncobj.temporary ? : sem->syncobj.permanent);1323}1324}13251326if (fence) {1327/* Transfer the last out fence to the fence object */1328panvk_queue_transfer_sync(queue, fence->syncobj.temporary ? : fence->syncobj.permanent);1329}13301331return VK_SUCCESS;1332}13331334VkResult1335panvk_QueueWaitIdle(VkQueue _queue)1336{1337VK_FROM_HANDLE(panvk_queue, queue, _queue);13381339if (panvk_device_is_lost(queue->device))1340return VK_ERROR_DEVICE_LOST;13411342const struct panfrost_device *pdev = &queue->device->physical_device->pdev;1343struct drm_syncobj_wait wait = {1344.handles = (uint64_t) (uintptr_t)(&queue->sync),1345.count_handles = 1,1346.timeout_nsec = INT64_MAX,1347.flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL,1348};1349int ret;13501351ret = drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_WAIT, &wait);1352assert(!ret);13531354return VK_SUCCESS;1355}13561357VkResult1358panvk_DeviceWaitIdle(VkDevice _device)1359{1360VK_FROM_HANDLE(panvk_device, device, _device);13611362if (panvk_device_is_lost(device))1363return VK_ERROR_DEVICE_LOST;13641365for (unsigned i = 0; i < PANVK_MAX_QUEUE_FAMILIES; i++) {1366for (unsigned q = 0; q < device->queue_count[i]; q++) {1367panvk_QueueWaitIdle(panvk_queue_to_handle(&device->queues[i][q]));1368}1369}1370return VK_SUCCESS;1371}13721373VkResult1374panvk_EnumerateInstanceExtensionProperties(const char *pLayerName,1375uint32_t *pPropertyCount,1376VkExtensionProperties *pProperties)1377{1378if (pLayerName)1379return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);13801381return vk_enumerate_instance_extension_properties(&panvk_instance_extensions,1382pPropertyCount, pProperties);1383}13841385PFN_vkVoidFunction1386panvk_GetInstanceProcAddr(VkInstance _instance, const char *pName)1387{1388VK_FROM_HANDLE(panvk_instance, instance, _instance);1389return vk_instance_get_proc_addr(&instance->vk,1390&panvk_instance_entrypoints,1391pName);1392}13931394/* The loader wants us to expose a second GetInstanceProcAddr function1395* to work around certain LD_PRELOAD issues seen in apps.1396*/1397PUBLIC1398VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL1399vk_icdGetInstanceProcAddr(VkInstance instance, const char *pName);14001401PUBLIC1402VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL1403vk_icdGetInstanceProcAddr(VkInstance instance, const char *pName)1404{1405return panvk_GetInstanceProcAddr(instance, pName);1406}14071408VkResult1409panvk_AllocateMemory(VkDevice _device,1410const VkMemoryAllocateInfo *pAllocateInfo,1411const VkAllocationCallbacks *pAllocator,1412VkDeviceMemory *pMem)1413{1414VK_FROM_HANDLE(panvk_device, device, _device);1415struct panvk_device_memory *mem;14161417assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);14181419if (pAllocateInfo->allocationSize == 0) {1420/* Apparently, this is allowed */1421*pMem = VK_NULL_HANDLE;1422return VK_SUCCESS;1423}14241425mem = vk_object_alloc(&device->vk, pAllocator, sizeof(*mem),1426VK_OBJECT_TYPE_DEVICE_MEMORY);1427if (mem == NULL)1428return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);14291430const VkImportMemoryFdInfoKHR *fd_info =1431vk_find_struct_const(pAllocateInfo->pNext,1432IMPORT_MEMORY_FD_INFO_KHR);14331434if (fd_info && !fd_info->handleType)1435fd_info = NULL;14361437if (fd_info) {1438assert(fd_info->handleType ==1439VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||1440fd_info->handleType ==1441VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);14421443/*1444* TODO Importing the same fd twice gives us the same handle without1445* reference counting. We need to maintain a per-instance handle-to-bo1446* table and add reference count to panvk_bo.1447*/1448mem->bo = panfrost_bo_import(&device->physical_device->pdev, fd_info->fd);1449/* take ownership and close the fd */1450close(fd_info->fd);1451} else {1452mem->bo = panfrost_bo_create(&device->physical_device->pdev,1453pAllocateInfo->allocationSize, 0,1454"User-requested memory");1455}14561457assert(mem->bo);14581459*pMem = panvk_device_memory_to_handle(mem);14601461return VK_SUCCESS;1462}14631464void1465panvk_FreeMemory(VkDevice _device,1466VkDeviceMemory _mem,1467const VkAllocationCallbacks *pAllocator)1468{1469VK_FROM_HANDLE(panvk_device, device, _device);1470VK_FROM_HANDLE(panvk_device_memory, mem, _mem);14711472if (mem == NULL)1473return;14741475panfrost_bo_unreference(mem->bo);1476vk_object_free(&device->vk, pAllocator, mem);1477}14781479VkResult1480panvk_MapMemory(VkDevice _device,1481VkDeviceMemory _memory,1482VkDeviceSize offset,1483VkDeviceSize size,1484VkMemoryMapFlags flags,1485void **ppData)1486{1487VK_FROM_HANDLE(panvk_device, device, _device);1488VK_FROM_HANDLE(panvk_device_memory, mem, _memory);14891490if (mem == NULL) {1491*ppData = NULL;1492return VK_SUCCESS;1493}14941495if (!mem->bo->ptr.cpu)1496panfrost_bo_mmap(mem->bo);14971498*ppData = mem->bo->ptr.cpu;14991500if (*ppData) {1501*ppData += offset;1502return VK_SUCCESS;1503}15041505return vk_error(device->instance, VK_ERROR_MEMORY_MAP_FAILED);1506}15071508void1509panvk_UnmapMemory(VkDevice _device, VkDeviceMemory _memory)1510{1511}15121513VkResult1514panvk_FlushMappedMemoryRanges(VkDevice _device,1515uint32_t memoryRangeCount,1516const VkMappedMemoryRange *pMemoryRanges)1517{1518return VK_SUCCESS;1519}15201521VkResult1522panvk_InvalidateMappedMemoryRanges(VkDevice _device,1523uint32_t memoryRangeCount,1524const VkMappedMemoryRange *pMemoryRanges)1525{1526return VK_SUCCESS;1527}15281529void1530panvk_GetBufferMemoryRequirements(VkDevice _device,1531VkBuffer _buffer,1532VkMemoryRequirements *pMemoryRequirements)1533{1534VK_FROM_HANDLE(panvk_buffer, buffer, _buffer);15351536pMemoryRequirements->memoryTypeBits = 1;1537pMemoryRequirements->alignment = 64;1538pMemoryRequirements->size =1539align64(buffer->size, pMemoryRequirements->alignment);1540}15411542void1543panvk_GetBufferMemoryRequirements2(VkDevice device,1544const VkBufferMemoryRequirementsInfo2 *pInfo,1545VkMemoryRequirements2 *pMemoryRequirements)1546{1547panvk_GetBufferMemoryRequirements(device, pInfo->buffer,1548&pMemoryRequirements->memoryRequirements);1549}15501551void1552panvk_GetImageMemoryRequirements(VkDevice _device,1553VkImage _image,1554VkMemoryRequirements *pMemoryRequirements)1555{1556VK_FROM_HANDLE(panvk_image, image, _image);15571558pMemoryRequirements->memoryTypeBits = 1;1559pMemoryRequirements->size = panvk_image_get_total_size(image);1560pMemoryRequirements->alignment = 4096;1561}15621563void1564panvk_GetImageMemoryRequirements2(VkDevice device,1565const VkImageMemoryRequirementsInfo2 *pInfo,1566VkMemoryRequirements2 *pMemoryRequirements)1567{1568panvk_GetImageMemoryRequirements(device, pInfo->image,1569&pMemoryRequirements->memoryRequirements);1570}15711572void1573panvk_GetImageSparseMemoryRequirements(VkDevice device, VkImage image,1574uint32_t *pSparseMemoryRequirementCount,1575VkSparseImageMemoryRequirements *pSparseMemoryRequirements)1576{1577panvk_stub();1578}15791580void1581panvk_GetImageSparseMemoryRequirements2(VkDevice device,1582const VkImageSparseMemoryRequirementsInfo2 *pInfo,1583uint32_t *pSparseMemoryRequirementCount,1584VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)1585{1586panvk_stub();1587}15881589void1590panvk_GetDeviceMemoryCommitment(VkDevice device,1591VkDeviceMemory memory,1592VkDeviceSize *pCommittedMemoryInBytes)1593{1594*pCommittedMemoryInBytes = 0;1595}15961597VkResult1598panvk_BindBufferMemory2(VkDevice device,1599uint32_t bindInfoCount,1600const VkBindBufferMemoryInfo *pBindInfos)1601{1602for (uint32_t i = 0; i < bindInfoCount; ++i) {1603VK_FROM_HANDLE(panvk_device_memory, mem, pBindInfos[i].memory);1604VK_FROM_HANDLE(panvk_buffer, buffer, pBindInfos[i].buffer);16051606if (mem) {1607buffer->bo = mem->bo;1608buffer->bo_offset = pBindInfos[i].memoryOffset;1609} else {1610buffer->bo = NULL;1611}1612}1613return VK_SUCCESS;1614}16151616VkResult1617panvk_BindBufferMemory(VkDevice device,1618VkBuffer buffer,1619VkDeviceMemory memory,1620VkDeviceSize memoryOffset)1621{1622const VkBindBufferMemoryInfo info = {1623.sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,1624.buffer = buffer,1625.memory = memory,1626.memoryOffset = memoryOffset1627};16281629return panvk_BindBufferMemory2(device, 1, &info);1630}16311632VkResult1633panvk_BindImageMemory2(VkDevice device,1634uint32_t bindInfoCount,1635const VkBindImageMemoryInfo *pBindInfos)1636{1637for (uint32_t i = 0; i < bindInfoCount; ++i) {1638VK_FROM_HANDLE(panvk_image, image, pBindInfos[i].image);1639VK_FROM_HANDLE(panvk_device_memory, mem, pBindInfos[i].memory);16401641if (mem) {1642panfrost_bo_reference(mem->bo);1643image->pimage.data.bo = mem->bo;1644image->pimage.data.offset = pBindInfos[i].memoryOffset;1645/* Reset the AFBC headers */1646if (drm_is_afbc(image->pimage.layout.modifier)) {1647void *base = image->pimage.data.bo->ptr.cpu + image->pimage.data.offset;16481649for (unsigned layer = 0; layer < image->pimage.layout.array_size; layer++) {1650for (unsigned level = 0; level < image->pimage.layout.nr_slices; level++) {1651void *header = base +1652(layer * image->pimage.layout.array_stride) +1653image->pimage.layout.slices[level].offset;1654memset(header, 0, image->pimage.layout.slices[level].afbc.header_size);1655}1656}1657}1658} else {1659panfrost_bo_unreference(image->pimage.data.bo);1660image->pimage.data.bo = NULL;1661image->pimage.data.offset = pBindInfos[i].memoryOffset;1662}1663}16641665return VK_SUCCESS;1666}16671668VkResult1669panvk_BindImageMemory(VkDevice device,1670VkImage image,1671VkDeviceMemory memory,1672VkDeviceSize memoryOffset)1673{1674const VkBindImageMemoryInfo info = {1675.sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,1676.image = image,1677.memory = memory,1678.memoryOffset = memoryOffset1679};16801681return panvk_BindImageMemory2(device, 1, &info);1682}16831684VkResult1685panvk_QueueBindSparse(VkQueue _queue,1686uint32_t bindInfoCount,1687const VkBindSparseInfo *pBindInfo,1688VkFence _fence)1689{1690return VK_SUCCESS;1691}16921693VkResult1694panvk_CreateEvent(VkDevice _device,1695const VkEventCreateInfo *pCreateInfo,1696const VkAllocationCallbacks *pAllocator,1697VkEvent *pEvent)1698{1699VK_FROM_HANDLE(panvk_device, device, _device);1700const struct panfrost_device *pdev = &device->physical_device->pdev;1701struct panvk_event *event =1702vk_object_zalloc(&device->vk, pAllocator, sizeof(*event),1703VK_OBJECT_TYPE_EVENT);1704if (!event)1705return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);17061707struct drm_syncobj_create create = {1708.flags = 0,1709};17101711int ret = drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_CREATE, &create);1712if (ret)1713return VK_ERROR_OUT_OF_HOST_MEMORY;17141715event->syncobj = create.handle;1716*pEvent = panvk_event_to_handle(event);17171718return VK_SUCCESS;1719}17201721void1722panvk_DestroyEvent(VkDevice _device,1723VkEvent _event,1724const VkAllocationCallbacks *pAllocator)1725{1726VK_FROM_HANDLE(panvk_device, device, _device);1727VK_FROM_HANDLE(panvk_event, event, _event);1728const struct panfrost_device *pdev = &device->physical_device->pdev;17291730if (!event)1731return;17321733struct drm_syncobj_destroy destroy = { .handle = event->syncobj };1734drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_DESTROY, &destroy);17351736vk_object_free(&device->vk, pAllocator, event);1737}17381739VkResult1740panvk_GetEventStatus(VkDevice _device, VkEvent _event)1741{1742VK_FROM_HANDLE(panvk_device, device, _device);1743VK_FROM_HANDLE(panvk_event, event, _event);1744const struct panfrost_device *pdev = &device->physical_device->pdev;1745bool signaled;17461747struct drm_syncobj_wait wait = {1748.handles = (uintptr_t) &event->syncobj,1749.count_handles = 1,1750.timeout_nsec = 0,1751.flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,1752};17531754int ret = drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_WAIT, &wait);1755if (ret) {1756if (errno == ETIME)1757signaled = false;1758else {1759assert(0);1760return VK_ERROR_DEVICE_LOST; /* TODO */1761}1762} else1763signaled = true;17641765return signaled ? VK_EVENT_SET : VK_EVENT_RESET;1766}17671768VkResult1769panvk_SetEvent(VkDevice _device, VkEvent _event)1770{1771VK_FROM_HANDLE(panvk_device, device, _device);1772VK_FROM_HANDLE(panvk_event, event, _event);1773const struct panfrost_device *pdev = &device->physical_device->pdev;17741775struct drm_syncobj_array objs = {1776.handles = (uint64_t) (uintptr_t) &event->syncobj,1777.count_handles = 11778};17791780/* This is going to just replace the fence for this syncobj with one that1781* is already in signaled state. This won't be a problem because the spec1782* mandates that the event will have been set before the vkCmdWaitEvents1783* command executes.1784* https://www.khronos.org/registry/vulkan/specs/1.2/html/chap6.html#commandbuffers-submission-progress1785*/1786if (drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_SIGNAL, &objs))1787return VK_ERROR_DEVICE_LOST;17881789return VK_SUCCESS;1790}17911792VkResult1793panvk_ResetEvent(VkDevice _device, VkEvent _event)1794{1795VK_FROM_HANDLE(panvk_device, device, _device);1796VK_FROM_HANDLE(panvk_event, event, _event);1797const struct panfrost_device *pdev = &device->physical_device->pdev;17981799struct drm_syncobj_array objs = {1800.handles = (uint64_t) (uintptr_t) &event->syncobj,1801.count_handles = 11802};18031804if (drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_RESET, &objs))1805return VK_ERROR_DEVICE_LOST;18061807return VK_SUCCESS;1808}18091810VkResult1811panvk_CreateBuffer(VkDevice _device,1812const VkBufferCreateInfo *pCreateInfo,1813const VkAllocationCallbacks *pAllocator,1814VkBuffer *pBuffer)1815{1816VK_FROM_HANDLE(panvk_device, device, _device);1817struct panvk_buffer *buffer;18181819assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);18201821buffer = vk_object_alloc(&device->vk, pAllocator, sizeof(*buffer),1822VK_OBJECT_TYPE_BUFFER);1823if (buffer == NULL)1824return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);18251826buffer->size = pCreateInfo->size;1827buffer->usage = pCreateInfo->usage;1828buffer->flags = pCreateInfo->flags;18291830*pBuffer = panvk_buffer_to_handle(buffer);18311832return VK_SUCCESS;1833}18341835void1836panvk_DestroyBuffer(VkDevice _device,1837VkBuffer _buffer,1838const VkAllocationCallbacks *pAllocator)1839{1840VK_FROM_HANDLE(panvk_device, device, _device);1841VK_FROM_HANDLE(panvk_buffer, buffer, _buffer);18421843if (!buffer)1844return;18451846vk_object_free(&device->vk, pAllocator, buffer);1847}18481849VkResult1850panvk_CreateFramebuffer(VkDevice _device,1851const VkFramebufferCreateInfo *pCreateInfo,1852const VkAllocationCallbacks *pAllocator,1853VkFramebuffer *pFramebuffer)1854{1855VK_FROM_HANDLE(panvk_device, device, _device);1856struct panvk_framebuffer *framebuffer;18571858assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO);18591860size_t size = sizeof(*framebuffer) + sizeof(struct panvk_attachment_info) *1861pCreateInfo->attachmentCount;1862framebuffer = vk_object_alloc(&device->vk, pAllocator, size,1863VK_OBJECT_TYPE_FRAMEBUFFER);1864if (framebuffer == NULL)1865return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);18661867framebuffer->attachment_count = pCreateInfo->attachmentCount;1868framebuffer->width = pCreateInfo->width;1869framebuffer->height = pCreateInfo->height;1870framebuffer->layers = pCreateInfo->layers;1871for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {1872VkImageView _iview = pCreateInfo->pAttachments[i];1873struct panvk_image_view *iview = panvk_image_view_from_handle(_iview);1874framebuffer->attachments[i].iview = iview;1875}18761877*pFramebuffer = panvk_framebuffer_to_handle(framebuffer);1878return VK_SUCCESS;1879}18801881void1882panvk_DestroyFramebuffer(VkDevice _device,1883VkFramebuffer _fb,1884const VkAllocationCallbacks *pAllocator)1885{1886VK_FROM_HANDLE(panvk_device, device, _device);1887VK_FROM_HANDLE(panvk_framebuffer, fb, _fb);18881889if (fb)1890vk_object_free(&device->vk, pAllocator, fb);1891}18921893static enum mali_mipmap_mode1894panvk_translate_sampler_mipmap_mode(VkSamplerMipmapMode mode)1895{1896switch (mode) {1897case VK_SAMPLER_MIPMAP_MODE_NEAREST: return MALI_MIPMAP_MODE_NEAREST;1898case VK_SAMPLER_MIPMAP_MODE_LINEAR: return MALI_MIPMAP_MODE_TRILINEAR;1899default: unreachable("Invalid mipmap mode");1900}1901}19021903static unsigned1904panvk_translate_sampler_address_mode(VkSamplerAddressMode mode)1905{1906switch (mode) {1907case VK_SAMPLER_ADDRESS_MODE_REPEAT: return MALI_WRAP_MODE_REPEAT;1908case VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT: return MALI_WRAP_MODE_MIRRORED_REPEAT;1909case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE: return MALI_WRAP_MODE_CLAMP_TO_EDGE;1910case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER: return MALI_WRAP_MODE_CLAMP_TO_BORDER;1911case VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE: return MALI_WRAP_MODE_MIRRORED_CLAMP_TO_EDGE;1912default: unreachable("Invalid wrap");1913}1914}19151916static enum mali_func1917panvk_translate_sampler_compare_func(const VkSamplerCreateInfo *pCreateInfo)1918{1919if (!pCreateInfo->compareEnable)1920return MALI_FUNC_NEVER;19211922enum mali_func f = panvk_translate_compare_func(pCreateInfo->compareOp);1923return panfrost_flip_compare_func(f);1924}19251926static void1927panvk_init_midgard_sampler(struct panvk_sampler *sampler,1928const VkSamplerCreateInfo *pCreateInfo)1929{1930const VkSamplerCustomBorderColorCreateInfoEXT *pBorderColor =1931vk_find_struct_const(pCreateInfo->pNext, SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT);19321933pan_pack(&sampler->desc, MIDGARD_SAMPLER, cfg) {1934cfg.magnify_nearest = pCreateInfo->magFilter == VK_FILTER_NEAREST;1935cfg.minify_nearest = pCreateInfo->minFilter == VK_FILTER_NEAREST;1936cfg.mipmap_mode = panvk_translate_sampler_mipmap_mode(pCreateInfo->mipmapMode);1937cfg.normalized_coordinates = !pCreateInfo->unnormalizedCoordinates;1938cfg.lod_bias = FIXED_16(pCreateInfo->mipLodBias, true);1939cfg.minimum_lod = FIXED_16(pCreateInfo->minLod, false);1940cfg.maximum_lod = FIXED_16(pCreateInfo->maxLod, false);19411942cfg.wrap_mode_s = panvk_translate_sampler_address_mode(pCreateInfo->addressModeU);1943cfg.wrap_mode_t = panvk_translate_sampler_address_mode(pCreateInfo->addressModeV);1944cfg.wrap_mode_r = panvk_translate_sampler_address_mode(pCreateInfo->addressModeW);1945cfg.compare_function = panvk_translate_sampler_compare_func(pCreateInfo);19461947switch (pCreateInfo->borderColor) {1948case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK:1949case VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK:1950cfg.border_color_r = fui(0.0);1951cfg.border_color_g = fui(0.0);1952cfg.border_color_b = fui(0.0);1953cfg.border_color_a =1954pCreateInfo->borderColor == VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK ?1955fui(1.0) : fui(0.0);1956break;1957case VK_BORDER_COLOR_INT_OPAQUE_BLACK:1958case VK_BORDER_COLOR_INT_TRANSPARENT_BLACK:1959cfg.border_color_r = 0;1960cfg.border_color_g = 0;1961cfg.border_color_b = 0;1962cfg.border_color_a =1963pCreateInfo->borderColor == VK_BORDER_COLOR_INT_OPAQUE_BLACK ?1964UINT_MAX : 0;1965break;1966case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE:1967cfg.border_color_r = fui(1.0);1968cfg.border_color_g = fui(1.0);1969cfg.border_color_b = fui(1.0);1970cfg.border_color_a = fui(1.0);1971break;1972case VK_BORDER_COLOR_INT_OPAQUE_WHITE:1973cfg.border_color_r = UINT_MAX;1974cfg.border_color_g = UINT_MAX;1975cfg.border_color_b = UINT_MAX;1976cfg.border_color_a = UINT_MAX;1977break;1978case VK_BORDER_COLOR_FLOAT_CUSTOM_EXT:1979case VK_BORDER_COLOR_INT_CUSTOM_EXT:1980cfg.border_color_r = pBorderColor->customBorderColor.int32[0];1981cfg.border_color_g = pBorderColor->customBorderColor.int32[1];1982cfg.border_color_b = pBorderColor->customBorderColor.int32[2];1983cfg.border_color_a = pBorderColor->customBorderColor.int32[3];1984break;1985default:1986unreachable("Invalid border color");1987}1988}1989}19901991static void1992panvk_init_bifrost_sampler(struct panvk_sampler *sampler,1993const VkSamplerCreateInfo *pCreateInfo)1994{1995const VkSamplerCustomBorderColorCreateInfoEXT *pBorderColor =1996vk_find_struct_const(pCreateInfo->pNext, SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT);19971998pan_pack(&sampler->desc, BIFROST_SAMPLER, cfg) {1999cfg.point_sample_magnify = pCreateInfo->magFilter == VK_FILTER_LINEAR;2000cfg.point_sample_minify = pCreateInfo->minFilter == VK_FILTER_LINEAR;2001cfg.mipmap_mode = panvk_translate_sampler_mipmap_mode(pCreateInfo->mipmapMode);2002cfg.normalized_coordinates = !pCreateInfo->unnormalizedCoordinates;20032004cfg.lod_bias = FIXED_16(pCreateInfo->mipLodBias, true);2005cfg.minimum_lod = FIXED_16(pCreateInfo->minLod, false);2006cfg.maximum_lod = FIXED_16(pCreateInfo->maxLod, false);2007cfg.wrap_mode_s = panvk_translate_sampler_address_mode(pCreateInfo->addressModeU);2008cfg.wrap_mode_t = panvk_translate_sampler_address_mode(pCreateInfo->addressModeV);2009cfg.wrap_mode_r = panvk_translate_sampler_address_mode(pCreateInfo->addressModeW);2010cfg.compare_function = panvk_translate_sampler_compare_func(pCreateInfo);20112012switch (pCreateInfo->borderColor) {2013case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK:2014case VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK:2015cfg.border_color_r = fui(0.0);2016cfg.border_color_g = fui(0.0);2017cfg.border_color_b = fui(0.0);2018cfg.border_color_a =2019pCreateInfo->borderColor == VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK ?2020fui(1.0) : fui(0.0);2021break;2022case VK_BORDER_COLOR_INT_OPAQUE_BLACK:2023case VK_BORDER_COLOR_INT_TRANSPARENT_BLACK:2024cfg.border_color_r = 0;2025cfg.border_color_g = 0;2026cfg.border_color_b = 0;2027cfg.border_color_a =2028pCreateInfo->borderColor == VK_BORDER_COLOR_INT_OPAQUE_BLACK ?2029UINT_MAX : 0;2030break;2031case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE:2032cfg.border_color_r = fui(1.0);2033cfg.border_color_g = fui(1.0);2034cfg.border_color_b = fui(1.0);2035cfg.border_color_a = fui(1.0);2036break;2037case VK_BORDER_COLOR_INT_OPAQUE_WHITE:2038cfg.border_color_r = UINT_MAX;2039cfg.border_color_g = UINT_MAX;2040cfg.border_color_b = UINT_MAX;2041cfg.border_color_a = UINT_MAX;2042break;2043case VK_BORDER_COLOR_FLOAT_CUSTOM_EXT:2044case VK_BORDER_COLOR_INT_CUSTOM_EXT:2045cfg.border_color_r = pBorderColor->customBorderColor.int32[0];2046cfg.border_color_g = pBorderColor->customBorderColor.int32[1];2047cfg.border_color_b = pBorderColor->customBorderColor.int32[2];2048cfg.border_color_a = pBorderColor->customBorderColor.int32[3];2049break;2050default:2051unreachable("Invalid border color");2052}2053}2054}20552056static void2057panvk_init_sampler(struct panvk_device *device,2058struct panvk_sampler *sampler,2059const VkSamplerCreateInfo *pCreateInfo)2060{2061if (pan_is_bifrost(&device->physical_device->pdev))2062panvk_init_bifrost_sampler(sampler, pCreateInfo);2063else2064panvk_init_midgard_sampler(sampler, pCreateInfo);2065}20662067VkResult2068panvk_CreateSampler(VkDevice _device,2069const VkSamplerCreateInfo *pCreateInfo,2070const VkAllocationCallbacks *pAllocator,2071VkSampler *pSampler)2072{2073VK_FROM_HANDLE(panvk_device, device, _device);2074struct panvk_sampler *sampler;20752076assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);20772078sampler = vk_object_alloc(&device->vk, pAllocator, sizeof(*sampler),2079VK_OBJECT_TYPE_SAMPLER);2080if (!sampler)2081return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);20822083panvk_init_sampler(device, sampler, pCreateInfo);2084*pSampler = panvk_sampler_to_handle(sampler);20852086return VK_SUCCESS;2087}20882089void2090panvk_DestroySampler(VkDevice _device,2091VkSampler _sampler,2092const VkAllocationCallbacks *pAllocator)2093{2094VK_FROM_HANDLE(panvk_device, device, _device);2095VK_FROM_HANDLE(panvk_sampler, sampler, _sampler);20962097if (!sampler)2098return;20992100vk_object_free(&device->vk, pAllocator, sampler);2101}21022103/* vk_icd.h does not declare this function, so we declare it here to2104* suppress Wmissing-prototypes.2105*/2106PUBLIC VKAPI_ATTR VkResult VKAPI_CALL2107vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t *pSupportedVersion);21082109PUBLIC VKAPI_ATTR VkResult VKAPI_CALL2110vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t *pSupportedVersion)2111{2112/* For the full details on loader interface versioning, see2113* <https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/loader/LoaderAndLayerInterface.md>.2114* What follows is a condensed summary, to help you navigate the large and2115* confusing official doc.2116*2117* - Loader interface v0 is incompatible with later versions. We don't2118* support it.2119*2120* - In loader interface v1:2121* - The first ICD entrypoint called by the loader is2122* vk_icdGetInstanceProcAddr(). The ICD must statically expose this2123* entrypoint.2124* - The ICD must statically expose no other Vulkan symbol unless it2125* is linked with -Bsymbolic.2126* - Each dispatchable Vulkan handle created by the ICD must be2127* a pointer to a struct whose first member is VK_LOADER_DATA. The2128* ICD must initialize VK_LOADER_DATA.loadMagic to2129* ICD_LOADER_MAGIC.2130* - The loader implements vkCreate{PLATFORM}SurfaceKHR() and2131* vkDestroySurfaceKHR(). The ICD must be capable of working with2132* such loader-managed surfaces.2133*2134* - Loader interface v2 differs from v1 in:2135* - The first ICD entrypoint called by the loader is2136* vk_icdNegotiateLoaderICDInterfaceVersion(). The ICD must2137* statically expose this entrypoint.2138*2139* - Loader interface v3 differs from v2 in:2140* - The ICD must implement vkCreate{PLATFORM}SurfaceKHR(),2141* vkDestroySurfaceKHR(), and other API which uses VKSurfaceKHR,2142* because the loader no longer does so.2143*/2144*pSupportedVersion = MIN2(*pSupportedVersion, 3u);2145return VK_SUCCESS;2146}21472148VkResult2149panvk_GetMemoryFdKHR(VkDevice _device,2150const VkMemoryGetFdInfoKHR *pGetFdInfo,2151int *pFd)2152{2153VK_FROM_HANDLE(panvk_device, device, _device);2154VK_FROM_HANDLE(panvk_device_memory, memory, pGetFdInfo->memory);21552156assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR);21572158/* At the moment, we support only the below handle types. */2159assert(pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||2160pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);21612162int prime_fd = panfrost_bo_export(memory->bo);2163if (prime_fd < 0)2164return vk_error(device->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY);21652166*pFd = prime_fd;2167return VK_SUCCESS;2168}21692170VkResult2171panvk_GetMemoryFdPropertiesKHR(VkDevice _device,2172VkExternalMemoryHandleTypeFlagBits handleType,2173int fd,2174VkMemoryFdPropertiesKHR *pMemoryFdProperties)2175{2176assert(handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);2177pMemoryFdProperties->memoryTypeBits = 1;2178return VK_SUCCESS;2179}21802181void2182panvk_GetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice,2183const VkPhysicalDeviceExternalSemaphoreInfo *pExternalSemaphoreInfo,2184VkExternalSemaphoreProperties *pExternalSemaphoreProperties)2185{2186if ((pExternalSemaphoreInfo->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT ||2187pExternalSemaphoreInfo->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)) {2188pExternalSemaphoreProperties->exportFromImportedHandleTypes =2189VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT |2190VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;2191pExternalSemaphoreProperties->compatibleHandleTypes =2192VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT |2193VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;2194pExternalSemaphoreProperties->externalSemaphoreFeatures =2195VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT |2196VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT;2197} else {2198pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0;2199pExternalSemaphoreProperties->compatibleHandleTypes = 0;2200pExternalSemaphoreProperties->externalSemaphoreFeatures = 0;2201}2202}22032204void2205panvk_GetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice,2206const VkPhysicalDeviceExternalFenceInfo *pExternalFenceInfo,2207VkExternalFenceProperties *pExternalFenceProperties)2208{2209pExternalFenceProperties->exportFromImportedHandleTypes = 0;2210pExternalFenceProperties->compatibleHandleTypes = 0;2211pExternalFenceProperties->externalFenceFeatures = 0;2212}22132214void2215panvk_GetDeviceGroupPeerMemoryFeatures(VkDevice device,2216uint32_t heapIndex,2217uint32_t localDeviceIndex,2218uint32_t remoteDeviceIndex,2219VkPeerMemoryFeatureFlags *pPeerMemoryFeatures)2220{2221assert(localDeviceIndex == remoteDeviceIndex);22222223*pPeerMemoryFeatures = VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT |2224VK_PEER_MEMORY_FEATURE_COPY_DST_BIT |2225VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT |2226VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT;2227}222822292230