1 /*
2  * Copyright 2019 Google LLC
3  * SPDX-License-Identifier: MIT
4  *
5  * based in part on anv and radv which are:
6  * Copyright © 2015 Intel Corporation
7  * Copyright © 2016 Red Hat.
8  * Copyright © 2016 Bas Nieuwenhuizen
9  */
10 
11 #include "vn_device.h"
12 
13 #include "venus-protocol/vn_protocol_driver_device.h"
14 
15 #include "vn_android.h"
16 #include "vn_instance.h"
17 #include "vn_physical_device.h"
18 #include "vn_queue.h"
19 
20 /* device commands */
21 
22 static void
vn_queue_fini(struct vn_queue * queue)23 vn_queue_fini(struct vn_queue *queue)
24 {
25    if (queue->wait_fence != VK_NULL_HANDLE) {
26       vn_DestroyFence(vn_device_to_handle(queue->device), queue->wait_fence,
27                       NULL);
28    }
29    vn_object_base_fini(&queue->base);
30 }
31 
32 static VkResult
vn_queue_init(struct vn_device * dev,struct vn_queue * queue,const VkDeviceQueueCreateInfo * queue_info,uint32_t queue_index)33 vn_queue_init(struct vn_device *dev,
34               struct vn_queue *queue,
35               const VkDeviceQueueCreateInfo *queue_info,
36               uint32_t queue_index)
37 {
38    vn_object_base_init(&queue->base, VK_OBJECT_TYPE_QUEUE, &dev->base);
39 
40    VkQueue queue_handle = vn_queue_to_handle(queue);
41    vn_async_vkGetDeviceQueue2(
42       dev->instance, vn_device_to_handle(dev),
43       &(VkDeviceQueueInfo2){
44          .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2,
45          .flags = queue_info->flags,
46          .queueFamilyIndex = queue_info->queueFamilyIndex,
47          .queueIndex = queue_index,
48       },
49       &queue_handle);
50 
51    queue->device = dev;
52    queue->family = queue_info->queueFamilyIndex;
53    queue->index = queue_index;
54    queue->flags = queue_info->flags;
55 
56    const VkExportFenceCreateInfo export_fence_info = {
57       .sType = VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO,
58       .pNext = NULL,
59       .handleTypes = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT,
60    };
61    const VkFenceCreateInfo fence_info = {
62       .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
63       .pNext = dev->instance->experimental.globalFencing == VK_TRUE
64                   ? &export_fence_info
65                   : NULL,
66       .flags = 0,
67    };
68    VkResult result = vn_CreateFence(vn_device_to_handle(dev), &fence_info,
69                                     NULL, &queue->wait_fence);
70    if (result != VK_SUCCESS)
71       return result;
72 
73    return VK_SUCCESS;
74 }
75 
76 static VkResult
vn_device_init_queues(struct vn_device * dev,const VkDeviceCreateInfo * create_info)77 vn_device_init_queues(struct vn_device *dev,
78                       const VkDeviceCreateInfo *create_info)
79 {
80    const VkAllocationCallbacks *alloc = &dev->base.base.alloc;
81 
82    uint32_t count = 0;
83    for (uint32_t i = 0; i < create_info->queueCreateInfoCount; i++)
84       count += create_info->pQueueCreateInfos[i].queueCount;
85 
86    struct vn_queue *queues =
87       vk_zalloc(alloc, sizeof(*queues) * count, VN_DEFAULT_ALIGN,
88                 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
89    if (!queues)
90       return VK_ERROR_OUT_OF_HOST_MEMORY;
91 
92    VkResult result = VK_SUCCESS;
93    count = 0;
94    for (uint32_t i = 0; i < create_info->queueCreateInfoCount; i++) {
95       const VkDeviceQueueCreateInfo *queue_info =
96          &create_info->pQueueCreateInfos[i];
97       for (uint32_t j = 0; j < queue_info->queueCount; j++) {
98          result = vn_queue_init(dev, &queues[count], queue_info, j);
99          if (result != VK_SUCCESS)
100             break;
101 
102          count++;
103       }
104    }
105 
106    if (result != VK_SUCCESS) {
107       for (uint32_t i = 0; i < count; i++)
108          vn_queue_fini(&queues[i]);
109       vk_free(alloc, queues);
110 
111       return result;
112    }
113 
114    dev->queues = queues;
115    dev->queue_count = count;
116 
117    return VK_SUCCESS;
118 }
119 
120 static bool
find_extension_names(const char * const * exts,uint32_t ext_count,const char * name)121 find_extension_names(const char *const *exts,
122                      uint32_t ext_count,
123                      const char *name)
124 {
125    for (uint32_t i = 0; i < ext_count; i++) {
126       if (!strcmp(exts[i], name))
127          return true;
128    }
129    return false;
130 }
131 
132 static bool
merge_extension_names(const char * const * exts,uint32_t ext_count,const char * const * extra_exts,uint32_t extra_count,const char * const * block_exts,uint32_t block_count,const VkAllocationCallbacks * alloc,const char * const ** out_exts,uint32_t * out_count)133 merge_extension_names(const char *const *exts,
134                       uint32_t ext_count,
135                       const char *const *extra_exts,
136                       uint32_t extra_count,
137                       const char *const *block_exts,
138                       uint32_t block_count,
139                       const VkAllocationCallbacks *alloc,
140                       const char *const **out_exts,
141                       uint32_t *out_count)
142 {
143    const char **merged =
144       vk_alloc(alloc, sizeof(*merged) * (ext_count + extra_count),
145                VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
146    if (!merged)
147       return false;
148 
149    uint32_t count = 0;
150    for (uint32_t i = 0; i < ext_count; i++) {
151       if (!find_extension_names(block_exts, block_count, exts[i]))
152          merged[count++] = exts[i];
153    }
154    for (uint32_t i = 0; i < extra_count; i++) {
155       if (!find_extension_names(exts, ext_count, extra_exts[i]))
156          merged[count++] = extra_exts[i];
157    }
158 
159    *out_exts = merged;
160    *out_count = count;
161    return true;
162 }
163 
164 static const VkDeviceCreateInfo *
vn_device_fix_create_info(const struct vn_device * dev,const VkDeviceCreateInfo * dev_info,const VkAllocationCallbacks * alloc,VkDeviceCreateInfo * local_info)165 vn_device_fix_create_info(const struct vn_device *dev,
166                           const VkDeviceCreateInfo *dev_info,
167                           const VkAllocationCallbacks *alloc,
168                           VkDeviceCreateInfo *local_info)
169 {
170    const struct vn_physical_device *physical_dev = dev->physical_device;
171    const struct vk_device_extension_table *app_exts =
172       &dev->base.base.enabled_extensions;
173    /* extra_exts and block_exts must not overlap */
174    const char *extra_exts[16];
175    const char *block_exts[16];
176    uint32_t extra_count = 0;
177    uint32_t block_count = 0;
178 
179    /* fix for WSI (treat AHB as WSI extension for simplicity) */
180    const bool has_wsi =
181       app_exts->KHR_swapchain || app_exts->ANDROID_native_buffer ||
182       app_exts->ANDROID_external_memory_android_hardware_buffer;
183    if (has_wsi) {
184       /* KHR_swapchain may be advertised without the renderer support for
185        * EXT_image_drm_format_modifier
186        */
187       if (!app_exts->EXT_image_drm_format_modifier &&
188           physical_dev->renderer_extensions.EXT_image_drm_format_modifier) {
189          extra_exts[extra_count++] =
190             VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME;
191 
192          if (physical_dev->renderer_version < VK_API_VERSION_1_2 &&
193              !app_exts->KHR_image_format_list) {
194             extra_exts[extra_count++] =
195                VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME;
196          }
197       }
198 
199       /* XXX KHR_swapchain may be advertised without the renderer support for
200        * EXT_queue_family_foreign
201        */
202       if (!app_exts->EXT_queue_family_foreign &&
203           physical_dev->renderer_extensions.EXT_queue_family_foreign) {
204          extra_exts[extra_count++] =
205             VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME;
206       }
207 
208       if (app_exts->KHR_swapchain) {
209          /* see vn_physical_device_get_native_extensions */
210          block_exts[block_count++] = VK_KHR_SWAPCHAIN_EXTENSION_NAME;
211          block_exts[block_count++] =
212             VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME;
213          block_exts[block_count++] =
214             VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME;
215       }
216 
217       if (app_exts->ANDROID_native_buffer)
218          block_exts[block_count++] = VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME;
219 
220       if (app_exts->ANDROID_external_memory_android_hardware_buffer) {
221          block_exts[block_count++] =
222             VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME;
223       }
224    }
225 
226    if (app_exts->KHR_external_memory_fd ||
227        app_exts->EXT_external_memory_dma_buf || has_wsi) {
228       switch (physical_dev->external_memory.renderer_handle_type) {
229       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
230          if (!app_exts->EXT_external_memory_dma_buf) {
231             extra_exts[extra_count++] =
232                VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME;
233          }
234          FALLTHROUGH;
235       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
236          if (!app_exts->KHR_external_memory_fd) {
237             extra_exts[extra_count++] =
238                VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME;
239          }
240          break;
241       default:
242          /* TODO other handle types */
243          break;
244       }
245    }
246 
247    assert(extra_count <= ARRAY_SIZE(extra_exts));
248    assert(block_count <= ARRAY_SIZE(block_exts));
249 
250    if (!extra_count && (!block_count || !dev_info->enabledExtensionCount))
251       return dev_info;
252 
253    *local_info = *dev_info;
254    if (!merge_extension_names(dev_info->ppEnabledExtensionNames,
255                               dev_info->enabledExtensionCount, extra_exts,
256                               extra_count, block_exts, block_count, alloc,
257                               &local_info->ppEnabledExtensionNames,
258                               &local_info->enabledExtensionCount))
259       return NULL;
260 
261    return local_info;
262 }
263 
264 VkResult
vn_CreateDevice(VkPhysicalDevice physicalDevice,const VkDeviceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDevice * pDevice)265 vn_CreateDevice(VkPhysicalDevice physicalDevice,
266                 const VkDeviceCreateInfo *pCreateInfo,
267                 const VkAllocationCallbacks *pAllocator,
268                 VkDevice *pDevice)
269 {
270    struct vn_physical_device *physical_dev =
271       vn_physical_device_from_handle(physicalDevice);
272    struct vn_instance *instance = physical_dev->instance;
273    const VkAllocationCallbacks *alloc =
274       pAllocator ? pAllocator : &instance->base.base.alloc;
275    struct vn_device *dev;
276    VkResult result;
277 
278    dev = vk_zalloc(alloc, sizeof(*dev), VN_DEFAULT_ALIGN,
279                    VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
280    if (!dev)
281       return vn_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
282 
283    struct vk_device_dispatch_table dispatch_table;
284    vk_device_dispatch_table_from_entrypoints(&dispatch_table,
285                                              &vn_device_entrypoints, true);
286    vk_device_dispatch_table_from_entrypoints(&dispatch_table,
287                                              &wsi_device_entrypoints, false);
288    result = vn_device_base_init(&dev->base, &physical_dev->base,
289                                 &dispatch_table, pCreateInfo, alloc);
290    if (result != VK_SUCCESS) {
291       vk_free(alloc, dev);
292       return vn_error(instance, result);
293    }
294 
295    dev->instance = instance;
296    dev->physical_device = physical_dev;
297    dev->renderer = instance->renderer;
298 
299    VkDeviceCreateInfo local_create_info;
300    pCreateInfo =
301       vn_device_fix_create_info(dev, pCreateInfo, alloc, &local_create_info);
302    if (!pCreateInfo) {
303       result = VK_ERROR_OUT_OF_HOST_MEMORY;
304       goto fail;
305    }
306 
307    VkDevice dev_handle = vn_device_to_handle(dev);
308    result = vn_call_vkCreateDevice(instance, physicalDevice, pCreateInfo,
309                                    NULL, &dev_handle);
310    if (result != VK_SUCCESS)
311       goto fail;
312 
313    result = vn_device_init_queues(dev, pCreateInfo);
314    if (result != VK_SUCCESS) {
315       vn_call_vkDestroyDevice(instance, dev_handle, NULL);
316       goto fail;
317    }
318 
319    for (uint32_t i = 0; i < ARRAY_SIZE(dev->memory_pools); i++) {
320       struct vn_device_memory_pool *pool = &dev->memory_pools[i];
321       mtx_init(&pool->mutex, mtx_plain);
322    }
323 
324    if (dev->base.base.enabled_extensions
325           .ANDROID_external_memory_android_hardware_buffer) {
326       result = vn_android_init_ahb_buffer_memory_type_bits(dev);
327       if (result != VK_SUCCESS) {
328          vn_call_vkDestroyDevice(instance, dev_handle, NULL);
329          goto fail;
330       }
331    }
332 
333    *pDevice = dev_handle;
334 
335    if (pCreateInfo == &local_create_info)
336       vk_free(alloc, (void *)pCreateInfo->ppEnabledExtensionNames);
337 
338    return VK_SUCCESS;
339 
340 fail:
341    if (pCreateInfo == &local_create_info)
342       vk_free(alloc, (void *)pCreateInfo->ppEnabledExtensionNames);
343    vn_device_base_fini(&dev->base);
344    vk_free(alloc, dev);
345    return vn_error(instance, result);
346 }
347 
348 void
vn_DestroyDevice(VkDevice device,const VkAllocationCallbacks * pAllocator)349 vn_DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator)
350 {
351    struct vn_device *dev = vn_device_from_handle(device);
352    const VkAllocationCallbacks *alloc =
353       pAllocator ? pAllocator : &dev->base.base.alloc;
354 
355    if (!dev)
356       return;
357 
358    for (uint32_t i = 0; i < ARRAY_SIZE(dev->memory_pools); i++)
359       vn_device_memory_pool_fini(dev, i);
360 
361    for (uint32_t i = 0; i < dev->queue_count; i++)
362       vn_queue_fini(&dev->queues[i]);
363 
364    /* We must emit vkDestroyDevice before freeing dev->queues.  Otherwise,
365     * another thread might reuse their object ids while they still refer to
366     * the queues in the renderer.
367     */
368    vn_async_vkDestroyDevice(dev->instance, device, NULL);
369 
370    vk_free(alloc, dev->queues);
371 
372    vn_device_base_fini(&dev->base);
373    vk_free(alloc, dev);
374 }
375 
376 PFN_vkVoidFunction
vn_GetDeviceProcAddr(VkDevice device,const char * pName)377 vn_GetDeviceProcAddr(VkDevice device, const char *pName)
378 {
379    struct vn_device *dev = vn_device_from_handle(device);
380    return vk_device_get_proc_addr(&dev->base.base, pName);
381 }
382 
383 void
vn_GetDeviceGroupPeerMemoryFeatures(VkDevice device,uint32_t heapIndex,uint32_t localDeviceIndex,uint32_t remoteDeviceIndex,VkPeerMemoryFeatureFlags * pPeerMemoryFeatures)384 vn_GetDeviceGroupPeerMemoryFeatures(
385    VkDevice device,
386    uint32_t heapIndex,
387    uint32_t localDeviceIndex,
388    uint32_t remoteDeviceIndex,
389    VkPeerMemoryFeatureFlags *pPeerMemoryFeatures)
390 {
391    struct vn_device *dev = vn_device_from_handle(device);
392 
393    /* TODO get and cache the values in vkCreateDevice */
394    vn_call_vkGetDeviceGroupPeerMemoryFeatures(
395       dev->instance, device, heapIndex, localDeviceIndex, remoteDeviceIndex,
396       pPeerMemoryFeatures);
397 }
398 
399 VkResult
vn_DeviceWaitIdle(VkDevice device)400 vn_DeviceWaitIdle(VkDevice device)
401 {
402    struct vn_device *dev = vn_device_from_handle(device);
403 
404    for (uint32_t i = 0; i < dev->queue_count; i++) {
405       struct vn_queue *queue = &dev->queues[i];
406       VkResult result = vn_QueueWaitIdle(vn_queue_to_handle(queue));
407       if (result != VK_SUCCESS)
408          return vn_error(dev->instance, result);
409    }
410 
411    return VK_SUCCESS;
412 }
413