Path: blob/21.2-virgl/src/freedreno/vulkan/tu_device.c
4565 views
/*1* Copyright © 2016 Red Hat.2* Copyright © 2016 Bas Nieuwenhuizen3*4* based in part on anv driver which is:5* Copyright © 2015 Intel Corporation6*7* Permission is hereby granted, free of charge, to any person obtaining a8* copy of this software and associated documentation files (the "Software"),9* to deal in the Software without restriction, including without limitation10* the rights to use, copy, modify, merge, publish, distribute, sublicense,11* and/or sell copies of the Software, and to permit persons to whom the12* Software is furnished to do so, subject to the following conditions:13*14* The above copyright notice and this permission notice (including the next15* paragraph) shall be included in all copies or substantial portions of the16* Software.17*18* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR19* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,20* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL21* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER22* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING23* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER24* DEALINGS IN THE SOFTWARE.25*/2627#include "tu_private.h"28#include "tu_cs.h"2930#include <fcntl.h>31#include <poll.h>32#include <stdbool.h>33#include <string.h>34#include <sys/sysinfo.h>35#include <unistd.h>3637#include "util/debug.h"38#include "util/disk_cache.h"39#include "util/u_atomic.h"40#include "vk_format.h"41#include "vk_util.h"4243/* for fd_get_driver/device_uuid() */44#include "freedreno/common/freedreno_uuid.h"4546#if defined(VK_USE_PLATFORM_WAYLAND_KHR) || \47defined(VK_USE_PLATFORM_XCB_KHR) || \48defined(VK_USE_PLATFORM_XLIB_KHR) || \49defined(VK_USE_PLATFORM_DISPLAY_KHR)50#define TU_HAS_SURFACE 151#else52#define TU_HAS_SURFACE 053#endif545556static int57tu_device_get_cache_uuid(uint16_t family, void *uuid)58{59uint32_t mesa_timestamp;60uint16_t f = family;61memset(uuid, 0, VK_UUID_SIZE);62if (!disk_cache_get_function_timestamp(tu_device_get_cache_uuid,63&mesa_timestamp))64return -1;6566memcpy(uuid, &mesa_timestamp, 4);67memcpy((char *) uuid + 4, &f, 2);68snprintf((char *) uuid + 6, VK_UUID_SIZE - 10, "tu");69return 0;70}7172#define TU_API_VERSION VK_MAKE_VERSION(1, 1, VK_HEADER_VERSION)7374VKAPI_ATTR VkResult VKAPI_CALL75tu_EnumerateInstanceVersion(uint32_t *pApiVersion)76{77*pApiVersion = TU_API_VERSION;78return VK_SUCCESS;79}8081static const struct vk_instance_extension_table tu_instance_extensions_supported = {82.KHR_device_group_creation = true,83.KHR_external_fence_capabilities = true,84.KHR_external_memory_capabilities = true,85.KHR_external_semaphore_capabilities = true,86.KHR_get_physical_device_properties2 = true,87.KHR_surface = TU_HAS_SURFACE,88.KHR_get_surface_capabilities2 = TU_HAS_SURFACE,89.EXT_debug_report = true,90#ifdef VK_USE_PLATFORM_WAYLAND_KHR91.KHR_wayland_surface = true,92#endif93#ifdef VK_USE_PLATFORM_XCB_KHR94.KHR_xcb_surface = true,95#endif96#ifdef VK_USE_PLATFORM_XLIB_KHR97.KHR_xlib_surface = true,98#endif99#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT100.EXT_acquire_xlib_display = true,101#endif102#ifdef VK_USE_PLATFORM_DISPLAY_KHR103.KHR_display = true,104.KHR_get_display_properties2 = true,105.EXT_direct_mode_display = true,106.EXT_display_surface_counter = true,107#endif108};109110static void111get_device_extensions(const struct tu_physical_device *device,112struct vk_device_extension_table *ext)113{114*ext = (struct vk_device_extension_table) {115.KHR_16bit_storage = device->info->a6xx.storage_16bit,116.KHR_bind_memory2 = true,117.KHR_create_renderpass2 = true,118.KHR_dedicated_allocation = true,119.KHR_depth_stencil_resolve = true,120.KHR_descriptor_update_template = true,121.KHR_device_group = true,122.KHR_draw_indirect_count = true,123.KHR_external_fence = true,124.KHR_external_fence_fd = true,125.KHR_external_memory = true,126.KHR_external_memory_fd = true,127.KHR_external_semaphore = true,128.KHR_external_semaphore_fd = true,129.KHR_get_memory_requirements2 = true,130.KHR_incremental_present = TU_HAS_SURFACE,131.KHR_image_format_list = true,132.KHR_maintenance1 = true,133.KHR_maintenance2 = true,134.KHR_maintenance3 = true,135.KHR_multiview = true,136.KHR_performance_query = device->instance->debug_flags & TU_DEBUG_PERFC,137.KHR_pipeline_executable_properties = true,138.KHR_push_descriptor = true,139.KHR_relaxed_block_layout = true,140.KHR_sampler_mirror_clamp_to_edge = true,141.KHR_sampler_ycbcr_conversion = true,142.KHR_shader_draw_parameters = true,143.KHR_shader_float_controls = true,144.KHR_shader_float16_int8 = true,145.KHR_shader_terminate_invocation = true,146.KHR_spirv_1_4 = true,147.KHR_storage_buffer_storage_class = true,148.KHR_swapchain = TU_HAS_SURFACE,149.KHR_variable_pointers = true,150.KHR_vulkan_memory_model = true,151#ifndef TU_USE_KGSL152.KHR_timeline_semaphore = true,153#endif154#ifdef VK_USE_PLATFORM_DISPLAY_KHR155.EXT_display_control = true,156#endif157.EXT_external_memory_dma_buf = true,158.EXT_image_drm_format_modifier = true,159.EXT_sample_locations = device->info->a6xx.has_sample_locations,160.EXT_sampler_filter_minmax = true,161.EXT_transform_feedback = true,162.EXT_4444_formats = true,163.EXT_conditional_rendering = true,164.EXT_custom_border_color = true,165.EXT_depth_clip_enable = true,166.EXT_descriptor_indexing = true,167.EXT_extended_dynamic_state = true,168.EXT_filter_cubic = device->info->a6xx.has_tex_filter_cubic,169.EXT_host_query_reset = true,170.EXT_index_type_uint8 = true,171.EXT_memory_budget = true,172.EXT_private_data = true,173.EXT_robustness2 = true,174.EXT_scalar_block_layout = true,175.EXT_separate_stencil_usage = true,176.EXT_shader_demote_to_helper_invocation = true,177.EXT_shader_stencil_export = true,178.EXT_shader_viewport_index_layer = true,179.EXT_vertex_attribute_divisor = true,180.EXT_provoking_vertex = true,181#ifdef ANDROID182.ANDROID_native_buffer = true,183#endif184.IMG_filter_cubic = device->info->a6xx.has_tex_filter_cubic,185};186}187188VkResult189tu_physical_device_init(struct tu_physical_device *device,190struct tu_instance *instance)191{192VkResult result = VK_SUCCESS;193194device->name = fd_dev_name(device->gpu_id);195196const struct fd_dev_info *info = fd_dev_info(device->gpu_id);197if (!info) {198result = vk_startup_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,199"device %s is unsupported", device->name);200return result;201}202switch (device->gpu_id / 100) {203case 6:204device->info = info;205device->ccu_offset_bypass = device->info->num_ccu * A6XX_CCU_DEPTH_SIZE;206device->ccu_offset_gmem = (device->gmem_size -207device->info->num_ccu * A6XX_CCU_GMEM_COLOR_SIZE);208break;209default:210result = vk_startup_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,211"device %s is unsupported", device->name);212return result;213}214if (tu_device_get_cache_uuid(device->gpu_id, device->cache_uuid)) {215result = vk_startup_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,216"cannot generate UUID");217return result;218}219220/* The gpu id is already embedded in the uuid so we just pass "tu"221* when creating the cache.222*/223char buf[VK_UUID_SIZE * 2 + 1];224disk_cache_format_hex_id(buf, device->cache_uuid, VK_UUID_SIZE * 2);225device->disk_cache = disk_cache_create(device->name, buf, 0);226227vk_warn_non_conformant_implementation("tu");228229fd_get_driver_uuid(device->driver_uuid);230fd_get_device_uuid(device->device_uuid, device->gpu_id);231232struct vk_device_extension_table supported_extensions;233get_device_extensions(device, &supported_extensions);234235struct vk_physical_device_dispatch_table dispatch_table;236vk_physical_device_dispatch_table_from_entrypoints(237&dispatch_table, &tu_physical_device_entrypoints, true);238239result = vk_physical_device_init(&device->vk, &instance->vk,240&supported_extensions,241&dispatch_table);242if (result != VK_SUCCESS)243return result;244245#if TU_HAS_SURFACE246result = tu_wsi_init(device);247if (result != VK_SUCCESS) {248vk_startup_errorf(instance, result, "WSI init failure");249vk_physical_device_finish(&device->vk);250return result;251}252#endif253254return VK_SUCCESS;255}256257static void258tu_physical_device_finish(struct tu_physical_device *device)259{260#if TU_HAS_SURFACE261tu_wsi_finish(device);262#endif263264disk_cache_destroy(device->disk_cache);265close(device->local_fd);266if (device->master_fd != -1)267close(device->master_fd);268269vk_physical_device_finish(&device->vk);270}271272static const struct debug_control tu_debug_options[] = {273{ "startup", TU_DEBUG_STARTUP },274{ "nir", TU_DEBUG_NIR },275{ "nobin", TU_DEBUG_NOBIN },276{ "sysmem", TU_DEBUG_SYSMEM },277{ "forcebin", TU_DEBUG_FORCEBIN },278{ "noubwc", TU_DEBUG_NOUBWC },279{ "nomultipos", TU_DEBUG_NOMULTIPOS },280{ "nolrz", TU_DEBUG_NOLRZ },281{ "perfc", TU_DEBUG_PERFC },282{ NULL, 0 }283};284285const char *286tu_get_debug_option_name(int id)287{288assert(id < ARRAY_SIZE(tu_debug_options) - 1);289return tu_debug_options[id].string;290}291292VKAPI_ATTR VkResult VKAPI_CALL293tu_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,294const VkAllocationCallbacks *pAllocator,295VkInstance *pInstance)296{297struct tu_instance *instance;298VkResult result;299300assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO);301302if (pAllocator == NULL)303pAllocator = vk_default_allocator();304305instance = vk_zalloc(pAllocator, sizeof(*instance), 8,306VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);307308if (!instance)309return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);310311struct vk_instance_dispatch_table dispatch_table;312vk_instance_dispatch_table_from_entrypoints(313&dispatch_table, &tu_instance_entrypoints, true);314315result = vk_instance_init(&instance->vk,316&tu_instance_extensions_supported,317&dispatch_table,318pCreateInfo, pAllocator);319if (result != VK_SUCCESS) {320vk_free(pAllocator, instance);321return vk_error(NULL, result);322}323324instance->physical_device_count = -1;325326instance->debug_flags =327parse_debug_string(getenv("TU_DEBUG"), tu_debug_options);328329#ifdef DEBUG330/* Enable startup debugging by default on debug drivers. You almost always331* want to see your startup failures in that case, and it's hard to set332* this env var on android.333*/334instance->debug_flags |= TU_DEBUG_STARTUP;335#endif336337if (instance->debug_flags & TU_DEBUG_STARTUP)338mesa_logi("Created an instance");339340VG(VALGRIND_CREATE_MEMPOOL(instance, 0, false));341342*pInstance = tu_instance_to_handle(instance);343344return VK_SUCCESS;345}346347VKAPI_ATTR void VKAPI_CALL348tu_DestroyInstance(VkInstance _instance,349const VkAllocationCallbacks *pAllocator)350{351TU_FROM_HANDLE(tu_instance, instance, _instance);352353if (!instance)354return;355356for (int i = 0; i < instance->physical_device_count; ++i) {357tu_physical_device_finish(instance->physical_devices + i);358}359360VG(VALGRIND_DESTROY_MEMPOOL(instance));361362vk_instance_finish(&instance->vk);363vk_free(&instance->vk.alloc, instance);364}365366VKAPI_ATTR VkResult VKAPI_CALL367tu_EnumeratePhysicalDevices(VkInstance _instance,368uint32_t *pPhysicalDeviceCount,369VkPhysicalDevice *pPhysicalDevices)370{371TU_FROM_HANDLE(tu_instance, instance, _instance);372VK_OUTARRAY_MAKE(out, pPhysicalDevices, pPhysicalDeviceCount);373374VkResult result;375376if (instance->physical_device_count < 0) {377result = tu_enumerate_devices(instance);378if (result != VK_SUCCESS && result != VK_ERROR_INCOMPATIBLE_DRIVER)379return result;380}381382for (uint32_t i = 0; i < instance->physical_device_count; ++i) {383vk_outarray_append(&out, p)384{385*p = tu_physical_device_to_handle(instance->physical_devices + i);386}387}388389return vk_outarray_status(&out);390}391392VKAPI_ATTR VkResult VKAPI_CALL393tu_EnumeratePhysicalDeviceGroups(394VkInstance _instance,395uint32_t *pPhysicalDeviceGroupCount,396VkPhysicalDeviceGroupProperties *pPhysicalDeviceGroupProperties)397{398TU_FROM_HANDLE(tu_instance, instance, _instance);399VK_OUTARRAY_MAKE(out, pPhysicalDeviceGroupProperties,400pPhysicalDeviceGroupCount);401VkResult result;402403if (instance->physical_device_count < 0) {404result = tu_enumerate_devices(instance);405if (result != VK_SUCCESS && result != VK_ERROR_INCOMPATIBLE_DRIVER)406return result;407}408409for (uint32_t i = 0; i < instance->physical_device_count; ++i) {410vk_outarray_append(&out, p)411{412p->physicalDeviceCount = 1;413p->physicalDevices[0] =414tu_physical_device_to_handle(instance->physical_devices + i);415p->subsetAllocation = false;416}417}418419return vk_outarray_status(&out);420}421422VKAPI_ATTR void VKAPI_CALL423tu_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,424VkPhysicalDeviceFeatures2 *pFeatures)425{426TU_FROM_HANDLE(tu_physical_device, pdevice, physicalDevice);427428pFeatures->features = (VkPhysicalDeviceFeatures) {429.robustBufferAccess = true,430.fullDrawIndexUint32 = true,431.imageCubeArray = true,432.independentBlend = true,433.geometryShader = true,434.tessellationShader = true,435.sampleRateShading = true,436.dualSrcBlend = true,437.logicOp = true,438.multiDrawIndirect = true,439.drawIndirectFirstInstance = true,440.depthClamp = true,441.depthBiasClamp = true,442.fillModeNonSolid = true,443.depthBounds = true,444.wideLines = false,445.largePoints = true,446.alphaToOne = true,447.multiViewport = true,448.samplerAnisotropy = true,449.textureCompressionETC2 = true,450.textureCompressionASTC_LDR = true,451.textureCompressionBC = true,452.occlusionQueryPrecise = true,453.pipelineStatisticsQuery = true,454.vertexPipelineStoresAndAtomics = true,455.fragmentStoresAndAtomics = true,456.shaderTessellationAndGeometryPointSize = false,457.shaderImageGatherExtended = true,458.shaderStorageImageExtendedFormats = true,459.shaderStorageImageMultisample = false,460.shaderUniformBufferArrayDynamicIndexing = true,461.shaderSampledImageArrayDynamicIndexing = true,462.shaderStorageBufferArrayDynamicIndexing = true,463.shaderStorageImageArrayDynamicIndexing = true,464.shaderStorageImageReadWithoutFormat = true,465.shaderStorageImageWriteWithoutFormat = true,466.shaderClipDistance = true,467.shaderCullDistance = true,468.shaderFloat64 = false,469.shaderInt64 = false,470.shaderInt16 = true,471.sparseBinding = false,472.variableMultisampleRate = true,473.inheritedQueries = true,474};475476vk_foreach_struct(ext, pFeatures->pNext)477{478switch (ext->sType) {479case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES: {480VkPhysicalDeviceVulkan11Features *features = (void *) ext;481features->storageBuffer16BitAccess = pdevice->info->a6xx.storage_16bit;482features->uniformAndStorageBuffer16BitAccess = false;483features->storagePushConstant16 = false;484features->storageInputOutput16 = false;485features->multiview = true;486features->multiviewGeometryShader = false;487features->multiviewTessellationShader = false;488features->variablePointersStorageBuffer = true;489features->variablePointers = true;490features->protectedMemory = false;491features->samplerYcbcrConversion = true;492features->shaderDrawParameters = true;493break;494}495case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES: {496VkPhysicalDeviceVulkan12Features *features = (void *) ext;497features->samplerMirrorClampToEdge = true;498features->drawIndirectCount = true;499features->storageBuffer8BitAccess = false;500features->uniformAndStorageBuffer8BitAccess = false;501features->storagePushConstant8 = false;502features->shaderBufferInt64Atomics = false;503features->shaderSharedInt64Atomics = false;504features->shaderFloat16 = true;505features->shaderInt8 = false;506507features->descriptorIndexing = true;508features->shaderInputAttachmentArrayDynamicIndexing = false;509features->shaderUniformTexelBufferArrayDynamicIndexing = true;510features->shaderStorageTexelBufferArrayDynamicIndexing = true;511features->shaderUniformBufferArrayNonUniformIndexing = true;512features->shaderSampledImageArrayNonUniformIndexing = true;513features->shaderStorageBufferArrayNonUniformIndexing = true;514features->shaderStorageImageArrayNonUniformIndexing = true;515features->shaderInputAttachmentArrayNonUniformIndexing = false;516features->shaderUniformTexelBufferArrayNonUniformIndexing = true;517features->shaderStorageTexelBufferArrayNonUniformIndexing = true;518features->descriptorBindingUniformBufferUpdateAfterBind = false;519features->descriptorBindingSampledImageUpdateAfterBind = true;520features->descriptorBindingStorageImageUpdateAfterBind = true;521features->descriptorBindingStorageBufferUpdateAfterBind = true;522features->descriptorBindingUniformTexelBufferUpdateAfterBind = true;523features->descriptorBindingStorageTexelBufferUpdateAfterBind = true;524features->descriptorBindingUpdateUnusedWhilePending = true;525features->descriptorBindingPartiallyBound = true;526features->descriptorBindingVariableDescriptorCount = true;527features->runtimeDescriptorArray = true;528529features->samplerFilterMinmax = true;530features->scalarBlockLayout = true;531features->imagelessFramebuffer = false;532features->uniformBufferStandardLayout = false;533features->shaderSubgroupExtendedTypes = false;534features->separateDepthStencilLayouts = false;535features->hostQueryReset = true;536features->timelineSemaphore = true;537features->bufferDeviceAddress = false;538features->bufferDeviceAddressCaptureReplay = false;539features->bufferDeviceAddressMultiDevice = false;540features->vulkanMemoryModel = true;541features->vulkanMemoryModelDeviceScope = true;542features->vulkanMemoryModelAvailabilityVisibilityChains = true;543features->shaderOutputViewportIndex = true;544features->shaderOutputLayer = true;545features->subgroupBroadcastDynamicId = false;546break;547}548case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES: {549VkPhysicalDeviceVariablePointersFeatures *features = (void *) ext;550features->variablePointersStorageBuffer = true;551features->variablePointers = true;552break;553}554case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES: {555VkPhysicalDeviceMultiviewFeatures *features =556(VkPhysicalDeviceMultiviewFeatures *) ext;557features->multiview = true;558features->multiviewGeometryShader = false;559features->multiviewTessellationShader = false;560break;561}562case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES: {563VkPhysicalDeviceShaderDrawParametersFeatures *features =564(VkPhysicalDeviceShaderDrawParametersFeatures *) ext;565features->shaderDrawParameters = true;566break;567}568case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES: {569VkPhysicalDeviceProtectedMemoryFeatures *features =570(VkPhysicalDeviceProtectedMemoryFeatures *) ext;571features->protectedMemory = false;572break;573}574case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES: {575VkPhysicalDevice16BitStorageFeatures *features =576(VkPhysicalDevice16BitStorageFeatures *) ext;577features->storageBuffer16BitAccess = pdevice->info->a6xx.storage_16bit;578features->uniformAndStorageBuffer16BitAccess = false;579features->storagePushConstant16 = false;580features->storageInputOutput16 = false;581break;582}583case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES: {584VkPhysicalDeviceSamplerYcbcrConversionFeatures *features =585(VkPhysicalDeviceSamplerYcbcrConversionFeatures *) ext;586features->samplerYcbcrConversion = true;587break;588}589case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT: {590VkPhysicalDeviceDescriptorIndexingFeaturesEXT *features =591(VkPhysicalDeviceDescriptorIndexingFeaturesEXT *) ext;592features->shaderInputAttachmentArrayDynamicIndexing = false;593features->shaderUniformTexelBufferArrayDynamicIndexing = true;594features->shaderStorageTexelBufferArrayDynamicIndexing = true;595features->shaderUniformBufferArrayNonUniformIndexing = true;596features->shaderSampledImageArrayNonUniformIndexing = true;597features->shaderStorageBufferArrayNonUniformIndexing = true;598features->shaderStorageImageArrayNonUniformIndexing = true;599features->shaderInputAttachmentArrayNonUniformIndexing = false;600features->shaderUniformTexelBufferArrayNonUniformIndexing = true;601features->shaderStorageTexelBufferArrayNonUniformIndexing = true;602features->descriptorBindingUniformBufferUpdateAfterBind = false;603features->descriptorBindingSampledImageUpdateAfterBind = true;604features->descriptorBindingStorageImageUpdateAfterBind = true;605features->descriptorBindingStorageBufferUpdateAfterBind = true;606features->descriptorBindingUniformTexelBufferUpdateAfterBind = true;607features->descriptorBindingStorageTexelBufferUpdateAfterBind = true;608features->descriptorBindingUpdateUnusedWhilePending = true;609features->descriptorBindingPartiallyBound = true;610features->descriptorBindingVariableDescriptorCount = true;611features->runtimeDescriptorArray = true;612break;613}614case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT: {615VkPhysicalDeviceConditionalRenderingFeaturesEXT *features =616(VkPhysicalDeviceConditionalRenderingFeaturesEXT *) ext;617features->conditionalRendering = true;618features->inheritedConditionalRendering = true;619break;620}621case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT: {622VkPhysicalDeviceTransformFeedbackFeaturesEXT *features =623(VkPhysicalDeviceTransformFeedbackFeaturesEXT *) ext;624features->transformFeedback = true;625features->geometryStreams = true;626break;627}628case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT: {629VkPhysicalDeviceIndexTypeUint8FeaturesEXT *features =630(VkPhysicalDeviceIndexTypeUint8FeaturesEXT *)ext;631features->indexTypeUint8 = true;632break;633}634case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: {635VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *features =636(VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *)ext;637features->vertexAttributeInstanceRateDivisor = true;638features->vertexAttributeInstanceRateZeroDivisor = true;639break;640}641case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT: {642VkPhysicalDevicePrivateDataFeaturesEXT *features =643(VkPhysicalDevicePrivateDataFeaturesEXT *)ext;644features->privateData = true;645break;646}647case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT: {648VkPhysicalDeviceDepthClipEnableFeaturesEXT *features =649(VkPhysicalDeviceDepthClipEnableFeaturesEXT *)ext;650features->depthClipEnable = true;651break;652}653case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT: {654VkPhysicalDevice4444FormatsFeaturesEXT *features = (void *)ext;655features->formatA4R4G4B4 = true;656features->formatA4B4G4R4 = true;657break;658}659case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT: {660VkPhysicalDeviceCustomBorderColorFeaturesEXT *features = (void *) ext;661features->customBorderColors = true;662features->customBorderColorWithoutFormat = true;663break;664}665case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT: {666VkPhysicalDeviceHostQueryResetFeaturesEXT *features =667(VkPhysicalDeviceHostQueryResetFeaturesEXT *)ext;668features->hostQueryReset = true;669break;670}671case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT: {672VkPhysicalDeviceExtendedDynamicStateFeaturesEXT *features = (void *)ext;673features->extendedDynamicState = true;674break;675}676case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR: {677VkPhysicalDevicePerformanceQueryFeaturesKHR *feature =678(VkPhysicalDevicePerformanceQueryFeaturesKHR *)ext;679feature->performanceCounterQueryPools = true;680feature->performanceCounterMultipleQueryPools = false;681break;682}683case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR: {684VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR *features =685(VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR *)ext;686features->pipelineExecutableInfo = true;687break;688}689case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES: {690VkPhysicalDeviceShaderFloat16Int8Features *features =691(VkPhysicalDeviceShaderFloat16Int8Features *) ext;692features->shaderFloat16 = true;693features->shaderInt8 = false;694break;695}696case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT: {697VkPhysicalDeviceScalarBlockLayoutFeaturesEXT *features = (void *)ext;698features->scalarBlockLayout = true;699break;700}701case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT: {702VkPhysicalDeviceRobustness2FeaturesEXT *features = (void *)ext;703features->robustBufferAccess2 = true;704features->robustImageAccess2 = true;705features->nullDescriptor = true;706break;707}708case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT: {709VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT *features =710(VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT *)ext;711features->shaderDemoteToHelperInvocation = true;712break;713}714case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES_KHR: {715VkPhysicalDeviceShaderTerminateInvocationFeaturesKHR *features =716(VkPhysicalDeviceShaderTerminateInvocationFeaturesKHR *)ext;717features->shaderTerminateInvocation = true;718break;719}720case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR: {721VkPhysicalDeviceVulkanMemoryModelFeaturesKHR *feature =722(VkPhysicalDeviceVulkanMemoryModelFeaturesKHR *)ext;723feature->vulkanMemoryModel = true;724feature->vulkanMemoryModelDeviceScope = true;725feature->vulkanMemoryModelAvailabilityVisibilityChains = true;726break;727}728case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES: {729VkPhysicalDeviceTimelineSemaphoreFeaturesKHR *features =730(VkPhysicalDeviceTimelineSemaphoreFeaturesKHR *) ext;731features->timelineSemaphore = true;732break;733}734case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT: {735VkPhysicalDeviceProvokingVertexFeaturesEXT *features =736(VkPhysicalDeviceProvokingVertexFeaturesEXT *)ext;737features->provokingVertexLast = true;738features->transformFeedbackPreservesProvokingVertex = true;739break;740}741742default:743break;744}745}746}747748VKAPI_ATTR void VKAPI_CALL749tu_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,750VkPhysicalDeviceProperties2 *pProperties)751{752TU_FROM_HANDLE(tu_physical_device, pdevice, physicalDevice);753VkSampleCountFlags sample_counts =754VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT;755756/* I have no idea what the maximum size is, but the hardware supports very757* large numbers of descriptors (at least 2^16). This limit is based on758* CP_LOAD_STATE6, which has a 28-bit field for the DWORD offset, so that759* we don't have to think about what to do if that overflows, but really760* nothing is likely to get close to this.761*/762const size_t max_descriptor_set_size = (1 << 28) / A6XX_TEX_CONST_DWORDS;763764VkPhysicalDeviceLimits limits = {765.maxImageDimension1D = (1 << 14),766.maxImageDimension2D = (1 << 14),767.maxImageDimension3D = (1 << 11),768.maxImageDimensionCube = (1 << 14),769.maxImageArrayLayers = (1 << 11),770.maxTexelBufferElements = 128 * 1024 * 1024,771.maxUniformBufferRange = MAX_UNIFORM_BUFFER_RANGE,772.maxStorageBufferRange = MAX_STORAGE_BUFFER_RANGE,773.maxPushConstantsSize = MAX_PUSH_CONSTANTS_SIZE,774.maxMemoryAllocationCount = UINT32_MAX,775.maxSamplerAllocationCount = 64 * 1024,776.bufferImageGranularity = 64, /* A cache line */777.sparseAddressSpaceSize = 0,778.maxBoundDescriptorSets = MAX_SETS,779.maxPerStageDescriptorSamplers = max_descriptor_set_size,780.maxPerStageDescriptorUniformBuffers = max_descriptor_set_size,781.maxPerStageDescriptorStorageBuffers = max_descriptor_set_size,782.maxPerStageDescriptorSampledImages = max_descriptor_set_size,783.maxPerStageDescriptorStorageImages = max_descriptor_set_size,784.maxPerStageDescriptorInputAttachments = MAX_RTS,785.maxPerStageResources = max_descriptor_set_size,786.maxDescriptorSetSamplers = max_descriptor_set_size,787.maxDescriptorSetUniformBuffers = max_descriptor_set_size,788.maxDescriptorSetUniformBuffersDynamic = MAX_DYNAMIC_UNIFORM_BUFFERS,789.maxDescriptorSetStorageBuffers = max_descriptor_set_size,790.maxDescriptorSetStorageBuffersDynamic = MAX_DYNAMIC_STORAGE_BUFFERS,791.maxDescriptorSetSampledImages = max_descriptor_set_size,792.maxDescriptorSetStorageImages = max_descriptor_set_size,793.maxDescriptorSetInputAttachments = MAX_RTS,794.maxVertexInputAttributes = 32,795.maxVertexInputBindings = 32,796.maxVertexInputAttributeOffset = 4095,797.maxVertexInputBindingStride = 2048,798.maxVertexOutputComponents = 128,799.maxTessellationGenerationLevel = 64,800.maxTessellationPatchSize = 32,801.maxTessellationControlPerVertexInputComponents = 128,802.maxTessellationControlPerVertexOutputComponents = 128,803.maxTessellationControlPerPatchOutputComponents = 120,804.maxTessellationControlTotalOutputComponents = 4096,805.maxTessellationEvaluationInputComponents = 128,806.maxTessellationEvaluationOutputComponents = 128,807.maxGeometryShaderInvocations = 32,808.maxGeometryInputComponents = 64,809.maxGeometryOutputComponents = 128,810.maxGeometryOutputVertices = 256,811.maxGeometryTotalOutputComponents = 1024,812.maxFragmentInputComponents = 124,813.maxFragmentOutputAttachments = 8,814.maxFragmentDualSrcAttachments = 1,815.maxFragmentCombinedOutputResources = 8,816.maxComputeSharedMemorySize = 32768,817.maxComputeWorkGroupCount = { 65535, 65535, 65535 },818.maxComputeWorkGroupInvocations = 2048,819.maxComputeWorkGroupSize = { 2048, 2048, 2048 },820.subPixelPrecisionBits = 8,821.subTexelPrecisionBits = 8,822.mipmapPrecisionBits = 8,823.maxDrawIndexedIndexValue = UINT32_MAX,824.maxDrawIndirectCount = UINT32_MAX,825.maxSamplerLodBias = 4095.0 / 256.0, /* [-16, 15.99609375] */826.maxSamplerAnisotropy = 16,827.maxViewports = MAX_VIEWPORTS,828.maxViewportDimensions = { (1 << 14), (1 << 14) },829.viewportBoundsRange = { INT16_MIN, INT16_MAX },830.viewportSubPixelBits = 8,831.minMemoryMapAlignment = 4096, /* A page */832.minTexelBufferOffsetAlignment = 64,833.minUniformBufferOffsetAlignment = 64,834.minStorageBufferOffsetAlignment = 64,835.minTexelOffset = -16,836.maxTexelOffset = 15,837.minTexelGatherOffset = -32,838.maxTexelGatherOffset = 31,839.minInterpolationOffset = -0.5,840.maxInterpolationOffset = 0.4375,841.subPixelInterpolationOffsetBits = 4,842.maxFramebufferWidth = (1 << 14),843.maxFramebufferHeight = (1 << 14),844.maxFramebufferLayers = (1 << 10),845.framebufferColorSampleCounts = sample_counts,846.framebufferDepthSampleCounts = sample_counts,847.framebufferStencilSampleCounts = sample_counts,848.framebufferNoAttachmentsSampleCounts = sample_counts,849.maxColorAttachments = MAX_RTS,850.sampledImageColorSampleCounts = sample_counts,851.sampledImageIntegerSampleCounts = VK_SAMPLE_COUNT_1_BIT,852.sampledImageDepthSampleCounts = sample_counts,853.sampledImageStencilSampleCounts = sample_counts,854.storageImageSampleCounts = VK_SAMPLE_COUNT_1_BIT,855.maxSampleMaskWords = 1,856.timestampComputeAndGraphics = true,857.timestampPeriod = 1000000000.0 / 19200000.0, /* CP_ALWAYS_ON_COUNTER is fixed 19.2MHz */858.maxClipDistances = 8,859.maxCullDistances = 8,860.maxCombinedClipAndCullDistances = 8,861.discreteQueuePriorities = 2,862.pointSizeRange = { 1, 4092 },863.lineWidthRange = { 1.0, 1.0 },864.pointSizeGranularity = 0.0625,865.lineWidthGranularity = 0.0,866.strictLines = false, /* FINISHME */867.standardSampleLocations = true,868.optimalBufferCopyOffsetAlignment = 128,869.optimalBufferCopyRowPitchAlignment = 128,870.nonCoherentAtomSize = 64,871};872873pProperties->properties = (VkPhysicalDeviceProperties) {874.apiVersion = TU_API_VERSION,875.driverVersion = vk_get_driver_version(),876.vendorID = 0, /* TODO */877.deviceID = 0,878.deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,879.limits = limits,880.sparseProperties = { 0 },881};882883strcpy(pProperties->properties.deviceName, pdevice->name);884memcpy(pProperties->properties.pipelineCacheUUID, pdevice->cache_uuid, VK_UUID_SIZE);885886vk_foreach_struct(ext, pProperties->pNext)887{888switch (ext->sType) {889case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: {890VkPhysicalDevicePushDescriptorPropertiesKHR *properties =891(VkPhysicalDevicePushDescriptorPropertiesKHR *) ext;892properties->maxPushDescriptors = MAX_PUSH_DESCRIPTORS;893break;894}895case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES: {896VkPhysicalDeviceIDProperties *properties =897(VkPhysicalDeviceIDProperties *) ext;898memcpy(properties->driverUUID, pdevice->driver_uuid, VK_UUID_SIZE);899memcpy(properties->deviceUUID, pdevice->device_uuid, VK_UUID_SIZE);900properties->deviceLUIDValid = false;901break;902}903case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES: {904VkPhysicalDeviceMultiviewProperties *properties =905(VkPhysicalDeviceMultiviewProperties *) ext;906properties->maxMultiviewViewCount = MAX_VIEWS;907properties->maxMultiviewInstanceIndex = INT_MAX;908break;909}910case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES: {911VkPhysicalDevicePointClippingProperties *properties =912(VkPhysicalDevicePointClippingProperties *) ext;913properties->pointClippingBehavior =914VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES;915break;916}917case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES: {918VkPhysicalDeviceMaintenance3Properties *properties =919(VkPhysicalDeviceMaintenance3Properties *) ext;920/* Make sure everything is addressable by a signed 32-bit int, and921* our largest descriptors are 96 bytes. */922properties->maxPerSetDescriptors = (1ull << 31) / 96;923/* Our buffer size fields allow only this much */924properties->maxMemoryAllocationSize = 0xFFFFFFFFull;925break;926}927case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT: {928VkPhysicalDeviceTransformFeedbackPropertiesEXT *properties =929(VkPhysicalDeviceTransformFeedbackPropertiesEXT *)ext;930931properties->maxTransformFeedbackStreams = IR3_MAX_SO_STREAMS;932properties->maxTransformFeedbackBuffers = IR3_MAX_SO_BUFFERS;933properties->maxTransformFeedbackBufferSize = UINT32_MAX;934properties->maxTransformFeedbackStreamDataSize = 512;935properties->maxTransformFeedbackBufferDataSize = 512;936properties->maxTransformFeedbackBufferDataStride = 512;937properties->transformFeedbackQueries = true;938properties->transformFeedbackStreamsLinesTriangles = true;939properties->transformFeedbackRasterizationStreamSelect = true;940properties->transformFeedbackDraw = true;941break;942}943case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT: {944VkPhysicalDeviceSampleLocationsPropertiesEXT *properties =945(VkPhysicalDeviceSampleLocationsPropertiesEXT *)ext;946properties->sampleLocationSampleCounts = 0;947if (pdevice->vk.supported_extensions.EXT_sample_locations) {948properties->sampleLocationSampleCounts =949VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT;950}951properties->maxSampleLocationGridSize = (VkExtent2D) { 1 , 1 };952properties->sampleLocationCoordinateRange[0] = 0.0f;953properties->sampleLocationCoordinateRange[1] = 0.9375f;954properties->sampleLocationSubPixelBits = 4;955properties->variableSampleLocations = true;956break;957}958case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES: {959VkPhysicalDeviceSamplerFilterMinmaxProperties *properties =960(VkPhysicalDeviceSamplerFilterMinmaxProperties *)ext;961properties->filterMinmaxImageComponentMapping = true;962properties->filterMinmaxSingleComponentFormats = true;963break;964}965case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES: {966VkPhysicalDeviceSubgroupProperties *properties =967(VkPhysicalDeviceSubgroupProperties *)ext;968properties->subgroupSize = 128;969properties->supportedStages = VK_SHADER_STAGE_COMPUTE_BIT;970properties->supportedOperations = VK_SUBGROUP_FEATURE_BASIC_BIT |971VK_SUBGROUP_FEATURE_VOTE_BIT |972VK_SUBGROUP_FEATURE_BALLOT_BIT;973properties->quadOperationsInAllStages = false;974break;975}976case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT: {977VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *props =978(VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *)ext;979props->maxVertexAttribDivisor = UINT32_MAX;980break;981}982case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT: {983VkPhysicalDeviceCustomBorderColorPropertiesEXT *props = (void *)ext;984props->maxCustomBorderColorSamplers = TU_BORDER_COLOR_COUNT;985break;986}987case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES: {988VkPhysicalDeviceDepthStencilResolveProperties *props =989(VkPhysicalDeviceDepthStencilResolveProperties *)ext;990props->independentResolve = false;991props->independentResolveNone = false;992props->supportedDepthResolveModes = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;993props->supportedStencilResolveModes = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;994break;995}996case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_PROPERTIES_KHR: {997VkPhysicalDevicePerformanceQueryPropertiesKHR *properties =998(VkPhysicalDevicePerformanceQueryPropertiesKHR *)ext;999properties->allowCommandBufferQueryCopies = false;1000break;1001}1002case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT: {1003VkPhysicalDeviceDescriptorIndexingPropertiesEXT *props =1004(VkPhysicalDeviceDescriptorIndexingPropertiesEXT *)ext;1005props->shaderUniformBufferArrayNonUniformIndexingNative = true;1006props->shaderSampledImageArrayNonUniformIndexingNative = true;1007props->shaderStorageBufferArrayNonUniformIndexingNative = true;1008props->shaderStorageImageArrayNonUniformIndexingNative = true;1009props->shaderInputAttachmentArrayNonUniformIndexingNative = false;1010props->robustBufferAccessUpdateAfterBind = false;1011props->quadDivergentImplicitLod = false;10121013props->maxUpdateAfterBindDescriptorsInAllPools = max_descriptor_set_size;1014props->maxPerStageDescriptorUpdateAfterBindSamplers = max_descriptor_set_size;1015props->maxPerStageDescriptorUpdateAfterBindUniformBuffers = max_descriptor_set_size;1016props->maxPerStageDescriptorUpdateAfterBindStorageBuffers = max_descriptor_set_size;1017props->maxPerStageDescriptorUpdateAfterBindSampledImages = max_descriptor_set_size;1018props->maxPerStageDescriptorUpdateAfterBindStorageImages = max_descriptor_set_size;1019props->maxPerStageDescriptorUpdateAfterBindInputAttachments = max_descriptor_set_size;1020props->maxPerStageUpdateAfterBindResources = max_descriptor_set_size;1021props->maxDescriptorSetUpdateAfterBindSamplers = max_descriptor_set_size;1022props->maxDescriptorSetUpdateAfterBindUniformBuffers = max_descriptor_set_size;1023props->maxDescriptorSetUpdateAfterBindUniformBuffersDynamic = MAX_DYNAMIC_BUFFERS / 2;1024props->maxDescriptorSetUpdateAfterBindStorageBuffers = max_descriptor_set_size;1025props->maxDescriptorSetUpdateAfterBindStorageBuffersDynamic = MAX_DYNAMIC_BUFFERS / 2;1026props->maxDescriptorSetUpdateAfterBindSampledImages = max_descriptor_set_size;1027props->maxDescriptorSetUpdateAfterBindStorageImages = max_descriptor_set_size;1028props->maxDescriptorSetUpdateAfterBindInputAttachments = max_descriptor_set_size;1029break;1030}1031case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES: {1032VkPhysicalDeviceFloatControlsProperties *properties =1033(VkPhysicalDeviceFloatControlsProperties *) ext;1034properties->denormBehaviorIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL;1035properties->roundingModeIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL;1036properties->shaderSignedZeroInfNanPreserveFloat16 = true;1037properties->shaderSignedZeroInfNanPreserveFloat32 = true;1038properties->shaderSignedZeroInfNanPreserveFloat64 = false;1039properties->shaderDenormPreserveFloat16 = false;1040properties->shaderDenormPreserveFloat32 = false;1041properties->shaderDenormPreserveFloat64 = false;1042properties->shaderDenormFlushToZeroFloat16 = true;1043properties->shaderDenormFlushToZeroFloat32 = true;1044properties->shaderDenormFlushToZeroFloat64 = false;1045properties->shaderRoundingModeRTEFloat16 = true;1046properties->shaderRoundingModeRTEFloat32 = true;1047properties->shaderRoundingModeRTEFloat64 = false;1048properties->shaderRoundingModeRTZFloat16 = false;1049properties->shaderRoundingModeRTZFloat32 = false;1050properties->shaderRoundingModeRTZFloat64 = false;1051break;1052}1053case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT: {1054VkPhysicalDeviceRobustness2PropertiesEXT *props = (void *)ext;1055/* see write_buffer_descriptor() */1056props->robustStorageBufferAccessSizeAlignment = 4;1057/* see write_ubo_descriptor() */1058props->robustUniformBufferAccessSizeAlignment = 16;1059break;1060}1061case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES: {1062VkPhysicalDeviceTimelineSemaphorePropertiesKHR *props =1063(VkPhysicalDeviceTimelineSemaphorePropertiesKHR *) ext;1064props->maxTimelineSemaphoreValueDifference = UINT64_MAX;1065break;1066}1067case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_PROPERTIES_EXT: {1068VkPhysicalDeviceProvokingVertexPropertiesEXT *properties =1069(VkPhysicalDeviceProvokingVertexPropertiesEXT *)ext;1070properties->provokingVertexModePerPipeline = true;1071properties->transformFeedbackPreservesTriangleFanProvokingVertex = false;1072break;1073}1074default:1075break;1076}1077}1078}10791080static const VkQueueFamilyProperties tu_queue_family_properties = {1081.queueFlags =1082VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT,1083.queueCount = 1,1084.timestampValidBits = 48,1085.minImageTransferGranularity = { 1, 1, 1 },1086};10871088VKAPI_ATTR void VKAPI_CALL1089tu_GetPhysicalDeviceQueueFamilyProperties2(1090VkPhysicalDevice physicalDevice,1091uint32_t *pQueueFamilyPropertyCount,1092VkQueueFamilyProperties2 *pQueueFamilyProperties)1093{1094VK_OUTARRAY_MAKE(out, pQueueFamilyProperties, pQueueFamilyPropertyCount);10951096vk_outarray_append(&out, p)1097{1098p->queueFamilyProperties = tu_queue_family_properties;1099}1100}11011102uint64_t1103tu_get_system_heap_size()1104{1105struct sysinfo info;1106sysinfo(&info);11071108uint64_t total_ram = (uint64_t) info.totalram * (uint64_t) info.mem_unit;11091110/* We don't want to burn too much ram with the GPU. If the user has 4GiB1111* or less, we use at most half. If they have more than 4GiB, we use 3/4.1112*/1113uint64_t available_ram;1114if (total_ram <= 4ull * 1024ull * 1024ull * 1024ull)1115available_ram = total_ram / 2;1116else1117available_ram = total_ram * 3 / 4;11181119return available_ram;1120}11211122static VkDeviceSize1123tu_get_budget_memory(struct tu_physical_device *physical_device)1124{1125uint64_t heap_size = physical_device->heap.size;1126uint64_t heap_used = physical_device->heap.used;1127uint64_t sys_available;1128ASSERTED bool has_available_memory =1129os_get_available_system_memory(&sys_available);1130assert(has_available_memory);11311132/*1133* Let's not incite the app to starve the system: report at most 90% of1134* available system memory.1135*/1136uint64_t heap_available = sys_available * 9 / 10;1137return MIN2(heap_size, heap_used + heap_available);1138}11391140VKAPI_ATTR void VKAPI_CALL1141tu_GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice pdev,1142VkPhysicalDeviceMemoryProperties2 *props2)1143{1144TU_FROM_HANDLE(tu_physical_device, physical_device, pdev);11451146VkPhysicalDeviceMemoryProperties *props = &props2->memoryProperties;1147props->memoryHeapCount = 1;1148props->memoryHeaps[0].size = physical_device->heap.size;1149props->memoryHeaps[0].flags = physical_device->heap.flags;11501151props->memoryTypeCount = 1;1152props->memoryTypes[0].propertyFlags =1153VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |1154VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |1155VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;1156props->memoryTypes[0].heapIndex = 0;11571158vk_foreach_struct(ext, props2->pNext)1159{1160switch (ext->sType) {1161case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT: {1162VkPhysicalDeviceMemoryBudgetPropertiesEXT *memory_budget_props =1163(VkPhysicalDeviceMemoryBudgetPropertiesEXT *) ext;1164memory_budget_props->heapUsage[0] = physical_device->heap.used;1165memory_budget_props->heapBudget[0] = tu_get_budget_memory(physical_device);11661167/* The heapBudget and heapUsage values must be zero for array elements1168* greater than or equal to VkPhysicalDeviceMemoryProperties::memoryHeapCount1169*/1170for (unsigned i = 1; i < VK_MAX_MEMORY_HEAPS; i++) {1171memory_budget_props->heapBudget[i] = 0u;1172memory_budget_props->heapUsage[i] = 0u;1173}1174break;1175}1176default:1177break;1178}1179}1180}11811182static VkResult1183tu_queue_init(struct tu_device *device,1184struct tu_queue *queue,1185uint32_t queue_family_index,1186int idx,1187VkDeviceQueueCreateFlags flags)1188{1189vk_object_base_init(&device->vk, &queue->base, VK_OBJECT_TYPE_QUEUE);11901191queue->device = device;1192queue->queue_family_index = queue_family_index;1193queue->queue_idx = idx;1194queue->flags = flags;11951196list_inithead(&queue->queued_submits);11971198int ret = tu_drm_submitqueue_new(device, 0, &queue->msm_queue_id);1199if (ret)1200return vk_startup_errorf(device->instance, VK_ERROR_INITIALIZATION_FAILED,1201"submitqueue create failed");12021203queue->fence = -1;12041205return VK_SUCCESS;1206}12071208static void1209tu_queue_finish(struct tu_queue *queue)1210{1211vk_object_base_finish(&queue->base);1212if (queue->fence >= 0)1213close(queue->fence);1214tu_drm_submitqueue_close(queue->device, queue->msm_queue_id);1215}12161217VKAPI_ATTR VkResult VKAPI_CALL1218tu_CreateDevice(VkPhysicalDevice physicalDevice,1219const VkDeviceCreateInfo *pCreateInfo,1220const VkAllocationCallbacks *pAllocator,1221VkDevice *pDevice)1222{1223TU_FROM_HANDLE(tu_physical_device, physical_device, physicalDevice);1224VkResult result;1225struct tu_device *device;1226bool custom_border_colors = false;1227bool perf_query_pools = false;1228bool robust_buffer_access2 = false;12291230/* Check enabled features */1231if (pCreateInfo->pEnabledFeatures) {1232VkPhysicalDeviceFeatures2 supported_features = {1233.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,1234};1235tu_GetPhysicalDeviceFeatures2(physicalDevice, &supported_features);1236VkBool32 *supported_feature = (VkBool32 *) &supported_features.features;1237VkBool32 *enabled_feature = (VkBool32 *) pCreateInfo->pEnabledFeatures;1238unsigned num_features =1239sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);1240for (uint32_t i = 0; i < num_features; i++) {1241if (enabled_feature[i] && !supported_feature[i])1242return vk_startup_errorf(physical_device->instance,1243VK_ERROR_FEATURE_NOT_PRESENT,1244"Missing feature bit %d\n", i);1245}1246}12471248vk_foreach_struct_const(ext, pCreateInfo->pNext) {1249switch (ext->sType) {1250case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT: {1251const VkPhysicalDeviceCustomBorderColorFeaturesEXT *border_color_features = (const void *)ext;1252custom_border_colors = border_color_features->customBorderColors;1253break;1254}1255case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR: {1256const VkPhysicalDevicePerformanceQueryFeaturesKHR *feature =1257(VkPhysicalDevicePerformanceQueryFeaturesKHR *)ext;1258perf_query_pools = feature->performanceCounterQueryPools;1259break;1260}1261case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT: {1262VkPhysicalDeviceRobustness2FeaturesEXT *features = (void *)ext;1263robust_buffer_access2 = features->robustBufferAccess2;1264break;1265}1266default:1267break;1268}1269}12701271device = vk_zalloc2(&physical_device->instance->vk.alloc, pAllocator,1272sizeof(*device), 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);1273if (!device)1274return vk_startup_errorf(physical_device->instance, VK_ERROR_OUT_OF_HOST_MEMORY, "OOM");12751276struct vk_device_dispatch_table dispatch_table;1277vk_device_dispatch_table_from_entrypoints(1278&dispatch_table, &tu_device_entrypoints, true);12791280result = vk_device_init(&device->vk, &physical_device->vk,1281&dispatch_table, pCreateInfo, pAllocator);1282if (result != VK_SUCCESS) {1283vk_free(&device->vk.alloc, device);1284return vk_startup_errorf(physical_device->instance, result,1285"vk_device_init failed");1286}12871288device->instance = physical_device->instance;1289device->physical_device = physical_device;1290device->fd = physical_device->local_fd;1291device->_lost = false;12921293mtx_init(&device->bo_mutex, mtx_plain);1294pthread_mutex_init(&device->submit_mutex, NULL);12951296for (unsigned i = 0; i < pCreateInfo->queueCreateInfoCount; i++) {1297const VkDeviceQueueCreateInfo *queue_create =1298&pCreateInfo->pQueueCreateInfos[i];1299uint32_t qfi = queue_create->queueFamilyIndex;1300device->queues[qfi] = vk_alloc(1301&device->vk.alloc, queue_create->queueCount * sizeof(struct tu_queue),13028, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);1303if (!device->queues[qfi]) {1304result = vk_startup_errorf(physical_device->instance,1305VK_ERROR_OUT_OF_HOST_MEMORY,1306"OOM");1307goto fail_queues;1308}13091310memset(device->queues[qfi], 0,1311queue_create->queueCount * sizeof(struct tu_queue));13121313device->queue_count[qfi] = queue_create->queueCount;13141315for (unsigned q = 0; q < queue_create->queueCount; q++) {1316result = tu_queue_init(device, &device->queues[qfi][q], qfi, q,1317queue_create->flags);1318if (result != VK_SUCCESS)1319goto fail_queues;1320}1321}13221323device->compiler = ir3_compiler_create(NULL, physical_device->gpu_id,1324robust_buffer_access2);1325if (!device->compiler) {1326result = vk_startup_errorf(physical_device->instance,1327VK_ERROR_INITIALIZATION_FAILED,1328"failed to initialize ir3 compiler");1329goto fail_queues;1330}13311332/* initial sizes, these will increase if there is overflow */1333device->vsc_draw_strm_pitch = 0x1000 + VSC_PAD;1334device->vsc_prim_strm_pitch = 0x4000 + VSC_PAD;13351336uint32_t global_size = sizeof(struct tu6_global);1337if (custom_border_colors)1338global_size += TU_BORDER_COLOR_COUNT * sizeof(struct bcolor_entry);13391340result = tu_bo_init_new(device, &device->global_bo, global_size,1341TU_BO_ALLOC_NO_FLAGS);1342if (result != VK_SUCCESS) {1343vk_startup_errorf(device->instance, result, "BO init");1344goto fail_global_bo;1345}13461347result = tu_bo_map(device, &device->global_bo);1348if (result != VK_SUCCESS) {1349vk_startup_errorf(device->instance, result, "BO map");1350goto fail_global_bo_map;1351}13521353struct tu6_global *global = device->global_bo.map;1354tu_init_clear_blit_shaders(device->global_bo.map);1355global->predicate = 0;1356tu6_pack_border_color(&global->bcolor_builtin[VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK],1357&(VkClearColorValue) {}, false);1358tu6_pack_border_color(&global->bcolor_builtin[VK_BORDER_COLOR_INT_TRANSPARENT_BLACK],1359&(VkClearColorValue) {}, true);1360tu6_pack_border_color(&global->bcolor_builtin[VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK],1361&(VkClearColorValue) { .float32[3] = 1.0f }, false);1362tu6_pack_border_color(&global->bcolor_builtin[VK_BORDER_COLOR_INT_OPAQUE_BLACK],1363&(VkClearColorValue) { .int32[3] = 1 }, true);1364tu6_pack_border_color(&global->bcolor_builtin[VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE],1365&(VkClearColorValue) { .float32[0 ... 3] = 1.0f }, false);1366tu6_pack_border_color(&global->bcolor_builtin[VK_BORDER_COLOR_INT_OPAQUE_WHITE],1367&(VkClearColorValue) { .int32[0 ... 3] = 1 }, true);13681369/* initialize to ones so ffs can be used to find unused slots */1370BITSET_ONES(device->custom_border_color);13711372VkPipelineCacheCreateInfo ci;1373ci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;1374ci.pNext = NULL;1375ci.flags = 0;1376ci.pInitialData = NULL;1377ci.initialDataSize = 0;1378VkPipelineCache pc;1379result =1380tu_CreatePipelineCache(tu_device_to_handle(device), &ci, NULL, &pc);1381if (result != VK_SUCCESS) {1382vk_startup_errorf(device->instance, result, "create pipeline cache failed");1383goto fail_pipeline_cache;1384}13851386if (perf_query_pools) {1387/* Prepare command streams setting pass index to the PERF_CNTRS_REG1388* from 0 to 31. One of these will be picked up at cmd submit time1389* when the perf query is executed.1390*/1391struct tu_cs *cs;13921393if (!(device->perfcntrs_pass_cs = calloc(1, sizeof(struct tu_cs)))) {1394result = vk_startup_errorf(device->instance,1395VK_ERROR_OUT_OF_HOST_MEMORY, "OOM");1396goto fail_perfcntrs_pass_alloc;1397}13981399device->perfcntrs_pass_cs_entries = calloc(32, sizeof(struct tu_cs_entry));1400if (!device->perfcntrs_pass_cs_entries) {1401result = vk_startup_errorf(device->instance,1402VK_ERROR_OUT_OF_HOST_MEMORY, "OOM");1403goto fail_perfcntrs_pass_entries_alloc;1404}14051406cs = device->perfcntrs_pass_cs;1407tu_cs_init(cs, device, TU_CS_MODE_SUB_STREAM, 96);14081409for (unsigned i = 0; i < 32; i++) {1410struct tu_cs sub_cs;14111412result = tu_cs_begin_sub_stream(cs, 3, &sub_cs);1413if (result != VK_SUCCESS) {1414vk_startup_errorf(device->instance, result,1415"failed to allocate commands streams");1416goto fail_prepare_perfcntrs_pass_cs;1417}14181419tu_cs_emit_regs(&sub_cs, A6XX_CP_SCRATCH_REG(PERF_CNTRS_REG, 1 << i));1420tu_cs_emit_pkt7(&sub_cs, CP_WAIT_FOR_ME, 0);14211422device->perfcntrs_pass_cs_entries[i] = tu_cs_end_sub_stream(cs, &sub_cs);1423}1424}14251426/* Initialize a condition variable for timeline semaphore */1427pthread_condattr_t condattr;1428if (pthread_condattr_init(&condattr) != 0) {1429result = vk_startup_errorf(physical_device->instance,1430VK_ERROR_INITIALIZATION_FAILED,1431"pthread condattr init");1432goto fail_timeline_cond;1433}1434if (pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC) != 0) {1435pthread_condattr_destroy(&condattr);1436result = vk_startup_errorf(physical_device->instance,1437VK_ERROR_INITIALIZATION_FAILED,1438"pthread condattr clock setup");1439goto fail_timeline_cond;1440}1441if (pthread_cond_init(&device->timeline_cond, &condattr) != 0) {1442pthread_condattr_destroy(&condattr);1443result = vk_startup_errorf(physical_device->instance,1444VK_ERROR_INITIALIZATION_FAILED,1445"pthread cond init");1446goto fail_timeline_cond;1447}1448pthread_condattr_destroy(&condattr);14491450device->mem_cache = tu_pipeline_cache_from_handle(pc);14511452for (unsigned i = 0; i < ARRAY_SIZE(device->scratch_bos); i++)1453mtx_init(&device->scratch_bos[i].construct_mtx, mtx_plain);14541455mtx_init(&device->mutex, mtx_plain);14561457*pDevice = tu_device_to_handle(device);1458return VK_SUCCESS;14591460fail_timeline_cond:1461fail_prepare_perfcntrs_pass_cs:1462free(device->perfcntrs_pass_cs_entries);1463tu_cs_finish(device->perfcntrs_pass_cs);1464fail_perfcntrs_pass_entries_alloc:1465free(device->perfcntrs_pass_cs);1466fail_perfcntrs_pass_alloc:1467tu_DestroyPipelineCache(tu_device_to_handle(device), pc, NULL);1468fail_pipeline_cache:1469fail_global_bo_map:1470tu_bo_finish(device, &device->global_bo);14711472fail_global_bo:1473ir3_compiler_destroy(device->compiler);14741475fail_queues:1476for (unsigned i = 0; i < TU_MAX_QUEUE_FAMILIES; i++) {1477for (unsigned q = 0; q < device->queue_count[i]; q++)1478tu_queue_finish(&device->queues[i][q]);1479if (device->queue_count[i])1480vk_free(&device->vk.alloc, device->queues[i]);1481}14821483vk_device_finish(&device->vk);1484vk_free(&device->vk.alloc, device);1485return result;1486}14871488VKAPI_ATTR void VKAPI_CALL1489tu_DestroyDevice(VkDevice _device, const VkAllocationCallbacks *pAllocator)1490{1491TU_FROM_HANDLE(tu_device, device, _device);14921493if (!device)1494return;14951496for (unsigned i = 0; i < TU_MAX_QUEUE_FAMILIES; i++) {1497for (unsigned q = 0; q < device->queue_count[i]; q++)1498tu_queue_finish(&device->queues[i][q]);1499if (device->queue_count[i])1500vk_free(&device->vk.alloc, device->queues[i]);1501}15021503for (unsigned i = 0; i < ARRAY_SIZE(device->scratch_bos); i++) {1504if (device->scratch_bos[i].initialized)1505tu_bo_finish(device, &device->scratch_bos[i].bo);1506}15071508ir3_compiler_destroy(device->compiler);15091510VkPipelineCache pc = tu_pipeline_cache_to_handle(device->mem_cache);1511tu_DestroyPipelineCache(tu_device_to_handle(device), pc, NULL);15121513if (device->perfcntrs_pass_cs) {1514free(device->perfcntrs_pass_cs_entries);1515tu_cs_finish(device->perfcntrs_pass_cs);1516free(device->perfcntrs_pass_cs);1517}15181519pthread_cond_destroy(&device->timeline_cond);1520vk_free(&device->vk.alloc, device->bo_list);1521vk_free(&device->vk.alloc, device->bo_idx);1522vk_device_finish(&device->vk);1523vk_free(&device->vk.alloc, device);1524}15251526VkResult1527_tu_device_set_lost(struct tu_device *device,1528const char *msg, ...)1529{1530/* Set the flag indicating that waits should return in finite time even1531* after device loss.1532*/1533p_atomic_inc(&device->_lost);15341535/* TODO: Report the log message through VkDebugReportCallbackEXT instead */1536va_list ap;1537va_start(ap, msg);1538mesa_loge_v(msg, ap);1539va_end(ap);15401541if (env_var_as_boolean("TU_ABORT_ON_DEVICE_LOSS", false))1542abort();15431544return VK_ERROR_DEVICE_LOST;1545}15461547VkResult1548tu_get_scratch_bo(struct tu_device *dev, uint64_t size, struct tu_bo **bo)1549{1550unsigned size_log2 = MAX2(util_logbase2_ceil64(size), MIN_SCRATCH_BO_SIZE_LOG2);1551unsigned index = size_log2 - MIN_SCRATCH_BO_SIZE_LOG2;1552assert(index < ARRAY_SIZE(dev->scratch_bos));15531554for (unsigned i = index; i < ARRAY_SIZE(dev->scratch_bos); i++) {1555if (p_atomic_read(&dev->scratch_bos[i].initialized)) {1556/* Fast path: just return the already-allocated BO. */1557*bo = &dev->scratch_bos[i].bo;1558return VK_SUCCESS;1559}1560}15611562/* Slow path: actually allocate the BO. We take a lock because the process1563* of allocating it is slow, and we don't want to block the CPU while it1564* finishes.1565*/1566mtx_lock(&dev->scratch_bos[index].construct_mtx);15671568/* Another thread may have allocated it already while we were waiting on1569* the lock. We need to check this in order to avoid double-allocating.1570*/1571if (dev->scratch_bos[index].initialized) {1572mtx_unlock(&dev->scratch_bos[index].construct_mtx);1573*bo = &dev->scratch_bos[index].bo;1574return VK_SUCCESS;1575}15761577unsigned bo_size = 1ull << size_log2;1578VkResult result = tu_bo_init_new(dev, &dev->scratch_bos[index].bo, bo_size,1579TU_BO_ALLOC_NO_FLAGS);1580if (result != VK_SUCCESS) {1581mtx_unlock(&dev->scratch_bos[index].construct_mtx);1582return result;1583}15841585p_atomic_set(&dev->scratch_bos[index].initialized, true);15861587mtx_unlock(&dev->scratch_bos[index].construct_mtx);15881589*bo = &dev->scratch_bos[index].bo;1590return VK_SUCCESS;1591}15921593VKAPI_ATTR VkResult VKAPI_CALL1594tu_EnumerateInstanceLayerProperties(uint32_t *pPropertyCount,1595VkLayerProperties *pProperties)1596{1597*pPropertyCount = 0;1598return VK_SUCCESS;1599}16001601VKAPI_ATTR void VKAPI_CALL1602tu_GetDeviceQueue2(VkDevice _device,1603const VkDeviceQueueInfo2 *pQueueInfo,1604VkQueue *pQueue)1605{1606TU_FROM_HANDLE(tu_device, device, _device);1607struct tu_queue *queue;16081609queue =1610&device->queues[pQueueInfo->queueFamilyIndex][pQueueInfo->queueIndex];1611if (pQueueInfo->flags != queue->flags) {1612/* From the Vulkan 1.1.70 spec:1613*1614* "The queue returned by vkGetDeviceQueue2 must have the same1615* flags value from this structure as that used at device1616* creation time in a VkDeviceQueueCreateInfo instance. If no1617* matching flags were specified at device creation time then1618* pQueue will return VK_NULL_HANDLE."1619*/1620*pQueue = VK_NULL_HANDLE;1621return;1622}16231624*pQueue = tu_queue_to_handle(queue);1625}16261627VKAPI_ATTR VkResult VKAPI_CALL1628tu_QueueWaitIdle(VkQueue _queue)1629{1630TU_FROM_HANDLE(tu_queue, queue, _queue);16311632if (tu_device_is_lost(queue->device))1633return VK_ERROR_DEVICE_LOST;16341635if (queue->fence < 0)1636return VK_SUCCESS;16371638pthread_mutex_lock(&queue->device->submit_mutex);16391640do {1641tu_device_submit_deferred_locked(queue->device);16421643if (list_is_empty(&queue->queued_submits))1644break;16451646pthread_cond_wait(&queue->device->timeline_cond,1647&queue->device->submit_mutex);1648} while (!list_is_empty(&queue->queued_submits));16491650pthread_mutex_unlock(&queue->device->submit_mutex);16511652struct pollfd fds = { .fd = queue->fence, .events = POLLIN };1653int ret;1654do {1655ret = poll(&fds, 1, -1);1656} while (ret == -1 && (errno == EINTR || errno == EAGAIN));16571658/* TODO: otherwise set device lost ? */1659assert(ret == 1 && !(fds.revents & (POLLERR | POLLNVAL)));16601661close(queue->fence);1662queue->fence = -1;1663return VK_SUCCESS;1664}16651666VKAPI_ATTR VkResult VKAPI_CALL1667tu_DeviceWaitIdle(VkDevice _device)1668{1669TU_FROM_HANDLE(tu_device, device, _device);16701671if (tu_device_is_lost(device))1672return VK_ERROR_DEVICE_LOST;16731674for (unsigned i = 0; i < TU_MAX_QUEUE_FAMILIES; i++) {1675for (unsigned q = 0; q < device->queue_count[i]; q++) {1676tu_QueueWaitIdle(tu_queue_to_handle(&device->queues[i][q]));1677}1678}1679return VK_SUCCESS;1680}16811682VKAPI_ATTR VkResult VKAPI_CALL1683tu_EnumerateInstanceExtensionProperties(const char *pLayerName,1684uint32_t *pPropertyCount,1685VkExtensionProperties *pProperties)1686{1687if (pLayerName)1688return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);16891690return vk_enumerate_instance_extension_properties(1691&tu_instance_extensions_supported, pPropertyCount, pProperties);1692}16931694VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL1695tu_GetInstanceProcAddr(VkInstance _instance, const char *pName)1696{1697TU_FROM_HANDLE(tu_instance, instance, _instance);1698return vk_instance_get_proc_addr(&instance->vk,1699&tu_instance_entrypoints,1700pName);1701}17021703/* The loader wants us to expose a second GetInstanceProcAddr function1704* to work around certain LD_PRELOAD issues seen in apps.1705*/1706PUBLIC1707VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL1708vk_icdGetInstanceProcAddr(VkInstance instance, const char *pName);17091710PUBLIC1711VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL1712vk_icdGetInstanceProcAddr(VkInstance instance, const char *pName)1713{1714return tu_GetInstanceProcAddr(instance, pName);1715}17161717VKAPI_ATTR VkResult VKAPI_CALL1718tu_AllocateMemory(VkDevice _device,1719const VkMemoryAllocateInfo *pAllocateInfo,1720const VkAllocationCallbacks *pAllocator,1721VkDeviceMemory *pMem)1722{1723TU_FROM_HANDLE(tu_device, device, _device);1724struct tu_device_memory *mem;1725VkResult result;17261727assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);17281729if (pAllocateInfo->allocationSize == 0) {1730/* Apparently, this is allowed */1731*pMem = VK_NULL_HANDLE;1732return VK_SUCCESS;1733}17341735struct tu_memory_heap *mem_heap = &device->physical_device->heap;1736uint64_t mem_heap_used = p_atomic_read(&mem_heap->used);1737if (mem_heap_used > mem_heap->size)1738return vk_error(device->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY);17391740mem = vk_object_alloc(&device->vk, pAllocator, sizeof(*mem),1741VK_OBJECT_TYPE_DEVICE_MEMORY);1742if (mem == NULL)1743return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);17441745const VkImportMemoryFdInfoKHR *fd_info =1746vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_FD_INFO_KHR);1747if (fd_info && !fd_info->handleType)1748fd_info = NULL;17491750if (fd_info) {1751assert(fd_info->handleType ==1752VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||1753fd_info->handleType ==1754VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);17551756/*1757* TODO Importing the same fd twice gives us the same handle without1758* reference counting. We need to maintain a per-instance handle-to-bo1759* table and add reference count to tu_bo.1760*/1761result = tu_bo_init_dmabuf(device, &mem->bo,1762pAllocateInfo->allocationSize, fd_info->fd);1763if (result == VK_SUCCESS) {1764/* take ownership and close the fd */1765close(fd_info->fd);1766}1767} else {1768result =1769tu_bo_init_new(device, &mem->bo, pAllocateInfo->allocationSize,1770TU_BO_ALLOC_NO_FLAGS);1771}177217731774if (result == VK_SUCCESS) {1775mem_heap_used = p_atomic_add_return(&mem_heap->used, mem->bo.size);1776if (mem_heap_used > mem_heap->size) {1777p_atomic_add(&mem_heap->used, -mem->bo.size);1778tu_bo_finish(device, &mem->bo);1779result = vk_errorf(device->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY,1780"Out of heap memory");1781}1782}17831784if (result != VK_SUCCESS) {1785vk_object_free(&device->vk, pAllocator, mem);1786return result;1787}17881789*pMem = tu_device_memory_to_handle(mem);17901791return VK_SUCCESS;1792}17931794VKAPI_ATTR void VKAPI_CALL1795tu_FreeMemory(VkDevice _device,1796VkDeviceMemory _mem,1797const VkAllocationCallbacks *pAllocator)1798{1799TU_FROM_HANDLE(tu_device, device, _device);1800TU_FROM_HANDLE(tu_device_memory, mem, _mem);18011802if (mem == NULL)1803return;18041805p_atomic_add(&device->physical_device->heap.used, -mem->bo.size);1806tu_bo_finish(device, &mem->bo);1807vk_object_free(&device->vk, pAllocator, mem);1808}18091810VKAPI_ATTR VkResult VKAPI_CALL1811tu_MapMemory(VkDevice _device,1812VkDeviceMemory _memory,1813VkDeviceSize offset,1814VkDeviceSize size,1815VkMemoryMapFlags flags,1816void **ppData)1817{1818TU_FROM_HANDLE(tu_device, device, _device);1819TU_FROM_HANDLE(tu_device_memory, mem, _memory);1820VkResult result;18211822if (mem == NULL) {1823*ppData = NULL;1824return VK_SUCCESS;1825}18261827if (!mem->bo.map) {1828result = tu_bo_map(device, &mem->bo);1829if (result != VK_SUCCESS)1830return result;1831}18321833*ppData = mem->bo.map + offset;1834return VK_SUCCESS;1835}18361837VKAPI_ATTR void VKAPI_CALL1838tu_UnmapMemory(VkDevice _device, VkDeviceMemory _memory)1839{1840/* TODO: unmap here instead of waiting for FreeMemory */1841}18421843VKAPI_ATTR VkResult VKAPI_CALL1844tu_FlushMappedMemoryRanges(VkDevice _device,1845uint32_t memoryRangeCount,1846const VkMappedMemoryRange *pMemoryRanges)1847{1848return VK_SUCCESS;1849}18501851VKAPI_ATTR VkResult VKAPI_CALL1852tu_InvalidateMappedMemoryRanges(VkDevice _device,1853uint32_t memoryRangeCount,1854const VkMappedMemoryRange *pMemoryRanges)1855{1856return VK_SUCCESS;1857}18581859VKAPI_ATTR void VKAPI_CALL1860tu_GetBufferMemoryRequirements2(1861VkDevice device,1862const VkBufferMemoryRequirementsInfo2 *pInfo,1863VkMemoryRequirements2 *pMemoryRequirements)1864{1865TU_FROM_HANDLE(tu_buffer, buffer, pInfo->buffer);18661867pMemoryRequirements->memoryRequirements = (VkMemoryRequirements) {1868.memoryTypeBits = 1,1869.alignment = 64,1870.size = MAX2(align64(buffer->size, 64), buffer->size),1871};18721873vk_foreach_struct(ext, pMemoryRequirements->pNext) {1874switch (ext->sType) {1875case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {1876VkMemoryDedicatedRequirements *req =1877(VkMemoryDedicatedRequirements *) ext;1878req->requiresDedicatedAllocation = false;1879req->prefersDedicatedAllocation = req->requiresDedicatedAllocation;1880break;1881}1882default:1883break;1884}1885}1886}18871888VKAPI_ATTR void VKAPI_CALL1889tu_GetImageMemoryRequirements2(VkDevice device,1890const VkImageMemoryRequirementsInfo2 *pInfo,1891VkMemoryRequirements2 *pMemoryRequirements)1892{1893TU_FROM_HANDLE(tu_image, image, pInfo->image);18941895pMemoryRequirements->memoryRequirements = (VkMemoryRequirements) {1896.memoryTypeBits = 1,1897.alignment = image->layout[0].base_align,1898.size = image->total_size1899};19001901vk_foreach_struct(ext, pMemoryRequirements->pNext) {1902switch (ext->sType) {1903case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {1904VkMemoryDedicatedRequirements *req =1905(VkMemoryDedicatedRequirements *) ext;1906req->requiresDedicatedAllocation = image->shareable;1907req->prefersDedicatedAllocation = req->requiresDedicatedAllocation;1908break;1909}1910default:1911break;1912}1913}1914}19151916VKAPI_ATTR void VKAPI_CALL1917tu_GetImageSparseMemoryRequirements2(1918VkDevice device,1919const VkImageSparseMemoryRequirementsInfo2 *pInfo,1920uint32_t *pSparseMemoryRequirementCount,1921VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)1922{1923tu_stub();1924}19251926VKAPI_ATTR void VKAPI_CALL1927tu_GetDeviceMemoryCommitment(VkDevice device,1928VkDeviceMemory memory,1929VkDeviceSize *pCommittedMemoryInBytes)1930{1931*pCommittedMemoryInBytes = 0;1932}19331934VKAPI_ATTR VkResult VKAPI_CALL1935tu_BindBufferMemory2(VkDevice device,1936uint32_t bindInfoCount,1937const VkBindBufferMemoryInfo *pBindInfos)1938{1939for (uint32_t i = 0; i < bindInfoCount; ++i) {1940TU_FROM_HANDLE(tu_device_memory, mem, pBindInfos[i].memory);1941TU_FROM_HANDLE(tu_buffer, buffer, pBindInfos[i].buffer);19421943if (mem) {1944buffer->bo = &mem->bo;1945buffer->bo_offset = pBindInfos[i].memoryOffset;1946} else {1947buffer->bo = NULL;1948}1949}1950return VK_SUCCESS;1951}19521953VKAPI_ATTR VkResult VKAPI_CALL1954tu_BindImageMemory2(VkDevice device,1955uint32_t bindInfoCount,1956const VkBindImageMemoryInfo *pBindInfos)1957{1958for (uint32_t i = 0; i < bindInfoCount; ++i) {1959TU_FROM_HANDLE(tu_image, image, pBindInfos[i].image);1960TU_FROM_HANDLE(tu_device_memory, mem, pBindInfos[i].memory);19611962if (mem) {1963image->bo = &mem->bo;1964image->bo_offset = pBindInfos[i].memoryOffset;1965} else {1966image->bo = NULL;1967image->bo_offset = 0;1968}1969}19701971return VK_SUCCESS;1972}19731974VKAPI_ATTR VkResult VKAPI_CALL1975tu_QueueBindSparse(VkQueue _queue,1976uint32_t bindInfoCount,1977const VkBindSparseInfo *pBindInfo,1978VkFence _fence)1979{1980return VK_SUCCESS;1981}19821983VKAPI_ATTR VkResult VKAPI_CALL1984tu_CreateEvent(VkDevice _device,1985const VkEventCreateInfo *pCreateInfo,1986const VkAllocationCallbacks *pAllocator,1987VkEvent *pEvent)1988{1989TU_FROM_HANDLE(tu_device, device, _device);19901991struct tu_event *event =1992vk_object_alloc(&device->vk, pAllocator, sizeof(*event),1993VK_OBJECT_TYPE_EVENT);1994if (!event)1995return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);19961997VkResult result = tu_bo_init_new(device, &event->bo, 0x1000,1998TU_BO_ALLOC_NO_FLAGS);1999if (result != VK_SUCCESS)2000goto fail_alloc;20012002result = tu_bo_map(device, &event->bo);2003if (result != VK_SUCCESS)2004goto fail_map;20052006*pEvent = tu_event_to_handle(event);20072008return VK_SUCCESS;20092010fail_map:2011tu_bo_finish(device, &event->bo);2012fail_alloc:2013vk_object_free(&device->vk, pAllocator, event);2014return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);2015}20162017VKAPI_ATTR void VKAPI_CALL2018tu_DestroyEvent(VkDevice _device,2019VkEvent _event,2020const VkAllocationCallbacks *pAllocator)2021{2022TU_FROM_HANDLE(tu_device, device, _device);2023TU_FROM_HANDLE(tu_event, event, _event);20242025if (!event)2026return;20272028tu_bo_finish(device, &event->bo);2029vk_object_free(&device->vk, pAllocator, event);2030}20312032VKAPI_ATTR VkResult VKAPI_CALL2033tu_GetEventStatus(VkDevice _device, VkEvent _event)2034{2035TU_FROM_HANDLE(tu_event, event, _event);20362037if (*(uint64_t*) event->bo.map == 1)2038return VK_EVENT_SET;2039return VK_EVENT_RESET;2040}20412042VKAPI_ATTR VkResult VKAPI_CALL2043tu_SetEvent(VkDevice _device, VkEvent _event)2044{2045TU_FROM_HANDLE(tu_event, event, _event);2046*(uint64_t*) event->bo.map = 1;20472048return VK_SUCCESS;2049}20502051VKAPI_ATTR VkResult VKAPI_CALL2052tu_ResetEvent(VkDevice _device, VkEvent _event)2053{2054TU_FROM_HANDLE(tu_event, event, _event);2055*(uint64_t*) event->bo.map = 0;20562057return VK_SUCCESS;2058}20592060VKAPI_ATTR VkResult VKAPI_CALL2061tu_CreateBuffer(VkDevice _device,2062const VkBufferCreateInfo *pCreateInfo,2063const VkAllocationCallbacks *pAllocator,2064VkBuffer *pBuffer)2065{2066TU_FROM_HANDLE(tu_device, device, _device);2067struct tu_buffer *buffer;20682069assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);20702071buffer = vk_object_alloc(&device->vk, pAllocator, sizeof(*buffer),2072VK_OBJECT_TYPE_BUFFER);2073if (buffer == NULL)2074return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);20752076buffer->size = pCreateInfo->size;2077buffer->usage = pCreateInfo->usage;2078buffer->flags = pCreateInfo->flags;20792080*pBuffer = tu_buffer_to_handle(buffer);20812082return VK_SUCCESS;2083}20842085VKAPI_ATTR void VKAPI_CALL2086tu_DestroyBuffer(VkDevice _device,2087VkBuffer _buffer,2088const VkAllocationCallbacks *pAllocator)2089{2090TU_FROM_HANDLE(tu_device, device, _device);2091TU_FROM_HANDLE(tu_buffer, buffer, _buffer);20922093if (!buffer)2094return;20952096vk_object_free(&device->vk, pAllocator, buffer);2097}20982099VKAPI_ATTR VkResult VKAPI_CALL2100tu_CreateFramebuffer(VkDevice _device,2101const VkFramebufferCreateInfo *pCreateInfo,2102const VkAllocationCallbacks *pAllocator,2103VkFramebuffer *pFramebuffer)2104{2105TU_FROM_HANDLE(tu_device, device, _device);2106TU_FROM_HANDLE(tu_render_pass, pass, pCreateInfo->renderPass);2107struct tu_framebuffer *framebuffer;21082109assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO);21102111size_t size = sizeof(*framebuffer) + sizeof(struct tu_attachment_info) *2112pCreateInfo->attachmentCount;2113framebuffer = vk_object_alloc(&device->vk, pAllocator, size,2114VK_OBJECT_TYPE_FRAMEBUFFER);2115if (framebuffer == NULL)2116return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);21172118framebuffer->attachment_count = pCreateInfo->attachmentCount;2119framebuffer->width = pCreateInfo->width;2120framebuffer->height = pCreateInfo->height;2121framebuffer->layers = pCreateInfo->layers;2122for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {2123VkImageView _iview = pCreateInfo->pAttachments[i];2124struct tu_image_view *iview = tu_image_view_from_handle(_iview);2125framebuffer->attachments[i].attachment = iview;2126}21272128tu_framebuffer_tiling_config(framebuffer, device, pass);21292130*pFramebuffer = tu_framebuffer_to_handle(framebuffer);2131return VK_SUCCESS;2132}21332134VKAPI_ATTR void VKAPI_CALL2135tu_DestroyFramebuffer(VkDevice _device,2136VkFramebuffer _fb,2137const VkAllocationCallbacks *pAllocator)2138{2139TU_FROM_HANDLE(tu_device, device, _device);2140TU_FROM_HANDLE(tu_framebuffer, fb, _fb);21412142if (!fb)2143return;21442145vk_object_free(&device->vk, pAllocator, fb);2146}21472148static void2149tu_init_sampler(struct tu_device *device,2150struct tu_sampler *sampler,2151const VkSamplerCreateInfo *pCreateInfo)2152{2153const struct VkSamplerReductionModeCreateInfo *reduction =2154vk_find_struct_const(pCreateInfo->pNext, SAMPLER_REDUCTION_MODE_CREATE_INFO);2155const struct VkSamplerYcbcrConversionInfo *ycbcr_conversion =2156vk_find_struct_const(pCreateInfo->pNext, SAMPLER_YCBCR_CONVERSION_INFO);2157const VkSamplerCustomBorderColorCreateInfoEXT *custom_border_color =2158vk_find_struct_const(pCreateInfo->pNext, SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT);2159/* for non-custom border colors, the VK enum is translated directly to an offset in2160* the border color buffer. custom border colors are located immediately after the2161* builtin colors, and thus an offset of TU_BORDER_COLOR_BUILTIN is added.2162*/2163uint32_t border_color = (unsigned) pCreateInfo->borderColor;2164if (pCreateInfo->borderColor == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT ||2165pCreateInfo->borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT) {2166mtx_lock(&device->mutex);2167border_color = BITSET_FFS(device->custom_border_color);2168BITSET_CLEAR(device->custom_border_color, border_color);2169mtx_unlock(&device->mutex);2170tu6_pack_border_color(device->global_bo.map + gb_offset(bcolor[border_color]),2171&custom_border_color->customBorderColor,2172pCreateInfo->borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT);2173border_color += TU_BORDER_COLOR_BUILTIN;2174}21752176unsigned aniso = pCreateInfo->anisotropyEnable ?2177util_last_bit(MIN2((uint32_t)pCreateInfo->maxAnisotropy >> 1, 8)) : 0;2178bool miplinear = (pCreateInfo->mipmapMode == VK_SAMPLER_MIPMAP_MODE_LINEAR);2179float min_lod = CLAMP(pCreateInfo->minLod, 0.0f, 4095.0f / 256.0f);2180float max_lod = CLAMP(pCreateInfo->maxLod, 0.0f, 4095.0f / 256.0f);21812182sampler->descriptor[0] =2183COND(miplinear, A6XX_TEX_SAMP_0_MIPFILTER_LINEAR_NEAR) |2184A6XX_TEX_SAMP_0_XY_MAG(tu6_tex_filter(pCreateInfo->magFilter, aniso)) |2185A6XX_TEX_SAMP_0_XY_MIN(tu6_tex_filter(pCreateInfo->minFilter, aniso)) |2186A6XX_TEX_SAMP_0_ANISO(aniso) |2187A6XX_TEX_SAMP_0_WRAP_S(tu6_tex_wrap(pCreateInfo->addressModeU)) |2188A6XX_TEX_SAMP_0_WRAP_T(tu6_tex_wrap(pCreateInfo->addressModeV)) |2189A6XX_TEX_SAMP_0_WRAP_R(tu6_tex_wrap(pCreateInfo->addressModeW)) |2190A6XX_TEX_SAMP_0_LOD_BIAS(pCreateInfo->mipLodBias);2191sampler->descriptor[1] =2192/* COND(!cso->seamless_cube_map, A6XX_TEX_SAMP_1_CUBEMAPSEAMLESSFILTOFF) | */2193COND(pCreateInfo->unnormalizedCoordinates, A6XX_TEX_SAMP_1_UNNORM_COORDS) |2194A6XX_TEX_SAMP_1_MIN_LOD(min_lod) |2195A6XX_TEX_SAMP_1_MAX_LOD(max_lod) |2196COND(pCreateInfo->compareEnable,2197A6XX_TEX_SAMP_1_COMPARE_FUNC(tu6_compare_func(pCreateInfo->compareOp)));2198sampler->descriptor[2] = A6XX_TEX_SAMP_2_BCOLOR(border_color);2199sampler->descriptor[3] = 0;22002201if (reduction) {2202sampler->descriptor[2] |= A6XX_TEX_SAMP_2_REDUCTION_MODE(2203tu6_reduction_mode(reduction->reductionMode));2204}22052206sampler->ycbcr_sampler = ycbcr_conversion ?2207tu_sampler_ycbcr_conversion_from_handle(ycbcr_conversion->conversion) : NULL;22082209if (sampler->ycbcr_sampler &&2210sampler->ycbcr_sampler->chroma_filter == VK_FILTER_LINEAR) {2211sampler->descriptor[2] |= A6XX_TEX_SAMP_2_CHROMA_LINEAR;2212}22132214/* TODO:2215* A6XX_TEX_SAMP_1_MIPFILTER_LINEAR_FAR disables mipmapping, but vk has no NONE mipfilter?2216*/2217}22182219VKAPI_ATTR VkResult VKAPI_CALL2220tu_CreateSampler(VkDevice _device,2221const VkSamplerCreateInfo *pCreateInfo,2222const VkAllocationCallbacks *pAllocator,2223VkSampler *pSampler)2224{2225TU_FROM_HANDLE(tu_device, device, _device);2226struct tu_sampler *sampler;22272228assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);22292230sampler = vk_object_alloc(&device->vk, pAllocator, sizeof(*sampler),2231VK_OBJECT_TYPE_SAMPLER);2232if (!sampler)2233return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);22342235tu_init_sampler(device, sampler, pCreateInfo);2236*pSampler = tu_sampler_to_handle(sampler);22372238return VK_SUCCESS;2239}22402241VKAPI_ATTR void VKAPI_CALL2242tu_DestroySampler(VkDevice _device,2243VkSampler _sampler,2244const VkAllocationCallbacks *pAllocator)2245{2246TU_FROM_HANDLE(tu_device, device, _device);2247TU_FROM_HANDLE(tu_sampler, sampler, _sampler);2248uint32_t border_color;22492250if (!sampler)2251return;22522253border_color = (sampler->descriptor[2] & A6XX_TEX_SAMP_2_BCOLOR__MASK) >> A6XX_TEX_SAMP_2_BCOLOR__SHIFT;2254if (border_color >= TU_BORDER_COLOR_BUILTIN) {2255border_color -= TU_BORDER_COLOR_BUILTIN;2256/* if the sampler had a custom border color, free it. TODO: no lock */2257mtx_lock(&device->mutex);2258assert(!BITSET_TEST(device->custom_border_color, border_color));2259BITSET_SET(device->custom_border_color, border_color);2260mtx_unlock(&device->mutex);2261}22622263vk_object_free(&device->vk, pAllocator, sampler);2264}22652266/* vk_icd.h does not declare this function, so we declare it here to2267* suppress Wmissing-prototypes.2268*/2269PUBLIC VKAPI_ATTR VkResult VKAPI_CALL2270vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t *pSupportedVersion);22712272PUBLIC VKAPI_ATTR VkResult VKAPI_CALL2273vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t *pSupportedVersion)2274{2275/* For the full details on loader interface versioning, see2276* <https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/loader/LoaderAndLayerInterface.md>.2277* What follows is a condensed summary, to help you navigate the large and2278* confusing official doc.2279*2280* - Loader interface v0 is incompatible with later versions. We don't2281* support it.2282*2283* - In loader interface v1:2284* - The first ICD entrypoint called by the loader is2285* vk_icdGetInstanceProcAddr(). The ICD must statically expose this2286* entrypoint.2287* - The ICD must statically expose no other Vulkan symbol unless it2288* is linked with -Bsymbolic.2289* - Each dispatchable Vulkan handle created by the ICD must be2290* a pointer to a struct whose first member is VK_LOADER_DATA. The2291* ICD must initialize VK_LOADER_DATA.loadMagic to2292* ICD_LOADER_MAGIC.2293* - The loader implements vkCreate{PLATFORM}SurfaceKHR() and2294* vkDestroySurfaceKHR(). The ICD must be capable of working with2295* such loader-managed surfaces.2296*2297* - Loader interface v2 differs from v1 in:2298* - The first ICD entrypoint called by the loader is2299* vk_icdNegotiateLoaderICDInterfaceVersion(). The ICD must2300* statically expose this entrypoint.2301*2302* - Loader interface v3 differs from v2 in:2303* - The ICD must implement vkCreate{PLATFORM}SurfaceKHR(),2304* vkDestroySurfaceKHR(), and other API which uses VKSurfaceKHR,2305* because the loader no longer does so.2306*/2307*pSupportedVersion = MIN2(*pSupportedVersion, 3u);2308return VK_SUCCESS;2309}23102311VKAPI_ATTR VkResult VKAPI_CALL2312tu_GetMemoryFdKHR(VkDevice _device,2313const VkMemoryGetFdInfoKHR *pGetFdInfo,2314int *pFd)2315{2316TU_FROM_HANDLE(tu_device, device, _device);2317TU_FROM_HANDLE(tu_device_memory, memory, pGetFdInfo->memory);23182319assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR);23202321/* At the moment, we support only the below handle types. */2322assert(pGetFdInfo->handleType ==2323VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||2324pGetFdInfo->handleType ==2325VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);23262327int prime_fd = tu_bo_export_dmabuf(device, &memory->bo);2328if (prime_fd < 0)2329return vk_error(device->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY);23302331*pFd = prime_fd;2332return VK_SUCCESS;2333}23342335VKAPI_ATTR VkResult VKAPI_CALL2336tu_GetMemoryFdPropertiesKHR(VkDevice _device,2337VkExternalMemoryHandleTypeFlagBits handleType,2338int fd,2339VkMemoryFdPropertiesKHR *pMemoryFdProperties)2340{2341assert(handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);2342pMemoryFdProperties->memoryTypeBits = 1;2343return VK_SUCCESS;2344}23452346VKAPI_ATTR void VKAPI_CALL2347tu_GetPhysicalDeviceExternalFenceProperties(2348VkPhysicalDevice physicalDevice,2349const VkPhysicalDeviceExternalFenceInfo *pExternalFenceInfo,2350VkExternalFenceProperties *pExternalFenceProperties)2351{2352pExternalFenceProperties->exportFromImportedHandleTypes = 0;2353pExternalFenceProperties->compatibleHandleTypes = 0;2354pExternalFenceProperties->externalFenceFeatures = 0;2355}23562357VKAPI_ATTR void VKAPI_CALL2358tu_GetDeviceGroupPeerMemoryFeatures(2359VkDevice device,2360uint32_t heapIndex,2361uint32_t localDeviceIndex,2362uint32_t remoteDeviceIndex,2363VkPeerMemoryFeatureFlags *pPeerMemoryFeatures)2364{2365assert(localDeviceIndex == remoteDeviceIndex);23662367*pPeerMemoryFeatures = VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT |2368VK_PEER_MEMORY_FEATURE_COPY_DST_BIT |2369VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT |2370VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT;2371}23722373VKAPI_ATTR void VKAPI_CALL2374tu_GetPhysicalDeviceMultisamplePropertiesEXT(2375VkPhysicalDevice physicalDevice,2376VkSampleCountFlagBits samples,2377VkMultisamplePropertiesEXT* pMultisampleProperties)2378{2379TU_FROM_HANDLE(tu_physical_device, pdevice, physicalDevice);23802381if (samples <= VK_SAMPLE_COUNT_4_BIT && pdevice->vk.supported_extensions.EXT_sample_locations)2382pMultisampleProperties->maxSampleLocationGridSize = (VkExtent2D){ 1, 1 };2383else2384pMultisampleProperties->maxSampleLocationGridSize = (VkExtent2D){ 0, 0 };2385}238623872388