1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2019 Google LLC 3bf215546Sopenharmony_ci * SPDX-License-Identifier: MIT 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * based in part on anv and radv which are: 6bf215546Sopenharmony_ci * Copyright © 2015 Intel Corporation 7bf215546Sopenharmony_ci * Copyright © 2016 Red Hat. 8bf215546Sopenharmony_ci * Copyright © 2016 Bas Nieuwenhuizen 9bf215546Sopenharmony_ci */ 10bf215546Sopenharmony_ci 11bf215546Sopenharmony_ci#include "vn_device.h" 12bf215546Sopenharmony_ci 13bf215546Sopenharmony_ci#include "venus-protocol/vn_protocol_driver_device.h" 14bf215546Sopenharmony_ci 15bf215546Sopenharmony_ci#include "vn_android.h" 16bf215546Sopenharmony_ci#include "vn_instance.h" 17bf215546Sopenharmony_ci#include "vn_physical_device.h" 18bf215546Sopenharmony_ci#include "vn_queue.h" 19bf215546Sopenharmony_ci 20bf215546Sopenharmony_ci/* device commands */ 21bf215546Sopenharmony_ci 22bf215546Sopenharmony_cistatic void 23bf215546Sopenharmony_civn_queue_fini(struct vn_queue *queue) 24bf215546Sopenharmony_ci{ 25bf215546Sopenharmony_ci if (queue->wait_fence != VK_NULL_HANDLE) { 26bf215546Sopenharmony_ci vn_DestroyFence(vn_device_to_handle(queue->device), queue->wait_fence, 27bf215546Sopenharmony_ci NULL); 28bf215546Sopenharmony_ci } 29bf215546Sopenharmony_ci vn_object_base_fini(&queue->base); 30bf215546Sopenharmony_ci} 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_cistatic VkResult 33bf215546Sopenharmony_civn_queue_init(struct vn_device *dev, 34bf215546Sopenharmony_ci struct vn_queue *queue, 35bf215546Sopenharmony_ci const VkDeviceQueueCreateInfo *queue_info, 36bf215546Sopenharmony_ci uint32_t queue_index) 37bf215546Sopenharmony_ci{ 38bf215546Sopenharmony_ci vn_object_base_init(&queue->base, VK_OBJECT_TYPE_QUEUE, &dev->base); 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci VkQueue queue_handle = vn_queue_to_handle(queue); 41bf215546Sopenharmony_ci vn_async_vkGetDeviceQueue2( 42bf215546Sopenharmony_ci dev->instance, vn_device_to_handle(dev), 43bf215546Sopenharmony_ci &(VkDeviceQueueInfo2){ 44bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2, 45bf215546Sopenharmony_ci .flags = queue_info->flags, 46bf215546Sopenharmony_ci .queueFamilyIndex = queue_info->queueFamilyIndex, 47bf215546Sopenharmony_ci .queueIndex = queue_index, 48bf215546Sopenharmony_ci }, 49bf215546Sopenharmony_ci &queue_handle); 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci queue->device = dev; 52bf215546Sopenharmony_ci queue->family = queue_info->queueFamilyIndex; 53bf215546Sopenharmony_ci queue->index = queue_index; 54bf215546Sopenharmony_ci queue->flags = queue_info->flags; 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci const VkExportFenceCreateInfo export_fence_info = { 57bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO, 58bf215546Sopenharmony_ci .pNext = NULL, 59bf215546Sopenharmony_ci .handleTypes = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT, 60bf215546Sopenharmony_ci }; 61bf215546Sopenharmony_ci const VkFenceCreateInfo fence_info = { 62bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, 63bf215546Sopenharmony_ci .pNext = dev->instance->experimental.globalFencing == VK_TRUE 64bf215546Sopenharmony_ci ? &export_fence_info 65bf215546Sopenharmony_ci : NULL, 66bf215546Sopenharmony_ci .flags = 0, 67bf215546Sopenharmony_ci }; 68bf215546Sopenharmony_ci VkResult result = vn_CreateFence(vn_device_to_handle(dev), &fence_info, 69bf215546Sopenharmony_ci NULL, &queue->wait_fence); 70bf215546Sopenharmony_ci if (result != VK_SUCCESS) 71bf215546Sopenharmony_ci return result; 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ci return VK_SUCCESS; 74bf215546Sopenharmony_ci} 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_cistatic VkResult 77bf215546Sopenharmony_civn_device_init_queues(struct vn_device *dev, 78bf215546Sopenharmony_ci const VkDeviceCreateInfo *create_info) 79bf215546Sopenharmony_ci{ 80bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc = &dev->base.base.alloc; 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ci uint32_t count = 0; 83bf215546Sopenharmony_ci for (uint32_t i = 0; i < create_info->queueCreateInfoCount; i++) 84bf215546Sopenharmony_ci count += create_info->pQueueCreateInfos[i].queueCount; 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_ci struct vn_queue *queues = 87bf215546Sopenharmony_ci vk_zalloc(alloc, sizeof(*queues) * count, VN_DEFAULT_ALIGN, 88bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 89bf215546Sopenharmony_ci if (!queues) 90bf215546Sopenharmony_ci return VK_ERROR_OUT_OF_HOST_MEMORY; 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_ci count = 0; 93bf215546Sopenharmony_ci for (uint32_t i = 0; i < create_info->queueCreateInfoCount; i++) { 94bf215546Sopenharmony_ci VkResult result; 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_ci const VkDeviceQueueCreateInfo *queue_info = 97bf215546Sopenharmony_ci &create_info->pQueueCreateInfos[i]; 98bf215546Sopenharmony_ci for (uint32_t j = 0; j < queue_info->queueCount; j++) { 99bf215546Sopenharmony_ci result = vn_queue_init(dev, &queues[count], queue_info, j); 100bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 101bf215546Sopenharmony_ci for (uint32_t k = 0; k < count; k++) 102bf215546Sopenharmony_ci vn_queue_fini(&queues[k]); 103bf215546Sopenharmony_ci vk_free(alloc, queues); 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_ci return result; 106bf215546Sopenharmony_ci } 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ci count++; 109bf215546Sopenharmony_ci } 110bf215546Sopenharmony_ci } 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ci dev->queues = queues; 113bf215546Sopenharmony_ci dev->queue_count = count; 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci return VK_SUCCESS; 116bf215546Sopenharmony_ci} 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_cistatic bool 119bf215546Sopenharmony_civn_device_queue_family_init(struct vn_device *dev, 120bf215546Sopenharmony_ci const VkDeviceCreateInfo *create_info) 121bf215546Sopenharmony_ci{ 122bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc = &dev->base.base.alloc; 123bf215546Sopenharmony_ci uint32_t *queue_families = NULL; 124bf215546Sopenharmony_ci uint32_t count = 0; 125bf215546Sopenharmony_ci 126bf215546Sopenharmony_ci queue_families = vk_zalloc( 127bf215546Sopenharmony_ci alloc, sizeof(*queue_families) * create_info->queueCreateInfoCount, 128bf215546Sopenharmony_ci VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 129bf215546Sopenharmony_ci if (!queue_families) 130bf215546Sopenharmony_ci return false; 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci for (uint32_t i = 0; i < create_info->queueCreateInfoCount; i++) { 133bf215546Sopenharmony_ci const uint32_t index = 134bf215546Sopenharmony_ci create_info->pQueueCreateInfos[i].queueFamilyIndex; 135bf215546Sopenharmony_ci bool new_index = true; 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci for (uint32_t j = 0; j < count; j++) { 138bf215546Sopenharmony_ci if (queue_families[j] == index) { 139bf215546Sopenharmony_ci new_index = false; 140bf215546Sopenharmony_ci break; 141bf215546Sopenharmony_ci } 142bf215546Sopenharmony_ci } 143bf215546Sopenharmony_ci if (new_index) 144bf215546Sopenharmony_ci queue_families[count++] = index; 145bf215546Sopenharmony_ci } 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci dev->queue_families = queue_families; 148bf215546Sopenharmony_ci dev->queue_family_count = count; 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ci return true; 151bf215546Sopenharmony_ci} 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_cistatic inline void 154bf215546Sopenharmony_civn_device_queue_family_fini(struct vn_device *dev) 155bf215546Sopenharmony_ci{ 156bf215546Sopenharmony_ci vk_free(&dev->base.base.alloc, dev->queue_families); 157bf215546Sopenharmony_ci} 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_cistatic bool 160bf215546Sopenharmony_cifind_extension_names(const char *const *exts, 161bf215546Sopenharmony_ci uint32_t ext_count, 162bf215546Sopenharmony_ci const char *name) 163bf215546Sopenharmony_ci{ 164bf215546Sopenharmony_ci for (uint32_t i = 0; i < ext_count; i++) { 165bf215546Sopenharmony_ci if (!strcmp(exts[i], name)) 166bf215546Sopenharmony_ci return true; 167bf215546Sopenharmony_ci } 168bf215546Sopenharmony_ci return false; 169bf215546Sopenharmony_ci} 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_cistatic bool 172bf215546Sopenharmony_cimerge_extension_names(const char *const *exts, 173bf215546Sopenharmony_ci uint32_t ext_count, 174bf215546Sopenharmony_ci const char *const *extra_exts, 175bf215546Sopenharmony_ci uint32_t extra_count, 176bf215546Sopenharmony_ci const char *const *block_exts, 177bf215546Sopenharmony_ci uint32_t block_count, 178bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc, 179bf215546Sopenharmony_ci const char *const **out_exts, 180bf215546Sopenharmony_ci uint32_t *out_count) 181bf215546Sopenharmony_ci{ 182bf215546Sopenharmony_ci const char **merged = 183bf215546Sopenharmony_ci vk_alloc(alloc, sizeof(*merged) * (ext_count + extra_count), 184bf215546Sopenharmony_ci VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 185bf215546Sopenharmony_ci if (!merged) 186bf215546Sopenharmony_ci return false; 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_ci uint32_t count = 0; 189bf215546Sopenharmony_ci for (uint32_t i = 0; i < ext_count; i++) { 190bf215546Sopenharmony_ci if (!find_extension_names(block_exts, block_count, exts[i])) 191bf215546Sopenharmony_ci merged[count++] = exts[i]; 192bf215546Sopenharmony_ci } 193bf215546Sopenharmony_ci for (uint32_t i = 0; i < extra_count; i++) { 194bf215546Sopenharmony_ci if (!find_extension_names(exts, ext_count, extra_exts[i])) 195bf215546Sopenharmony_ci merged[count++] = extra_exts[i]; 196bf215546Sopenharmony_ci } 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_ci *out_exts = merged; 199bf215546Sopenharmony_ci *out_count = count; 200bf215546Sopenharmony_ci return true; 201bf215546Sopenharmony_ci} 202bf215546Sopenharmony_ci 203bf215546Sopenharmony_cistatic const VkDeviceCreateInfo * 204bf215546Sopenharmony_civn_device_fix_create_info(const struct vn_device *dev, 205bf215546Sopenharmony_ci const VkDeviceCreateInfo *dev_info, 206bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc, 207bf215546Sopenharmony_ci VkDeviceCreateInfo *local_info) 208bf215546Sopenharmony_ci{ 209bf215546Sopenharmony_ci const struct vn_physical_device *physical_dev = dev->physical_device; 210bf215546Sopenharmony_ci const struct vk_device_extension_table *app_exts = 211bf215546Sopenharmony_ci &dev->base.base.enabled_extensions; 212bf215546Sopenharmony_ci /* extra_exts and block_exts must not overlap */ 213bf215546Sopenharmony_ci const char *extra_exts[16]; 214bf215546Sopenharmony_ci const char *block_exts[16]; 215bf215546Sopenharmony_ci uint32_t extra_count = 0; 216bf215546Sopenharmony_ci uint32_t block_count = 0; 217bf215546Sopenharmony_ci 218bf215546Sopenharmony_ci /* fix for WSI (treat AHB as WSI extension for simplicity) */ 219bf215546Sopenharmony_ci const bool has_wsi = 220bf215546Sopenharmony_ci app_exts->KHR_swapchain || app_exts->ANDROID_native_buffer || 221bf215546Sopenharmony_ci app_exts->ANDROID_external_memory_android_hardware_buffer; 222bf215546Sopenharmony_ci if (has_wsi) { 223bf215546Sopenharmony_ci /* KHR_swapchain may be advertised without the renderer support for 224bf215546Sopenharmony_ci * EXT_image_drm_format_modifier 225bf215546Sopenharmony_ci */ 226bf215546Sopenharmony_ci if (!app_exts->EXT_image_drm_format_modifier && 227bf215546Sopenharmony_ci physical_dev->renderer_extensions.EXT_image_drm_format_modifier) { 228bf215546Sopenharmony_ci extra_exts[extra_count++] = 229bf215546Sopenharmony_ci VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME; 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_ci if (physical_dev->renderer_version < VK_API_VERSION_1_2 && 232bf215546Sopenharmony_ci !app_exts->KHR_image_format_list) { 233bf215546Sopenharmony_ci extra_exts[extra_count++] = 234bf215546Sopenharmony_ci VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME; 235bf215546Sopenharmony_ci } 236bf215546Sopenharmony_ci } 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_ci /* XXX KHR_swapchain may be advertised without the renderer support for 239bf215546Sopenharmony_ci * EXT_queue_family_foreign 240bf215546Sopenharmony_ci */ 241bf215546Sopenharmony_ci if (!app_exts->EXT_queue_family_foreign && 242bf215546Sopenharmony_ci physical_dev->renderer_extensions.EXT_queue_family_foreign) { 243bf215546Sopenharmony_ci extra_exts[extra_count++] = 244bf215546Sopenharmony_ci VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME; 245bf215546Sopenharmony_ci } 246bf215546Sopenharmony_ci 247bf215546Sopenharmony_ci if (app_exts->KHR_swapchain) { 248bf215546Sopenharmony_ci /* see vn_physical_device_get_native_extensions */ 249bf215546Sopenharmony_ci block_exts[block_count++] = VK_KHR_SWAPCHAIN_EXTENSION_NAME; 250bf215546Sopenharmony_ci block_exts[block_count++] = 251bf215546Sopenharmony_ci VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME; 252bf215546Sopenharmony_ci block_exts[block_count++] = 253bf215546Sopenharmony_ci VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME; 254bf215546Sopenharmony_ci } 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_ci if (app_exts->ANDROID_native_buffer) 257bf215546Sopenharmony_ci block_exts[block_count++] = VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME; 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_ci if (app_exts->ANDROID_external_memory_android_hardware_buffer) { 260bf215546Sopenharmony_ci block_exts[block_count++] = 261bf215546Sopenharmony_ci VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME; 262bf215546Sopenharmony_ci } 263bf215546Sopenharmony_ci } 264bf215546Sopenharmony_ci 265bf215546Sopenharmony_ci if (app_exts->KHR_external_memory_fd || 266bf215546Sopenharmony_ci app_exts->EXT_external_memory_dma_buf || has_wsi) { 267bf215546Sopenharmony_ci switch (physical_dev->external_memory.renderer_handle_type) { 268bf215546Sopenharmony_ci case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: 269bf215546Sopenharmony_ci if (!app_exts->EXT_external_memory_dma_buf) { 270bf215546Sopenharmony_ci extra_exts[extra_count++] = 271bf215546Sopenharmony_ci VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME; 272bf215546Sopenharmony_ci } 273bf215546Sopenharmony_ci if (!app_exts->KHR_external_memory_fd) { 274bf215546Sopenharmony_ci extra_exts[extra_count++] = 275bf215546Sopenharmony_ci VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME; 276bf215546Sopenharmony_ci } 277bf215546Sopenharmony_ci break; 278bf215546Sopenharmony_ci case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT: 279bf215546Sopenharmony_ci if (app_exts->EXT_external_memory_dma_buf) { 280bf215546Sopenharmony_ci block_exts[block_count++] = 281bf215546Sopenharmony_ci VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME; 282bf215546Sopenharmony_ci } 283bf215546Sopenharmony_ci if (!app_exts->KHR_external_memory_fd) { 284bf215546Sopenharmony_ci extra_exts[extra_count++] = 285bf215546Sopenharmony_ci VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME; 286bf215546Sopenharmony_ci } 287bf215546Sopenharmony_ci break; 288bf215546Sopenharmony_ci default: 289bf215546Sopenharmony_ci assert(!physical_dev->instance->renderer->info.has_dma_buf_import); 290bf215546Sopenharmony_ci break; 291bf215546Sopenharmony_ci } 292bf215546Sopenharmony_ci } 293bf215546Sopenharmony_ci 294bf215546Sopenharmony_ci if (app_exts->EXT_physical_device_drm) { 295bf215546Sopenharmony_ci /* see vn_physical_device_get_native_extensions */ 296bf215546Sopenharmony_ci block_exts[block_count++] = VK_EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME; 297bf215546Sopenharmony_ci } 298bf215546Sopenharmony_ci 299bf215546Sopenharmony_ci assert(extra_count <= ARRAY_SIZE(extra_exts)); 300bf215546Sopenharmony_ci assert(block_count <= ARRAY_SIZE(block_exts)); 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_ci if (!extra_count && (!block_count || !dev_info->enabledExtensionCount)) 303bf215546Sopenharmony_ci return dev_info; 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_ci *local_info = *dev_info; 306bf215546Sopenharmony_ci if (!merge_extension_names(dev_info->ppEnabledExtensionNames, 307bf215546Sopenharmony_ci dev_info->enabledExtensionCount, extra_exts, 308bf215546Sopenharmony_ci extra_count, block_exts, block_count, alloc, 309bf215546Sopenharmony_ci &local_info->ppEnabledExtensionNames, 310bf215546Sopenharmony_ci &local_info->enabledExtensionCount)) 311bf215546Sopenharmony_ci return NULL; 312bf215546Sopenharmony_ci 313bf215546Sopenharmony_ci return local_info; 314bf215546Sopenharmony_ci} 315bf215546Sopenharmony_ci 316bf215546Sopenharmony_cistatic inline VkResult 317bf215546Sopenharmony_civn_device_feedback_pool_init(struct vn_device *dev) 318bf215546Sopenharmony_ci{ 319bf215546Sopenharmony_ci /* The feedback pool defaults to suballocate slots of 8 bytes each. Initial 320bf215546Sopenharmony_ci * pool size of 4096 corresponds to a total of 512 fences, semaphores and 321bf215546Sopenharmony_ci * events, which well covers the common scenarios. Pool can grow anyway. 322bf215546Sopenharmony_ci */ 323bf215546Sopenharmony_ci static const uint32_t pool_size = 4096; 324bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc = &dev->base.base.alloc; 325bf215546Sopenharmony_ci 326bf215546Sopenharmony_ci if (VN_PERF(NO_EVENT_FEEDBACK) && VN_PERF(NO_FENCE_FEEDBACK)) 327bf215546Sopenharmony_ci return VK_SUCCESS; 328bf215546Sopenharmony_ci 329bf215546Sopenharmony_ci return vn_feedback_pool_init(dev, &dev->feedback_pool, pool_size, alloc); 330bf215546Sopenharmony_ci} 331bf215546Sopenharmony_ci 332bf215546Sopenharmony_cistatic inline void 333bf215546Sopenharmony_civn_device_feedback_pool_fini(struct vn_device *dev) 334bf215546Sopenharmony_ci{ 335bf215546Sopenharmony_ci if (VN_PERF(NO_EVENT_FEEDBACK) && VN_PERF(NO_FENCE_FEEDBACK)) 336bf215546Sopenharmony_ci return; 337bf215546Sopenharmony_ci 338bf215546Sopenharmony_ci vn_feedback_pool_fini(&dev->feedback_pool); 339bf215546Sopenharmony_ci} 340bf215546Sopenharmony_ci 341bf215546Sopenharmony_cistatic VkResult 342bf215546Sopenharmony_civn_device_init(struct vn_device *dev, 343bf215546Sopenharmony_ci struct vn_physical_device *physical_dev, 344bf215546Sopenharmony_ci const VkDeviceCreateInfo *create_info, 345bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc) 346bf215546Sopenharmony_ci{ 347bf215546Sopenharmony_ci struct vn_instance *instance = physical_dev->instance; 348bf215546Sopenharmony_ci VkPhysicalDevice physical_dev_handle = 349bf215546Sopenharmony_ci vn_physical_device_to_handle(physical_dev); 350bf215546Sopenharmony_ci VkDevice dev_handle = vn_device_to_handle(dev); 351bf215546Sopenharmony_ci VkDeviceCreateInfo local_create_info; 352bf215546Sopenharmony_ci VkResult result; 353bf215546Sopenharmony_ci 354bf215546Sopenharmony_ci dev->instance = instance; 355bf215546Sopenharmony_ci dev->physical_device = physical_dev; 356bf215546Sopenharmony_ci dev->renderer = instance->renderer; 357bf215546Sopenharmony_ci 358bf215546Sopenharmony_ci create_info = 359bf215546Sopenharmony_ci vn_device_fix_create_info(dev, create_info, alloc, &local_create_info); 360bf215546Sopenharmony_ci if (!create_info) 361bf215546Sopenharmony_ci return VK_ERROR_OUT_OF_HOST_MEMORY; 362bf215546Sopenharmony_ci 363bf215546Sopenharmony_ci result = vn_call_vkCreateDevice(instance, physical_dev_handle, create_info, 364bf215546Sopenharmony_ci NULL, &dev_handle); 365bf215546Sopenharmony_ci 366bf215546Sopenharmony_ci /* free the fixed extensions here since no longer needed below */ 367bf215546Sopenharmony_ci if (create_info == &local_create_info) 368bf215546Sopenharmony_ci vk_free(alloc, (void *)create_info->ppEnabledExtensionNames); 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_ci if (result != VK_SUCCESS) 371bf215546Sopenharmony_ci return result; 372bf215546Sopenharmony_ci 373bf215546Sopenharmony_ci if (!vn_device_queue_family_init(dev, create_info)) { 374bf215546Sopenharmony_ci result = VK_ERROR_OUT_OF_HOST_MEMORY; 375bf215546Sopenharmony_ci goto out_destroy_device; 376bf215546Sopenharmony_ci } 377bf215546Sopenharmony_ci 378bf215546Sopenharmony_ci for (uint32_t i = 0; i < ARRAY_SIZE(dev->memory_pools); i++) { 379bf215546Sopenharmony_ci struct vn_device_memory_pool *pool = &dev->memory_pools[i]; 380bf215546Sopenharmony_ci mtx_init(&pool->mutex, mtx_plain); 381bf215546Sopenharmony_ci } 382bf215546Sopenharmony_ci 383bf215546Sopenharmony_ci result = vn_buffer_cache_init(dev); 384bf215546Sopenharmony_ci if (result != VK_SUCCESS) 385bf215546Sopenharmony_ci goto out_memory_pool_fini; 386bf215546Sopenharmony_ci 387bf215546Sopenharmony_ci result = vn_device_feedback_pool_init(dev); 388bf215546Sopenharmony_ci if (result != VK_SUCCESS) 389bf215546Sopenharmony_ci goto out_buffer_cache_fini; 390bf215546Sopenharmony_ci 391bf215546Sopenharmony_ci result = vn_feedback_cmd_pools_init(dev); 392bf215546Sopenharmony_ci if (result != VK_SUCCESS) 393bf215546Sopenharmony_ci goto out_feedback_pool_fini; 394bf215546Sopenharmony_ci 395bf215546Sopenharmony_ci result = vn_device_init_queues(dev, create_info); 396bf215546Sopenharmony_ci if (result != VK_SUCCESS) 397bf215546Sopenharmony_ci goto out_cmd_pools_fini; 398bf215546Sopenharmony_ci 399bf215546Sopenharmony_ci return VK_SUCCESS; 400bf215546Sopenharmony_ci 401bf215546Sopenharmony_ciout_cmd_pools_fini: 402bf215546Sopenharmony_ci vn_feedback_cmd_pools_fini(dev); 403bf215546Sopenharmony_ci 404bf215546Sopenharmony_ciout_feedback_pool_fini: 405bf215546Sopenharmony_ci vn_device_feedback_pool_fini(dev); 406bf215546Sopenharmony_ci 407bf215546Sopenharmony_ciout_buffer_cache_fini: 408bf215546Sopenharmony_ci vn_buffer_cache_fini(dev); 409bf215546Sopenharmony_ci 410bf215546Sopenharmony_ciout_memory_pool_fini: 411bf215546Sopenharmony_ci for (uint32_t i = 0; i < ARRAY_SIZE(dev->memory_pools); i++) 412bf215546Sopenharmony_ci vn_device_memory_pool_fini(dev, i); 413bf215546Sopenharmony_ci 414bf215546Sopenharmony_ci vn_device_queue_family_fini(dev); 415bf215546Sopenharmony_ci 416bf215546Sopenharmony_ciout_destroy_device: 417bf215546Sopenharmony_ci vn_call_vkDestroyDevice(instance, dev_handle, NULL); 418bf215546Sopenharmony_ci 419bf215546Sopenharmony_ci return result; 420bf215546Sopenharmony_ci} 421bf215546Sopenharmony_ci 422bf215546Sopenharmony_ciVkResult 423bf215546Sopenharmony_civn_CreateDevice(VkPhysicalDevice physicalDevice, 424bf215546Sopenharmony_ci const VkDeviceCreateInfo *pCreateInfo, 425bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 426bf215546Sopenharmony_ci VkDevice *pDevice) 427bf215546Sopenharmony_ci{ 428bf215546Sopenharmony_ci VN_TRACE_FUNC(); 429bf215546Sopenharmony_ci struct vn_physical_device *physical_dev = 430bf215546Sopenharmony_ci vn_physical_device_from_handle(physicalDevice); 431bf215546Sopenharmony_ci struct vn_instance *instance = physical_dev->instance; 432bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc = 433bf215546Sopenharmony_ci pAllocator ? pAllocator : &instance->base.base.alloc; 434bf215546Sopenharmony_ci struct vn_device *dev; 435bf215546Sopenharmony_ci VkResult result; 436bf215546Sopenharmony_ci 437bf215546Sopenharmony_ci dev = vk_zalloc(alloc, sizeof(*dev), VN_DEFAULT_ALIGN, 438bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 439bf215546Sopenharmony_ci if (!dev) 440bf215546Sopenharmony_ci return vn_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY); 441bf215546Sopenharmony_ci 442bf215546Sopenharmony_ci struct vk_device_dispatch_table dispatch_table; 443bf215546Sopenharmony_ci vk_device_dispatch_table_from_entrypoints(&dispatch_table, 444bf215546Sopenharmony_ci &vn_device_entrypoints, true); 445bf215546Sopenharmony_ci vk_device_dispatch_table_from_entrypoints(&dispatch_table, 446bf215546Sopenharmony_ci &wsi_device_entrypoints, false); 447bf215546Sopenharmony_ci result = vn_device_base_init(&dev->base, &physical_dev->base, 448bf215546Sopenharmony_ci &dispatch_table, pCreateInfo, alloc); 449bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 450bf215546Sopenharmony_ci vk_free(alloc, dev); 451bf215546Sopenharmony_ci return vn_error(instance, result); 452bf215546Sopenharmony_ci } 453bf215546Sopenharmony_ci 454bf215546Sopenharmony_ci result = vn_device_init(dev, physical_dev, pCreateInfo, alloc); 455bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 456bf215546Sopenharmony_ci vn_device_base_fini(&dev->base); 457bf215546Sopenharmony_ci vk_free(alloc, dev); 458bf215546Sopenharmony_ci return vn_error(instance, result); 459bf215546Sopenharmony_ci } 460bf215546Sopenharmony_ci 461bf215546Sopenharmony_ci *pDevice = vn_device_to_handle(dev); 462bf215546Sopenharmony_ci 463bf215546Sopenharmony_ci return VK_SUCCESS; 464bf215546Sopenharmony_ci} 465bf215546Sopenharmony_ci 466bf215546Sopenharmony_civoid 467bf215546Sopenharmony_civn_DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) 468bf215546Sopenharmony_ci{ 469bf215546Sopenharmony_ci VN_TRACE_FUNC(); 470bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 471bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc = 472bf215546Sopenharmony_ci pAllocator ? pAllocator : &dev->base.base.alloc; 473bf215546Sopenharmony_ci 474bf215546Sopenharmony_ci if (!dev) 475bf215546Sopenharmony_ci return; 476bf215546Sopenharmony_ci 477bf215546Sopenharmony_ci for (uint32_t i = 0; i < dev->queue_count; i++) 478bf215546Sopenharmony_ci vn_queue_fini(&dev->queues[i]); 479bf215546Sopenharmony_ci 480bf215546Sopenharmony_ci vn_feedback_cmd_pools_fini(dev); 481bf215546Sopenharmony_ci 482bf215546Sopenharmony_ci vn_device_feedback_pool_fini(dev); 483bf215546Sopenharmony_ci 484bf215546Sopenharmony_ci vn_buffer_cache_fini(dev); 485bf215546Sopenharmony_ci 486bf215546Sopenharmony_ci for (uint32_t i = 0; i < ARRAY_SIZE(dev->memory_pools); i++) 487bf215546Sopenharmony_ci vn_device_memory_pool_fini(dev, i); 488bf215546Sopenharmony_ci 489bf215546Sopenharmony_ci vn_device_queue_family_fini(dev); 490bf215546Sopenharmony_ci 491bf215546Sopenharmony_ci /* We must emit vkDestroyDevice before freeing dev->queues. Otherwise, 492bf215546Sopenharmony_ci * another thread might reuse their object ids while they still refer to 493bf215546Sopenharmony_ci * the queues in the renderer. 494bf215546Sopenharmony_ci */ 495bf215546Sopenharmony_ci vn_async_vkDestroyDevice(dev->instance, device, NULL); 496bf215546Sopenharmony_ci 497bf215546Sopenharmony_ci vk_free(alloc, dev->queues); 498bf215546Sopenharmony_ci 499bf215546Sopenharmony_ci vn_device_base_fini(&dev->base); 500bf215546Sopenharmony_ci vk_free(alloc, dev); 501bf215546Sopenharmony_ci} 502bf215546Sopenharmony_ci 503bf215546Sopenharmony_ciPFN_vkVoidFunction 504bf215546Sopenharmony_civn_GetDeviceProcAddr(VkDevice device, const char *pName) 505bf215546Sopenharmony_ci{ 506bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 507bf215546Sopenharmony_ci return vk_device_get_proc_addr(&dev->base.base, pName); 508bf215546Sopenharmony_ci} 509bf215546Sopenharmony_ci 510bf215546Sopenharmony_civoid 511bf215546Sopenharmony_civn_GetDeviceGroupPeerMemoryFeatures( 512bf215546Sopenharmony_ci VkDevice device, 513bf215546Sopenharmony_ci uint32_t heapIndex, 514bf215546Sopenharmony_ci uint32_t localDeviceIndex, 515bf215546Sopenharmony_ci uint32_t remoteDeviceIndex, 516bf215546Sopenharmony_ci VkPeerMemoryFeatureFlags *pPeerMemoryFeatures) 517bf215546Sopenharmony_ci{ 518bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 519bf215546Sopenharmony_ci 520bf215546Sopenharmony_ci /* TODO get and cache the values in vkCreateDevice */ 521bf215546Sopenharmony_ci vn_call_vkGetDeviceGroupPeerMemoryFeatures( 522bf215546Sopenharmony_ci dev->instance, device, heapIndex, localDeviceIndex, remoteDeviceIndex, 523bf215546Sopenharmony_ci pPeerMemoryFeatures); 524bf215546Sopenharmony_ci} 525bf215546Sopenharmony_ci 526bf215546Sopenharmony_ciVkResult 527bf215546Sopenharmony_civn_DeviceWaitIdle(VkDevice device) 528bf215546Sopenharmony_ci{ 529bf215546Sopenharmony_ci VN_TRACE_FUNC(); 530bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 531bf215546Sopenharmony_ci 532bf215546Sopenharmony_ci for (uint32_t i = 0; i < dev->queue_count; i++) { 533bf215546Sopenharmony_ci struct vn_queue *queue = &dev->queues[i]; 534bf215546Sopenharmony_ci VkResult result = vn_QueueWaitIdle(vn_queue_to_handle(queue)); 535bf215546Sopenharmony_ci if (result != VK_SUCCESS) 536bf215546Sopenharmony_ci return vn_error(dev->instance, result); 537bf215546Sopenharmony_ci } 538bf215546Sopenharmony_ci 539bf215546Sopenharmony_ci return VK_SUCCESS; 540bf215546Sopenharmony_ci} 541bf215546Sopenharmony_ci 542bf215546Sopenharmony_ciVkResult 543bf215546Sopenharmony_civn_GetCalibratedTimestampsEXT( 544bf215546Sopenharmony_ci VkDevice device, 545bf215546Sopenharmony_ci uint32_t timestampCount, 546bf215546Sopenharmony_ci const VkCalibratedTimestampInfoEXT *pTimestampInfos, 547bf215546Sopenharmony_ci uint64_t *pTimestamps, 548bf215546Sopenharmony_ci uint64_t *pMaxDeviation) 549bf215546Sopenharmony_ci{ 550bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 551bf215546Sopenharmony_ci 552bf215546Sopenharmony_ci return vn_call_vkGetCalibratedTimestampsEXT( 553bf215546Sopenharmony_ci dev->instance, device, timestampCount, pTimestampInfos, pTimestamps, 554bf215546Sopenharmony_ci pMaxDeviation); 555bf215546Sopenharmony_ci} 556