1/* 2 * Copyright © 2019 Raspberry Pi Ltd 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24#include <assert.h> 25#include <fcntl.h> 26#include <stdbool.h> 27#include <string.h> 28#include <sys/mman.h> 29#include <sys/sysinfo.h> 30#include <unistd.h> 31#include <xf86drm.h> 32 33#ifdef MAJOR_IN_MKDEV 34#include <sys/mkdev.h> 35#endif 36#ifdef MAJOR_IN_SYSMACROS 37#include <sys/sysmacros.h> 38#endif 39 40#include "v3dv_private.h" 41 42#include "common/v3d_debug.h" 43 44#include "compiler/v3d_compiler.h" 45 46#include "drm-uapi/v3d_drm.h" 47#include "format/u_format.h" 48#include "vk_drm_syncobj.h" 49#include "vk_util.h" 50#include "git_sha1.h" 51 52#include "util/build_id.h" 53#include "util/debug.h" 54 55#ifdef VK_USE_PLATFORM_XCB_KHR 56#include <xcb/xcb.h> 57#include <xcb/dri3.h> 58#include <X11/Xlib-xcb.h> 59#endif 60 61#ifdef VK_USE_PLATFORM_WAYLAND_KHR 62#include <wayland-client.h> 63#include "wayland-drm-client-protocol.h" 64#endif 65 66#ifndef ANDROID 67# define V3DV_API_VERSION VK_MAKE_VERSION(1, 2, VK_HEADER_VERSION) 68#else 69/* Android CDD require additional extensions for API v1.1+ */ 70# define V3DV_API_VERSION VK_MAKE_VERSION(1, 0, VK_HEADER_VERSION) 71#endif 72 73VKAPI_ATTR VkResult VKAPI_CALL 74v3dv_EnumerateInstanceVersion(uint32_t *pApiVersion) 75{ 76 *pApiVersion = V3DV_API_VERSION; 77 return VK_SUCCESS; 78} 79 80#if defined(VK_USE_PLATFORM_WIN32_KHR) || \ 81 defined(VK_USE_PLATFORM_WAYLAND_KHR) || \ 82 defined(VK_USE_PLATFORM_XCB_KHR) || \ 83 defined(VK_USE_PLATFORM_XLIB_KHR) || \ 84 defined(VK_USE_PLATFORM_DISPLAY_KHR) 85#define V3DV_USE_WSI_PLATFORM 86#endif 87 88static const struct vk_instance_extension_table instance_extensions = { 89 .KHR_device_group_creation = true, 90#ifdef VK_USE_PLATFORM_DISPLAY_KHR 91 .KHR_display = true, 92 .KHR_get_display_properties2 = true, 93#endif 94 .KHR_external_fence_capabilities = true, 95 .KHR_external_memory_capabilities = true, 96 .KHR_external_semaphore_capabilities = true, 97 .KHR_get_physical_device_properties2 = true, 98#ifdef V3DV_USE_WSI_PLATFORM 99 .KHR_get_surface_capabilities2 = true, 100 .KHR_surface = true, 101 .KHR_surface_protected_capabilities = true, 102#endif 103#ifdef VK_USE_PLATFORM_WAYLAND_KHR 104 .KHR_wayland_surface = true, 105#endif 106#ifdef VK_USE_PLATFORM_XCB_KHR 107 .KHR_xcb_surface = true, 108#endif 109#ifdef VK_USE_PLATFORM_XLIB_KHR 110 .KHR_xlib_surface = true, 111#endif 112 .EXT_debug_report = true, 113 .EXT_debug_utils = true, 114}; 115 116static void 117get_device_extensions(const struct v3dv_physical_device *device, 118 struct vk_device_extension_table *ext) 119{ 120 *ext = (struct vk_device_extension_table) { 121 .KHR_8bit_storage = true, 122 .KHR_16bit_storage = true, 123 .KHR_bind_memory2 = true, 124 .KHR_buffer_device_address = true, 125 .KHR_copy_commands2 = true, 126 .KHR_create_renderpass2 = true, 127 .KHR_dedicated_allocation = true, 128 .KHR_device_group = true, 129 .KHR_driver_properties = true, 130 .KHR_descriptor_update_template = true, 131 .KHR_depth_stencil_resolve = true, 132 .KHR_external_fence = true, 133 .KHR_external_fence_fd = true, 134 .KHR_external_memory = true, 135 .KHR_external_memory_fd = true, 136 .KHR_external_semaphore = true, 137 .KHR_external_semaphore_fd = true, 138 .KHR_format_feature_flags2 = true, 139 .KHR_get_memory_requirements2 = true, 140 .KHR_image_format_list = true, 141 .KHR_imageless_framebuffer = true, 142 .KHR_performance_query = device->caps.perfmon, 143 .KHR_relaxed_block_layout = true, 144 .KHR_maintenance1 = true, 145 .KHR_maintenance2 = true, 146 .KHR_maintenance3 = true, 147 .KHR_multiview = true, 148 .KHR_pipeline_executable_properties = true, 149 .KHR_separate_depth_stencil_layouts = true, 150 .KHR_shader_float_controls = true, 151 .KHR_shader_non_semantic_info = true, 152 .KHR_sampler_mirror_clamp_to_edge = true, 153 .KHR_spirv_1_4 = true, 154 .KHR_storage_buffer_storage_class = true, 155 .KHR_timeline_semaphore = true, 156 .KHR_uniform_buffer_standard_layout = true, 157#ifdef V3DV_USE_WSI_PLATFORM 158 .KHR_swapchain = true, 159 .KHR_swapchain_mutable_format = true, 160 .KHR_incremental_present = true, 161#endif 162 .KHR_variable_pointers = true, 163 .KHR_vulkan_memory_model = true, 164 .EXT_4444_formats = true, 165 .EXT_color_write_enable = true, 166 .EXT_custom_border_color = true, 167 .EXT_inline_uniform_block = true, 168 .EXT_external_memory_dma_buf = true, 169 .EXT_host_query_reset = true, 170 .EXT_image_drm_format_modifier = true, 171 .EXT_index_type_uint8 = true, 172 .EXT_line_rasterization = true, 173 .EXT_physical_device_drm = true, 174 .EXT_pipeline_creation_cache_control = true, 175 .EXT_pipeline_creation_feedback = true, 176 .EXT_private_data = true, 177 .EXT_provoking_vertex = true, 178 .EXT_separate_stencil_usage = true, 179 .EXT_vertex_attribute_divisor = true, 180#ifdef ANDROID 181 .ANDROID_native_buffer = true, 182#endif 183 }; 184} 185 186VKAPI_ATTR VkResult VKAPI_CALL 187v3dv_EnumerateInstanceExtensionProperties(const char *pLayerName, 188 uint32_t *pPropertyCount, 189 VkExtensionProperties *pProperties) 190{ 191 /* We don't support any layers */ 192 if (pLayerName) 193 return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT); 194 195 return vk_enumerate_instance_extension_properties( 196 &instance_extensions, pPropertyCount, pProperties); 197} 198 199VKAPI_ATTR VkResult VKAPI_CALL 200v3dv_CreateInstance(const VkInstanceCreateInfo *pCreateInfo, 201 const VkAllocationCallbacks *pAllocator, 202 VkInstance *pInstance) 203{ 204 struct v3dv_instance *instance; 205 VkResult result; 206 207 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO); 208 209 if (pAllocator == NULL) 210 pAllocator = vk_default_allocator(); 211 212 instance = vk_alloc(pAllocator, sizeof(*instance), 8, 213 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 214 if (!instance) 215 return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY); 216 217 struct vk_instance_dispatch_table dispatch_table; 218 vk_instance_dispatch_table_from_entrypoints( 219 &dispatch_table, &v3dv_instance_entrypoints, true); 220 vk_instance_dispatch_table_from_entrypoints( 221 &dispatch_table, &wsi_instance_entrypoints, false); 222 223 result = vk_instance_init(&instance->vk, 224 &instance_extensions, 225 &dispatch_table, 226 pCreateInfo, pAllocator); 227 228 if (result != VK_SUCCESS) { 229 vk_free(pAllocator, instance); 230 return vk_error(NULL, result); 231 } 232 233 v3d_process_debug_variable(); 234 235 instance->physicalDeviceCount = -1; 236 237 /* We start with the default values for the pipeline_cache envvars */ 238 instance->pipeline_cache_enabled = true; 239 instance->default_pipeline_cache_enabled = true; 240 const char *pipeline_cache_str = getenv("V3DV_ENABLE_PIPELINE_CACHE"); 241 if (pipeline_cache_str != NULL) { 242 if (strncmp(pipeline_cache_str, "full", 4) == 0) { 243 /* nothing to do, just to filter correct values */ 244 } else if (strncmp(pipeline_cache_str, "no-default-cache", 16) == 0) { 245 instance->default_pipeline_cache_enabled = false; 246 } else if (strncmp(pipeline_cache_str, "off", 3) == 0) { 247 instance->pipeline_cache_enabled = false; 248 instance->default_pipeline_cache_enabled = false; 249 } else { 250 fprintf(stderr, "Wrong value for envvar V3DV_ENABLE_PIPELINE_CACHE. " 251 "Allowed values are: full, no-default-cache, off\n"); 252 } 253 } 254 255 if (instance->pipeline_cache_enabled == false) { 256 fprintf(stderr, "WARNING: v3dv pipeline cache is disabled. Performance " 257 "can be affected negatively\n"); 258 } else { 259 if (instance->default_pipeline_cache_enabled == false) { 260 fprintf(stderr, "WARNING: default v3dv pipeline cache is disabled. " 261 "Performance can be affected negatively\n"); 262 } 263 } 264 265 VG(VALGRIND_CREATE_MEMPOOL(instance, 0, false)); 266 267 *pInstance = v3dv_instance_to_handle(instance); 268 269 return VK_SUCCESS; 270} 271 272static void 273v3dv_physical_device_free_disk_cache(struct v3dv_physical_device *device) 274{ 275#ifdef ENABLE_SHADER_CACHE 276 if (device->disk_cache) 277 disk_cache_destroy(device->disk_cache); 278#else 279 assert(device->disk_cache == NULL); 280#endif 281} 282 283static void 284physical_device_finish(struct v3dv_physical_device *device) 285{ 286 v3dv_wsi_finish(device); 287 v3dv_physical_device_free_disk_cache(device); 288 v3d_compiler_free(device->compiler); 289 290 util_sparse_array_finish(&device->bo_map); 291 292 close(device->render_fd); 293 if (device->display_fd >= 0) 294 close(device->display_fd); 295 if (device->master_fd >= 0) 296 close(device->master_fd); 297 298 free(device->name); 299 300#if using_v3d_simulator 301 v3d_simulator_destroy(device->sim_file); 302#endif 303 304 vk_physical_device_finish(&device->vk); 305 mtx_destroy(&device->mutex); 306} 307 308VKAPI_ATTR void VKAPI_CALL 309v3dv_DestroyInstance(VkInstance _instance, 310 const VkAllocationCallbacks *pAllocator) 311{ 312 V3DV_FROM_HANDLE(v3dv_instance, instance, _instance); 313 314 if (!instance) 315 return; 316 317 if (instance->physicalDeviceCount > 0) { 318 /* We support at most one physical device. */ 319 assert(instance->physicalDeviceCount == 1); 320 physical_device_finish(&instance->physicalDevice); 321 } 322 323 VG(VALGRIND_DESTROY_MEMPOOL(instance)); 324 325 vk_instance_finish(&instance->vk); 326 vk_free(&instance->vk.alloc, instance); 327} 328 329static uint64_t 330compute_heap_size() 331{ 332#if !using_v3d_simulator 333 /* Query the total ram from the system */ 334 struct sysinfo info; 335 sysinfo(&info); 336 337 uint64_t total_ram = (uint64_t)info.totalram * (uint64_t)info.mem_unit; 338#else 339 uint64_t total_ram = (uint64_t) v3d_simulator_get_mem_size(); 340#endif 341 342 /* We don't want to burn too much ram with the GPU. If the user has 4GiB 343 * or less, we use at most half. If they have more than 4GiB, we use 3/4. 344 */ 345 uint64_t available_ram; 346 if (total_ram <= 4ull * 1024ull * 1024ull * 1024ull) 347 available_ram = total_ram / 2; 348 else 349 available_ram = total_ram * 3 / 4; 350 351 return available_ram; 352} 353 354#if !using_v3d_simulator 355#ifdef VK_USE_PLATFORM_XCB_KHR 356static int 357create_display_fd_xcb(VkIcdSurfaceBase *surface) 358{ 359 int fd = -1; 360 361 xcb_connection_t *conn; 362 xcb_dri3_open_reply_t *reply = NULL; 363 if (surface) { 364 if (surface->platform == VK_ICD_WSI_PLATFORM_XLIB) 365 conn = XGetXCBConnection(((VkIcdSurfaceXlib *)surface)->dpy); 366 else 367 conn = ((VkIcdSurfaceXcb *)surface)->connection; 368 } else { 369 conn = xcb_connect(NULL, NULL); 370 } 371 372 if (xcb_connection_has_error(conn)) 373 goto finish; 374 375 const xcb_setup_t *setup = xcb_get_setup(conn); 376 xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup); 377 xcb_screen_t *screen = iter.data; 378 379 xcb_dri3_open_cookie_t cookie; 380 cookie = xcb_dri3_open(conn, screen->root, None); 381 reply = xcb_dri3_open_reply(conn, cookie, NULL); 382 if (!reply) 383 goto finish; 384 385 if (reply->nfd != 1) 386 goto finish; 387 388 fd = xcb_dri3_open_reply_fds(conn, reply)[0]; 389 fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); 390 391finish: 392 if (!surface) 393 xcb_disconnect(conn); 394 if (reply) 395 free(reply); 396 397 return fd; 398} 399#endif 400 401#ifdef VK_USE_PLATFORM_WAYLAND_KHR 402struct v3dv_wayland_info { 403 struct wl_drm *wl_drm; 404 int fd; 405 bool is_set; 406 bool authenticated; 407}; 408 409static void 410v3dv_drm_handle_device(void *data, struct wl_drm *drm, const char *device) 411{ 412 struct v3dv_wayland_info *info = data; 413 info->fd = open(device, O_RDWR | O_CLOEXEC); 414 info->is_set = info->fd != -1; 415 if (!info->is_set) { 416 fprintf(stderr, "v3dv_drm_handle_device: could not open %s (%s)\n", 417 device, strerror(errno)); 418 return; 419 } 420 421 drm_magic_t magic; 422 if (drmGetMagic(info->fd, &magic)) { 423 fprintf(stderr, "v3dv_drm_handle_device: drmGetMagic failed\n"); 424 close(info->fd); 425 info->fd = -1; 426 info->is_set = false; 427 return; 428 } 429 wl_drm_authenticate(info->wl_drm, magic); 430} 431 432static void 433v3dv_drm_handle_format(void *data, struct wl_drm *drm, uint32_t format) 434{ 435} 436 437static void 438v3dv_drm_handle_authenticated(void *data, struct wl_drm *drm) 439{ 440 struct v3dv_wayland_info *info = data; 441 info->authenticated = true; 442} 443 444static void 445v3dv_drm_handle_capabilities(void *data, struct wl_drm *drm, uint32_t value) 446{ 447} 448 449struct wl_drm_listener v3dv_drm_listener = { 450 .device = v3dv_drm_handle_device, 451 .format = v3dv_drm_handle_format, 452 .authenticated = v3dv_drm_handle_authenticated, 453 .capabilities = v3dv_drm_handle_capabilities 454}; 455 456static void 457v3dv_registry_global(void *data, 458 struct wl_registry *registry, 459 uint32_t name, 460 const char *interface, 461 uint32_t version) 462{ 463 struct v3dv_wayland_info *info = data; 464 if (strcmp(interface, "wl_drm") == 0) { 465 info->wl_drm = wl_registry_bind(registry, name, &wl_drm_interface, 466 MIN2(version, 2)); 467 wl_drm_add_listener(info->wl_drm, &v3dv_drm_listener, data); 468 }; 469} 470 471static void 472v3dv_registry_global_remove_cb(void *data, 473 struct wl_registry *registry, 474 uint32_t name) 475{ 476} 477 478static int 479create_display_fd_wayland(VkIcdSurfaceBase *surface) 480{ 481 struct wl_display *display; 482 struct wl_registry *registry = NULL; 483 484 struct v3dv_wayland_info info = { 485 .wl_drm = NULL, 486 .fd = -1, 487 .is_set = false, 488 .authenticated = false 489 }; 490 491 if (surface) 492 display = ((VkIcdSurfaceWayland *) surface)->display; 493 else 494 display = wl_display_connect(NULL); 495 496 if (!display) 497 return -1; 498 499 registry = wl_display_get_registry(display); 500 if (!registry) { 501 if (!surface) 502 wl_display_disconnect(display); 503 return -1; 504 } 505 506 static const struct wl_registry_listener registry_listener = { 507 v3dv_registry_global, 508 v3dv_registry_global_remove_cb 509 }; 510 wl_registry_add_listener(registry, ®istry_listener, &info); 511 512 wl_display_roundtrip(display); /* For the registry advertisement */ 513 wl_display_roundtrip(display); /* For the DRM device event */ 514 wl_display_roundtrip(display); /* For the authentication event */ 515 516 wl_drm_destroy(info.wl_drm); 517 wl_registry_destroy(registry); 518 519 if (!surface) 520 wl_display_disconnect(display); 521 522 if (!info.is_set) 523 return -1; 524 525 if (!info.authenticated) 526 return -1; 527 528 return info.fd; 529} 530#endif 531 532/* Acquire an authenticated display fd without a surface reference. This is the 533 * case where the application is making WSI allocations outside the Vulkan 534 * swapchain context (only Zink, for now). Since we lack information about the 535 * underlying surface we just try our best to figure out the correct display 536 * and platform to use. It should work in most cases. 537 */ 538static void 539acquire_display_device_no_surface(struct v3dv_instance *instance, 540 struct v3dv_physical_device *pdevice) 541{ 542#ifdef VK_USE_PLATFORM_WAYLAND_KHR 543 pdevice->display_fd = create_display_fd_wayland(NULL); 544#endif 545 546#ifdef VK_USE_PLATFORM_XCB_KHR 547 if (pdevice->display_fd == -1) 548 pdevice->display_fd = create_display_fd_xcb(NULL); 549#endif 550 551#ifdef VK_USE_PLATFORM_DISPLAY_KHR 552 if (pdevice->display_fd == - 1 && pdevice->master_fd >= 0) 553 pdevice->display_fd = dup(pdevice->master_fd); 554#endif 555} 556 557/* Acquire an authenticated display fd from the surface. This is the regular 558 * case where the application is using swapchains to create WSI allocations. 559 * In this case we use the surface information to figure out the correct 560 * display and platform combination. 561 */ 562static void 563acquire_display_device_surface(struct v3dv_instance *instance, 564 struct v3dv_physical_device *pdevice, 565 VkIcdSurfaceBase *surface) 566{ 567 /* Mesa will set both of VK_USE_PLATFORM_{XCB,XLIB} when building with 568 * platform X11, so only check for XCB and rely on XCB to get an 569 * authenticated device also for Xlib. 570 */ 571#ifdef VK_USE_PLATFORM_XCB_KHR 572 if (surface->platform == VK_ICD_WSI_PLATFORM_XCB || 573 surface->platform == VK_ICD_WSI_PLATFORM_XLIB) { 574 pdevice->display_fd = create_display_fd_xcb(surface); 575 } 576#endif 577 578#ifdef VK_USE_PLATFORM_WAYLAND_KHR 579 if (surface->platform == VK_ICD_WSI_PLATFORM_WAYLAND) 580 pdevice->display_fd = create_display_fd_wayland(surface); 581#endif 582 583#ifdef VK_USE_PLATFORM_DISPLAY_KHR 584 if (surface->platform == VK_ICD_WSI_PLATFORM_DISPLAY && 585 pdevice->master_fd >= 0) { 586 pdevice->display_fd = dup(pdevice->master_fd); 587 } 588#endif 589} 590#endif /* !using_v3d_simulator */ 591 592/* Attempts to get an authenticated display fd from the display server that 593 * we can use to allocate BOs for presentable images. 594 */ 595VkResult 596v3dv_physical_device_acquire_display(struct v3dv_instance *instance, 597 struct v3dv_physical_device *pdevice, 598 VkIcdSurfaceBase *surface) 599{ 600 VkResult result = VK_SUCCESS; 601 mtx_lock(&pdevice->mutex); 602 603 if (pdevice->display_fd != -1) 604 goto done; 605 606 /* When running on the simulator we do everything on a single render node so 607 * we don't need to get an authenticated display fd from the display server. 608 */ 609#if !using_v3d_simulator 610 if (surface) 611 acquire_display_device_surface(instance, pdevice, surface); 612 else 613 acquire_display_device_no_surface(instance, pdevice); 614 615 if (pdevice->display_fd == -1) 616 result = VK_ERROR_INITIALIZATION_FAILED; 617#endif 618 619done: 620 mtx_unlock(&pdevice->mutex); 621 return result; 622} 623 624static bool 625v3d_has_feature(struct v3dv_physical_device *device, enum drm_v3d_param feature) 626{ 627 struct drm_v3d_get_param p = { 628 .param = feature, 629 }; 630 if (v3dv_ioctl(device->render_fd, DRM_IOCTL_V3D_GET_PARAM, &p) != 0) 631 return false; 632 return p.value; 633} 634 635static bool 636device_has_expected_features(struct v3dv_physical_device *device) 637{ 638 return v3d_has_feature(device, DRM_V3D_PARAM_SUPPORTS_TFU) && 639 v3d_has_feature(device, DRM_V3D_PARAM_SUPPORTS_CSD) && 640 v3d_has_feature(device, DRM_V3D_PARAM_SUPPORTS_CACHE_FLUSH); 641} 642 643 644static VkResult 645init_uuids(struct v3dv_physical_device *device) 646{ 647 const struct build_id_note *note = 648 build_id_find_nhdr_for_addr(init_uuids); 649 if (!note) { 650 return vk_errorf(device->vk.instance, 651 VK_ERROR_INITIALIZATION_FAILED, 652 "Failed to find build-id"); 653 } 654 655 unsigned build_id_len = build_id_length(note); 656 if (build_id_len < 20) { 657 return vk_errorf(device->vk.instance, 658 VK_ERROR_INITIALIZATION_FAILED, 659 "build-id too short. It needs to be a SHA"); 660 } 661 662 memcpy(device->driver_build_sha1, build_id_data(note), 20); 663 664 uint32_t vendor_id = v3dv_physical_device_vendor_id(device); 665 uint32_t device_id = v3dv_physical_device_device_id(device); 666 667 struct mesa_sha1 sha1_ctx; 668 uint8_t sha1[20]; 669 STATIC_ASSERT(VK_UUID_SIZE <= sizeof(sha1)); 670 671 /* The pipeline cache UUID is used for determining when a pipeline cache is 672 * invalid. It needs both a driver build and the PCI ID of the device. 673 */ 674 _mesa_sha1_init(&sha1_ctx); 675 _mesa_sha1_update(&sha1_ctx, build_id_data(note), build_id_len); 676 _mesa_sha1_update(&sha1_ctx, &device_id, sizeof(device_id)); 677 _mesa_sha1_final(&sha1_ctx, sha1); 678 memcpy(device->pipeline_cache_uuid, sha1, VK_UUID_SIZE); 679 680 /* The driver UUID is used for determining sharability of images and memory 681 * between two Vulkan instances in separate processes. People who want to 682 * share memory need to also check the device UUID (below) so all this 683 * needs to be is the build-id. 684 */ 685 memcpy(device->driver_uuid, build_id_data(note), VK_UUID_SIZE); 686 687 /* The device UUID uniquely identifies the given device within the machine. 688 * Since we never have more than one device, this doesn't need to be a real 689 * UUID. 690 */ 691 _mesa_sha1_init(&sha1_ctx); 692 _mesa_sha1_update(&sha1_ctx, &vendor_id, sizeof(vendor_id)); 693 _mesa_sha1_update(&sha1_ctx, &device_id, sizeof(device_id)); 694 _mesa_sha1_final(&sha1_ctx, sha1); 695 memcpy(device->device_uuid, sha1, VK_UUID_SIZE); 696 697 return VK_SUCCESS; 698} 699 700static void 701v3dv_physical_device_init_disk_cache(struct v3dv_physical_device *device) 702{ 703#ifdef ENABLE_SHADER_CACHE 704 char timestamp[41]; 705 _mesa_sha1_format(timestamp, device->driver_build_sha1); 706 707 assert(device->name); 708 device->disk_cache = disk_cache_create(device->name, timestamp, 0); 709#else 710 device->disk_cache = NULL; 711#endif 712} 713 714static VkResult 715physical_device_init(struct v3dv_physical_device *device, 716 struct v3dv_instance *instance, 717 drmDevicePtr drm_render_device, 718 drmDevicePtr drm_primary_device) 719{ 720 VkResult result = VK_SUCCESS; 721 int32_t master_fd = -1; 722 int32_t render_fd = -1; 723 724 struct vk_physical_device_dispatch_table dispatch_table; 725 vk_physical_device_dispatch_table_from_entrypoints 726 (&dispatch_table, &v3dv_physical_device_entrypoints, true); 727 vk_physical_device_dispatch_table_from_entrypoints( 728 &dispatch_table, &wsi_physical_device_entrypoints, false); 729 730 result = vk_physical_device_init(&device->vk, &instance->vk, NULL, 731 &dispatch_table); 732 733 if (result != VK_SUCCESS) 734 goto fail; 735 736 assert(drm_render_device); 737 const char *path = drm_render_device->nodes[DRM_NODE_RENDER]; 738 render_fd = open(path, O_RDWR | O_CLOEXEC); 739 if (render_fd < 0) { 740 fprintf(stderr, "Opening %s failed: %s\n", path, strerror(errno)); 741 result = VK_ERROR_INCOMPATIBLE_DRIVER; 742 goto fail; 743 } 744 745 /* If we are running on VK_KHR_display we need to acquire the master 746 * display device now for the v3dv_wsi_init() call below. For anything else 747 * we postpone that until a swapchain is created. 748 */ 749 750 const char *primary_path; 751#if !using_v3d_simulator 752 if (drm_primary_device) 753 primary_path = drm_primary_device->nodes[DRM_NODE_PRIMARY]; 754 else 755 primary_path = NULL; 756#else 757 primary_path = drm_render_device->nodes[DRM_NODE_PRIMARY]; 758#endif 759 760 struct stat primary_stat = {0}, render_stat = {0}; 761 762 device->has_primary = primary_path; 763 if (device->has_primary) { 764 if (stat(primary_path, &primary_stat) != 0) { 765 result = vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED, 766 "failed to stat DRM primary node %s", 767 primary_path); 768 goto fail; 769 } 770 771 device->primary_devid = primary_stat.st_rdev; 772 } 773 774 if (fstat(render_fd, &render_stat) != 0) { 775 result = vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED, 776 "failed to stat DRM render node %s", 777 path); 778 goto fail; 779 } 780 device->has_render = true; 781 device->render_devid = render_stat.st_rdev; 782 783#if using_v3d_simulator 784 device->device_id = drm_render_device->deviceinfo.pci->device_id; 785#endif 786 787 if (instance->vk.enabled_extensions.KHR_display) { 788#if !using_v3d_simulator 789 /* Open the primary node on the vc4 display device */ 790 assert(drm_primary_device); 791 master_fd = open(primary_path, O_RDWR | O_CLOEXEC); 792#else 793 /* There is only one device with primary and render nodes. 794 * Open its primary node. 795 */ 796 master_fd = open(primary_path, O_RDWR | O_CLOEXEC); 797#endif 798 } 799 800#if using_v3d_simulator 801 device->sim_file = v3d_simulator_init(render_fd); 802#endif 803 804 device->render_fd = render_fd; /* The v3d render node */ 805 device->display_fd = -1; /* Authenticated vc4 primary node */ 806 device->master_fd = master_fd; /* Master vc4 primary node */ 807 808 if (!v3d_get_device_info(device->render_fd, &device->devinfo, &v3dv_ioctl)) { 809 result = VK_ERROR_INCOMPATIBLE_DRIVER; 810 goto fail; 811 } 812 813 if (device->devinfo.ver < 42) { 814 result = VK_ERROR_INCOMPATIBLE_DRIVER; 815 goto fail; 816 } 817 818 if (!device_has_expected_features(device)) { 819 result = VK_ERROR_INCOMPATIBLE_DRIVER; 820 goto fail; 821 } 822 823 device->caps.multisync = 824 v3d_has_feature(device, DRM_V3D_PARAM_SUPPORTS_MULTISYNC_EXT); 825 826 device->caps.perfmon = 827 v3d_has_feature(device, DRM_V3D_PARAM_SUPPORTS_PERFMON); 828 829 result = init_uuids(device); 830 if (result != VK_SUCCESS) 831 goto fail; 832 833 device->compiler = v3d_compiler_init(&device->devinfo, 834 MAX_INLINE_UNIFORM_BUFFERS); 835 device->next_program_id = 0; 836 837 ASSERTED int len = 838 asprintf(&device->name, "V3D %d.%d", 839 device->devinfo.ver / 10, device->devinfo.ver % 10); 840 assert(len != -1); 841 842 v3dv_physical_device_init_disk_cache(device); 843 844 /* Setup available memory heaps and types */ 845 VkPhysicalDeviceMemoryProperties *mem = &device->memory; 846 mem->memoryHeapCount = 1; 847 mem->memoryHeaps[0].size = compute_heap_size(); 848 mem->memoryHeaps[0].flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT; 849 850 /* This is the only combination required by the spec */ 851 mem->memoryTypeCount = 1; 852 mem->memoryTypes[0].propertyFlags = 853 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | 854 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | 855 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; 856 mem->memoryTypes[0].heapIndex = 0; 857 858 /* Initialize sparse array for refcounting imported BOs */ 859 util_sparse_array_init(&device->bo_map, sizeof(struct v3dv_bo), 512); 860 861 device->options.merge_jobs = !(V3D_DEBUG & V3D_DEBUG_NO_MERGE_JOBS); 862 863 device->drm_syncobj_type = vk_drm_syncobj_get_type(device->render_fd); 864 865 /* We don't support timelines in the uAPI yet and we don't want it getting 866 * suddenly turned on by vk_drm_syncobj_get_type() without us adding v3dv 867 * code for it first. 868 */ 869 device->drm_syncobj_type.features &= ~VK_SYNC_FEATURE_TIMELINE; 870 871#ifndef ANDROID 872 /* Sync file export is incompatible with the current model of execution 873 * where some jobs may run on the CPU. There are CTS tests which do the 874 * following: 875 * 876 * 1. Create a command buffer with a vkCmdWaitEvents() 877 * 2. Submit the command buffer 878 * 3. vkGetSemaphoreFdKHR() to try to get a sync_file 879 * 4. vkSetEvent() 880 * 881 * This deadlocks because we have to wait for the syncobj to get a real 882 * fence in vkGetSemaphoreFdKHR() which only happens after all the work 883 * from the command buffer is complete which only happens after 884 * vkSetEvent(). No amount of CPU threading in userspace will ever fix 885 * this. Sadly, this is pretty explicitly allowed by the Vulkan spec: 886 * 887 * VUID-vkCmdWaitEvents-pEvents-01163 888 * 889 * "If pEvents includes one or more events that will be signaled by 890 * vkSetEvent after commandBuffer has been submitted to a queue, then 891 * vkCmdWaitEvents must not be called inside a render pass instance" 892 * 893 * Disable sync file support for now. 894 */ 895 device->drm_syncobj_type.import_sync_file = NULL; 896 device->drm_syncobj_type.export_sync_file = NULL; 897#endif 898 899 /* Multiwait is required for emulated timeline semaphores and is supported 900 * by the v3d kernel interface. 901 */ 902 device->drm_syncobj_type.features |= VK_SYNC_FEATURE_GPU_MULTI_WAIT; 903 904 device->sync_timeline_type = 905 vk_sync_timeline_get_type(&device->drm_syncobj_type); 906 907 device->sync_types[0] = &device->drm_syncobj_type; 908 device->sync_types[1] = &device->sync_timeline_type.sync; 909 device->sync_types[2] = NULL; 910 device->vk.supported_sync_types = device->sync_types; 911 912 result = v3dv_wsi_init(device); 913 if (result != VK_SUCCESS) { 914 vk_error(instance, result); 915 goto fail; 916 } 917 918 get_device_extensions(device, &device->vk.supported_extensions); 919 920 mtx_init(&device->mutex, mtx_plain); 921 922 return VK_SUCCESS; 923 924fail: 925 vk_physical_device_finish(&device->vk); 926 927 if (render_fd >= 0) 928 close(render_fd); 929 if (master_fd >= 0) 930 close(master_fd); 931 932 return result; 933} 934 935static VkResult 936enumerate_devices(struct v3dv_instance *instance) 937{ 938 /* TODO: Check for more devices? */ 939 drmDevicePtr devices[8]; 940 VkResult result = VK_ERROR_INCOMPATIBLE_DRIVER; 941 int max_devices; 942 943 instance->physicalDeviceCount = 0; 944 945 max_devices = drmGetDevices2(0, devices, ARRAY_SIZE(devices)); 946 if (max_devices < 1) 947 return VK_ERROR_INCOMPATIBLE_DRIVER; 948 949#if !using_v3d_simulator 950 int32_t v3d_idx = -1; 951 int32_t vc4_idx = -1; 952#endif 953 for (unsigned i = 0; i < (unsigned)max_devices; i++) { 954#if using_v3d_simulator 955 /* In the simulator, we look for an Intel/AMD render node */ 956 const int required_nodes = (1 << DRM_NODE_RENDER) | (1 << DRM_NODE_PRIMARY); 957 if ((devices[i]->available_nodes & required_nodes) == required_nodes && 958 devices[i]->bustype == DRM_BUS_PCI && 959 (devices[i]->deviceinfo.pci->vendor_id == 0x8086 || 960 devices[i]->deviceinfo.pci->vendor_id == 0x1002)) { 961 result = physical_device_init(&instance->physicalDevice, instance, 962 devices[i], NULL); 963 if (result != VK_ERROR_INCOMPATIBLE_DRIVER) 964 break; 965 } 966#else 967 /* On actual hardware, we should have a render node (v3d) 968 * and a primary node (vc4). We will need to use the primary 969 * to allocate WSI buffers and share them with the render node 970 * via prime, but that is a privileged operation so we need the 971 * primary node to be authenticated, and for that we need the 972 * display server to provide the device fd (with DRI3), so we 973 * here we only check that the device is present but we don't 974 * try to open it. 975 */ 976 if (devices[i]->bustype != DRM_BUS_PLATFORM) 977 continue; 978 979 if (devices[i]->available_nodes & 1 << DRM_NODE_RENDER) { 980 char **compat = devices[i]->deviceinfo.platform->compatible; 981 while (*compat) { 982 if (strncmp(*compat, "brcm,2711-v3d", 13) == 0) { 983 v3d_idx = i; 984 break; 985 } 986 compat++; 987 } 988 } else if (devices[i]->available_nodes & 1 << DRM_NODE_PRIMARY) { 989 char **compat = devices[i]->deviceinfo.platform->compatible; 990 while (*compat) { 991 if (strncmp(*compat, "brcm,bcm2711-vc5", 16) == 0 || 992 strncmp(*compat, "brcm,bcm2835-vc4", 16) == 0 ) { 993 vc4_idx = i; 994 break; 995 } 996 compat++; 997 } 998 } 999#endif 1000 } 1001 1002#if !using_v3d_simulator 1003 if (v3d_idx == -1 || vc4_idx == -1) 1004 result = VK_ERROR_INCOMPATIBLE_DRIVER; 1005 else 1006 result = physical_device_init(&instance->physicalDevice, instance, 1007 devices[v3d_idx], devices[vc4_idx]); 1008#endif 1009 1010 drmFreeDevices(devices, max_devices); 1011 1012 if (result == VK_SUCCESS) 1013 instance->physicalDeviceCount = 1; 1014 1015 return result; 1016} 1017 1018static VkResult 1019instance_ensure_physical_device(struct v3dv_instance *instance) 1020{ 1021 if (instance->physicalDeviceCount < 0) { 1022 VkResult result = enumerate_devices(instance); 1023 if (result != VK_SUCCESS && 1024 result != VK_ERROR_INCOMPATIBLE_DRIVER) 1025 return result; 1026 } 1027 1028 return VK_SUCCESS; 1029} 1030 1031VKAPI_ATTR VkResult VKAPI_CALL 1032v3dv_EnumeratePhysicalDevices(VkInstance _instance, 1033 uint32_t *pPhysicalDeviceCount, 1034 VkPhysicalDevice *pPhysicalDevices) 1035{ 1036 V3DV_FROM_HANDLE(v3dv_instance, instance, _instance); 1037 VK_OUTARRAY_MAKE_TYPED(VkPhysicalDevice, out, 1038 pPhysicalDevices, pPhysicalDeviceCount); 1039 1040 VkResult result = instance_ensure_physical_device(instance); 1041 if (result != VK_SUCCESS) 1042 return result; 1043 1044 if (instance->physicalDeviceCount == 0) 1045 return VK_SUCCESS; 1046 1047 assert(instance->physicalDeviceCount == 1); 1048 vk_outarray_append_typed(VkPhysicalDevice, &out, i) { 1049 *i = v3dv_physical_device_to_handle(&instance->physicalDevice); 1050 } 1051 1052 return vk_outarray_status(&out); 1053} 1054 1055VKAPI_ATTR VkResult VKAPI_CALL 1056v3dv_EnumeratePhysicalDeviceGroups( 1057 VkInstance _instance, 1058 uint32_t *pPhysicalDeviceGroupCount, 1059 VkPhysicalDeviceGroupProperties *pPhysicalDeviceGroupProperties) 1060{ 1061 V3DV_FROM_HANDLE(v3dv_instance, instance, _instance); 1062 VK_OUTARRAY_MAKE_TYPED(VkPhysicalDeviceGroupProperties, out, 1063 pPhysicalDeviceGroupProperties, 1064 pPhysicalDeviceGroupCount); 1065 1066 VkResult result = instance_ensure_physical_device(instance); 1067 if (result != VK_SUCCESS) 1068 return result; 1069 1070 assert(instance->physicalDeviceCount == 1); 1071 1072 vk_outarray_append_typed(VkPhysicalDeviceGroupProperties, &out, p) { 1073 p->physicalDeviceCount = 1; 1074 memset(p->physicalDevices, 0, sizeof(p->physicalDevices)); 1075 p->physicalDevices[0] = 1076 v3dv_physical_device_to_handle(&instance->physicalDevice); 1077 p->subsetAllocation = false; 1078 1079 vk_foreach_struct(ext, p->pNext) 1080 v3dv_debug_ignored_stype(ext->sType); 1081 } 1082 1083 return vk_outarray_status(&out); 1084} 1085 1086VKAPI_ATTR void VKAPI_CALL 1087v3dv_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, 1088 VkPhysicalDeviceFeatures *pFeatures) 1089{ 1090 memset(pFeatures, 0, sizeof(*pFeatures)); 1091 1092 *pFeatures = (VkPhysicalDeviceFeatures) { 1093 .robustBufferAccess = true, /* This feature is mandatory */ 1094 .fullDrawIndexUint32 = false, /* Only available since V3D 4.4.9.1 */ 1095 .imageCubeArray = true, 1096 .independentBlend = true, 1097 .geometryShader = true, 1098 .tessellationShader = false, 1099 .sampleRateShading = true, 1100 .dualSrcBlend = false, 1101 .logicOp = true, 1102 .multiDrawIndirect = false, 1103 .drawIndirectFirstInstance = true, 1104 .depthClamp = false, /* Only available since V3D 4.5.1.1 */ 1105 .depthBiasClamp = true, 1106 .fillModeNonSolid = true, 1107 .depthBounds = false, /* Only available since V3D 4.3.16.2 */ 1108 .wideLines = true, 1109 .largePoints = true, 1110 .alphaToOne = true, 1111 .multiViewport = false, 1112 .samplerAnisotropy = true, 1113 .textureCompressionETC2 = true, 1114 .textureCompressionASTC_LDR = true, 1115 /* Note that textureCompressionBC requires that the driver support all 1116 * the BC formats. V3D 4.2 only support the BC1-3, so we can't claim 1117 * that we support it. 1118 */ 1119 .textureCompressionBC = false, 1120 .occlusionQueryPrecise = true, 1121 .pipelineStatisticsQuery = false, 1122 .vertexPipelineStoresAndAtomics = true, 1123 .fragmentStoresAndAtomics = true, 1124 .shaderTessellationAndGeometryPointSize = true, 1125 .shaderImageGatherExtended = false, 1126 .shaderStorageImageExtendedFormats = true, 1127 .shaderStorageImageMultisample = false, 1128 .shaderStorageImageReadWithoutFormat = false, 1129 .shaderStorageImageWriteWithoutFormat = false, 1130 .shaderUniformBufferArrayDynamicIndexing = false, 1131 .shaderSampledImageArrayDynamicIndexing = false, 1132 .shaderStorageBufferArrayDynamicIndexing = false, 1133 .shaderStorageImageArrayDynamicIndexing = false, 1134 .shaderClipDistance = true, 1135 .shaderCullDistance = false, 1136 .shaderFloat64 = false, 1137 .shaderInt64 = false, 1138 .shaderInt16 = false, 1139 .shaderResourceResidency = false, 1140 .shaderResourceMinLod = false, 1141 .sparseBinding = false, 1142 .sparseResidencyBuffer = false, 1143 .sparseResidencyImage2D = false, 1144 .sparseResidencyImage3D = false, 1145 .sparseResidency2Samples = false, 1146 .sparseResidency4Samples = false, 1147 .sparseResidency8Samples = false, 1148 .sparseResidency16Samples = false, 1149 .sparseResidencyAliased = false, 1150 .variableMultisampleRate = false, 1151 .inheritedQueries = true, 1152 }; 1153} 1154 1155VKAPI_ATTR void VKAPI_CALL 1156v3dv_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, 1157 VkPhysicalDeviceFeatures2 *pFeatures) 1158{ 1159 V3DV_FROM_HANDLE(v3dv_physical_device, physical_device, physicalDevice); 1160 v3dv_GetPhysicalDeviceFeatures(physicalDevice, &pFeatures->features); 1161 1162 VkPhysicalDeviceVulkan13Features vk13 = { 1163 .inlineUniformBlock = true, 1164 /* Inline buffers work like push constants, so after their are bound 1165 * some of their contents may be copied into the uniform stream as soon 1166 * as the next draw/dispatch is recorded in the command buffer. This means 1167 * that if the client updates the buffer contents after binding it to 1168 * a command buffer, the next queue submit of that command buffer may 1169 * not use the latest update to the buffer contents, but the data that 1170 * was present in the buffer at the time it was bound to the command 1171 * buffer. 1172 */ 1173 .descriptorBindingInlineUniformBlockUpdateAfterBind = false, 1174 .pipelineCreationCacheControl = true, 1175 .privateData = true, 1176 }; 1177 1178 VkPhysicalDeviceVulkan12Features vk12 = { 1179 .hostQueryReset = true, 1180 .uniformAndStorageBuffer8BitAccess = true, 1181 .uniformBufferStandardLayout = true, 1182 /* V3D 4.2 wraps TMU vector accesses to 16-byte boundaries, so loads and 1183 * stores of vectors that cross these boundaries would not work correcly 1184 * with scalarBlockLayout and would need to be split into smaller vectors 1185 * (and/or scalars) that don't cross these boundaries. For load/stores 1186 * with dynamic offsets where we can't identify if the offset is 1187 * problematic, we would always have to scalarize. Overall, this would 1188 * not lead to best performance so let's just not support it. 1189 */ 1190 .scalarBlockLayout = false, 1191 /* This tells applications 2 things: 1192 * 1193 * 1. If they can select just one aspect for barriers. For us barriers 1194 * decide if we need to split a job and we don't care if it is only 1195 * for one of the aspects of the image or both, so we don't really 1196 * benefit from seeing barriers that select just one aspect. 1197 * 1198 * 2. If they can program different layouts for each aspect. We 1199 * generally don't care about layouts, so again, we don't get any 1200 * benefits from this to limit the scope of image layout transitions. 1201 * 1202 * Still, Vulkan 1.2 requires this feature to be supported so we 1203 * advertise it even though we don't really take advantage of it. 1204 */ 1205 .separateDepthStencilLayouts = true, 1206 .storageBuffer8BitAccess = true, 1207 .storagePushConstant8 = true, 1208 .imagelessFramebuffer = true, 1209 .timelineSemaphore = true, 1210 1211 .samplerMirrorClampToEdge = true, 1212 1213 /* These are mandatory by Vulkan 1.2, however, we don't support any of 1214 * the optional features affected by them (non 32-bit types for 1215 * shaderSubgroupExtendedTypes and additional subgroup ballot for 1216 * subgroupBroadcastDynamicId), so in practice setting them to true 1217 * doesn't have any implications for us until we implement any of these 1218 * optional features. 1219 */ 1220 .shaderSubgroupExtendedTypes = true, 1221 .subgroupBroadcastDynamicId = true, 1222 1223 .vulkanMemoryModel = true, 1224 .vulkanMemoryModelDeviceScope = true, 1225 .vulkanMemoryModelAvailabilityVisibilityChains = true, 1226 1227 .bufferDeviceAddress = true, 1228 .bufferDeviceAddressCaptureReplay = false, 1229 .bufferDeviceAddressMultiDevice = false, 1230 }; 1231 1232 VkPhysicalDeviceVulkan11Features vk11 = { 1233 .storageBuffer16BitAccess = true, 1234 .uniformAndStorageBuffer16BitAccess = true, 1235 .storagePushConstant16 = true, 1236 .storageInputOutput16 = false, 1237 .multiview = true, 1238 .multiviewGeometryShader = false, 1239 .multiviewTessellationShader = false, 1240 .variablePointersStorageBuffer = true, 1241 /* FIXME: this needs support for non-constant index on UBO/SSBO */ 1242 .variablePointers = false, 1243 .protectedMemory = false, 1244 .samplerYcbcrConversion = false, 1245 .shaderDrawParameters = false, 1246 }; 1247 1248 vk_foreach_struct(ext, pFeatures->pNext) { 1249 if (vk_get_physical_device_core_1_1_feature_ext(ext, &vk11)) 1250 continue; 1251 if (vk_get_physical_device_core_1_2_feature_ext(ext, &vk12)) 1252 continue; 1253 if (vk_get_physical_device_core_1_3_feature_ext(ext, &vk13)) 1254 continue; 1255 1256 switch (ext->sType) { 1257 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT: { 1258 VkPhysicalDevice4444FormatsFeaturesEXT *features = 1259 (VkPhysicalDevice4444FormatsFeaturesEXT *)ext; 1260 features->formatA4R4G4B4 = true; 1261 features->formatA4B4G4R4 = true; 1262 break; 1263 } 1264 1265 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT: { 1266 VkPhysicalDeviceCustomBorderColorFeaturesEXT *features = 1267 (VkPhysicalDeviceCustomBorderColorFeaturesEXT *)ext; 1268 features->customBorderColors = true; 1269 features->customBorderColorWithoutFormat = false; 1270 break; 1271 } 1272 1273 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT: { 1274 VkPhysicalDeviceIndexTypeUint8FeaturesEXT *features = 1275 (VkPhysicalDeviceIndexTypeUint8FeaturesEXT *)ext; 1276 features->indexTypeUint8 = true; 1277 break; 1278 } 1279 1280 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT: { 1281 VkPhysicalDeviceLineRasterizationFeaturesEXT *features = 1282 (VkPhysicalDeviceLineRasterizationFeaturesEXT *)ext; 1283 features->rectangularLines = true; 1284 features->bresenhamLines = true; 1285 features->smoothLines = false; 1286 features->stippledRectangularLines = false; 1287 features->stippledBresenhamLines = false; 1288 features->stippledSmoothLines = false; 1289 break; 1290 } 1291 1292 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT: { 1293 VkPhysicalDeviceColorWriteEnableFeaturesEXT *features = (void *) ext; 1294 features->colorWriteEnable = true; 1295 break; 1296 } 1297 1298 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR: { 1299 VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR *features = 1300 (VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR *) ext; 1301 features->pipelineExecutableInfo = true; 1302 break; 1303 } 1304 1305 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT: { 1306 VkPhysicalDeviceProvokingVertexFeaturesEXT *features = (void *) ext; 1307 features->provokingVertexLast = true; 1308 /* FIXME: update when supporting EXT_transform_feedback */ 1309 features->transformFeedbackPreservesProvokingVertex = false; 1310 break; 1311 } 1312 1313 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: { 1314 VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *features = 1315 (void *) ext; 1316 features->vertexAttributeInstanceRateDivisor = true; 1317 features->vertexAttributeInstanceRateZeroDivisor = false; 1318 break; 1319 } 1320 1321 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR: { 1322 VkPhysicalDevicePerformanceQueryFeaturesKHR *features = 1323 (void *) ext; 1324 1325 features->performanceCounterQueryPools = 1326 physical_device->caps.perfmon; 1327 features->performanceCounterMultipleQueryPools = false; 1328 break; 1329 } 1330 1331 default: 1332 v3dv_debug_ignored_stype(ext->sType); 1333 break; 1334 } 1335 } 1336} 1337 1338VKAPI_ATTR void VKAPI_CALL 1339v3dv_GetDeviceGroupPeerMemoryFeatures(VkDevice device, 1340 uint32_t heapIndex, 1341 uint32_t localDeviceIndex, 1342 uint32_t remoteDeviceIndex, 1343 VkPeerMemoryFeatureFlags *pPeerMemoryFeatures) 1344{ 1345 assert(localDeviceIndex == 0 && remoteDeviceIndex == 0); 1346 *pPeerMemoryFeatures = VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT | 1347 VK_PEER_MEMORY_FEATURE_COPY_DST_BIT | 1348 VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT | 1349 VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT; 1350} 1351 1352uint32_t 1353v3dv_physical_device_vendor_id(struct v3dv_physical_device *dev) 1354{ 1355 return 0x14E4; /* Broadcom */ 1356} 1357 1358uint32_t 1359v3dv_physical_device_device_id(struct v3dv_physical_device *dev) 1360{ 1361#if using_v3d_simulator 1362 return dev->device_id; 1363#else 1364 switch (dev->devinfo.ver) { 1365 case 42: 1366 return 0xBE485FD3; /* Broadcom deviceID for 2711 */ 1367 default: 1368 unreachable("Unsupported V3D version"); 1369 } 1370#endif 1371} 1372 1373VKAPI_ATTR void VKAPI_CALL 1374v3dv_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, 1375 VkPhysicalDeviceProperties *pProperties) 1376{ 1377 V3DV_FROM_HANDLE(v3dv_physical_device, pdevice, physicalDevice); 1378 1379 STATIC_ASSERT(MAX_SAMPLED_IMAGES + MAX_STORAGE_IMAGES + MAX_INPUT_ATTACHMENTS 1380 <= V3D_MAX_TEXTURE_SAMPLERS); 1381 STATIC_ASSERT(MAX_UNIFORM_BUFFERS >= MAX_DYNAMIC_UNIFORM_BUFFERS); 1382 STATIC_ASSERT(MAX_STORAGE_BUFFERS >= MAX_DYNAMIC_STORAGE_BUFFERS); 1383 1384 const uint32_t page_size = 4096; 1385 const uint32_t mem_size = compute_heap_size(); 1386 1387 const uint32_t max_varying_components = 16 * 4; 1388 1389 const float v3d_point_line_granularity = 2.0f / (1 << V3D_COORD_SHIFT); 1390 const uint32_t max_fb_size = V3D_MAX_IMAGE_DIMENSION; 1391 1392 const VkSampleCountFlags supported_sample_counts = 1393 VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT; 1394 1395 struct timespec clock_res; 1396 clock_getres(CLOCK_MONOTONIC, &clock_res); 1397 const float timestamp_period = 1398 clock_res.tv_sec * 1000000000.0f + clock_res.tv_nsec; 1399 1400 /* FIXME: this will probably require an in-depth review */ 1401 VkPhysicalDeviceLimits limits = { 1402 .maxImageDimension1D = V3D_MAX_IMAGE_DIMENSION, 1403 .maxImageDimension2D = V3D_MAX_IMAGE_DIMENSION, 1404 .maxImageDimension3D = V3D_MAX_IMAGE_DIMENSION, 1405 .maxImageDimensionCube = V3D_MAX_IMAGE_DIMENSION, 1406 .maxImageArrayLayers = V3D_MAX_ARRAY_LAYERS, 1407 .maxTexelBufferElements = (1ul << 28), 1408 .maxUniformBufferRange = V3D_MAX_BUFFER_RANGE, 1409 .maxStorageBufferRange = V3D_MAX_BUFFER_RANGE, 1410 .maxPushConstantsSize = MAX_PUSH_CONSTANTS_SIZE, 1411 .maxMemoryAllocationCount = mem_size / page_size, 1412 .maxSamplerAllocationCount = 64 * 1024, 1413 .bufferImageGranularity = V3D_NON_COHERENT_ATOM_SIZE, 1414 .sparseAddressSpaceSize = 0, 1415 .maxBoundDescriptorSets = MAX_SETS, 1416 .maxPerStageDescriptorSamplers = V3D_MAX_TEXTURE_SAMPLERS, 1417 .maxPerStageDescriptorUniformBuffers = MAX_UNIFORM_BUFFERS, 1418 .maxPerStageDescriptorStorageBuffers = MAX_STORAGE_BUFFERS, 1419 .maxPerStageDescriptorSampledImages = MAX_SAMPLED_IMAGES, 1420 .maxPerStageDescriptorStorageImages = MAX_STORAGE_IMAGES, 1421 .maxPerStageDescriptorInputAttachments = MAX_INPUT_ATTACHMENTS, 1422 .maxPerStageResources = 128, 1423 1424 /* Some of these limits are multiplied by 6 because they need to 1425 * include all possible shader stages (even if not supported). See 1426 * 'Required Limits' table in the Vulkan spec. 1427 */ 1428 .maxDescriptorSetSamplers = 6 * V3D_MAX_TEXTURE_SAMPLERS, 1429 .maxDescriptorSetUniformBuffers = 6 * MAX_UNIFORM_BUFFERS, 1430 .maxDescriptorSetUniformBuffersDynamic = MAX_DYNAMIC_UNIFORM_BUFFERS, 1431 .maxDescriptorSetStorageBuffers = 6 * MAX_STORAGE_BUFFERS, 1432 .maxDescriptorSetStorageBuffersDynamic = MAX_DYNAMIC_STORAGE_BUFFERS, 1433 .maxDescriptorSetSampledImages = 6 * MAX_SAMPLED_IMAGES, 1434 .maxDescriptorSetStorageImages = 6 * MAX_STORAGE_IMAGES, 1435 .maxDescriptorSetInputAttachments = MAX_INPUT_ATTACHMENTS, 1436 1437 /* Vertex limits */ 1438 .maxVertexInputAttributes = MAX_VERTEX_ATTRIBS, 1439 .maxVertexInputBindings = MAX_VBS, 1440 .maxVertexInputAttributeOffset = 0xffffffff, 1441 .maxVertexInputBindingStride = 0xffffffff, 1442 .maxVertexOutputComponents = max_varying_components, 1443 1444 /* Tessellation limits */ 1445 .maxTessellationGenerationLevel = 0, 1446 .maxTessellationPatchSize = 0, 1447 .maxTessellationControlPerVertexInputComponents = 0, 1448 .maxTessellationControlPerVertexOutputComponents = 0, 1449 .maxTessellationControlPerPatchOutputComponents = 0, 1450 .maxTessellationControlTotalOutputComponents = 0, 1451 .maxTessellationEvaluationInputComponents = 0, 1452 .maxTessellationEvaluationOutputComponents = 0, 1453 1454 /* Geometry limits */ 1455 .maxGeometryShaderInvocations = 32, 1456 .maxGeometryInputComponents = 64, 1457 .maxGeometryOutputComponents = 64, 1458 .maxGeometryOutputVertices = 256, 1459 .maxGeometryTotalOutputComponents = 1024, 1460 1461 /* Fragment limits */ 1462 .maxFragmentInputComponents = max_varying_components, 1463 .maxFragmentOutputAttachments = 4, 1464 .maxFragmentDualSrcAttachments = 0, 1465 .maxFragmentCombinedOutputResources = MAX_RENDER_TARGETS + 1466 MAX_STORAGE_BUFFERS + 1467 MAX_STORAGE_IMAGES, 1468 1469 /* Compute limits */ 1470 .maxComputeSharedMemorySize = 16384, 1471 .maxComputeWorkGroupCount = { 65535, 65535, 65535 }, 1472 .maxComputeWorkGroupInvocations = 256, 1473 .maxComputeWorkGroupSize = { 256, 256, 256 }, 1474 1475 .subPixelPrecisionBits = V3D_COORD_SHIFT, 1476 .subTexelPrecisionBits = 8, 1477 .mipmapPrecisionBits = 8, 1478 .maxDrawIndexedIndexValue = 0x00ffffff, 1479 .maxDrawIndirectCount = 0x7fffffff, 1480 .maxSamplerLodBias = 14.0f, 1481 .maxSamplerAnisotropy = 16.0f, 1482 .maxViewports = MAX_VIEWPORTS, 1483 .maxViewportDimensions = { max_fb_size, max_fb_size }, 1484 .viewportBoundsRange = { -2.0 * max_fb_size, 1485 2.0 * max_fb_size - 1 }, 1486 .viewportSubPixelBits = 0, 1487 .minMemoryMapAlignment = page_size, 1488 .minTexelBufferOffsetAlignment = V3D_UIFBLOCK_SIZE, 1489 .minUniformBufferOffsetAlignment = 32, 1490 .minStorageBufferOffsetAlignment = 32, 1491 .minTexelOffset = -8, 1492 .maxTexelOffset = 7, 1493 .minTexelGatherOffset = -8, 1494 .maxTexelGatherOffset = 7, 1495 .minInterpolationOffset = -0.5, 1496 .maxInterpolationOffset = 0.5, 1497 .subPixelInterpolationOffsetBits = V3D_COORD_SHIFT, 1498 .maxFramebufferWidth = max_fb_size, 1499 .maxFramebufferHeight = max_fb_size, 1500 .maxFramebufferLayers = 256, 1501 .framebufferColorSampleCounts = supported_sample_counts, 1502 .framebufferDepthSampleCounts = supported_sample_counts, 1503 .framebufferStencilSampleCounts = supported_sample_counts, 1504 .framebufferNoAttachmentsSampleCounts = supported_sample_counts, 1505 .maxColorAttachments = MAX_RENDER_TARGETS, 1506 .sampledImageColorSampleCounts = supported_sample_counts, 1507 .sampledImageIntegerSampleCounts = supported_sample_counts, 1508 .sampledImageDepthSampleCounts = supported_sample_counts, 1509 .sampledImageStencilSampleCounts = supported_sample_counts, 1510 .storageImageSampleCounts = VK_SAMPLE_COUNT_1_BIT, 1511 .maxSampleMaskWords = 1, 1512 .timestampComputeAndGraphics = true, 1513 .timestampPeriod = timestamp_period, 1514 .maxClipDistances = 8, 1515 .maxCullDistances = 0, 1516 .maxCombinedClipAndCullDistances = 8, 1517 .discreteQueuePriorities = 2, 1518 .pointSizeRange = { v3d_point_line_granularity, 1519 V3D_MAX_POINT_SIZE }, 1520 .lineWidthRange = { 1.0f, V3D_MAX_LINE_WIDTH }, 1521 .pointSizeGranularity = v3d_point_line_granularity, 1522 .lineWidthGranularity = v3d_point_line_granularity, 1523 .strictLines = true, 1524 .standardSampleLocations = false, 1525 .optimalBufferCopyOffsetAlignment = 32, 1526 .optimalBufferCopyRowPitchAlignment = 32, 1527 .nonCoherentAtomSize = V3D_NON_COHERENT_ATOM_SIZE, 1528 }; 1529 1530 *pProperties = (VkPhysicalDeviceProperties) { 1531 .apiVersion = V3DV_API_VERSION, 1532 .driverVersion = vk_get_driver_version(), 1533 .vendorID = v3dv_physical_device_vendor_id(pdevice), 1534 .deviceID = v3dv_physical_device_device_id(pdevice), 1535 .deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU, 1536 .limits = limits, 1537 .sparseProperties = { 0 }, 1538 }; 1539 1540 snprintf(pProperties->deviceName, sizeof(pProperties->deviceName), 1541 "%s", pdevice->name); 1542 memcpy(pProperties->pipelineCacheUUID, 1543 pdevice->pipeline_cache_uuid, VK_UUID_SIZE); 1544} 1545 1546VKAPI_ATTR void VKAPI_CALL 1547v3dv_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, 1548 VkPhysicalDeviceProperties2 *pProperties) 1549{ 1550 V3DV_FROM_HANDLE(v3dv_physical_device, pdevice, physicalDevice); 1551 1552 v3dv_GetPhysicalDeviceProperties(physicalDevice, &pProperties->properties); 1553 1554 /* We don't really have special restrictions for the maximum 1555 * descriptors per set, other than maybe not exceeding the limits 1556 * of addressable memory in a single allocation on either the host 1557 * or the GPU. This will be a much larger limit than any of the 1558 * per-stage limits already available in Vulkan though, so in practice, 1559 * it is not expected to limit anything beyond what is already 1560 * constrained through per-stage limits. 1561 */ 1562 const uint32_t max_host_descriptors = 1563 (UINT32_MAX - sizeof(struct v3dv_descriptor_set)) / 1564 sizeof(struct v3dv_descriptor); 1565 const uint32_t max_gpu_descriptors = 1566 (UINT32_MAX / v3dv_X(pdevice, max_descriptor_bo_size)()); 1567 1568 VkPhysicalDeviceVulkan13Properties vk13 = { 1569 .maxInlineUniformBlockSize = 4096, 1570 .maxPerStageDescriptorInlineUniformBlocks = MAX_INLINE_UNIFORM_BUFFERS, 1571 .maxDescriptorSetInlineUniformBlocks = MAX_INLINE_UNIFORM_BUFFERS, 1572 .maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks = 1573 MAX_INLINE_UNIFORM_BUFFERS, 1574 .maxDescriptorSetUpdateAfterBindInlineUniformBlocks = 1575 MAX_INLINE_UNIFORM_BUFFERS, 1576 }; 1577 1578 VkPhysicalDeviceVulkan12Properties vk12 = { 1579 .driverID = VK_DRIVER_ID_MESA_V3DV, 1580 .conformanceVersion = { 1581 .major = 1, 1582 .minor = 2, 1583 .subminor = 7, 1584 .patch = 1, 1585 }, 1586 .supportedDepthResolveModes = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT, 1587 .supportedStencilResolveModes = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT, 1588 /* FIXME: if we want to support independentResolveNone then we would 1589 * need to honor attachment load operations on resolve attachments, 1590 * which we currently ignore because the resolve makes them irrelevant, 1591 * as it unconditionally writes all pixels in the render area. However, 1592 * with independentResolveNone, it is possible to have one aspect of a 1593 * D/S resolve attachment stay unresolved, in which case the attachment 1594 * load operation is relevant. 1595 * 1596 * NOTE: implementing attachment load for resolve attachments isn't 1597 * immediately trivial because these attachments are not part of the 1598 * framebuffer and therefore we can't use the same mechanism we use 1599 * for framebuffer attachments. Instead, we should probably have to 1600 * emit a meta operation for that right at the start of the render 1601 * pass (or subpass). 1602 */ 1603 .independentResolveNone = false, 1604 .independentResolve = false, 1605 .maxTimelineSemaphoreValueDifference = UINT64_MAX, 1606 1607 .denormBehaviorIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL, 1608 .roundingModeIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL, 1609 .shaderSignedZeroInfNanPreserveFloat16 = true, 1610 .shaderSignedZeroInfNanPreserveFloat32 = true, 1611 .shaderSignedZeroInfNanPreserveFloat64 = false, 1612 .shaderDenormPreserveFloat16 = true, 1613 .shaderDenormPreserveFloat32 = true, 1614 .shaderDenormPreserveFloat64 = false, 1615 .shaderDenormFlushToZeroFloat16 = false, 1616 .shaderDenormFlushToZeroFloat32 = false, 1617 .shaderDenormFlushToZeroFloat64 = false, 1618 .shaderRoundingModeRTEFloat16 = true, 1619 .shaderRoundingModeRTEFloat32 = true, 1620 .shaderRoundingModeRTEFloat64 = false, 1621 .shaderRoundingModeRTZFloat16 = false, 1622 .shaderRoundingModeRTZFloat32 = false, 1623 .shaderRoundingModeRTZFloat64 = false, 1624 1625 /* V3D doesn't support min/max filtering */ 1626 .filterMinmaxSingleComponentFormats = false, 1627 .filterMinmaxImageComponentMapping = false, 1628 1629 .framebufferIntegerColorSampleCounts = 1630 VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT, 1631 }; 1632 memset(vk12.driverName, 0, VK_MAX_DRIVER_NAME_SIZE); 1633 snprintf(vk12.driverName, VK_MAX_DRIVER_NAME_SIZE, "V3DV Mesa"); 1634 memset(vk12.driverInfo, 0, VK_MAX_DRIVER_INFO_SIZE); 1635 snprintf(vk12.driverInfo, VK_MAX_DRIVER_INFO_SIZE, 1636 "Mesa " PACKAGE_VERSION MESA_GIT_SHA1); 1637 1638 VkPhysicalDeviceVulkan11Properties vk11 = { 1639 .deviceLUIDValid = false, 1640 .subgroupSize = V3D_CHANNELS, 1641 .subgroupSupportedStages = VK_SHADER_STAGE_COMPUTE_BIT, 1642 .subgroupSupportedOperations = VK_SUBGROUP_FEATURE_BASIC_BIT, 1643 .subgroupQuadOperationsInAllStages = false, 1644 .pointClippingBehavior = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES, 1645 .maxMultiviewViewCount = MAX_MULTIVIEW_VIEW_COUNT, 1646 .maxMultiviewInstanceIndex = UINT32_MAX - 1, 1647 .protectedNoFault = false, 1648 .maxPerSetDescriptors = MIN2(max_host_descriptors, max_gpu_descriptors), 1649 /* Minimum required by the spec */ 1650 .maxMemoryAllocationSize = MAX_MEMORY_ALLOCATION_SIZE, 1651 }; 1652 memcpy(vk11.deviceUUID, pdevice->device_uuid, VK_UUID_SIZE); 1653 memcpy(vk11.driverUUID, pdevice->driver_uuid, VK_UUID_SIZE); 1654 1655 1656 vk_foreach_struct(ext, pProperties->pNext) { 1657 if (vk_get_physical_device_core_1_1_property_ext(ext, &vk11)) 1658 continue; 1659 if (vk_get_physical_device_core_1_2_property_ext(ext, &vk12)) 1660 continue; 1661 if (vk_get_physical_device_core_1_3_property_ext(ext, &vk13)) 1662 continue; 1663 1664 switch (ext->sType) { 1665 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT: { 1666 VkPhysicalDeviceCustomBorderColorPropertiesEXT *props = 1667 (VkPhysicalDeviceCustomBorderColorPropertiesEXT *)ext; 1668 props->maxCustomBorderColorSamplers = V3D_MAX_TEXTURE_SAMPLERS; 1669 break; 1670 } 1671 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_PROPERTIES_EXT: { 1672 VkPhysicalDeviceProvokingVertexPropertiesEXT *props = 1673 (VkPhysicalDeviceProvokingVertexPropertiesEXT *)ext; 1674 props->provokingVertexModePerPipeline = true; 1675 /* FIXME: update when supporting EXT_transform_feedback */ 1676 props->transformFeedbackPreservesTriangleFanProvokingVertex = false; 1677 break; 1678 } 1679 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT: { 1680 VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *props = 1681 (VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *)ext; 1682 props->maxVertexAttribDivisor = 0xffff; 1683 break; 1684 } 1685 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_PROPERTIES_KHR : { 1686 VkPhysicalDevicePerformanceQueryPropertiesKHR *props = 1687 (VkPhysicalDevicePerformanceQueryPropertiesKHR *)ext; 1688 1689 props->allowCommandBufferQueryCopies = true; 1690 break; 1691 } 1692 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT: { 1693 VkPhysicalDeviceDrmPropertiesEXT *props = 1694 (VkPhysicalDeviceDrmPropertiesEXT *)ext; 1695 props->hasPrimary = pdevice->has_primary; 1696 if (props->hasPrimary) { 1697 props->primaryMajor = (int64_t) major(pdevice->primary_devid); 1698 props->primaryMinor = (int64_t) minor(pdevice->primary_devid); 1699 } 1700 props->hasRender = pdevice->has_render; 1701 if (props->hasRender) { 1702 props->renderMajor = (int64_t) major(pdevice->render_devid); 1703 props->renderMinor = (int64_t) minor(pdevice->render_devid); 1704 } 1705 break; 1706 } 1707 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT: { 1708 VkPhysicalDeviceLineRasterizationPropertiesEXT *props = 1709 (VkPhysicalDeviceLineRasterizationPropertiesEXT *)ext; 1710 props->lineSubPixelPrecisionBits = V3D_COORD_SHIFT; 1711 break; 1712 } 1713 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT: 1714 /* Do nothing, not even logging. This is a non-PCI device, so we will 1715 * never provide this extension. 1716 */ 1717 break; 1718 default: 1719 v3dv_debug_ignored_stype(ext->sType); 1720 break; 1721 } 1722 } 1723} 1724 1725/* We support exactly one queue family. */ 1726static const VkQueueFamilyProperties 1727v3dv_queue_family_properties = { 1728 .queueFlags = VK_QUEUE_GRAPHICS_BIT | 1729 VK_QUEUE_COMPUTE_BIT | 1730 VK_QUEUE_TRANSFER_BIT, 1731 .queueCount = 1, 1732 .timestampValidBits = 64, 1733 .minImageTransferGranularity = { 1, 1, 1 }, 1734}; 1735 1736VKAPI_ATTR void VKAPI_CALL 1737v3dv_GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice, 1738 uint32_t *pQueueFamilyPropertyCount, 1739 VkQueueFamilyProperties2 *pQueueFamilyProperties) 1740{ 1741 VK_OUTARRAY_MAKE_TYPED(VkQueueFamilyProperties2, out, 1742 pQueueFamilyProperties, pQueueFamilyPropertyCount); 1743 1744 vk_outarray_append_typed(VkQueueFamilyProperties2, &out, p) { 1745 p->queueFamilyProperties = v3dv_queue_family_properties; 1746 1747 vk_foreach_struct(s, p->pNext) { 1748 v3dv_debug_ignored_stype(s->sType); 1749 } 1750 } 1751} 1752 1753VKAPI_ATTR void VKAPI_CALL 1754v3dv_GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice, 1755 VkPhysicalDeviceMemoryProperties *pMemoryProperties) 1756{ 1757 V3DV_FROM_HANDLE(v3dv_physical_device, device, physicalDevice); 1758 *pMemoryProperties = device->memory; 1759} 1760 1761VKAPI_ATTR void VKAPI_CALL 1762v3dv_GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice, 1763 VkPhysicalDeviceMemoryProperties2 *pMemoryProperties) 1764{ 1765 v3dv_GetPhysicalDeviceMemoryProperties(physicalDevice, 1766 &pMemoryProperties->memoryProperties); 1767 1768 vk_foreach_struct(ext, pMemoryProperties->pNext) { 1769 switch (ext->sType) { 1770 default: 1771 v3dv_debug_ignored_stype(ext->sType); 1772 break; 1773 } 1774 } 1775} 1776 1777VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL 1778v3dv_GetInstanceProcAddr(VkInstance _instance, 1779 const char *pName) 1780{ 1781 V3DV_FROM_HANDLE(v3dv_instance, instance, _instance); 1782 return vk_instance_get_proc_addr(&instance->vk, 1783 &v3dv_instance_entrypoints, 1784 pName); 1785} 1786 1787/* With version 1+ of the loader interface the ICD should expose 1788 * vk_icdGetInstanceProcAddr to work around certain LD_PRELOAD issues seen in apps. 1789 */ 1790PUBLIC 1791VKAPI_ATTR PFN_vkVoidFunction 1792VKAPI_CALL vk_icdGetInstanceProcAddr(VkInstance instance, 1793 const char *pName); 1794 1795PUBLIC 1796VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL 1797vk_icdGetInstanceProcAddr(VkInstance instance, 1798 const char* pName) 1799{ 1800 return v3dv_GetInstanceProcAddr(instance, pName); 1801} 1802 1803/* With version 4+ of the loader interface the ICD should expose 1804 * vk_icdGetPhysicalDeviceProcAddr() 1805 */ 1806PUBLIC 1807VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL 1808vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance, 1809 const char* pName); 1810 1811PFN_vkVoidFunction 1812vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance, 1813 const char* pName) 1814{ 1815 V3DV_FROM_HANDLE(v3dv_instance, instance, _instance); 1816 1817 return vk_instance_get_physical_device_proc_addr(&instance->vk, pName); 1818} 1819 1820VKAPI_ATTR VkResult VKAPI_CALL 1821v3dv_EnumerateInstanceLayerProperties(uint32_t *pPropertyCount, 1822 VkLayerProperties *pProperties) 1823{ 1824 if (pProperties == NULL) { 1825 *pPropertyCount = 0; 1826 return VK_SUCCESS; 1827 } 1828 1829 return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT); 1830} 1831 1832VKAPI_ATTR VkResult VKAPI_CALL 1833v3dv_EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, 1834 uint32_t *pPropertyCount, 1835 VkLayerProperties *pProperties) 1836{ 1837 V3DV_FROM_HANDLE(v3dv_physical_device, physical_device, physicalDevice); 1838 1839 if (pProperties == NULL) { 1840 *pPropertyCount = 0; 1841 return VK_SUCCESS; 1842 } 1843 1844 return vk_error(physical_device, VK_ERROR_LAYER_NOT_PRESENT); 1845} 1846 1847static void 1848destroy_queue_syncs(struct v3dv_queue *queue) 1849{ 1850 for (int i = 0; i < V3DV_QUEUE_COUNT; i++) { 1851 if (queue->last_job_syncs.syncs[i]) { 1852 drmSyncobjDestroy(queue->device->pdevice->render_fd, 1853 queue->last_job_syncs.syncs[i]); 1854 } 1855 } 1856} 1857 1858static VkResult 1859queue_init(struct v3dv_device *device, struct v3dv_queue *queue, 1860 const VkDeviceQueueCreateInfo *create_info, 1861 uint32_t index_in_family) 1862{ 1863 VkResult result = vk_queue_init(&queue->vk, &device->vk, create_info, 1864 index_in_family); 1865 if (result != VK_SUCCESS) 1866 return result; 1867 1868 result = vk_queue_enable_submit_thread(&queue->vk); 1869 if (result != VK_SUCCESS) 1870 goto fail_submit_thread; 1871 1872 queue->device = device; 1873 queue->vk.driver_submit = v3dv_queue_driver_submit; 1874 1875 for (int i = 0; i < V3DV_QUEUE_COUNT; i++) { 1876 queue->last_job_syncs.first[i] = true; 1877 int ret = drmSyncobjCreate(device->pdevice->render_fd, 1878 DRM_SYNCOBJ_CREATE_SIGNALED, 1879 &queue->last_job_syncs.syncs[i]); 1880 if (ret) { 1881 result = vk_errorf(device, VK_ERROR_INITIALIZATION_FAILED, 1882 "syncobj create failed: %m"); 1883 goto fail_last_job_syncs; 1884 } 1885 } 1886 1887 queue->noop_job = NULL; 1888 return VK_SUCCESS; 1889 1890fail_last_job_syncs: 1891 destroy_queue_syncs(queue); 1892fail_submit_thread: 1893 vk_queue_finish(&queue->vk); 1894 return result; 1895} 1896 1897static void 1898queue_finish(struct v3dv_queue *queue) 1899{ 1900 if (queue->noop_job) 1901 v3dv_job_destroy(queue->noop_job); 1902 destroy_queue_syncs(queue); 1903 vk_queue_finish(&queue->vk); 1904} 1905 1906static void 1907init_device_meta(struct v3dv_device *device) 1908{ 1909 mtx_init(&device->meta.mtx, mtx_plain); 1910 v3dv_meta_clear_init(device); 1911 v3dv_meta_blit_init(device); 1912 v3dv_meta_texel_buffer_copy_init(device); 1913} 1914 1915static void 1916destroy_device_meta(struct v3dv_device *device) 1917{ 1918 mtx_destroy(&device->meta.mtx); 1919 v3dv_meta_clear_finish(device); 1920 v3dv_meta_blit_finish(device); 1921 v3dv_meta_texel_buffer_copy_finish(device); 1922} 1923 1924VKAPI_ATTR VkResult VKAPI_CALL 1925v3dv_CreateDevice(VkPhysicalDevice physicalDevice, 1926 const VkDeviceCreateInfo *pCreateInfo, 1927 const VkAllocationCallbacks *pAllocator, 1928 VkDevice *pDevice) 1929{ 1930 V3DV_FROM_HANDLE(v3dv_physical_device, physical_device, physicalDevice); 1931 struct v3dv_instance *instance = (struct v3dv_instance*) physical_device->vk.instance; 1932 VkResult result; 1933 struct v3dv_device *device; 1934 1935 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO); 1936 1937 /* Check requested queues (we only expose one queue ) */ 1938 assert(pCreateInfo->queueCreateInfoCount == 1); 1939 for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++) { 1940 assert(pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex == 0); 1941 assert(pCreateInfo->pQueueCreateInfos[i].queueCount == 1); 1942 if (pCreateInfo->pQueueCreateInfos[i].flags != 0) 1943 return vk_error(instance, VK_ERROR_INITIALIZATION_FAILED); 1944 } 1945 1946 device = vk_zalloc2(&physical_device->vk.instance->alloc, pAllocator, 1947 sizeof(*device), 8, 1948 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 1949 if (!device) 1950 return vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY); 1951 1952 struct vk_device_dispatch_table dispatch_table; 1953 vk_device_dispatch_table_from_entrypoints(&dispatch_table, 1954 &v3dv_device_entrypoints, true); 1955 vk_device_dispatch_table_from_entrypoints(&dispatch_table, 1956 &wsi_device_entrypoints, false); 1957 result = vk_device_init(&device->vk, &physical_device->vk, 1958 &dispatch_table, pCreateInfo, pAllocator); 1959 if (result != VK_SUCCESS) { 1960 vk_free(&device->vk.alloc, device); 1961 return vk_error(NULL, result); 1962 } 1963 1964 device->instance = instance; 1965 device->pdevice = physical_device; 1966 1967 mtx_init(&device->query_mutex, mtx_plain); 1968 cnd_init(&device->query_ended); 1969 1970 vk_device_set_drm_fd(&device->vk, physical_device->render_fd); 1971 vk_device_enable_threaded_submit(&device->vk); 1972 1973 result = queue_init(device, &device->queue, 1974 pCreateInfo->pQueueCreateInfos, 0); 1975 if (result != VK_SUCCESS) 1976 goto fail; 1977 1978 device->devinfo = physical_device->devinfo; 1979 1980 /* Vulkan 1.1 and VK_KHR_get_physical_device_properties2 added 1981 * VkPhysicalDeviceFeatures2 which can be used in the pNext chain of 1982 * vkDeviceCreateInfo, in which case it should be used instead of 1983 * pEnabledFeatures. 1984 */ 1985 const VkPhysicalDeviceFeatures2 *features2 = 1986 vk_find_struct_const(pCreateInfo->pNext, PHYSICAL_DEVICE_FEATURES_2); 1987 if (features2) { 1988 memcpy(&device->features, &features2->features, 1989 sizeof(device->features)); 1990 } else if (pCreateInfo->pEnabledFeatures) { 1991 memcpy(&device->features, pCreateInfo->pEnabledFeatures, 1992 sizeof(device->features)); 1993 } 1994 1995 if (device->features.robustBufferAccess) 1996 perf_debug("Device created with Robust Buffer Access enabled.\n"); 1997 1998#ifdef DEBUG 1999 v3dv_X(device, device_check_prepacked_sizes)(); 2000#endif 2001 init_device_meta(device); 2002 v3dv_bo_cache_init(device); 2003 v3dv_pipeline_cache_init(&device->default_pipeline_cache, device, 0, 2004 device->instance->default_pipeline_cache_enabled); 2005 device->default_attribute_float = 2006 v3dv_pipeline_create_default_attribute_values(device, NULL); 2007 2008 device->device_address_mem_ctx = ralloc_context(NULL); 2009 util_dynarray_init(&device->device_address_bo_list, 2010 device->device_address_mem_ctx); 2011 2012 *pDevice = v3dv_device_to_handle(device); 2013 2014 return VK_SUCCESS; 2015 2016fail: 2017 cnd_destroy(&device->query_ended); 2018 mtx_destroy(&device->query_mutex); 2019 queue_finish(&device->queue); 2020 destroy_device_meta(device); 2021 v3dv_pipeline_cache_finish(&device->default_pipeline_cache); 2022 vk_device_finish(&device->vk); 2023 vk_free(&device->vk.alloc, device); 2024 2025 return result; 2026} 2027 2028VKAPI_ATTR void VKAPI_CALL 2029v3dv_DestroyDevice(VkDevice _device, 2030 const VkAllocationCallbacks *pAllocator) 2031{ 2032 V3DV_FROM_HANDLE(v3dv_device, device, _device); 2033 2034 device->vk.dispatch_table.DeviceWaitIdle(_device); 2035 queue_finish(&device->queue); 2036 destroy_device_meta(device); 2037 v3dv_pipeline_cache_finish(&device->default_pipeline_cache); 2038 2039 if (device->default_attribute_float) { 2040 v3dv_bo_free(device, device->default_attribute_float); 2041 device->default_attribute_float = NULL; 2042 } 2043 2044 ralloc_free(device->device_address_mem_ctx); 2045 2046 /* Bo cache should be removed the last, as any other object could be 2047 * freeing their private bos 2048 */ 2049 v3dv_bo_cache_destroy(device); 2050 2051 cnd_destroy(&device->query_ended); 2052 mtx_destroy(&device->query_mutex); 2053 2054 vk_device_finish(&device->vk); 2055 vk_free2(&device->vk.alloc, pAllocator, device); 2056} 2057 2058static VkResult 2059device_alloc(struct v3dv_device *device, 2060 struct v3dv_device_memory *mem, 2061 VkDeviceSize size) 2062{ 2063 /* Our kernel interface is 32-bit */ 2064 assert(size <= UINT32_MAX); 2065 2066 mem->bo = v3dv_bo_alloc(device, size, "device_alloc", false); 2067 if (!mem->bo) 2068 return VK_ERROR_OUT_OF_DEVICE_MEMORY; 2069 2070 return VK_SUCCESS; 2071} 2072 2073static void 2074device_free_wsi_dumb(int32_t display_fd, int32_t dumb_handle) 2075{ 2076 assert(display_fd != -1); 2077 if (dumb_handle < 0) 2078 return; 2079 2080 struct drm_mode_destroy_dumb destroy_dumb = { 2081 .handle = dumb_handle, 2082 }; 2083 if (v3dv_ioctl(display_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb)) { 2084 fprintf(stderr, "destroy dumb object %d: %s\n", dumb_handle, strerror(errno)); 2085 } 2086} 2087 2088static void 2089device_free(struct v3dv_device *device, struct v3dv_device_memory *mem) 2090{ 2091 /* If this memory allocation was for WSI, then we need to use the 2092 * display device to free the allocated dumb BO. 2093 */ 2094 if (mem->is_for_wsi) { 2095 device_free_wsi_dumb(device->instance->physicalDevice.display_fd, 2096 mem->bo->dumb_handle); 2097 } 2098 2099 v3dv_bo_free(device, mem->bo); 2100} 2101 2102static void 2103device_unmap(struct v3dv_device *device, struct v3dv_device_memory *mem) 2104{ 2105 assert(mem && mem->bo->map && mem->bo->map_size > 0); 2106 v3dv_bo_unmap(device, mem->bo); 2107} 2108 2109static VkResult 2110device_map(struct v3dv_device *device, struct v3dv_device_memory *mem) 2111{ 2112 assert(mem && mem->bo); 2113 2114 /* From the spec: 2115 * 2116 * "After a successful call to vkMapMemory the memory object memory is 2117 * considered to be currently host mapped. It is an application error to 2118 * call vkMapMemory on a memory object that is already host mapped." 2119 * 2120 * We are not concerned with this ourselves (validation layers should 2121 * catch these errors and warn users), however, the driver may internally 2122 * map things (for example for debug CLIF dumps or some CPU-side operations) 2123 * so by the time the user calls here the buffer might already been mapped 2124 * internally by the driver. 2125 */ 2126 if (mem->bo->map) { 2127 assert(mem->bo->map_size == mem->bo->size); 2128 return VK_SUCCESS; 2129 } 2130 2131 bool ok = v3dv_bo_map(device, mem->bo, mem->bo->size); 2132 if (!ok) 2133 return VK_ERROR_MEMORY_MAP_FAILED; 2134 2135 return VK_SUCCESS; 2136} 2137 2138static VkResult 2139device_import_bo(struct v3dv_device *device, 2140 const VkAllocationCallbacks *pAllocator, 2141 int fd, uint64_t size, 2142 struct v3dv_bo **bo) 2143{ 2144 *bo = NULL; 2145 2146 off_t real_size = lseek(fd, 0, SEEK_END); 2147 lseek(fd, 0, SEEK_SET); 2148 if (real_size < 0 || (uint64_t) real_size < size) 2149 return VK_ERROR_INVALID_EXTERNAL_HANDLE; 2150 2151 int render_fd = device->pdevice->render_fd; 2152 assert(render_fd >= 0); 2153 2154 int ret; 2155 uint32_t handle; 2156 ret = drmPrimeFDToHandle(render_fd, fd, &handle); 2157 if (ret) 2158 return VK_ERROR_INVALID_EXTERNAL_HANDLE; 2159 2160 struct drm_v3d_get_bo_offset get_offset = { 2161 .handle = handle, 2162 }; 2163 ret = v3dv_ioctl(render_fd, DRM_IOCTL_V3D_GET_BO_OFFSET, &get_offset); 2164 if (ret) 2165 return VK_ERROR_INVALID_EXTERNAL_HANDLE; 2166 assert(get_offset.offset != 0); 2167 2168 *bo = v3dv_device_lookup_bo(device->pdevice, handle); 2169 assert(*bo); 2170 2171 if ((*bo)->refcnt == 0) 2172 v3dv_bo_init(*bo, handle, size, get_offset.offset, "import", false); 2173 else 2174 p_atomic_inc(&(*bo)->refcnt); 2175 2176 return VK_SUCCESS; 2177} 2178 2179static VkResult 2180device_alloc_for_wsi(struct v3dv_device *device, 2181 const VkAllocationCallbacks *pAllocator, 2182 struct v3dv_device_memory *mem, 2183 VkDeviceSize size) 2184{ 2185 /* In the simulator we can get away with a regular allocation since both 2186 * allocation and rendering happen in the same DRM render node. On actual 2187 * hardware we need to allocate our winsys BOs on the vc4 display device 2188 * and import them into v3d. 2189 */ 2190#if using_v3d_simulator 2191 return device_alloc(device, mem, size); 2192#else 2193 /* If we are allocating for WSI we should have a swapchain and thus, 2194 * we should've initialized the display device. However, Zink doesn't 2195 * use swapchains, so in that case we can get here without acquiring the 2196 * display device and we need to do it now. 2197 */ 2198 VkResult result; 2199 struct v3dv_instance *instance = device->instance; 2200 struct v3dv_physical_device *pdevice = &device->instance->physicalDevice; 2201 if (unlikely(pdevice->display_fd < 0)) { 2202 result = v3dv_physical_device_acquire_display(instance, pdevice, NULL); 2203 if (result != VK_SUCCESS) 2204 return result; 2205 } 2206 assert(pdevice->display_fd != -1); 2207 2208 mem->is_for_wsi = true; 2209 2210 int display_fd = pdevice->display_fd; 2211 struct drm_mode_create_dumb create_dumb = { 2212 .width = 1024, /* one page */ 2213 .height = align(size, 4096) / 4096, 2214 .bpp = util_format_get_blocksizebits(PIPE_FORMAT_RGBA8888_UNORM), 2215 }; 2216 2217 int err; 2218 err = v3dv_ioctl(display_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb); 2219 if (err < 0) 2220 goto fail_create; 2221 2222 int fd; 2223 err = 2224 drmPrimeHandleToFD(display_fd, create_dumb.handle, O_CLOEXEC, &fd); 2225 if (err < 0) 2226 goto fail_export; 2227 2228 result = device_import_bo(device, pAllocator, fd, size, &mem->bo); 2229 close(fd); 2230 if (result != VK_SUCCESS) 2231 goto fail_import; 2232 2233 mem->bo->dumb_handle = create_dumb.handle; 2234 return VK_SUCCESS; 2235 2236fail_import: 2237fail_export: 2238 device_free_wsi_dumb(display_fd, create_dumb.handle); 2239 2240fail_create: 2241 return VK_ERROR_OUT_OF_DEVICE_MEMORY; 2242#endif 2243} 2244 2245static void 2246device_add_device_address_bo(struct v3dv_device *device, 2247 struct v3dv_bo *bo) 2248{ 2249 util_dynarray_append(&device->device_address_bo_list, 2250 struct v3dv_bo *, 2251 bo); 2252} 2253 2254static void 2255device_remove_device_address_bo(struct v3dv_device *device, 2256 struct v3dv_bo *bo) 2257{ 2258 util_dynarray_delete_unordered(&device->device_address_bo_list, 2259 struct v3dv_bo *, 2260 bo); 2261} 2262 2263VKAPI_ATTR VkResult VKAPI_CALL 2264v3dv_AllocateMemory(VkDevice _device, 2265 const VkMemoryAllocateInfo *pAllocateInfo, 2266 const VkAllocationCallbacks *pAllocator, 2267 VkDeviceMemory *pMem) 2268{ 2269 V3DV_FROM_HANDLE(v3dv_device, device, _device); 2270 struct v3dv_device_memory *mem; 2271 struct v3dv_physical_device *pdevice = &device->instance->physicalDevice; 2272 2273 assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO); 2274 2275 /* The Vulkan 1.0.33 spec says "allocationSize must be greater than 0". */ 2276 assert(pAllocateInfo->allocationSize > 0); 2277 2278 mem = vk_object_zalloc(&device->vk, pAllocator, sizeof(*mem), 2279 VK_OBJECT_TYPE_DEVICE_MEMORY); 2280 if (mem == NULL) 2281 return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY); 2282 2283 assert(pAllocateInfo->memoryTypeIndex < pdevice->memory.memoryTypeCount); 2284 mem->type = &pdevice->memory.memoryTypes[pAllocateInfo->memoryTypeIndex]; 2285 mem->is_for_wsi = false; 2286 2287 const struct wsi_memory_allocate_info *wsi_info = NULL; 2288 const VkImportMemoryFdInfoKHR *fd_info = NULL; 2289 const VkMemoryAllocateFlagsInfo *flags_info = NULL; 2290 vk_foreach_struct_const(ext, pAllocateInfo->pNext) { 2291 switch ((unsigned)ext->sType) { 2292 case VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA: 2293 wsi_info = (void *)ext; 2294 break; 2295 case VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR: 2296 fd_info = (void *)ext; 2297 break; 2298 case VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO: 2299 flags_info = (void *)ext; 2300 break; 2301 case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO: 2302 /* We don't have particular optimizations associated with memory 2303 * allocations that won't be suballocated to multiple resources. 2304 */ 2305 break; 2306 case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO: 2307 /* The mask of handle types specified here must be supported 2308 * according to VkExternalImageFormatProperties, so it must be 2309 * fd or dmabuf, which don't have special requirements for us. 2310 */ 2311 break; 2312 default: 2313 v3dv_debug_ignored_stype(ext->sType); 2314 break; 2315 } 2316 } 2317 2318 VkResult result = VK_SUCCESS; 2319 2320 /* We always allocate device memory in multiples of a page, so round up 2321 * requested size to that. 2322 */ 2323 VkDeviceSize alloc_size = ALIGN(pAllocateInfo->allocationSize, 4096); 2324 2325 if (unlikely(alloc_size > MAX_MEMORY_ALLOCATION_SIZE)) { 2326 result = VK_ERROR_OUT_OF_DEVICE_MEMORY; 2327 } else { 2328 if (wsi_info) { 2329 result = device_alloc_for_wsi(device, pAllocator, mem, alloc_size); 2330 } else if (fd_info && fd_info->handleType) { 2331 assert(fd_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT || 2332 fd_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT); 2333 result = device_import_bo(device, pAllocator, 2334 fd_info->fd, alloc_size, &mem->bo); 2335 if (result == VK_SUCCESS) 2336 close(fd_info->fd); 2337 } else { 2338 result = device_alloc(device, mem, alloc_size); 2339 } 2340 } 2341 2342 if (result != VK_SUCCESS) { 2343 vk_object_free(&device->vk, pAllocator, mem); 2344 return vk_error(device, result); 2345 } 2346 2347 /* If this memory can be used via VK_KHR_buffer_device_address then we 2348 * will need to manually add the BO to any job submit that makes use of 2349 * VK_KHR_buffer_device_address, since such jobs may produde buffer 2350 * load/store operations that may access any buffer memory allocated with 2351 * this flag and we don't have any means to tell which buffers will be 2352 * accessed through this mechanism since they don't even have to be bound 2353 * through descriptor state. 2354 */ 2355 if (flags_info && 2356 (flags_info->flags & VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR)) { 2357 mem->is_for_device_address = true; 2358 device_add_device_address_bo(device, mem->bo); 2359 } 2360 2361 *pMem = v3dv_device_memory_to_handle(mem); 2362 return result; 2363} 2364 2365VKAPI_ATTR void VKAPI_CALL 2366v3dv_FreeMemory(VkDevice _device, 2367 VkDeviceMemory _mem, 2368 const VkAllocationCallbacks *pAllocator) 2369{ 2370 V3DV_FROM_HANDLE(v3dv_device, device, _device); 2371 V3DV_FROM_HANDLE(v3dv_device_memory, mem, _mem); 2372 2373 if (mem == NULL) 2374 return; 2375 2376 if (mem->bo->map) 2377 v3dv_UnmapMemory(_device, _mem); 2378 2379 if (mem->is_for_device_address) 2380 device_remove_device_address_bo(device, mem->bo); 2381 2382 device_free(device, mem); 2383 2384 vk_object_free(&device->vk, pAllocator, mem); 2385} 2386 2387VKAPI_ATTR VkResult VKAPI_CALL 2388v3dv_MapMemory(VkDevice _device, 2389 VkDeviceMemory _memory, 2390 VkDeviceSize offset, 2391 VkDeviceSize size, 2392 VkMemoryMapFlags flags, 2393 void **ppData) 2394{ 2395 V3DV_FROM_HANDLE(v3dv_device, device, _device); 2396 V3DV_FROM_HANDLE(v3dv_device_memory, mem, _memory); 2397 2398 if (mem == NULL) { 2399 *ppData = NULL; 2400 return VK_SUCCESS; 2401 } 2402 2403 assert(offset < mem->bo->size); 2404 2405 /* Since the driver can map BOs internally as well and the mapped range 2406 * required by the user or the driver might not be the same, we always map 2407 * the entire BO and then add the requested offset to the start address 2408 * of the mapped region. 2409 */ 2410 VkResult result = device_map(device, mem); 2411 if (result != VK_SUCCESS) 2412 return vk_error(device, result); 2413 2414 *ppData = ((uint8_t *) mem->bo->map) + offset; 2415 return VK_SUCCESS; 2416} 2417 2418VKAPI_ATTR void VKAPI_CALL 2419v3dv_UnmapMemory(VkDevice _device, 2420 VkDeviceMemory _memory) 2421{ 2422 V3DV_FROM_HANDLE(v3dv_device, device, _device); 2423 V3DV_FROM_HANDLE(v3dv_device_memory, mem, _memory); 2424 2425 if (mem == NULL) 2426 return; 2427 2428 device_unmap(device, mem); 2429} 2430 2431VKAPI_ATTR VkResult VKAPI_CALL 2432v3dv_FlushMappedMemoryRanges(VkDevice _device, 2433 uint32_t memoryRangeCount, 2434 const VkMappedMemoryRange *pMemoryRanges) 2435{ 2436 return VK_SUCCESS; 2437} 2438 2439VKAPI_ATTR VkResult VKAPI_CALL 2440v3dv_InvalidateMappedMemoryRanges(VkDevice _device, 2441 uint32_t memoryRangeCount, 2442 const VkMappedMemoryRange *pMemoryRanges) 2443{ 2444 return VK_SUCCESS; 2445} 2446 2447VKAPI_ATTR void VKAPI_CALL 2448v3dv_GetImageMemoryRequirements2(VkDevice device, 2449 const VkImageMemoryRequirementsInfo2 *pInfo, 2450 VkMemoryRequirements2 *pMemoryRequirements) 2451{ 2452 V3DV_FROM_HANDLE(v3dv_image, image, pInfo->image); 2453 2454 pMemoryRequirements->memoryRequirements = (VkMemoryRequirements) { 2455 .memoryTypeBits = 0x1, 2456 .alignment = image->alignment, 2457 .size = image->size 2458 }; 2459 2460 vk_foreach_struct(ext, pMemoryRequirements->pNext) { 2461 switch (ext->sType) { 2462 case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: { 2463 VkMemoryDedicatedRequirements *req = 2464 (VkMemoryDedicatedRequirements *) ext; 2465 req->requiresDedicatedAllocation = image->vk.external_handle_types != 0; 2466 req->prefersDedicatedAllocation = image->vk.external_handle_types != 0; 2467 break; 2468 } 2469 default: 2470 v3dv_debug_ignored_stype(ext->sType); 2471 break; 2472 } 2473 } 2474} 2475 2476static void 2477bind_image_memory(const VkBindImageMemoryInfo *info) 2478{ 2479 V3DV_FROM_HANDLE(v3dv_image, image, info->image); 2480 V3DV_FROM_HANDLE(v3dv_device_memory, mem, info->memory); 2481 2482 /* Valid usage: 2483 * 2484 * "memoryOffset must be an integer multiple of the alignment member of 2485 * the VkMemoryRequirements structure returned from a call to 2486 * vkGetImageMemoryRequirements with image" 2487 */ 2488 assert(info->memoryOffset % image->alignment == 0); 2489 assert(info->memoryOffset < mem->bo->size); 2490 2491 image->mem = mem; 2492 image->mem_offset = info->memoryOffset; 2493} 2494 2495VKAPI_ATTR VkResult VKAPI_CALL 2496v3dv_BindImageMemory2(VkDevice _device, 2497 uint32_t bindInfoCount, 2498 const VkBindImageMemoryInfo *pBindInfos) 2499{ 2500 for (uint32_t i = 0; i < bindInfoCount; i++) { 2501 const VkBindImageMemorySwapchainInfoKHR *swapchain_info = 2502 vk_find_struct_const(pBindInfos->pNext, 2503 BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR); 2504 if (swapchain_info && swapchain_info->swapchain) { 2505 struct v3dv_image *swapchain_image = 2506 v3dv_wsi_get_image_from_swapchain(swapchain_info->swapchain, 2507 swapchain_info->imageIndex); 2508 VkBindImageMemoryInfo swapchain_bind = { 2509 .sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO, 2510 .image = pBindInfos[i].image, 2511 .memory = v3dv_device_memory_to_handle(swapchain_image->mem), 2512 .memoryOffset = swapchain_image->mem_offset, 2513 }; 2514 bind_image_memory(&swapchain_bind); 2515 } else { 2516 bind_image_memory(&pBindInfos[i]); 2517 } 2518 } 2519 2520 return VK_SUCCESS; 2521} 2522 2523VKAPI_ATTR void VKAPI_CALL 2524v3dv_GetBufferMemoryRequirements2(VkDevice device, 2525 const VkBufferMemoryRequirementsInfo2 *pInfo, 2526 VkMemoryRequirements2 *pMemoryRequirements) 2527{ 2528 V3DV_FROM_HANDLE(v3dv_buffer, buffer, pInfo->buffer); 2529 2530 pMemoryRequirements->memoryRequirements = (VkMemoryRequirements) { 2531 .memoryTypeBits = 0x1, 2532 .alignment = buffer->alignment, 2533 .size = align64(buffer->size, buffer->alignment), 2534 }; 2535 2536 vk_foreach_struct(ext, pMemoryRequirements->pNext) { 2537 switch (ext->sType) { 2538 case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: { 2539 VkMemoryDedicatedRequirements *req = 2540 (VkMemoryDedicatedRequirements *) ext; 2541 req->requiresDedicatedAllocation = false; 2542 req->prefersDedicatedAllocation = false; 2543 break; 2544 } 2545 default: 2546 v3dv_debug_ignored_stype(ext->sType); 2547 break; 2548 } 2549 } 2550} 2551 2552static void 2553bind_buffer_memory(const VkBindBufferMemoryInfo *info) 2554{ 2555 V3DV_FROM_HANDLE(v3dv_buffer, buffer, info->buffer); 2556 V3DV_FROM_HANDLE(v3dv_device_memory, mem, info->memory); 2557 2558 /* Valid usage: 2559 * 2560 * "memoryOffset must be an integer multiple of the alignment member of 2561 * the VkMemoryRequirements structure returned from a call to 2562 * vkGetBufferMemoryRequirements with buffer" 2563 */ 2564 assert(info->memoryOffset % buffer->alignment == 0); 2565 assert(info->memoryOffset < mem->bo->size); 2566 2567 buffer->mem = mem; 2568 buffer->mem_offset = info->memoryOffset; 2569} 2570 2571 2572VKAPI_ATTR VkResult VKAPI_CALL 2573v3dv_BindBufferMemory2(VkDevice device, 2574 uint32_t bindInfoCount, 2575 const VkBindBufferMemoryInfo *pBindInfos) 2576{ 2577 for (uint32_t i = 0; i < bindInfoCount; i++) 2578 bind_buffer_memory(&pBindInfos[i]); 2579 2580 return VK_SUCCESS; 2581} 2582 2583VKAPI_ATTR VkResult VKAPI_CALL 2584v3dv_CreateBuffer(VkDevice _device, 2585 const VkBufferCreateInfo *pCreateInfo, 2586 const VkAllocationCallbacks *pAllocator, 2587 VkBuffer *pBuffer) 2588{ 2589 V3DV_FROM_HANDLE(v3dv_device, device, _device); 2590 struct v3dv_buffer *buffer; 2591 2592 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO); 2593 assert(pCreateInfo->usage != 0); 2594 2595 /* We don't support any flags for now */ 2596 assert(pCreateInfo->flags == 0); 2597 2598 buffer = vk_object_zalloc(&device->vk, pAllocator, sizeof(*buffer), 2599 VK_OBJECT_TYPE_BUFFER); 2600 if (buffer == NULL) 2601 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 2602 2603 buffer->size = pCreateInfo->size; 2604 buffer->usage = pCreateInfo->usage; 2605 buffer->alignment = V3D_NON_COHERENT_ATOM_SIZE; 2606 2607 /* Limit allocations to 32-bit */ 2608 const VkDeviceSize aligned_size = align64(buffer->size, buffer->alignment); 2609 if (aligned_size > UINT32_MAX || aligned_size < buffer->size) { 2610 vk_free(&device->vk.alloc, buffer); 2611 return VK_ERROR_OUT_OF_DEVICE_MEMORY; 2612 } 2613 2614 *pBuffer = v3dv_buffer_to_handle(buffer); 2615 2616 return VK_SUCCESS; 2617} 2618 2619VKAPI_ATTR void VKAPI_CALL 2620v3dv_DestroyBuffer(VkDevice _device, 2621 VkBuffer _buffer, 2622 const VkAllocationCallbacks *pAllocator) 2623{ 2624 V3DV_FROM_HANDLE(v3dv_device, device, _device); 2625 V3DV_FROM_HANDLE(v3dv_buffer, buffer, _buffer); 2626 2627 if (!buffer) 2628 return; 2629 2630 vk_object_free(&device->vk, pAllocator, buffer); 2631} 2632 2633VKAPI_ATTR VkResult VKAPI_CALL 2634v3dv_CreateFramebuffer(VkDevice _device, 2635 const VkFramebufferCreateInfo *pCreateInfo, 2636 const VkAllocationCallbacks *pAllocator, 2637 VkFramebuffer *pFramebuffer) 2638{ 2639 V3DV_FROM_HANDLE(v3dv_device, device, _device); 2640 struct v3dv_framebuffer *framebuffer; 2641 2642 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO); 2643 2644 size_t size = sizeof(*framebuffer) + 2645 sizeof(struct v3dv_image_view *) * pCreateInfo->attachmentCount; 2646 framebuffer = vk_object_zalloc(&device->vk, pAllocator, size, 2647 VK_OBJECT_TYPE_FRAMEBUFFER); 2648 if (framebuffer == NULL) 2649 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 2650 2651 framebuffer->width = pCreateInfo->width; 2652 framebuffer->height = pCreateInfo->height; 2653 framebuffer->layers = pCreateInfo->layers; 2654 framebuffer->has_edge_padding = true; 2655 2656 const VkFramebufferAttachmentsCreateInfo *imageless = 2657 vk_find_struct_const(pCreateInfo->pNext, 2658 FRAMEBUFFER_ATTACHMENTS_CREATE_INFO); 2659 2660 framebuffer->attachment_count = pCreateInfo->attachmentCount; 2661 framebuffer->color_attachment_count = 0; 2662 for (uint32_t i = 0; i < framebuffer->attachment_count; i++) { 2663 if (!imageless) { 2664 framebuffer->attachments[i] = 2665 v3dv_image_view_from_handle(pCreateInfo->pAttachments[i]); 2666 if (framebuffer->attachments[i]->vk.aspects & VK_IMAGE_ASPECT_COLOR_BIT) 2667 framebuffer->color_attachment_count++; 2668 } else { 2669 assert(i < imageless->attachmentImageInfoCount); 2670 if (imageless->pAttachmentImageInfos[i].usage & 2671 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) { 2672 framebuffer->color_attachment_count++; 2673 } 2674 } 2675 } 2676 2677 *pFramebuffer = v3dv_framebuffer_to_handle(framebuffer); 2678 2679 return VK_SUCCESS; 2680} 2681 2682VKAPI_ATTR void VKAPI_CALL 2683v3dv_DestroyFramebuffer(VkDevice _device, 2684 VkFramebuffer _fb, 2685 const VkAllocationCallbacks *pAllocator) 2686{ 2687 V3DV_FROM_HANDLE(v3dv_device, device, _device); 2688 V3DV_FROM_HANDLE(v3dv_framebuffer, fb, _fb); 2689 2690 if (!fb) 2691 return; 2692 2693 vk_object_free(&device->vk, pAllocator, fb); 2694} 2695 2696VKAPI_ATTR VkResult VKAPI_CALL 2697v3dv_GetMemoryFdPropertiesKHR(VkDevice _device, 2698 VkExternalMemoryHandleTypeFlagBits handleType, 2699 int fd, 2700 VkMemoryFdPropertiesKHR *pMemoryFdProperties) 2701{ 2702 V3DV_FROM_HANDLE(v3dv_device, device, _device); 2703 struct v3dv_physical_device *pdevice = &device->instance->physicalDevice; 2704 2705 switch (handleType) { 2706 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: 2707 pMemoryFdProperties->memoryTypeBits = 2708 (1 << pdevice->memory.memoryTypeCount) - 1; 2709 return VK_SUCCESS; 2710 default: 2711 return vk_error(device, VK_ERROR_INVALID_EXTERNAL_HANDLE); 2712 } 2713} 2714 2715VKAPI_ATTR VkResult VKAPI_CALL 2716v3dv_GetMemoryFdKHR(VkDevice _device, 2717 const VkMemoryGetFdInfoKHR *pGetFdInfo, 2718 int *pFd) 2719{ 2720 V3DV_FROM_HANDLE(v3dv_device, device, _device); 2721 V3DV_FROM_HANDLE(v3dv_device_memory, mem, pGetFdInfo->memory); 2722 2723 assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR); 2724 assert(pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT || 2725 pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT); 2726 2727 int fd, ret; 2728 ret = drmPrimeHandleToFD(device->pdevice->render_fd, 2729 mem->bo->handle, 2730 DRM_CLOEXEC, &fd); 2731 if (ret) 2732 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 2733 2734 *pFd = fd; 2735 2736 return VK_SUCCESS; 2737} 2738 2739VKAPI_ATTR VkResult VKAPI_CALL 2740v3dv_CreateEvent(VkDevice _device, 2741 const VkEventCreateInfo *pCreateInfo, 2742 const VkAllocationCallbacks *pAllocator, 2743 VkEvent *pEvent) 2744{ 2745 V3DV_FROM_HANDLE(v3dv_device, device, _device); 2746 struct v3dv_event *event = 2747 vk_object_zalloc(&device->vk, pAllocator, sizeof(*event), 2748 VK_OBJECT_TYPE_EVENT); 2749 if (!event) 2750 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 2751 2752 /* Events are created in the unsignaled state */ 2753 event->state = false; 2754 *pEvent = v3dv_event_to_handle(event); 2755 2756 return VK_SUCCESS; 2757} 2758 2759VKAPI_ATTR void VKAPI_CALL 2760v3dv_DestroyEvent(VkDevice _device, 2761 VkEvent _event, 2762 const VkAllocationCallbacks *pAllocator) 2763{ 2764 V3DV_FROM_HANDLE(v3dv_device, device, _device); 2765 V3DV_FROM_HANDLE(v3dv_event, event, _event); 2766 2767 if (!event) 2768 return; 2769 2770 vk_object_free(&device->vk, pAllocator, event); 2771} 2772 2773VKAPI_ATTR VkResult VKAPI_CALL 2774v3dv_GetEventStatus(VkDevice _device, VkEvent _event) 2775{ 2776 V3DV_FROM_HANDLE(v3dv_event, event, _event); 2777 return p_atomic_read(&event->state) ? VK_EVENT_SET : VK_EVENT_RESET; 2778} 2779 2780VKAPI_ATTR VkResult VKAPI_CALL 2781v3dv_SetEvent(VkDevice _device, VkEvent _event) 2782{ 2783 V3DV_FROM_HANDLE(v3dv_event, event, _event); 2784 p_atomic_set(&event->state, 1); 2785 return VK_SUCCESS; 2786} 2787 2788VKAPI_ATTR VkResult VKAPI_CALL 2789v3dv_ResetEvent(VkDevice _device, VkEvent _event) 2790{ 2791 V3DV_FROM_HANDLE(v3dv_event, event, _event); 2792 p_atomic_set(&event->state, 0); 2793 return VK_SUCCESS; 2794} 2795 2796VKAPI_ATTR VkResult VKAPI_CALL 2797v3dv_CreateSampler(VkDevice _device, 2798 const VkSamplerCreateInfo *pCreateInfo, 2799 const VkAllocationCallbacks *pAllocator, 2800 VkSampler *pSampler) 2801{ 2802 V3DV_FROM_HANDLE(v3dv_device, device, _device); 2803 struct v3dv_sampler *sampler; 2804 2805 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO); 2806 2807 sampler = vk_object_zalloc(&device->vk, pAllocator, sizeof(*sampler), 2808 VK_OBJECT_TYPE_SAMPLER); 2809 if (!sampler) 2810 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 2811 2812 sampler->compare_enable = pCreateInfo->compareEnable; 2813 sampler->unnormalized_coordinates = pCreateInfo->unnormalizedCoordinates; 2814 2815 const VkSamplerCustomBorderColorCreateInfoEXT *bc_info = 2816 vk_find_struct_const(pCreateInfo->pNext, 2817 SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT); 2818 2819 v3dv_X(device, pack_sampler_state)(sampler, pCreateInfo, bc_info); 2820 2821 *pSampler = v3dv_sampler_to_handle(sampler); 2822 2823 return VK_SUCCESS; 2824} 2825 2826VKAPI_ATTR void VKAPI_CALL 2827v3dv_DestroySampler(VkDevice _device, 2828 VkSampler _sampler, 2829 const VkAllocationCallbacks *pAllocator) 2830{ 2831 V3DV_FROM_HANDLE(v3dv_device, device, _device); 2832 V3DV_FROM_HANDLE(v3dv_sampler, sampler, _sampler); 2833 2834 if (!sampler) 2835 return; 2836 2837 vk_object_free(&device->vk, pAllocator, sampler); 2838} 2839 2840VKAPI_ATTR void VKAPI_CALL 2841v3dv_GetDeviceMemoryCommitment(VkDevice device, 2842 VkDeviceMemory memory, 2843 VkDeviceSize *pCommittedMemoryInBytes) 2844{ 2845 *pCommittedMemoryInBytes = 0; 2846} 2847 2848VKAPI_ATTR void VKAPI_CALL 2849v3dv_GetImageSparseMemoryRequirements( 2850 VkDevice device, 2851 VkImage image, 2852 uint32_t *pSparseMemoryRequirementCount, 2853 VkSparseImageMemoryRequirements *pSparseMemoryRequirements) 2854{ 2855 *pSparseMemoryRequirementCount = 0; 2856} 2857 2858VKAPI_ATTR void VKAPI_CALL 2859v3dv_GetImageSparseMemoryRequirements2( 2860 VkDevice device, 2861 const VkImageSparseMemoryRequirementsInfo2 *pInfo, 2862 uint32_t *pSparseMemoryRequirementCount, 2863 VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements) 2864{ 2865 *pSparseMemoryRequirementCount = 0; 2866} 2867 2868/* vk_icd.h does not declare this function, so we declare it here to 2869 * suppress Wmissing-prototypes. 2870 */ 2871PUBLIC VKAPI_ATTR VkResult VKAPI_CALL 2872vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion); 2873 2874PUBLIC VKAPI_ATTR VkResult VKAPI_CALL 2875vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion) 2876{ 2877 /* For the full details on loader interface versioning, see 2878 * <https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/loader/LoaderAndLayerInterface.md>. 2879 * What follows is a condensed summary, to help you navigate the large and 2880 * confusing official doc. 2881 * 2882 * - Loader interface v0 is incompatible with later versions. We don't 2883 * support it. 2884 * 2885 * - In loader interface v1: 2886 * - The first ICD entrypoint called by the loader is 2887 * vk_icdGetInstanceProcAddr(). The ICD must statically expose this 2888 * entrypoint. 2889 * - The ICD must statically expose no other Vulkan symbol unless it is 2890 * linked with -Bsymbolic. 2891 * - Each dispatchable Vulkan handle created by the ICD must be 2892 * a pointer to a struct whose first member is VK_LOADER_DATA. The 2893 * ICD must initialize VK_LOADER_DATA.loadMagic to ICD_LOADER_MAGIC. 2894 * - The loader implements vkCreate{PLATFORM}SurfaceKHR() and 2895 * vkDestroySurfaceKHR(). The ICD must be capable of working with 2896 * such loader-managed surfaces. 2897 * 2898 * - Loader interface v2 differs from v1 in: 2899 * - The first ICD entrypoint called by the loader is 2900 * vk_icdNegotiateLoaderICDInterfaceVersion(). The ICD must 2901 * statically expose this entrypoint. 2902 * 2903 * - Loader interface v3 differs from v2 in: 2904 * - The ICD must implement vkCreate{PLATFORM}SurfaceKHR(), 2905 * vkDestroySurfaceKHR(), and other API which uses VKSurfaceKHR, 2906 * because the loader no longer does so. 2907 * 2908 * - Loader interface v4 differs from v3 in: 2909 * - The ICD must implement vk_icdGetPhysicalDeviceProcAddr(). 2910 * 2911 * - Loader interface v5 differs from v4 in: 2912 * - The ICD must support Vulkan API version 1.1 and must not return 2913 * VK_ERROR_INCOMPATIBLE_DRIVER from vkCreateInstance() unless a 2914 * Vulkan Loader with interface v4 or smaller is being used and the 2915 * application provides an API version that is greater than 1.0. 2916 */ 2917 *pSupportedVersion = MIN2(*pSupportedVersion, 5u); 2918 return VK_SUCCESS; 2919} 2920 2921VkDeviceAddress 2922v3dv_GetBufferDeviceAddress(VkDevice device, 2923 const VkBufferDeviceAddressInfoKHR *pInfo) 2924{ 2925 V3DV_FROM_HANDLE(v3dv_buffer, buffer, pInfo->buffer); 2926 return buffer->mem_offset + buffer->mem->bo->offset; 2927} 2928 2929uint64_t 2930v3dv_GetBufferOpaqueCaptureAddress(VkDevice device, 2931 const VkBufferDeviceAddressInfoKHR *pInfo) 2932{ 2933 /* Not implemented */ 2934 return 0; 2935} 2936 2937uint64_t 2938v3dv_GetDeviceMemoryOpaqueCaptureAddress( 2939 VkDevice device, 2940 const VkDeviceMemoryOpaqueCaptureAddressInfoKHR *pInfo) 2941{ 2942 /* Not implemented */ 2943 return 0; 2944} 2945