17ec681f3Smrg/* 27ec681f3Smrg * Copyright 2019 Google LLC 37ec681f3Smrg * SPDX-License-Identifier: MIT 47ec681f3Smrg * 57ec681f3Smrg * based in part on anv and radv which are: 67ec681f3Smrg * Copyright © 2015 Intel Corporation 77ec681f3Smrg * Copyright © 2016 Red Hat. 87ec681f3Smrg * Copyright © 2016 Bas Nieuwenhuizen 97ec681f3Smrg */ 107ec681f3Smrg 117ec681f3Smrg#include "vn_device.h" 127ec681f3Smrg 137ec681f3Smrg#include "venus-protocol/vn_protocol_driver_device.h" 147ec681f3Smrg 157ec681f3Smrg#include "vn_android.h" 167ec681f3Smrg#include "vn_instance.h" 177ec681f3Smrg#include "vn_physical_device.h" 187ec681f3Smrg#include "vn_queue.h" 197ec681f3Smrg 207ec681f3Smrg/* device commands */ 217ec681f3Smrg 227ec681f3Smrgstatic void 237ec681f3Smrgvn_queue_fini(struct vn_queue *queue) 247ec681f3Smrg{ 257ec681f3Smrg if (queue->wait_fence != VK_NULL_HANDLE) { 267ec681f3Smrg vn_DestroyFence(vn_device_to_handle(queue->device), queue->wait_fence, 277ec681f3Smrg NULL); 287ec681f3Smrg } 297ec681f3Smrg vn_object_base_fini(&queue->base); 307ec681f3Smrg} 317ec681f3Smrg 327ec681f3Smrgstatic VkResult 337ec681f3Smrgvn_queue_init(struct vn_device *dev, 347ec681f3Smrg struct vn_queue *queue, 357ec681f3Smrg const VkDeviceQueueCreateInfo *queue_info, 367ec681f3Smrg uint32_t queue_index) 377ec681f3Smrg{ 387ec681f3Smrg vn_object_base_init(&queue->base, VK_OBJECT_TYPE_QUEUE, &dev->base); 397ec681f3Smrg 407ec681f3Smrg VkQueue queue_handle = vn_queue_to_handle(queue); 417ec681f3Smrg vn_async_vkGetDeviceQueue2( 427ec681f3Smrg dev->instance, vn_device_to_handle(dev), 437ec681f3Smrg &(VkDeviceQueueInfo2){ 447ec681f3Smrg .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2, 457ec681f3Smrg .flags = queue_info->flags, 467ec681f3Smrg .queueFamilyIndex = queue_info->queueFamilyIndex, 477ec681f3Smrg .queueIndex = queue_index, 487ec681f3Smrg }, 497ec681f3Smrg &queue_handle); 507ec681f3Smrg 517ec681f3Smrg queue->device = dev; 527ec681f3Smrg queue->family = queue_info->queueFamilyIndex; 537ec681f3Smrg queue->index = queue_index; 547ec681f3Smrg queue->flags = queue_info->flags; 557ec681f3Smrg 567ec681f3Smrg const VkExportFenceCreateInfo export_fence_info = { 577ec681f3Smrg .sType = VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO, 587ec681f3Smrg .pNext = NULL, 597ec681f3Smrg .handleTypes = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT, 607ec681f3Smrg }; 617ec681f3Smrg const VkFenceCreateInfo fence_info = { 627ec681f3Smrg .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, 637ec681f3Smrg .pNext = dev->instance->experimental.globalFencing == VK_TRUE 647ec681f3Smrg ? &export_fence_info 657ec681f3Smrg : NULL, 667ec681f3Smrg .flags = 0, 677ec681f3Smrg }; 687ec681f3Smrg VkResult result = vn_CreateFence(vn_device_to_handle(dev), &fence_info, 697ec681f3Smrg NULL, &queue->wait_fence); 707ec681f3Smrg if (result != VK_SUCCESS) 717ec681f3Smrg return result; 727ec681f3Smrg 737ec681f3Smrg return VK_SUCCESS; 747ec681f3Smrg} 757ec681f3Smrg 767ec681f3Smrgstatic VkResult 777ec681f3Smrgvn_device_init_queues(struct vn_device *dev, 787ec681f3Smrg const VkDeviceCreateInfo *create_info) 797ec681f3Smrg{ 807ec681f3Smrg const VkAllocationCallbacks *alloc = &dev->base.base.alloc; 817ec681f3Smrg 827ec681f3Smrg uint32_t count = 0; 837ec681f3Smrg for (uint32_t i = 0; i < create_info->queueCreateInfoCount; i++) 847ec681f3Smrg count += create_info->pQueueCreateInfos[i].queueCount; 857ec681f3Smrg 867ec681f3Smrg struct vn_queue *queues = 877ec681f3Smrg vk_zalloc(alloc, sizeof(*queues) * count, VN_DEFAULT_ALIGN, 887ec681f3Smrg VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 897ec681f3Smrg if (!queues) 907ec681f3Smrg return VK_ERROR_OUT_OF_HOST_MEMORY; 917ec681f3Smrg 927ec681f3Smrg VkResult result = VK_SUCCESS; 937ec681f3Smrg count = 0; 947ec681f3Smrg for (uint32_t i = 0; i < create_info->queueCreateInfoCount; i++) { 957ec681f3Smrg const VkDeviceQueueCreateInfo *queue_info = 967ec681f3Smrg &create_info->pQueueCreateInfos[i]; 977ec681f3Smrg for (uint32_t j = 0; j < queue_info->queueCount; j++) { 987ec681f3Smrg result = vn_queue_init(dev, &queues[count], queue_info, j); 997ec681f3Smrg if (result != VK_SUCCESS) 1007ec681f3Smrg break; 1017ec681f3Smrg 1027ec681f3Smrg count++; 1037ec681f3Smrg } 1047ec681f3Smrg } 1057ec681f3Smrg 1067ec681f3Smrg if (result != VK_SUCCESS) { 1077ec681f3Smrg for (uint32_t i = 0; i < count; i++) 1087ec681f3Smrg vn_queue_fini(&queues[i]); 1097ec681f3Smrg vk_free(alloc, queues); 1107ec681f3Smrg 1117ec681f3Smrg return result; 1127ec681f3Smrg } 1137ec681f3Smrg 1147ec681f3Smrg dev->queues = queues; 1157ec681f3Smrg dev->queue_count = count; 1167ec681f3Smrg 1177ec681f3Smrg return VK_SUCCESS; 1187ec681f3Smrg} 1197ec681f3Smrg 1207ec681f3Smrgstatic bool 1217ec681f3Smrgfind_extension_names(const char *const *exts, 1227ec681f3Smrg uint32_t ext_count, 1237ec681f3Smrg const char *name) 1247ec681f3Smrg{ 1257ec681f3Smrg for (uint32_t i = 0; i < ext_count; i++) { 1267ec681f3Smrg if (!strcmp(exts[i], name)) 1277ec681f3Smrg return true; 1287ec681f3Smrg } 1297ec681f3Smrg return false; 1307ec681f3Smrg} 1317ec681f3Smrg 1327ec681f3Smrgstatic bool 1337ec681f3Smrgmerge_extension_names(const char *const *exts, 1347ec681f3Smrg uint32_t ext_count, 1357ec681f3Smrg const char *const *extra_exts, 1367ec681f3Smrg uint32_t extra_count, 1377ec681f3Smrg const char *const *block_exts, 1387ec681f3Smrg uint32_t block_count, 1397ec681f3Smrg const VkAllocationCallbacks *alloc, 1407ec681f3Smrg const char *const **out_exts, 1417ec681f3Smrg uint32_t *out_count) 1427ec681f3Smrg{ 1437ec681f3Smrg const char **merged = 1447ec681f3Smrg vk_alloc(alloc, sizeof(*merged) * (ext_count + extra_count), 1457ec681f3Smrg VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 1467ec681f3Smrg if (!merged) 1477ec681f3Smrg return false; 1487ec681f3Smrg 1497ec681f3Smrg uint32_t count = 0; 1507ec681f3Smrg for (uint32_t i = 0; i < ext_count; i++) { 1517ec681f3Smrg if (!find_extension_names(block_exts, block_count, exts[i])) 1527ec681f3Smrg merged[count++] = exts[i]; 1537ec681f3Smrg } 1547ec681f3Smrg for (uint32_t i = 0; i < extra_count; i++) { 1557ec681f3Smrg if (!find_extension_names(exts, ext_count, extra_exts[i])) 1567ec681f3Smrg merged[count++] = extra_exts[i]; 1577ec681f3Smrg } 1587ec681f3Smrg 1597ec681f3Smrg *out_exts = merged; 1607ec681f3Smrg *out_count = count; 1617ec681f3Smrg return true; 1627ec681f3Smrg} 1637ec681f3Smrg 1647ec681f3Smrgstatic const VkDeviceCreateInfo * 1657ec681f3Smrgvn_device_fix_create_info(const struct vn_device *dev, 1667ec681f3Smrg const VkDeviceCreateInfo *dev_info, 1677ec681f3Smrg const VkAllocationCallbacks *alloc, 1687ec681f3Smrg VkDeviceCreateInfo *local_info) 1697ec681f3Smrg{ 1707ec681f3Smrg const struct vn_physical_device *physical_dev = dev->physical_device; 1717ec681f3Smrg const struct vk_device_extension_table *app_exts = 1727ec681f3Smrg &dev->base.base.enabled_extensions; 1737ec681f3Smrg /* extra_exts and block_exts must not overlap */ 1747ec681f3Smrg const char *extra_exts[16]; 1757ec681f3Smrg const char *block_exts[16]; 1767ec681f3Smrg uint32_t extra_count = 0; 1777ec681f3Smrg uint32_t block_count = 0; 1787ec681f3Smrg 1797ec681f3Smrg /* fix for WSI (treat AHB as WSI extension for simplicity) */ 1807ec681f3Smrg const bool has_wsi = 1817ec681f3Smrg app_exts->KHR_swapchain || app_exts->ANDROID_native_buffer || 1827ec681f3Smrg app_exts->ANDROID_external_memory_android_hardware_buffer; 1837ec681f3Smrg if (has_wsi) { 1847ec681f3Smrg /* KHR_swapchain may be advertised without the renderer support for 1857ec681f3Smrg * EXT_image_drm_format_modifier 1867ec681f3Smrg */ 1877ec681f3Smrg if (!app_exts->EXT_image_drm_format_modifier && 1887ec681f3Smrg physical_dev->renderer_extensions.EXT_image_drm_format_modifier) { 1897ec681f3Smrg extra_exts[extra_count++] = 1907ec681f3Smrg VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME; 1917ec681f3Smrg 1927ec681f3Smrg if (physical_dev->renderer_version < VK_API_VERSION_1_2 && 1937ec681f3Smrg !app_exts->KHR_image_format_list) { 1947ec681f3Smrg extra_exts[extra_count++] = 1957ec681f3Smrg VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME; 1967ec681f3Smrg } 1977ec681f3Smrg } 1987ec681f3Smrg 1997ec681f3Smrg /* XXX KHR_swapchain may be advertised without the renderer support for 2007ec681f3Smrg * EXT_queue_family_foreign 2017ec681f3Smrg */ 2027ec681f3Smrg if (!app_exts->EXT_queue_family_foreign && 2037ec681f3Smrg physical_dev->renderer_extensions.EXT_queue_family_foreign) { 2047ec681f3Smrg extra_exts[extra_count++] = 2057ec681f3Smrg VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME; 2067ec681f3Smrg } 2077ec681f3Smrg 2087ec681f3Smrg if (app_exts->KHR_swapchain) { 2097ec681f3Smrg /* see vn_physical_device_get_native_extensions */ 2107ec681f3Smrg block_exts[block_count++] = VK_KHR_SWAPCHAIN_EXTENSION_NAME; 2117ec681f3Smrg block_exts[block_count++] = 2127ec681f3Smrg VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME; 2137ec681f3Smrg block_exts[block_count++] = 2147ec681f3Smrg VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME; 2157ec681f3Smrg } 2167ec681f3Smrg 2177ec681f3Smrg if (app_exts->ANDROID_native_buffer) 2187ec681f3Smrg block_exts[block_count++] = VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME; 2197ec681f3Smrg 2207ec681f3Smrg if (app_exts->ANDROID_external_memory_android_hardware_buffer) { 2217ec681f3Smrg block_exts[block_count++] = 2227ec681f3Smrg VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME; 2237ec681f3Smrg } 2247ec681f3Smrg } 2257ec681f3Smrg 2267ec681f3Smrg if (app_exts->KHR_external_memory_fd || 2277ec681f3Smrg app_exts->EXT_external_memory_dma_buf || has_wsi) { 2287ec681f3Smrg switch (physical_dev->external_memory.renderer_handle_type) { 2297ec681f3Smrg case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: 2307ec681f3Smrg if (!app_exts->EXT_external_memory_dma_buf) { 2317ec681f3Smrg extra_exts[extra_count++] = 2327ec681f3Smrg VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME; 2337ec681f3Smrg } 2347ec681f3Smrg FALLTHROUGH; 2357ec681f3Smrg case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT: 2367ec681f3Smrg if (!app_exts->KHR_external_memory_fd) { 2377ec681f3Smrg extra_exts[extra_count++] = 2387ec681f3Smrg VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME; 2397ec681f3Smrg } 2407ec681f3Smrg break; 2417ec681f3Smrg default: 2427ec681f3Smrg /* TODO other handle types */ 2437ec681f3Smrg break; 2447ec681f3Smrg } 2457ec681f3Smrg } 2467ec681f3Smrg 2477ec681f3Smrg assert(extra_count <= ARRAY_SIZE(extra_exts)); 2487ec681f3Smrg assert(block_count <= ARRAY_SIZE(block_exts)); 2497ec681f3Smrg 2507ec681f3Smrg if (!extra_count && (!block_count || !dev_info->enabledExtensionCount)) 2517ec681f3Smrg return dev_info; 2527ec681f3Smrg 2537ec681f3Smrg *local_info = *dev_info; 2547ec681f3Smrg if (!merge_extension_names(dev_info->ppEnabledExtensionNames, 2557ec681f3Smrg dev_info->enabledExtensionCount, extra_exts, 2567ec681f3Smrg extra_count, block_exts, block_count, alloc, 2577ec681f3Smrg &local_info->ppEnabledExtensionNames, 2587ec681f3Smrg &local_info->enabledExtensionCount)) 2597ec681f3Smrg return NULL; 2607ec681f3Smrg 2617ec681f3Smrg return local_info; 2627ec681f3Smrg} 2637ec681f3Smrg 2647ec681f3SmrgVkResult 2657ec681f3Smrgvn_CreateDevice(VkPhysicalDevice physicalDevice, 2667ec681f3Smrg const VkDeviceCreateInfo *pCreateInfo, 2677ec681f3Smrg const VkAllocationCallbacks *pAllocator, 2687ec681f3Smrg VkDevice *pDevice) 2697ec681f3Smrg{ 2707ec681f3Smrg struct vn_physical_device *physical_dev = 2717ec681f3Smrg vn_physical_device_from_handle(physicalDevice); 2727ec681f3Smrg struct vn_instance *instance = physical_dev->instance; 2737ec681f3Smrg const VkAllocationCallbacks *alloc = 2747ec681f3Smrg pAllocator ? pAllocator : &instance->base.base.alloc; 2757ec681f3Smrg struct vn_device *dev; 2767ec681f3Smrg VkResult result; 2777ec681f3Smrg 2787ec681f3Smrg dev = vk_zalloc(alloc, sizeof(*dev), VN_DEFAULT_ALIGN, 2797ec681f3Smrg VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 2807ec681f3Smrg if (!dev) 2817ec681f3Smrg return vn_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY); 2827ec681f3Smrg 2837ec681f3Smrg struct vk_device_dispatch_table dispatch_table; 2847ec681f3Smrg vk_device_dispatch_table_from_entrypoints(&dispatch_table, 2857ec681f3Smrg &vn_device_entrypoints, true); 2867ec681f3Smrg vk_device_dispatch_table_from_entrypoints(&dispatch_table, 2877ec681f3Smrg &wsi_device_entrypoints, false); 2887ec681f3Smrg result = vn_device_base_init(&dev->base, &physical_dev->base, 2897ec681f3Smrg &dispatch_table, pCreateInfo, alloc); 2907ec681f3Smrg if (result != VK_SUCCESS) { 2917ec681f3Smrg vk_free(alloc, dev); 2927ec681f3Smrg return vn_error(instance, result); 2937ec681f3Smrg } 2947ec681f3Smrg 2957ec681f3Smrg dev->instance = instance; 2967ec681f3Smrg dev->physical_device = physical_dev; 2977ec681f3Smrg dev->renderer = instance->renderer; 2987ec681f3Smrg 2997ec681f3Smrg VkDeviceCreateInfo local_create_info; 3007ec681f3Smrg pCreateInfo = 3017ec681f3Smrg vn_device_fix_create_info(dev, pCreateInfo, alloc, &local_create_info); 3027ec681f3Smrg if (!pCreateInfo) { 3037ec681f3Smrg result = VK_ERROR_OUT_OF_HOST_MEMORY; 3047ec681f3Smrg goto fail; 3057ec681f3Smrg } 3067ec681f3Smrg 3077ec681f3Smrg VkDevice dev_handle = vn_device_to_handle(dev); 3087ec681f3Smrg result = vn_call_vkCreateDevice(instance, physicalDevice, pCreateInfo, 3097ec681f3Smrg NULL, &dev_handle); 3107ec681f3Smrg if (result != VK_SUCCESS) 3117ec681f3Smrg goto fail; 3127ec681f3Smrg 3137ec681f3Smrg result = vn_device_init_queues(dev, pCreateInfo); 3147ec681f3Smrg if (result != VK_SUCCESS) { 3157ec681f3Smrg vn_call_vkDestroyDevice(instance, dev_handle, NULL); 3167ec681f3Smrg goto fail; 3177ec681f3Smrg } 3187ec681f3Smrg 3197ec681f3Smrg for (uint32_t i = 0; i < ARRAY_SIZE(dev->memory_pools); i++) { 3207ec681f3Smrg struct vn_device_memory_pool *pool = &dev->memory_pools[i]; 3217ec681f3Smrg mtx_init(&pool->mutex, mtx_plain); 3227ec681f3Smrg } 3237ec681f3Smrg 3247ec681f3Smrg if (dev->base.base.enabled_extensions 3257ec681f3Smrg .ANDROID_external_memory_android_hardware_buffer) { 3267ec681f3Smrg result = vn_android_init_ahb_buffer_memory_type_bits(dev); 3277ec681f3Smrg if (result != VK_SUCCESS) { 3287ec681f3Smrg vn_call_vkDestroyDevice(instance, dev_handle, NULL); 3297ec681f3Smrg goto fail; 3307ec681f3Smrg } 3317ec681f3Smrg } 3327ec681f3Smrg 3337ec681f3Smrg *pDevice = dev_handle; 3347ec681f3Smrg 3357ec681f3Smrg if (pCreateInfo == &local_create_info) 3367ec681f3Smrg vk_free(alloc, (void *)pCreateInfo->ppEnabledExtensionNames); 3377ec681f3Smrg 3387ec681f3Smrg return VK_SUCCESS; 3397ec681f3Smrg 3407ec681f3Smrgfail: 3417ec681f3Smrg if (pCreateInfo == &local_create_info) 3427ec681f3Smrg vk_free(alloc, (void *)pCreateInfo->ppEnabledExtensionNames); 3437ec681f3Smrg vn_device_base_fini(&dev->base); 3447ec681f3Smrg vk_free(alloc, dev); 3457ec681f3Smrg return vn_error(instance, result); 3467ec681f3Smrg} 3477ec681f3Smrg 3487ec681f3Smrgvoid 3497ec681f3Smrgvn_DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) 3507ec681f3Smrg{ 3517ec681f3Smrg struct vn_device *dev = vn_device_from_handle(device); 3527ec681f3Smrg const VkAllocationCallbacks *alloc = 3537ec681f3Smrg pAllocator ? pAllocator : &dev->base.base.alloc; 3547ec681f3Smrg 3557ec681f3Smrg if (!dev) 3567ec681f3Smrg return; 3577ec681f3Smrg 3587ec681f3Smrg for (uint32_t i = 0; i < ARRAY_SIZE(dev->memory_pools); i++) 3597ec681f3Smrg vn_device_memory_pool_fini(dev, i); 3607ec681f3Smrg 3617ec681f3Smrg for (uint32_t i = 0; i < dev->queue_count; i++) 3627ec681f3Smrg vn_queue_fini(&dev->queues[i]); 3637ec681f3Smrg 3647ec681f3Smrg /* We must emit vkDestroyDevice before freeing dev->queues. Otherwise, 3657ec681f3Smrg * another thread might reuse their object ids while they still refer to 3667ec681f3Smrg * the queues in the renderer. 3677ec681f3Smrg */ 3687ec681f3Smrg vn_async_vkDestroyDevice(dev->instance, device, NULL); 3697ec681f3Smrg 3707ec681f3Smrg vk_free(alloc, dev->queues); 3717ec681f3Smrg 3727ec681f3Smrg vn_device_base_fini(&dev->base); 3737ec681f3Smrg vk_free(alloc, dev); 3747ec681f3Smrg} 3757ec681f3Smrg 3767ec681f3SmrgPFN_vkVoidFunction 3777ec681f3Smrgvn_GetDeviceProcAddr(VkDevice device, const char *pName) 3787ec681f3Smrg{ 3797ec681f3Smrg struct vn_device *dev = vn_device_from_handle(device); 3807ec681f3Smrg return vk_device_get_proc_addr(&dev->base.base, pName); 3817ec681f3Smrg} 3827ec681f3Smrg 3837ec681f3Smrgvoid 3847ec681f3Smrgvn_GetDeviceGroupPeerMemoryFeatures( 3857ec681f3Smrg VkDevice device, 3867ec681f3Smrg uint32_t heapIndex, 3877ec681f3Smrg uint32_t localDeviceIndex, 3887ec681f3Smrg uint32_t remoteDeviceIndex, 3897ec681f3Smrg VkPeerMemoryFeatureFlags *pPeerMemoryFeatures) 3907ec681f3Smrg{ 3917ec681f3Smrg struct vn_device *dev = vn_device_from_handle(device); 3927ec681f3Smrg 3937ec681f3Smrg /* TODO get and cache the values in vkCreateDevice */ 3947ec681f3Smrg vn_call_vkGetDeviceGroupPeerMemoryFeatures( 3957ec681f3Smrg dev->instance, device, heapIndex, localDeviceIndex, remoteDeviceIndex, 3967ec681f3Smrg pPeerMemoryFeatures); 3977ec681f3Smrg} 3987ec681f3Smrg 3997ec681f3SmrgVkResult 4007ec681f3Smrgvn_DeviceWaitIdle(VkDevice device) 4017ec681f3Smrg{ 4027ec681f3Smrg struct vn_device *dev = vn_device_from_handle(device); 4037ec681f3Smrg 4047ec681f3Smrg for (uint32_t i = 0; i < dev->queue_count; i++) { 4057ec681f3Smrg struct vn_queue *queue = &dev->queues[i]; 4067ec681f3Smrg VkResult result = vn_QueueWaitIdle(vn_queue_to_handle(queue)); 4077ec681f3Smrg if (result != VK_SUCCESS) 4087ec681f3Smrg return vn_error(dev->instance, result); 4097ec681f3Smrg } 4107ec681f3Smrg 4117ec681f3Smrg return VK_SUCCESS; 4127ec681f3Smrg} 413