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_memory.h"
12bf215546Sopenharmony_ci
13bf215546Sopenharmony_ci#include "venus-protocol/vn_protocol_driver_device_memory.h"
14bf215546Sopenharmony_ci#include "venus-protocol/vn_protocol_driver_transport.h"
15bf215546Sopenharmony_ci
16bf215546Sopenharmony_ci#include "vn_android.h"
17bf215546Sopenharmony_ci#include "vn_buffer.h"
18bf215546Sopenharmony_ci#include "vn_device.h"
19bf215546Sopenharmony_ci#include "vn_image.h"
20bf215546Sopenharmony_ci#include "vn_physical_device.h"
21bf215546Sopenharmony_ci
22bf215546Sopenharmony_ci/* device memory commands */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_cistatic VkResult
25bf215546Sopenharmony_civn_device_memory_pool_grow_alloc(struct vn_device *dev,
26bf215546Sopenharmony_ci                                 uint32_t mem_type_index,
27bf215546Sopenharmony_ci                                 VkDeviceSize size,
28bf215546Sopenharmony_ci                                 struct vn_device_memory **out_mem)
29bf215546Sopenharmony_ci{
30bf215546Sopenharmony_ci   VkDevice dev_handle = vn_device_to_handle(dev);
31bf215546Sopenharmony_ci   const VkAllocationCallbacks *alloc = &dev->base.base.alloc;
32bf215546Sopenharmony_ci   const VkPhysicalDeviceMemoryProperties *mem_props =
33bf215546Sopenharmony_ci      &dev->physical_device->memory_properties.memoryProperties;
34bf215546Sopenharmony_ci   const VkMemoryPropertyFlags mem_flags =
35bf215546Sopenharmony_ci      mem_props->memoryTypes[mem_type_index].propertyFlags;
36bf215546Sopenharmony_ci   struct vn_device_memory *mem = NULL;
37bf215546Sopenharmony_ci   VkDeviceMemory mem_handle = VK_NULL_HANDLE;
38bf215546Sopenharmony_ci   VkResult result;
39bf215546Sopenharmony_ci
40bf215546Sopenharmony_ci   mem = vk_zalloc(alloc, sizeof(*mem), VN_DEFAULT_ALIGN,
41bf215546Sopenharmony_ci                   VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
42bf215546Sopenharmony_ci   if (!mem)
43bf215546Sopenharmony_ci      return VK_ERROR_OUT_OF_HOST_MEMORY;
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci   vn_object_base_init(&mem->base, VK_OBJECT_TYPE_DEVICE_MEMORY, &dev->base);
46bf215546Sopenharmony_ci   mem->size = size;
47bf215546Sopenharmony_ci   mem->flags = mem_flags;
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci   mem_handle = vn_device_memory_to_handle(mem);
50bf215546Sopenharmony_ci   result = vn_call_vkAllocateMemory(
51bf215546Sopenharmony_ci      dev->instance, dev_handle,
52bf215546Sopenharmony_ci      &(const VkMemoryAllocateInfo){
53bf215546Sopenharmony_ci         .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
54bf215546Sopenharmony_ci         .allocationSize = size,
55bf215546Sopenharmony_ci         .memoryTypeIndex = mem_type_index,
56bf215546Sopenharmony_ci      },
57bf215546Sopenharmony_ci      NULL, &mem_handle);
58bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
59bf215546Sopenharmony_ci      mem_handle = VK_NULL_HANDLE;
60bf215546Sopenharmony_ci      goto fail;
61bf215546Sopenharmony_ci   }
62bf215546Sopenharmony_ci
63bf215546Sopenharmony_ci   result = vn_renderer_bo_create_from_device_memory(
64bf215546Sopenharmony_ci      dev->renderer, mem->size, mem->base.id, mem->flags, 0, &mem->base_bo);
65bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
66bf215546Sopenharmony_ci      assert(!mem->base_bo);
67bf215546Sopenharmony_ci      goto fail;
68bf215546Sopenharmony_ci   }
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_ci   result =
71bf215546Sopenharmony_ci      vn_instance_submit_roundtrip(dev->instance, &mem->bo_roundtrip_seqno);
72bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
73bf215546Sopenharmony_ci      goto fail;
74bf215546Sopenharmony_ci
75bf215546Sopenharmony_ci   mem->bo_roundtrip_seqno_valid = true;
76bf215546Sopenharmony_ci   *out_mem = mem;
77bf215546Sopenharmony_ci
78bf215546Sopenharmony_ci   return VK_SUCCESS;
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_cifail:
81bf215546Sopenharmony_ci   if (mem->base_bo)
82bf215546Sopenharmony_ci      vn_renderer_bo_unref(dev->renderer, mem->base_bo);
83bf215546Sopenharmony_ci   if (mem_handle != VK_NULL_HANDLE)
84bf215546Sopenharmony_ci      vn_async_vkFreeMemory(dev->instance, dev_handle, mem_handle, NULL);
85bf215546Sopenharmony_ci   vn_object_base_fini(&mem->base);
86bf215546Sopenharmony_ci   vk_free(alloc, mem);
87bf215546Sopenharmony_ci   return result;
88bf215546Sopenharmony_ci}
89bf215546Sopenharmony_ci
90bf215546Sopenharmony_cistatic struct vn_device_memory *
91bf215546Sopenharmony_civn_device_memory_pool_ref(struct vn_device *dev,
92bf215546Sopenharmony_ci                          struct vn_device_memory *pool_mem)
93bf215546Sopenharmony_ci{
94bf215546Sopenharmony_ci   assert(pool_mem->base_bo);
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_ci   vn_renderer_bo_ref(dev->renderer, pool_mem->base_bo);
97bf215546Sopenharmony_ci
98bf215546Sopenharmony_ci   return pool_mem;
99bf215546Sopenharmony_ci}
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_cistatic void
102bf215546Sopenharmony_civn_device_memory_pool_unref(struct vn_device *dev,
103bf215546Sopenharmony_ci                            struct vn_device_memory *pool_mem)
104bf215546Sopenharmony_ci{
105bf215546Sopenharmony_ci   const VkAllocationCallbacks *alloc = &dev->base.base.alloc;
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_ci   assert(pool_mem->base_bo);
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_ci   if (!vn_renderer_bo_unref(dev->renderer, pool_mem->base_bo))
110bf215546Sopenharmony_ci      return;
111bf215546Sopenharmony_ci
112bf215546Sopenharmony_ci   /* wait on valid bo_roundtrip_seqno before vkFreeMemory */
113bf215546Sopenharmony_ci   if (pool_mem->bo_roundtrip_seqno_valid)
114bf215546Sopenharmony_ci      vn_instance_wait_roundtrip(dev->instance, pool_mem->bo_roundtrip_seqno);
115bf215546Sopenharmony_ci
116bf215546Sopenharmony_ci   vn_async_vkFreeMemory(dev->instance, vn_device_to_handle(dev),
117bf215546Sopenharmony_ci                         vn_device_memory_to_handle(pool_mem), NULL);
118bf215546Sopenharmony_ci   vn_object_base_fini(&pool_mem->base);
119bf215546Sopenharmony_ci   vk_free(alloc, pool_mem);
120bf215546Sopenharmony_ci}
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_civoid
123bf215546Sopenharmony_civn_device_memory_pool_fini(struct vn_device *dev, uint32_t mem_type_index)
124bf215546Sopenharmony_ci{
125bf215546Sopenharmony_ci   struct vn_device_memory_pool *pool = &dev->memory_pools[mem_type_index];
126bf215546Sopenharmony_ci   if (pool->memory)
127bf215546Sopenharmony_ci      vn_device_memory_pool_unref(dev, pool->memory);
128bf215546Sopenharmony_ci   mtx_destroy(&pool->mutex);
129bf215546Sopenharmony_ci}
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_cistatic VkResult
132bf215546Sopenharmony_civn_device_memory_pool_grow_locked(struct vn_device *dev,
133bf215546Sopenharmony_ci                                  uint32_t mem_type_index,
134bf215546Sopenharmony_ci                                  VkDeviceSize size)
135bf215546Sopenharmony_ci{
136bf215546Sopenharmony_ci   struct vn_device_memory *mem;
137bf215546Sopenharmony_ci   VkResult result =
138bf215546Sopenharmony_ci      vn_device_memory_pool_grow_alloc(dev, mem_type_index, size, &mem);
139bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
140bf215546Sopenharmony_ci      return result;
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci   struct vn_device_memory_pool *pool = &dev->memory_pools[mem_type_index];
143bf215546Sopenharmony_ci   if (pool->memory)
144bf215546Sopenharmony_ci      vn_device_memory_pool_unref(dev, pool->memory);
145bf215546Sopenharmony_ci
146bf215546Sopenharmony_ci   pool->memory = mem;
147bf215546Sopenharmony_ci   pool->used = 0;
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ci   return VK_SUCCESS;
150bf215546Sopenharmony_ci}
151bf215546Sopenharmony_ci
152bf215546Sopenharmony_cistatic VkResult
153bf215546Sopenharmony_civn_device_memory_pool_suballocate(struct vn_device *dev,
154bf215546Sopenharmony_ci                                  struct vn_device_memory *mem,
155bf215546Sopenharmony_ci                                  uint32_t mem_type_index)
156bf215546Sopenharmony_ci{
157bf215546Sopenharmony_ci   const VkDeviceSize pool_size = 16 * 1024 * 1024;
158bf215546Sopenharmony_ci   /* XXX We don't know the alignment requirement.  Use 64K because some GPUs
159bf215546Sopenharmony_ci    * have 64K pages.  It is also required by newer Intel GPUs.  But really we
160bf215546Sopenharmony_ci    * should require kernel 5.12+, where there is no KVM memslot limit, and
161bf215546Sopenharmony_ci    * remove this whole thing.
162bf215546Sopenharmony_ci    */
163bf215546Sopenharmony_ci   const VkDeviceSize pool_align = 64 * 1024;
164bf215546Sopenharmony_ci   struct vn_device_memory_pool *pool = &dev->memory_pools[mem_type_index];
165bf215546Sopenharmony_ci
166bf215546Sopenharmony_ci   assert(mem->size <= pool_size);
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_ci   mtx_lock(&pool->mutex);
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_ci   if (!pool->memory || pool->used + mem->size > pool_size) {
171bf215546Sopenharmony_ci      VkResult result =
172bf215546Sopenharmony_ci         vn_device_memory_pool_grow_locked(dev, mem_type_index, pool_size);
173bf215546Sopenharmony_ci      if (result != VK_SUCCESS) {
174bf215546Sopenharmony_ci         mtx_unlock(&pool->mutex);
175bf215546Sopenharmony_ci         return result;
176bf215546Sopenharmony_ci      }
177bf215546Sopenharmony_ci   }
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_ci   mem->base_memory = vn_device_memory_pool_ref(dev, pool->memory);
180bf215546Sopenharmony_ci
181bf215546Sopenharmony_ci   /* point mem->base_bo at pool base_bo and assign base_offset accordingly */
182bf215546Sopenharmony_ci   mem->base_bo = pool->memory->base_bo;
183bf215546Sopenharmony_ci   mem->base_offset = pool->used;
184bf215546Sopenharmony_ci   pool->used += align64(mem->size, pool_align);
185bf215546Sopenharmony_ci
186bf215546Sopenharmony_ci   mtx_unlock(&pool->mutex);
187bf215546Sopenharmony_ci
188bf215546Sopenharmony_ci   return VK_SUCCESS;
189bf215546Sopenharmony_ci}
190bf215546Sopenharmony_ci
191bf215546Sopenharmony_cistatic bool
192bf215546Sopenharmony_civn_device_memory_should_suballocate(const struct vn_device *dev,
193bf215546Sopenharmony_ci                                    const VkMemoryAllocateInfo *alloc_info,
194bf215546Sopenharmony_ci                                    const VkMemoryPropertyFlags flags)
195bf215546Sopenharmony_ci{
196bf215546Sopenharmony_ci   const struct vn_instance *instance = dev->physical_device->instance;
197bf215546Sopenharmony_ci   const struct vn_renderer_info *renderer = &instance->renderer->info;
198bf215546Sopenharmony_ci
199bf215546Sopenharmony_ci   if (renderer->has_guest_vram)
200bf215546Sopenharmony_ci      return false;
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_ci   /* We should not support suballocations because apps can do better.  But
203bf215546Sopenharmony_ci    * each BO takes up a KVM memslot currently and some CTS tests exhausts
204bf215546Sopenharmony_ci    * them.  This might not be needed on newer (host) kernels where there are
205bf215546Sopenharmony_ci    * many more KVM memslots.
206bf215546Sopenharmony_ci    */
207bf215546Sopenharmony_ci
208bf215546Sopenharmony_ci   /* consider host-visible memory only */
209bf215546Sopenharmony_ci   if (!(flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT))
210bf215546Sopenharmony_ci      return false;
211bf215546Sopenharmony_ci
212bf215546Sopenharmony_ci   /* reject larger allocations */
213bf215546Sopenharmony_ci   if (alloc_info->allocationSize > 64 * 1024)
214bf215546Sopenharmony_ci      return false;
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ci   /* reject if there is any pnext struct other than
217bf215546Sopenharmony_ci    * VkMemoryDedicatedAllocateInfo, or if dedicated allocation is required
218bf215546Sopenharmony_ci    */
219bf215546Sopenharmony_ci   if (alloc_info->pNext) {
220bf215546Sopenharmony_ci      const VkMemoryDedicatedAllocateInfo *dedicated = alloc_info->pNext;
221bf215546Sopenharmony_ci      if (dedicated->sType !=
222bf215546Sopenharmony_ci             VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO ||
223bf215546Sopenharmony_ci          dedicated->pNext)
224bf215546Sopenharmony_ci         return false;
225bf215546Sopenharmony_ci
226bf215546Sopenharmony_ci      const struct vn_image *img = vn_image_from_handle(dedicated->image);
227bf215546Sopenharmony_ci      if (img) {
228bf215546Sopenharmony_ci         for (uint32_t i = 0; i < ARRAY_SIZE(img->requirements); i++) {
229bf215546Sopenharmony_ci            if (img->requirements[i].dedicated.requiresDedicatedAllocation)
230bf215546Sopenharmony_ci               return false;
231bf215546Sopenharmony_ci         }
232bf215546Sopenharmony_ci      }
233bf215546Sopenharmony_ci
234bf215546Sopenharmony_ci      const struct vn_buffer *buf = vn_buffer_from_handle(dedicated->buffer);
235bf215546Sopenharmony_ci      if (buf && buf->requirements.dedicated.requiresDedicatedAllocation)
236bf215546Sopenharmony_ci         return false;
237bf215546Sopenharmony_ci   }
238bf215546Sopenharmony_ci
239bf215546Sopenharmony_ci   return true;
240bf215546Sopenharmony_ci}
241bf215546Sopenharmony_ci
242bf215546Sopenharmony_ciVkResult
243bf215546Sopenharmony_civn_device_memory_import_dma_buf(struct vn_device *dev,
244bf215546Sopenharmony_ci                                struct vn_device_memory *mem,
245bf215546Sopenharmony_ci                                const VkMemoryAllocateInfo *alloc_info,
246bf215546Sopenharmony_ci                                bool force_unmappable,
247bf215546Sopenharmony_ci                                int fd)
248bf215546Sopenharmony_ci{
249bf215546Sopenharmony_ci   VkDevice device = vn_device_to_handle(dev);
250bf215546Sopenharmony_ci   VkDeviceMemory memory = vn_device_memory_to_handle(mem);
251bf215546Sopenharmony_ci   const VkPhysicalDeviceMemoryProperties *mem_props =
252bf215546Sopenharmony_ci      &dev->physical_device->memory_properties.memoryProperties;
253bf215546Sopenharmony_ci   VkMemoryPropertyFlags mem_flags =
254bf215546Sopenharmony_ci      mem_props->memoryTypes[alloc_info->memoryTypeIndex].propertyFlags;
255bf215546Sopenharmony_ci   struct vn_renderer_bo *bo;
256bf215546Sopenharmony_ci   VkResult result = VK_SUCCESS;
257bf215546Sopenharmony_ci
258bf215546Sopenharmony_ci   if (force_unmappable)
259bf215546Sopenharmony_ci      mem_flags &= ~VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
260bf215546Sopenharmony_ci
261bf215546Sopenharmony_ci   result = vn_renderer_bo_create_from_dma_buf(
262bf215546Sopenharmony_ci      dev->renderer, alloc_info->allocationSize, fd, mem_flags, &bo);
263bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
264bf215546Sopenharmony_ci      return result;
265bf215546Sopenharmony_ci
266bf215546Sopenharmony_ci   vn_instance_roundtrip(dev->instance);
267bf215546Sopenharmony_ci
268bf215546Sopenharmony_ci   /* XXX fix VkImportMemoryResourceInfoMESA to support memory planes */
269bf215546Sopenharmony_ci   const VkImportMemoryResourceInfoMESA import_memory_resource_info = {
270bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_RESOURCE_INFO_MESA,
271bf215546Sopenharmony_ci      .pNext = alloc_info->pNext,
272bf215546Sopenharmony_ci      .resourceId = bo->res_id,
273bf215546Sopenharmony_ci   };
274bf215546Sopenharmony_ci   const VkMemoryAllocateInfo memory_allocate_info = {
275bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
276bf215546Sopenharmony_ci      .pNext = &import_memory_resource_info,
277bf215546Sopenharmony_ci      .allocationSize = alloc_info->allocationSize,
278bf215546Sopenharmony_ci      .memoryTypeIndex = alloc_info->memoryTypeIndex,
279bf215546Sopenharmony_ci   };
280bf215546Sopenharmony_ci   result = vn_call_vkAllocateMemory(dev->instance, device,
281bf215546Sopenharmony_ci                                     &memory_allocate_info, NULL, &memory);
282bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
283bf215546Sopenharmony_ci      vn_renderer_bo_unref(dev->renderer, bo);
284bf215546Sopenharmony_ci      return result;
285bf215546Sopenharmony_ci   }
286bf215546Sopenharmony_ci
287bf215546Sopenharmony_ci   /* need to close import fd on success to avoid fd leak */
288bf215546Sopenharmony_ci   close(fd);
289bf215546Sopenharmony_ci   mem->base_bo = bo;
290bf215546Sopenharmony_ci
291bf215546Sopenharmony_ci   return VK_SUCCESS;
292bf215546Sopenharmony_ci}
293bf215546Sopenharmony_ci
294bf215546Sopenharmony_cistatic VkResult
295bf215546Sopenharmony_civn_device_memory_alloc_guest_vram(
296bf215546Sopenharmony_ci   struct vn_device *dev,
297bf215546Sopenharmony_ci   struct vn_device_memory *mem,
298bf215546Sopenharmony_ci   const VkMemoryAllocateInfo *alloc_info,
299bf215546Sopenharmony_ci   VkExternalMemoryHandleTypeFlags external_handles)
300bf215546Sopenharmony_ci{
301bf215546Sopenharmony_ci   VkDevice dev_handle = vn_device_to_handle(dev);
302bf215546Sopenharmony_ci   VkDeviceMemory mem_handle = vn_device_memory_to_handle(mem);
303bf215546Sopenharmony_ci   VkResult result = VK_SUCCESS;
304bf215546Sopenharmony_ci
305bf215546Sopenharmony_ci   result = vn_renderer_bo_create_from_device_memory(
306bf215546Sopenharmony_ci      dev->renderer, mem->size, 0, mem->flags, external_handles,
307bf215546Sopenharmony_ci      &mem->base_bo);
308bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
309bf215546Sopenharmony_ci      return result;
310bf215546Sopenharmony_ci   }
311bf215546Sopenharmony_ci
312bf215546Sopenharmony_ci   const VkImportMemoryResourceInfoMESA import_memory_resource_info = {
313bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_RESOURCE_INFO_MESA,
314bf215546Sopenharmony_ci      .pNext = alloc_info->pNext,
315bf215546Sopenharmony_ci      .resourceId = mem->base_bo->res_id,
316bf215546Sopenharmony_ci   };
317bf215546Sopenharmony_ci
318bf215546Sopenharmony_ci   const VkMemoryAllocateInfo memory_allocate_info = {
319bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
320bf215546Sopenharmony_ci      .pNext = &import_memory_resource_info,
321bf215546Sopenharmony_ci      .allocationSize = alloc_info->allocationSize,
322bf215546Sopenharmony_ci      .memoryTypeIndex = alloc_info->memoryTypeIndex,
323bf215546Sopenharmony_ci   };
324bf215546Sopenharmony_ci
325bf215546Sopenharmony_ci   vn_instance_roundtrip(dev->instance);
326bf215546Sopenharmony_ci
327bf215546Sopenharmony_ci   result = vn_call_vkAllocateMemory(
328bf215546Sopenharmony_ci      dev->instance, dev_handle, &memory_allocate_info, NULL, &mem_handle);
329bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
330bf215546Sopenharmony_ci      vn_renderer_bo_unref(dev->renderer, mem->base_bo);
331bf215546Sopenharmony_ci      return result;
332bf215546Sopenharmony_ci   }
333bf215546Sopenharmony_ci
334bf215546Sopenharmony_ci   result =
335bf215546Sopenharmony_ci      vn_instance_submit_roundtrip(dev->instance, &mem->bo_roundtrip_seqno);
336bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
337bf215546Sopenharmony_ci      vn_renderer_bo_unref(dev->renderer, mem->base_bo);
338bf215546Sopenharmony_ci      vn_async_vkFreeMemory(dev->instance, dev_handle, mem_handle, NULL);
339bf215546Sopenharmony_ci      return result;
340bf215546Sopenharmony_ci   }
341bf215546Sopenharmony_ci
342bf215546Sopenharmony_ci   mem->bo_roundtrip_seqno_valid = true;
343bf215546Sopenharmony_ci
344bf215546Sopenharmony_ci   return VK_SUCCESS;
345bf215546Sopenharmony_ci}
346bf215546Sopenharmony_ci
347bf215546Sopenharmony_cistatic VkResult
348bf215546Sopenharmony_civn_device_memory_alloc_generic(
349bf215546Sopenharmony_ci   struct vn_device *dev,
350bf215546Sopenharmony_ci   struct vn_device_memory *mem,
351bf215546Sopenharmony_ci   const VkMemoryAllocateInfo *alloc_info,
352bf215546Sopenharmony_ci   VkExternalMemoryHandleTypeFlags external_handles)
353bf215546Sopenharmony_ci{
354bf215546Sopenharmony_ci   VkDevice dev_handle = vn_device_to_handle(dev);
355bf215546Sopenharmony_ci   VkDeviceMemory mem_handle = vn_device_memory_to_handle(mem);
356bf215546Sopenharmony_ci   VkResult result = VK_SUCCESS;
357bf215546Sopenharmony_ci
358bf215546Sopenharmony_ci   result = vn_call_vkAllocateMemory(dev->instance, dev_handle, alloc_info,
359bf215546Sopenharmony_ci                                     NULL, &mem_handle);
360bf215546Sopenharmony_ci   if (result != VK_SUCCESS || !external_handles)
361bf215546Sopenharmony_ci      return result;
362bf215546Sopenharmony_ci
363bf215546Sopenharmony_ci   result = vn_renderer_bo_create_from_device_memory(
364bf215546Sopenharmony_ci      dev->renderer, mem->size, mem->base.id, mem->flags, external_handles,
365bf215546Sopenharmony_ci      &mem->base_bo);
366bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
367bf215546Sopenharmony_ci      vn_async_vkFreeMemory(dev->instance, dev_handle, mem_handle, NULL);
368bf215546Sopenharmony_ci      return result;
369bf215546Sopenharmony_ci   }
370bf215546Sopenharmony_ci
371bf215546Sopenharmony_ci   result =
372bf215546Sopenharmony_ci      vn_instance_submit_roundtrip(dev->instance, &mem->bo_roundtrip_seqno);
373bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
374bf215546Sopenharmony_ci      vn_renderer_bo_unref(dev->renderer, mem->base_bo);
375bf215546Sopenharmony_ci      vn_async_vkFreeMemory(dev->instance, dev_handle, mem_handle, NULL);
376bf215546Sopenharmony_ci      return result;
377bf215546Sopenharmony_ci   }
378bf215546Sopenharmony_ci
379bf215546Sopenharmony_ci   mem->bo_roundtrip_seqno_valid = true;
380bf215546Sopenharmony_ci
381bf215546Sopenharmony_ci   return VK_SUCCESS;
382bf215546Sopenharmony_ci}
383bf215546Sopenharmony_ci
384bf215546Sopenharmony_cistatic VkResult
385bf215546Sopenharmony_civn_device_memory_alloc(struct vn_device *dev,
386bf215546Sopenharmony_ci                       struct vn_device_memory *mem,
387bf215546Sopenharmony_ci                       const VkMemoryAllocateInfo *alloc_info,
388bf215546Sopenharmony_ci                       VkExternalMemoryHandleTypeFlags external_handles)
389bf215546Sopenharmony_ci{
390bf215546Sopenharmony_ci   const struct vn_instance *instance = dev->physical_device->instance;
391bf215546Sopenharmony_ci   const struct vn_renderer_info *renderer_info = &instance->renderer->info;
392bf215546Sopenharmony_ci
393bf215546Sopenharmony_ci   if (renderer_info->has_guest_vram) {
394bf215546Sopenharmony_ci      return vn_device_memory_alloc_guest_vram(dev, mem, alloc_info,
395bf215546Sopenharmony_ci                                               external_handles);
396bf215546Sopenharmony_ci   }
397bf215546Sopenharmony_ci
398bf215546Sopenharmony_ci   return vn_device_memory_alloc_generic(dev, mem, alloc_info,
399bf215546Sopenharmony_ci                                         external_handles);
400bf215546Sopenharmony_ci}
401bf215546Sopenharmony_ci
402bf215546Sopenharmony_ciVkResult
403bf215546Sopenharmony_civn_AllocateMemory(VkDevice device,
404bf215546Sopenharmony_ci                  const VkMemoryAllocateInfo *pAllocateInfo,
405bf215546Sopenharmony_ci                  const VkAllocationCallbacks *pAllocator,
406bf215546Sopenharmony_ci                  VkDeviceMemory *pMemory)
407bf215546Sopenharmony_ci{
408bf215546Sopenharmony_ci   VN_TRACE_FUNC();
409bf215546Sopenharmony_ci   struct vn_device *dev = vn_device_from_handle(device);
410bf215546Sopenharmony_ci   const VkAllocationCallbacks *alloc =
411bf215546Sopenharmony_ci      pAllocator ? pAllocator : &dev->base.base.alloc;
412bf215546Sopenharmony_ci
413bf215546Sopenharmony_ci   const VkPhysicalDeviceMemoryProperties *mem_props =
414bf215546Sopenharmony_ci      &dev->physical_device->memory_properties.memoryProperties;
415bf215546Sopenharmony_ci   const VkMemoryPropertyFlags mem_flags =
416bf215546Sopenharmony_ci      mem_props->memoryTypes[pAllocateInfo->memoryTypeIndex].propertyFlags;
417bf215546Sopenharmony_ci
418bf215546Sopenharmony_ci   const VkExportMemoryAllocateInfo *export_info = NULL;
419bf215546Sopenharmony_ci   const VkImportAndroidHardwareBufferInfoANDROID *import_ahb_info = NULL;
420bf215546Sopenharmony_ci   const VkImportMemoryFdInfoKHR *import_fd_info = NULL;
421bf215546Sopenharmony_ci   bool export_ahb = false;
422bf215546Sopenharmony_ci
423bf215546Sopenharmony_ci   vk_foreach_struct_const(pnext, pAllocateInfo->pNext) {
424bf215546Sopenharmony_ci      switch (pnext->sType) {
425bf215546Sopenharmony_ci      case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO:
426bf215546Sopenharmony_ci         export_info = (void *)pnext;
427bf215546Sopenharmony_ci         if (export_info->handleTypes &
428bf215546Sopenharmony_ci             VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
429bf215546Sopenharmony_ci            export_ahb = true;
430bf215546Sopenharmony_ci         else if (!export_info->handleTypes)
431bf215546Sopenharmony_ci            export_info = NULL;
432bf215546Sopenharmony_ci         break;
433bf215546Sopenharmony_ci      case VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID:
434bf215546Sopenharmony_ci         import_ahb_info = (void *)pnext;
435bf215546Sopenharmony_ci         break;
436bf215546Sopenharmony_ci      case VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR:
437bf215546Sopenharmony_ci         import_fd_info = (void *)pnext;
438bf215546Sopenharmony_ci         break;
439bf215546Sopenharmony_ci      default:
440bf215546Sopenharmony_ci         break;
441bf215546Sopenharmony_ci      }
442bf215546Sopenharmony_ci   }
443bf215546Sopenharmony_ci
444bf215546Sopenharmony_ci   struct vn_device_memory *mem =
445bf215546Sopenharmony_ci      vk_zalloc(alloc, sizeof(*mem), VN_DEFAULT_ALIGN,
446bf215546Sopenharmony_ci                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
447bf215546Sopenharmony_ci   if (!mem)
448bf215546Sopenharmony_ci      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
449bf215546Sopenharmony_ci
450bf215546Sopenharmony_ci   vn_object_base_init(&mem->base, VK_OBJECT_TYPE_DEVICE_MEMORY, &dev->base);
451bf215546Sopenharmony_ci   mem->size = pAllocateInfo->allocationSize;
452bf215546Sopenharmony_ci   mem->flags = mem_flags;
453bf215546Sopenharmony_ci
454bf215546Sopenharmony_ci   VkDeviceMemory mem_handle = vn_device_memory_to_handle(mem);
455bf215546Sopenharmony_ci   VkResult result;
456bf215546Sopenharmony_ci   if (import_ahb_info) {
457bf215546Sopenharmony_ci      result = vn_android_device_import_ahb(dev, mem, pAllocateInfo, alloc,
458bf215546Sopenharmony_ci                                            import_ahb_info->buffer, false);
459bf215546Sopenharmony_ci   } else if (export_ahb) {
460bf215546Sopenharmony_ci      result = vn_android_device_allocate_ahb(dev, mem, pAllocateInfo, alloc);
461bf215546Sopenharmony_ci   } else if (import_fd_info) {
462bf215546Sopenharmony_ci      result = vn_device_memory_import_dma_buf(dev, mem, pAllocateInfo, false,
463bf215546Sopenharmony_ci                                               import_fd_info->fd);
464bf215546Sopenharmony_ci   } else if (export_info) {
465bf215546Sopenharmony_ci      result = vn_device_memory_alloc(dev, mem, pAllocateInfo,
466bf215546Sopenharmony_ci                                      export_info->handleTypes);
467bf215546Sopenharmony_ci   } else if (vn_device_memory_should_suballocate(dev, pAllocateInfo,
468bf215546Sopenharmony_ci                                                  mem_flags)) {
469bf215546Sopenharmony_ci      result = vn_device_memory_pool_suballocate(
470bf215546Sopenharmony_ci         dev, mem, pAllocateInfo->memoryTypeIndex);
471bf215546Sopenharmony_ci   } else {
472bf215546Sopenharmony_ci      result = vn_device_memory_alloc(dev, mem, pAllocateInfo, 0);
473bf215546Sopenharmony_ci   }
474bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
475bf215546Sopenharmony_ci      vn_object_base_fini(&mem->base);
476bf215546Sopenharmony_ci      vk_free(alloc, mem);
477bf215546Sopenharmony_ci      return vn_error(dev->instance, result);
478bf215546Sopenharmony_ci   }
479bf215546Sopenharmony_ci
480bf215546Sopenharmony_ci   *pMemory = mem_handle;
481bf215546Sopenharmony_ci
482bf215546Sopenharmony_ci   return VK_SUCCESS;
483bf215546Sopenharmony_ci}
484bf215546Sopenharmony_ci
485bf215546Sopenharmony_civoid
486bf215546Sopenharmony_civn_FreeMemory(VkDevice device,
487bf215546Sopenharmony_ci              VkDeviceMemory memory,
488bf215546Sopenharmony_ci              const VkAllocationCallbacks *pAllocator)
489bf215546Sopenharmony_ci{
490bf215546Sopenharmony_ci   VN_TRACE_FUNC();
491bf215546Sopenharmony_ci   struct vn_device *dev = vn_device_from_handle(device);
492bf215546Sopenharmony_ci   struct vn_device_memory *mem = vn_device_memory_from_handle(memory);
493bf215546Sopenharmony_ci   const VkAllocationCallbacks *alloc =
494bf215546Sopenharmony_ci      pAllocator ? pAllocator : &dev->base.base.alloc;
495bf215546Sopenharmony_ci
496bf215546Sopenharmony_ci   if (!mem)
497bf215546Sopenharmony_ci      return;
498bf215546Sopenharmony_ci
499bf215546Sopenharmony_ci   if (mem->base_memory) {
500bf215546Sopenharmony_ci      vn_device_memory_pool_unref(dev, mem->base_memory);
501bf215546Sopenharmony_ci   } else {
502bf215546Sopenharmony_ci      if (mem->base_bo)
503bf215546Sopenharmony_ci         vn_renderer_bo_unref(dev->renderer, mem->base_bo);
504bf215546Sopenharmony_ci
505bf215546Sopenharmony_ci      if (mem->bo_roundtrip_seqno_valid)
506bf215546Sopenharmony_ci         vn_instance_wait_roundtrip(dev->instance, mem->bo_roundtrip_seqno);
507bf215546Sopenharmony_ci
508bf215546Sopenharmony_ci      vn_async_vkFreeMemory(dev->instance, device, memory, NULL);
509bf215546Sopenharmony_ci   }
510bf215546Sopenharmony_ci
511bf215546Sopenharmony_ci   if (mem->ahb)
512bf215546Sopenharmony_ci      vn_android_release_ahb(mem->ahb);
513bf215546Sopenharmony_ci
514bf215546Sopenharmony_ci   vn_object_base_fini(&mem->base);
515bf215546Sopenharmony_ci   vk_free(alloc, mem);
516bf215546Sopenharmony_ci}
517bf215546Sopenharmony_ci
518bf215546Sopenharmony_ciuint64_t
519bf215546Sopenharmony_civn_GetDeviceMemoryOpaqueCaptureAddress(
520bf215546Sopenharmony_ci   VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo *pInfo)
521bf215546Sopenharmony_ci{
522bf215546Sopenharmony_ci   struct vn_device *dev = vn_device_from_handle(device);
523bf215546Sopenharmony_ci   ASSERTED struct vn_device_memory *mem =
524bf215546Sopenharmony_ci      vn_device_memory_from_handle(pInfo->memory);
525bf215546Sopenharmony_ci
526bf215546Sopenharmony_ci   assert(!mem->base_memory);
527bf215546Sopenharmony_ci   return vn_call_vkGetDeviceMemoryOpaqueCaptureAddress(dev->instance, device,
528bf215546Sopenharmony_ci                                                        pInfo);
529bf215546Sopenharmony_ci}
530bf215546Sopenharmony_ci
531bf215546Sopenharmony_ciVkResult
532bf215546Sopenharmony_civn_MapMemory(VkDevice device,
533bf215546Sopenharmony_ci             VkDeviceMemory memory,
534bf215546Sopenharmony_ci             VkDeviceSize offset,
535bf215546Sopenharmony_ci             VkDeviceSize size,
536bf215546Sopenharmony_ci             VkMemoryMapFlags flags,
537bf215546Sopenharmony_ci             void **ppData)
538bf215546Sopenharmony_ci{
539bf215546Sopenharmony_ci   VN_TRACE_FUNC();
540bf215546Sopenharmony_ci   struct vn_device *dev = vn_device_from_handle(device);
541bf215546Sopenharmony_ci   struct vn_device_memory *mem = vn_device_memory_from_handle(memory);
542bf215546Sopenharmony_ci   const bool need_bo = !mem->base_bo;
543bf215546Sopenharmony_ci   void *ptr = NULL;
544bf215546Sopenharmony_ci   VkResult result;
545bf215546Sopenharmony_ci
546bf215546Sopenharmony_ci   assert(mem->flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
547bf215546Sopenharmony_ci
548bf215546Sopenharmony_ci   /* We don't want to blindly create a bo for each HOST_VISIBLE memory as
549bf215546Sopenharmony_ci    * that has a cost. By deferring bo creation until now, we can avoid the
550bf215546Sopenharmony_ci    * cost unless a bo is really needed. However, that means
551bf215546Sopenharmony_ci    * vn_renderer_bo_map will block until the renderer creates the resource
552bf215546Sopenharmony_ci    * and injects the pages into the guest.
553bf215546Sopenharmony_ci    */
554bf215546Sopenharmony_ci   if (need_bo) {
555bf215546Sopenharmony_ci      result = vn_renderer_bo_create_from_device_memory(
556bf215546Sopenharmony_ci         dev->renderer, mem->size, mem->base.id, mem->flags, 0,
557bf215546Sopenharmony_ci         &mem->base_bo);
558bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
559bf215546Sopenharmony_ci         return vn_error(dev->instance, result);
560bf215546Sopenharmony_ci   }
561bf215546Sopenharmony_ci
562bf215546Sopenharmony_ci   ptr = vn_renderer_bo_map(dev->renderer, mem->base_bo);
563bf215546Sopenharmony_ci   if (!ptr) {
564bf215546Sopenharmony_ci      /* vn_renderer_bo_map implies a roundtrip on success, but not here. */
565bf215546Sopenharmony_ci      if (need_bo) {
566bf215546Sopenharmony_ci         result = vn_instance_submit_roundtrip(dev->instance,
567bf215546Sopenharmony_ci                                               &mem->bo_roundtrip_seqno);
568bf215546Sopenharmony_ci         if (result != VK_SUCCESS)
569bf215546Sopenharmony_ci            return vn_error(dev->instance, result);
570bf215546Sopenharmony_ci
571bf215546Sopenharmony_ci         mem->bo_roundtrip_seqno_valid = true;
572bf215546Sopenharmony_ci      }
573bf215546Sopenharmony_ci
574bf215546Sopenharmony_ci      return vn_error(dev->instance, VK_ERROR_MEMORY_MAP_FAILED);
575bf215546Sopenharmony_ci   }
576bf215546Sopenharmony_ci
577bf215546Sopenharmony_ci   mem->map_end = size == VK_WHOLE_SIZE ? mem->size : offset + size;
578bf215546Sopenharmony_ci
579bf215546Sopenharmony_ci   *ppData = ptr + mem->base_offset + offset;
580bf215546Sopenharmony_ci
581bf215546Sopenharmony_ci   return VK_SUCCESS;
582bf215546Sopenharmony_ci}
583bf215546Sopenharmony_ci
584bf215546Sopenharmony_civoid
585bf215546Sopenharmony_civn_UnmapMemory(VkDevice device, VkDeviceMemory memory)
586bf215546Sopenharmony_ci{
587bf215546Sopenharmony_ci   VN_TRACE_FUNC();
588bf215546Sopenharmony_ci}
589bf215546Sopenharmony_ci
590bf215546Sopenharmony_ciVkResult
591bf215546Sopenharmony_civn_FlushMappedMemoryRanges(VkDevice device,
592bf215546Sopenharmony_ci                           uint32_t memoryRangeCount,
593bf215546Sopenharmony_ci                           const VkMappedMemoryRange *pMemoryRanges)
594bf215546Sopenharmony_ci{
595bf215546Sopenharmony_ci   VN_TRACE_FUNC();
596bf215546Sopenharmony_ci   struct vn_device *dev = vn_device_from_handle(device);
597bf215546Sopenharmony_ci
598bf215546Sopenharmony_ci   for (uint32_t i = 0; i < memoryRangeCount; i++) {
599bf215546Sopenharmony_ci      const VkMappedMemoryRange *range = &pMemoryRanges[i];
600bf215546Sopenharmony_ci      struct vn_device_memory *mem =
601bf215546Sopenharmony_ci         vn_device_memory_from_handle(range->memory);
602bf215546Sopenharmony_ci
603bf215546Sopenharmony_ci      const VkDeviceSize size = range->size == VK_WHOLE_SIZE
604bf215546Sopenharmony_ci                                   ? mem->map_end - range->offset
605bf215546Sopenharmony_ci                                   : range->size;
606bf215546Sopenharmony_ci      vn_renderer_bo_flush(dev->renderer, mem->base_bo,
607bf215546Sopenharmony_ci                           mem->base_offset + range->offset, size);
608bf215546Sopenharmony_ci   }
609bf215546Sopenharmony_ci
610bf215546Sopenharmony_ci   return VK_SUCCESS;
611bf215546Sopenharmony_ci}
612bf215546Sopenharmony_ci
613bf215546Sopenharmony_ciVkResult
614bf215546Sopenharmony_civn_InvalidateMappedMemoryRanges(VkDevice device,
615bf215546Sopenharmony_ci                                uint32_t memoryRangeCount,
616bf215546Sopenharmony_ci                                const VkMappedMemoryRange *pMemoryRanges)
617bf215546Sopenharmony_ci{
618bf215546Sopenharmony_ci   VN_TRACE_FUNC();
619bf215546Sopenharmony_ci   struct vn_device *dev = vn_device_from_handle(device);
620bf215546Sopenharmony_ci
621bf215546Sopenharmony_ci   for (uint32_t i = 0; i < memoryRangeCount; i++) {
622bf215546Sopenharmony_ci      const VkMappedMemoryRange *range = &pMemoryRanges[i];
623bf215546Sopenharmony_ci      struct vn_device_memory *mem =
624bf215546Sopenharmony_ci         vn_device_memory_from_handle(range->memory);
625bf215546Sopenharmony_ci
626bf215546Sopenharmony_ci      const VkDeviceSize size = range->size == VK_WHOLE_SIZE
627bf215546Sopenharmony_ci                                   ? mem->map_end - range->offset
628bf215546Sopenharmony_ci                                   : range->size;
629bf215546Sopenharmony_ci      vn_renderer_bo_invalidate(dev->renderer, mem->base_bo,
630bf215546Sopenharmony_ci                                mem->base_offset + range->offset, size);
631bf215546Sopenharmony_ci   }
632bf215546Sopenharmony_ci
633bf215546Sopenharmony_ci   return VK_SUCCESS;
634bf215546Sopenharmony_ci}
635bf215546Sopenharmony_ci
636bf215546Sopenharmony_civoid
637bf215546Sopenharmony_civn_GetDeviceMemoryCommitment(VkDevice device,
638bf215546Sopenharmony_ci                             VkDeviceMemory memory,
639bf215546Sopenharmony_ci                             VkDeviceSize *pCommittedMemoryInBytes)
640bf215546Sopenharmony_ci{
641bf215546Sopenharmony_ci   struct vn_device *dev = vn_device_from_handle(device);
642bf215546Sopenharmony_ci   ASSERTED struct vn_device_memory *mem =
643bf215546Sopenharmony_ci      vn_device_memory_from_handle(memory);
644bf215546Sopenharmony_ci
645bf215546Sopenharmony_ci   assert(!mem->base_memory);
646bf215546Sopenharmony_ci   vn_call_vkGetDeviceMemoryCommitment(dev->instance, device, memory,
647bf215546Sopenharmony_ci                                       pCommittedMemoryInBytes);
648bf215546Sopenharmony_ci}
649bf215546Sopenharmony_ci
650bf215546Sopenharmony_ciVkResult
651bf215546Sopenharmony_civn_GetMemoryFdKHR(VkDevice device,
652bf215546Sopenharmony_ci                  const VkMemoryGetFdInfoKHR *pGetFdInfo,
653bf215546Sopenharmony_ci                  int *pFd)
654bf215546Sopenharmony_ci{
655bf215546Sopenharmony_ci   VN_TRACE_FUNC();
656bf215546Sopenharmony_ci   struct vn_device *dev = vn_device_from_handle(device);
657bf215546Sopenharmony_ci   struct vn_device_memory *mem =
658bf215546Sopenharmony_ci      vn_device_memory_from_handle(pGetFdInfo->memory);
659bf215546Sopenharmony_ci
660bf215546Sopenharmony_ci   /* At the moment, we support only the below handle types. */
661bf215546Sopenharmony_ci   assert(pGetFdInfo->handleType &
662bf215546Sopenharmony_ci          (VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
663bf215546Sopenharmony_ci           VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT));
664bf215546Sopenharmony_ci   assert(!mem->base_memory && mem->base_bo);
665bf215546Sopenharmony_ci   *pFd = vn_renderer_bo_export_dma_buf(dev->renderer, mem->base_bo);
666bf215546Sopenharmony_ci   if (*pFd < 0)
667bf215546Sopenharmony_ci      return vn_error(dev->instance, VK_ERROR_TOO_MANY_OBJECTS);
668bf215546Sopenharmony_ci
669bf215546Sopenharmony_ci   return VK_SUCCESS;
670bf215546Sopenharmony_ci}
671bf215546Sopenharmony_ci
672bf215546Sopenharmony_ciVkResult
673bf215546Sopenharmony_civn_get_memory_dma_buf_properties(struct vn_device *dev,
674bf215546Sopenharmony_ci                                 int fd,
675bf215546Sopenharmony_ci                                 uint64_t *out_alloc_size,
676bf215546Sopenharmony_ci                                 uint32_t *out_mem_type_bits)
677bf215546Sopenharmony_ci{
678bf215546Sopenharmony_ci   VkDevice device = vn_device_to_handle(dev);
679bf215546Sopenharmony_ci   struct vn_renderer_bo *bo = NULL;
680bf215546Sopenharmony_ci   VkResult result = VK_SUCCESS;
681bf215546Sopenharmony_ci
682bf215546Sopenharmony_ci   result = vn_renderer_bo_create_from_dma_buf(dev->renderer, 0 /* size */,
683bf215546Sopenharmony_ci                                               fd, 0 /* flags */, &bo);
684bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
685bf215546Sopenharmony_ci      return result;
686bf215546Sopenharmony_ci
687bf215546Sopenharmony_ci   vn_instance_roundtrip(dev->instance);
688bf215546Sopenharmony_ci
689bf215546Sopenharmony_ci   VkMemoryResourceAllocationSizeProperties100000MESA alloc_size_props = {
690bf215546Sopenharmony_ci      .sType =
691bf215546Sopenharmony_ci         VK_STRUCTURE_TYPE_MEMORY_RESOURCE_ALLOCATION_SIZE_PROPERTIES_100000_MESA,
692bf215546Sopenharmony_ci      .pNext = NULL,
693bf215546Sopenharmony_ci      .allocationSize = 0,
694bf215546Sopenharmony_ci   };
695bf215546Sopenharmony_ci   VkMemoryResourcePropertiesMESA props = {
696bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_MEMORY_RESOURCE_PROPERTIES_MESA,
697bf215546Sopenharmony_ci      .pNext =
698bf215546Sopenharmony_ci         dev->instance->experimental.memoryResourceAllocationSize == VK_TRUE
699bf215546Sopenharmony_ci            ? &alloc_size_props
700bf215546Sopenharmony_ci            : NULL,
701bf215546Sopenharmony_ci      .memoryTypeBits = 0,
702bf215546Sopenharmony_ci   };
703bf215546Sopenharmony_ci   result = vn_call_vkGetMemoryResourcePropertiesMESA(dev->instance, device,
704bf215546Sopenharmony_ci                                                      bo->res_id, &props);
705bf215546Sopenharmony_ci   vn_renderer_bo_unref(dev->renderer, bo);
706bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
707bf215546Sopenharmony_ci      return result;
708bf215546Sopenharmony_ci
709bf215546Sopenharmony_ci   *out_alloc_size = alloc_size_props.allocationSize;
710bf215546Sopenharmony_ci   *out_mem_type_bits = props.memoryTypeBits;
711bf215546Sopenharmony_ci
712bf215546Sopenharmony_ci   return VK_SUCCESS;
713bf215546Sopenharmony_ci}
714bf215546Sopenharmony_ci
715bf215546Sopenharmony_ciVkResult
716bf215546Sopenharmony_civn_GetMemoryFdPropertiesKHR(VkDevice device,
717bf215546Sopenharmony_ci                            VkExternalMemoryHandleTypeFlagBits handleType,
718bf215546Sopenharmony_ci                            int fd,
719bf215546Sopenharmony_ci                            VkMemoryFdPropertiesKHR *pMemoryFdProperties)
720bf215546Sopenharmony_ci{
721bf215546Sopenharmony_ci   VN_TRACE_FUNC();
722bf215546Sopenharmony_ci   struct vn_device *dev = vn_device_from_handle(device);
723bf215546Sopenharmony_ci   uint64_t alloc_size = 0;
724bf215546Sopenharmony_ci   uint32_t mem_type_bits = 0;
725bf215546Sopenharmony_ci   VkResult result = VK_SUCCESS;
726bf215546Sopenharmony_ci
727bf215546Sopenharmony_ci   if (handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
728bf215546Sopenharmony_ci      return vn_error(dev->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE);
729bf215546Sopenharmony_ci
730bf215546Sopenharmony_ci   result =
731bf215546Sopenharmony_ci      vn_get_memory_dma_buf_properties(dev, fd, &alloc_size, &mem_type_bits);
732bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
733bf215546Sopenharmony_ci      return vn_error(dev->instance, result);
734bf215546Sopenharmony_ci
735bf215546Sopenharmony_ci   pMemoryFdProperties->memoryTypeBits = mem_type_bits;
736bf215546Sopenharmony_ci
737bf215546Sopenharmony_ci   return VK_SUCCESS;
738bf215546Sopenharmony_ci}
739