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