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