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