Module: Mesa
Branch: master
Commit: 49a15148fa7e20aad94b5b4924efab15d1f4c955
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=49a15148fa7e20aad94b5b4924efab15d1f4c955

Author: Chia-I Wu <olva...@gmail.com>
Date:   Wed Apr  7 17:30:54 2021 -0700

venus: split out vn_device_memory.[ch]

Move VkDeviceMemory functions to the new files.

Signed-off-by: Chia-I Wu <olva...@gmail.com>
Reviewed-by: Yiwei Zhang <zzyi...@chromium.org>
Acked-by: Erik Faye-Lund <erik.faye-l...@collabora.com>
Reviewed-by: Ryan Neph <ryann...@google.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10117>

---

 src/virtio/vulkan/meson.build        |   1 +
 src/virtio/vulkan/vn_buffer.c        |   1 +
 src/virtio/vulkan/vn_device.c        | 409 +---------------------------------
 src/virtio/vulkan/vn_device.h        |  25 +--
 src/virtio/vulkan/vn_device_memory.c | 420 +++++++++++++++++++++++++++++++++++
 src/virtio/vulkan/vn_device_memory.h |  43 ++++
 src/virtio/vulkan/vn_image.c         |   1 +
 7 files changed, 468 insertions(+), 432 deletions(-)

diff --git a/src/virtio/vulkan/meson.build b/src/virtio/vulkan/meson.build
index 35a11bbf310..e0c8779cdb5 100644
--- a/src/virtio/vulkan/meson.build
+++ b/src/virtio/vulkan/meson.build
@@ -37,6 +37,7 @@ libvn_files = files(
   'vn_cs.c',
   'vn_descriptor_set.c',
   'vn_device.c',
+  'vn_device_memory.c',
   'vn_icd.c',
   'vn_image.c',
   'vn_pipeline.c',
diff --git a/src/virtio/vulkan/vn_buffer.c b/src/virtio/vulkan/vn_buffer.c
index 70d129c21b3..34ec3b170a9 100644
--- a/src/virtio/vulkan/vn_buffer.c
+++ b/src/virtio/vulkan/vn_buffer.c
@@ -14,6 +14,7 @@
 #include "venus-protocol/vn_protocol_driver_buffer_view.h"
 
 #include "vn_device.h"
+#include "vn_device_memory.h"
 
 /* buffer commands */
 
diff --git a/src/virtio/vulkan/vn_device.c b/src/virtio/vulkan/vn_device.c
index b74235a7d3e..3f942cdb2bb 100644
--- a/src/virtio/vulkan/vn_device.c
+++ b/src/virtio/vulkan/vn_device.c
@@ -17,6 +17,7 @@
 #include "util/mesa-sha1.h"
 #include "venus-protocol/vn_protocol_driver.h"
 
+#include "vn_device_memory.h"
 #include "vn_icd.h"
 #include "vn_renderer.h"
 
@@ -3043,9 +3044,6 @@ fail:
    return vn_error(instance, result);
 }
 
-static void
-vn_device_memory_pool_fini(struct vn_device *dev, uint32_t mem_type_index);
-
 void
 vn_DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator)
 {
@@ -4347,411 +4345,6 @@ vn_GetSemaphoreFdKHR(VkDevice device,
    return VK_SUCCESS;
 }
 
-/* device memory commands */
-
-static VkResult
-vn_device_memory_simple_alloc(struct vn_device *dev,
-                              uint32_t mem_type_index,
-                              VkDeviceSize size,
-                              struct vn_device_memory **out_mem)
-{
-   const VkAllocationCallbacks *alloc = &dev->base.base.alloc;
-
-   struct vn_device_memory *mem =
-      vk_zalloc(alloc, sizeof(*mem), VN_DEFAULT_ALIGN,
-                VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
-   if (!mem)
-      return VK_ERROR_OUT_OF_HOST_MEMORY;
-
-   vn_object_base_init(&mem->base, VK_OBJECT_TYPE_DEVICE_MEMORY, &dev->base);
-   mem->size = size;
-
-   VkDeviceMemory mem_handle = vn_device_memory_to_handle(mem);
-   VkResult result = vn_call_vkAllocateMemory(
-      dev->instance, vn_device_to_handle(dev),
-      &(const VkMemoryAllocateInfo){
-         .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
-         .allocationSize = size,
-         .memoryTypeIndex = mem_type_index,
-      },
-      NULL, &mem_handle);
-   if (result != VK_SUCCESS) {
-      vk_free(alloc, mem);
-      return result;
-   }
-
-   const VkPhysicalDeviceMemoryProperties *mem_props =
-      &dev->physical_device->memory_properties.memoryProperties;
-   const VkMemoryType *mem_type = &mem_props->memoryTypes[mem_type_index];
-   result = vn_renderer_bo_create_gpu(dev->instance->renderer, mem->size,
-                                      mem->base.id, mem_type->propertyFlags,
-                                      0, &mem->base_bo);
-   if (result != VK_SUCCESS) {
-      vn_async_vkFreeMemory(dev->instance, vn_device_to_handle(dev),
-                            mem_handle, NULL);
-      vk_free(alloc, mem);
-      return result;
-   }
-   vn_instance_roundtrip(dev->instance);
-
-   *out_mem = mem;
-
-   return VK_SUCCESS;
-}
-
-static void
-vn_device_memory_simple_free(struct vn_device *dev,
-                             struct vn_device_memory *mem)
-{
-   const VkAllocationCallbacks *alloc = &dev->base.base.alloc;
-
-   if (mem->base_bo)
-      vn_renderer_bo_unref(mem->base_bo);
-
-   vn_async_vkFreeMemory(dev->instance, vn_device_to_handle(dev),
-                         vn_device_memory_to_handle(mem), NULL);
-   vn_object_base_fini(&mem->base);
-   vk_free(alloc, mem);
-}
-
-static void
-vn_device_memory_pool_fini(struct vn_device *dev, uint32_t mem_type_index)
-{
-   struct vn_device_memory_pool *pool = &dev->memory_pools[mem_type_index];
-   if (pool->memory)
-      vn_device_memory_simple_free(dev, pool->memory);
-   mtx_destroy(&pool->mutex);
-}
-
-static VkResult
-vn_device_memory_pool_grow_locked(struct vn_device *dev,
-                                  uint32_t mem_type_index,
-                                  VkDeviceSize size)
-{
-   struct vn_device_memory *mem;
-   VkResult result =
-      vn_device_memory_simple_alloc(dev, mem_type_index, size, &mem);
-   if (result != VK_SUCCESS)
-      return result;
-
-   struct vn_device_memory_pool *pool = &dev->memory_pools[mem_type_index];
-   if (pool->memory) {
-      const bool bo_destroyed = vn_renderer_bo_unref(pool->memory->base_bo);
-      pool->memory->base_bo = NULL;
-
-      /* we use pool->memory's base_bo to keep it alive */
-      if (bo_destroyed)
-         vn_device_memory_simple_free(dev, pool->memory);
-   }
-
-   pool->memory = mem;
-   pool->used = 0;
-
-   return VK_SUCCESS;
-}
-
-static VkResult
-vn_device_memory_pool_alloc(struct vn_device *dev,
-                            uint32_t mem_type_index,
-                            VkDeviceSize size,
-                            struct vn_device_memory **base_mem,
-                            struct vn_renderer_bo **base_bo,
-                            VkDeviceSize *base_offset)
-{
-   /* We should not support suballocations because apps can do better and we
-    * also don't know the alignment requirements.  But each BO takes up a
-    * precious KVM memslot currently and some CTS tests exhausts them...
-    */
-   const VkDeviceSize pool_size = 16 * 1024 * 1024;
-   const VkDeviceSize pool_align = 4096; /* XXX */
-   struct vn_device_memory_pool *pool = &dev->memory_pools[mem_type_index];
-
-   assert(size <= pool_size);
-
-   mtx_lock(&pool->mutex);
-
-   if (!pool->memory || pool->used + size > pool_size) {
-      VkResult result =
-         vn_device_memory_pool_grow_locked(dev, mem_type_index, pool_size);
-      if (result != VK_SUCCESS) {
-         mtx_unlock(&pool->mutex);
-         return result;
-      }
-   }
-
-   /* we use base_bo to keep base_mem alive */
-   *base_mem = pool->memory;
-   *base_bo = vn_renderer_bo_ref(pool->memory->base_bo);
-
-   *base_offset = pool->used;
-   pool->used += align64(size, pool_align);
-
-   mtx_unlock(&pool->mutex);
-
-   return VK_SUCCESS;
-}
-
-static void
-vn_device_memory_pool_free(struct vn_device *dev,
-                           struct vn_device_memory *base_mem,
-                           struct vn_renderer_bo *base_bo)
-{
-   /* we use base_bo to keep base_mem alive */
-   if (vn_renderer_bo_unref(base_bo))
-      vn_device_memory_simple_free(dev, base_mem);
-}
-
-VkResult
-vn_AllocateMemory(VkDevice device,
-                  const VkMemoryAllocateInfo *pAllocateInfo,
-                  const VkAllocationCallbacks *pAllocator,
-                  VkDeviceMemory *pMemory)
-{
-   struct vn_device *dev = vn_device_from_handle(device);
-   const VkAllocationCallbacks *alloc =
-      pAllocator ? pAllocator : &dev->base.base.alloc;
-
-   const VkPhysicalDeviceMemoryProperties *mem_props =
-      &dev->physical_device->memory_properties.memoryProperties;
-   const VkMemoryType *mem_type =
-      &mem_props->memoryTypes[pAllocateInfo->memoryTypeIndex];
-   const VkImportMemoryFdInfoKHR *import_info =
-      vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_FD_INFO_KHR);
-   const VkExportMemoryAllocateInfo *export_info =
-      vk_find_struct_const(pAllocateInfo->pNext, EXPORT_MEMORY_ALLOCATE_INFO);
-   if (export_info && !export_info->handleTypes)
-      export_info = NULL;
-
-   const bool need_bo =
-      (mem_type->propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) ||
-      import_info || export_info;
-   const bool suballocate =
-      need_bo && !pAllocateInfo->pNext &&
-      !(mem_type->propertyFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) &&
-      pAllocateInfo->allocationSize <= 64 * 1024;
-
-   struct vn_device_memory *mem =
-      vk_zalloc(alloc, sizeof(*mem), VN_DEFAULT_ALIGN,
-                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
-   if (!mem)
-      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
-
-   vn_object_base_init(&mem->base, VK_OBJECT_TYPE_DEVICE_MEMORY, &dev->base);
-   mem->size = pAllocateInfo->allocationSize;
-
-   VkDeviceMemory mem_handle = vn_device_memory_to_handle(mem);
-   VkResult result;
-   if (import_info) {
-      struct vn_renderer_bo *bo;
-      result = vn_renderer_bo_create_dmabuf(
-         dev->instance->renderer, pAllocateInfo->allocationSize,
-         import_info->fd, mem_type->propertyFlags,
-         export_info ? export_info->handleTypes : 0, &bo);
-      if (result != VK_SUCCESS) {
-         vk_free(alloc, mem);
-         return vn_error(dev->instance, result);
-      }
-
-      /* TODO create host-side memory from bo->res_id */
-      result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
-      if (result != VK_SUCCESS) {
-         vn_renderer_bo_unref(bo);
-         vk_free(alloc, mem);
-         return vn_error(dev->instance, result);
-      }
-
-      mem->base_bo = bo;
-   } else if (suballocate) {
-      result = vn_device_memory_pool_alloc(
-         dev, pAllocateInfo->memoryTypeIndex, mem->size, &mem->base_memory,
-         &mem->base_bo, &mem->base_offset);
-      if (result != VK_SUCCESS) {
-         vk_free(alloc, mem);
-         return vn_error(dev->instance, result);
-      }
-   } else {
-      result = vn_call_vkAllocateMemory(dev->instance, device, pAllocateInfo,
-                                        NULL, &mem_handle);
-      if (result != VK_SUCCESS) {
-         vk_free(alloc, mem);
-         return vn_error(dev->instance, result);
-      }
-   }
-
-   if (need_bo && !mem->base_bo) {
-      result = vn_renderer_bo_create_gpu(
-         dev->instance->renderer, mem->size, mem->base.id,
-         mem_type->propertyFlags, export_info ? export_info->handleTypes : 0,
-         &mem->base_bo);
-      if (result != VK_SUCCESS) {
-         vn_async_vkFreeMemory(dev->instance, device, mem_handle, NULL);
-         vk_free(alloc, mem);
-         return vn_error(dev->instance, result);
-      }
-      vn_instance_roundtrip(dev->instance);
-   }
-
-   *pMemory = mem_handle;
-
-   return VK_SUCCESS;
-}
-
-void
-vn_FreeMemory(VkDevice device,
-              VkDeviceMemory memory,
-              const VkAllocationCallbacks *pAllocator)
-{
-   struct vn_device *dev = vn_device_from_handle(device);
-   struct vn_device_memory *mem = vn_device_memory_from_handle(memory);
-   const VkAllocationCallbacks *alloc =
-      pAllocator ? pAllocator : &dev->base.base.alloc;
-
-   if (!mem)
-      return;
-
-   if (mem->base_memory) {
-      vn_device_memory_pool_free(dev, mem->base_memory, mem->base_bo);
-   } else {
-      if (mem->base_bo)
-         vn_renderer_bo_unref(mem->base_bo);
-      vn_async_vkFreeMemory(dev->instance, device, memory, NULL);
-   }
-
-   vn_object_base_fini(&mem->base);
-   vk_free(alloc, mem);
-}
-
-uint64_t
-vn_GetDeviceMemoryOpaqueCaptureAddress(
-   VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo *pInfo)
-{
-   struct vn_device *dev = vn_device_from_handle(device);
-   struct vn_device_memory *mem = vn_device_memory_from_handle(pInfo->memory);
-
-   assert(!mem->base_memory);
-   return vn_call_vkGetDeviceMemoryOpaqueCaptureAddress(dev->instance, device,
-                                                        pInfo);
-}
-
-VkResult
-vn_MapMemory(VkDevice device,
-             VkDeviceMemory memory,
-             VkDeviceSize offset,
-             VkDeviceSize size,
-             VkMemoryMapFlags flags,
-             void **ppData)
-{
-   struct vn_device *dev = vn_device_from_handle(device);
-   struct vn_device_memory *mem = vn_device_memory_from_handle(memory);
-
-   void *ptr = vn_renderer_bo_map(mem->base_bo);
-   if (!ptr)
-      return vn_error(dev->instance, VK_ERROR_MEMORY_MAP_FAILED);
-
-   mem->map_end = size == VK_WHOLE_SIZE ? mem->size : offset + size;
-
-   *ppData = ptr + mem->base_offset + offset;
-
-   return VK_SUCCESS;
-}
-
-void
-vn_UnmapMemory(VkDevice device, VkDeviceMemory memory)
-{
-}
-
-VkResult
-vn_FlushMappedMemoryRanges(VkDevice device,
-                           uint32_t memoryRangeCount,
-                           const VkMappedMemoryRange *pMemoryRanges)
-{
-   for (uint32_t i = 0; i < memoryRangeCount; i++) {
-      const VkMappedMemoryRange *range = &pMemoryRanges[i];
-      struct vn_device_memory *mem =
-         vn_device_memory_from_handle(range->memory);
-
-      const VkDeviceSize size = range->size == VK_WHOLE_SIZE
-                                   ? mem->map_end - range->offset
-                                   : range->size;
-      vn_renderer_bo_flush(mem->base_bo, mem->base_offset + range->offset,
-                           size);
-   }
-
-   return VK_SUCCESS;
-}
-
-VkResult
-vn_InvalidateMappedMemoryRanges(VkDevice device,
-                                uint32_t memoryRangeCount,
-                                const VkMappedMemoryRange *pMemoryRanges)
-{
-   for (uint32_t i = 0; i < memoryRangeCount; i++) {
-      const VkMappedMemoryRange *range = &pMemoryRanges[i];
-      struct vn_device_memory *mem =
-         vn_device_memory_from_handle(range->memory);
-
-      const VkDeviceSize size = range->size == VK_WHOLE_SIZE
-                                   ? mem->map_end - range->offset
-                                   : range->size;
-      vn_renderer_bo_invalidate(mem->base_bo,
-                                mem->base_offset + range->offset, size);
-   }
-
-   return VK_SUCCESS;
-}
-
-void
-vn_GetDeviceMemoryCommitment(VkDevice device,
-                             VkDeviceMemory memory,
-                             VkDeviceSize *pCommittedMemoryInBytes)
-{
-   struct vn_device *dev = vn_device_from_handle(device);
-   struct vn_device_memory *mem = vn_device_memory_from_handle(memory);
-
-   assert(!mem->base_memory);
-   vn_call_vkGetDeviceMemoryCommitment(dev->instance, device, memory,
-                                       pCommittedMemoryInBytes);
-}
-
-VkResult
-vn_GetMemoryFdKHR(VkDevice device,
-                  const VkMemoryGetFdInfoKHR *pGetFdInfo,
-                  int *pFd)
-{
-   struct vn_device *dev = vn_device_from_handle(device);
-   struct vn_device_memory *mem =
-      vn_device_memory_from_handle(pGetFdInfo->memory);
-
-   assert(!mem->base_memory && mem->base_bo);
-   *pFd = vn_renderer_bo_export_dmabuf(mem->base_bo);
-   if (*pFd < 0)
-      return vn_error(dev->instance, VK_ERROR_TOO_MANY_OBJECTS);
-
-   return VK_SUCCESS;
-}
-
-VkResult
-vn_GetMemoryFdPropertiesKHR(VkDevice device,
-                            VkExternalMemoryHandleTypeFlagBits handleType,
-                            int fd,
-                            VkMemoryFdPropertiesKHR *pMemoryFdProperties)
-{
-   struct vn_device *dev = vn_device_from_handle(device);
-
-   struct vn_renderer_bo *bo;
-   VkResult result = vn_renderer_bo_create_dmabuf(dev->instance->renderer, 0,
-                                                  fd, 0, handleType, &bo);
-   if (result != VK_SUCCESS)
-      return vn_error(dev->instance, result);
-
-   /* TODO call into the host with bo->res_id */
-   result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
-
-   vn_renderer_bo_unref(bo);
-
-   return result;
-}
-
 /* event commands */
 
 VkResult
diff --git a/src/virtio/vulkan/vn_device.h b/src/virtio/vulkan/vn_device.h
index fc242bd9340..ed981a4a1e8 100644
--- a/src/virtio/vulkan/vn_device.h
+++ b/src/virtio/vulkan/vn_device.h
@@ -14,6 +14,7 @@
 #include "vn_common.h"
 
 #include "vn_cs.h"
+#include "vn_device_memory.h"
 #include "vn_renderer.h"
 #include "vn_ring.h"
 #include "vn_wsi.h"
@@ -97,12 +98,6 @@ VK_DEFINE_HANDLE_CASTS(vn_physical_device,
                        VkPhysicalDevice,
                        VK_OBJECT_TYPE_PHYSICAL_DEVICE)
 
-struct vn_device_memory_pool {
-   mtx_t mutex;
-   struct vn_device_memory *memory;
-   VkDeviceSize used;
-};
-
 struct vn_device {
    struct vn_device_base base;
 
@@ -185,24 +180,6 @@ VK_DEFINE_NONDISP_HANDLE_CASTS(vn_semaphore,
                                VkSemaphore,
                                VK_OBJECT_TYPE_SEMAPHORE)
 
-struct vn_device_memory {
-   struct vn_object_base base;
-
-   VkDeviceSize size;
-
-   /* non-NULL when suballocated */
-   struct vn_device_memory *base_memory;
-   /* non-NULL when mappable or external */
-   struct vn_renderer_bo *base_bo;
-   VkDeviceSize base_offset;
-
-   VkDeviceSize map_end;
-};
-VK_DEFINE_NONDISP_HANDLE_CASTS(vn_device_memory,
-                               base.base,
-                               VkDeviceMemory,
-                               VK_OBJECT_TYPE_DEVICE_MEMORY)
-
 struct vn_event {
    struct vn_object_base base;
 };
diff --git a/src/virtio/vulkan/vn_device_memory.c 
b/src/virtio/vulkan/vn_device_memory.c
new file mode 100644
index 00000000000..4d529617bb6
--- /dev/null
+++ b/src/virtio/vulkan/vn_device_memory.c
@@ -0,0 +1,420 @@
+/*
+ * Copyright 2019 Google LLC
+ * SPDX-License-Identifier: MIT
+ *
+ * based in part on anv and radv which are:
+ * Copyright © 2015 Intel Corporation
+ * Copyright © 2016 Red Hat.
+ * Copyright © 2016 Bas Nieuwenhuizen
+ */
+
+#include "vn_device_memory.h"
+
+#include "venus-protocol/vn_protocol_driver_device_memory.h"
+
+#include "vn_device.h"
+
+/* device memory commands */
+
+static VkResult
+vn_device_memory_simple_alloc(struct vn_device *dev,
+                              uint32_t mem_type_index,
+                              VkDeviceSize size,
+                              struct vn_device_memory **out_mem)
+{
+   const VkAllocationCallbacks *alloc = &dev->base.base.alloc;
+
+   struct vn_device_memory *mem =
+      vk_zalloc(alloc, sizeof(*mem), VN_DEFAULT_ALIGN,
+                VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
+   if (!mem)
+      return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+   vn_object_base_init(&mem->base, VK_OBJECT_TYPE_DEVICE_MEMORY, &dev->base);
+   mem->size = size;
+
+   VkDeviceMemory mem_handle = vn_device_memory_to_handle(mem);
+   VkResult result = vn_call_vkAllocateMemory(
+      dev->instance, vn_device_to_handle(dev),
+      &(const VkMemoryAllocateInfo){
+         .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+         .allocationSize = size,
+         .memoryTypeIndex = mem_type_index,
+      },
+      NULL, &mem_handle);
+   if (result != VK_SUCCESS) {
+      vk_free(alloc, mem);
+      return result;
+   }
+
+   const VkPhysicalDeviceMemoryProperties *mem_props =
+      &dev->physical_device->memory_properties.memoryProperties;
+   const VkMemoryType *mem_type = &mem_props->memoryTypes[mem_type_index];
+   result = vn_renderer_bo_create_gpu(dev->instance->renderer, mem->size,
+                                      mem->base.id, mem_type->propertyFlags,
+                                      0, &mem->base_bo);
+   if (result != VK_SUCCESS) {
+      vn_async_vkFreeMemory(dev->instance, vn_device_to_handle(dev),
+                            mem_handle, NULL);
+      vk_free(alloc, mem);
+      return result;
+   }
+   vn_instance_roundtrip(dev->instance);
+
+   *out_mem = mem;
+
+   return VK_SUCCESS;
+}
+
+static void
+vn_device_memory_simple_free(struct vn_device *dev,
+                             struct vn_device_memory *mem)
+{
+   const VkAllocationCallbacks *alloc = &dev->base.base.alloc;
+
+   if (mem->base_bo)
+      vn_renderer_bo_unref(mem->base_bo);
+
+   vn_async_vkFreeMemory(dev->instance, vn_device_to_handle(dev),
+                         vn_device_memory_to_handle(mem), NULL);
+   vn_object_base_fini(&mem->base);
+   vk_free(alloc, mem);
+}
+
+void
+vn_device_memory_pool_fini(struct vn_device *dev, uint32_t mem_type_index)
+{
+   struct vn_device_memory_pool *pool = &dev->memory_pools[mem_type_index];
+   if (pool->memory)
+      vn_device_memory_simple_free(dev, pool->memory);
+   mtx_destroy(&pool->mutex);
+}
+
+static VkResult
+vn_device_memory_pool_grow_locked(struct vn_device *dev,
+                                  uint32_t mem_type_index,
+                                  VkDeviceSize size)
+{
+   struct vn_device_memory *mem;
+   VkResult result =
+      vn_device_memory_simple_alloc(dev, mem_type_index, size, &mem);
+   if (result != VK_SUCCESS)
+      return result;
+
+   struct vn_device_memory_pool *pool = &dev->memory_pools[mem_type_index];
+   if (pool->memory) {
+      const bool bo_destroyed = vn_renderer_bo_unref(pool->memory->base_bo);
+      pool->memory->base_bo = NULL;
+
+      /* we use pool->memory's base_bo to keep it alive */
+      if (bo_destroyed)
+         vn_device_memory_simple_free(dev, pool->memory);
+   }
+
+   pool->memory = mem;
+   pool->used = 0;
+
+   return VK_SUCCESS;
+}
+
+static VkResult
+vn_device_memory_pool_alloc(struct vn_device *dev,
+                            uint32_t mem_type_index,
+                            VkDeviceSize size,
+                            struct vn_device_memory **base_mem,
+                            struct vn_renderer_bo **base_bo,
+                            VkDeviceSize *base_offset)
+{
+   /* We should not support suballocations because apps can do better and we
+    * also don't know the alignment requirements.  But each BO takes up a
+    * precious KVM memslot currently and some CTS tests exhausts them...
+    */
+   const VkDeviceSize pool_size = 16 * 1024 * 1024;
+   const VkDeviceSize pool_align = 4096; /* XXX */
+   struct vn_device_memory_pool *pool = &dev->memory_pools[mem_type_index];
+
+   assert(size <= pool_size);
+
+   mtx_lock(&pool->mutex);
+
+   if (!pool->memory || pool->used + size > pool_size) {
+      VkResult result =
+         vn_device_memory_pool_grow_locked(dev, mem_type_index, pool_size);
+      if (result != VK_SUCCESS) {
+         mtx_unlock(&pool->mutex);
+         return result;
+      }
+   }
+
+   /* we use base_bo to keep base_mem alive */
+   *base_mem = pool->memory;
+   *base_bo = vn_renderer_bo_ref(pool->memory->base_bo);
+
+   *base_offset = pool->used;
+   pool->used += align64(size, pool_align);
+
+   mtx_unlock(&pool->mutex);
+
+   return VK_SUCCESS;
+}
+
+static void
+vn_device_memory_pool_free(struct vn_device *dev,
+                           struct vn_device_memory *base_mem,
+                           struct vn_renderer_bo *base_bo)
+{
+   /* we use base_bo to keep base_mem alive */
+   if (vn_renderer_bo_unref(base_bo))
+      vn_device_memory_simple_free(dev, base_mem);
+}
+
+VkResult
+vn_AllocateMemory(VkDevice device,
+                  const VkMemoryAllocateInfo *pAllocateInfo,
+                  const VkAllocationCallbacks *pAllocator,
+                  VkDeviceMemory *pMemory)
+{
+   struct vn_device *dev = vn_device_from_handle(device);
+   const VkAllocationCallbacks *alloc =
+      pAllocator ? pAllocator : &dev->base.base.alloc;
+
+   const VkPhysicalDeviceMemoryProperties *mem_props =
+      &dev->physical_device->memory_properties.memoryProperties;
+   const VkMemoryType *mem_type =
+      &mem_props->memoryTypes[pAllocateInfo->memoryTypeIndex];
+   const VkImportMemoryFdInfoKHR *import_info =
+      vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_FD_INFO_KHR);
+   const VkExportMemoryAllocateInfo *export_info =
+      vk_find_struct_const(pAllocateInfo->pNext, EXPORT_MEMORY_ALLOCATE_INFO);
+   if (export_info && !export_info->handleTypes)
+      export_info = NULL;
+
+   const bool need_bo =
+      (mem_type->propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) ||
+      import_info || export_info;
+   const bool suballocate =
+      need_bo && !pAllocateInfo->pNext &&
+      !(mem_type->propertyFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) &&
+      pAllocateInfo->allocationSize <= 64 * 1024;
+
+   struct vn_device_memory *mem =
+      vk_zalloc(alloc, sizeof(*mem), VN_DEFAULT_ALIGN,
+                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+   if (!mem)
+      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+   vn_object_base_init(&mem->base, VK_OBJECT_TYPE_DEVICE_MEMORY, &dev->base);
+   mem->size = pAllocateInfo->allocationSize;
+
+   VkDeviceMemory mem_handle = vn_device_memory_to_handle(mem);
+   VkResult result;
+   if (import_info) {
+      struct vn_renderer_bo *bo;
+      result = vn_renderer_bo_create_dmabuf(
+         dev->instance->renderer, pAllocateInfo->allocationSize,
+         import_info->fd, mem_type->propertyFlags,
+         export_info ? export_info->handleTypes : 0, &bo);
+      if (result != VK_SUCCESS) {
+         vk_free(alloc, mem);
+         return vn_error(dev->instance, result);
+      }
+
+      /* TODO create host-side memory from bo->res_id */
+      result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
+      if (result != VK_SUCCESS) {
+         vn_renderer_bo_unref(bo);
+         vk_free(alloc, mem);
+         return vn_error(dev->instance, result);
+      }
+
+      mem->base_bo = bo;
+   } else if (suballocate) {
+      result = vn_device_memory_pool_alloc(
+         dev, pAllocateInfo->memoryTypeIndex, mem->size, &mem->base_memory,
+         &mem->base_bo, &mem->base_offset);
+      if (result != VK_SUCCESS) {
+         vk_free(alloc, mem);
+         return vn_error(dev->instance, result);
+      }
+   } else {
+      result = vn_call_vkAllocateMemory(dev->instance, device, pAllocateInfo,
+                                        NULL, &mem_handle);
+      if (result != VK_SUCCESS) {
+         vk_free(alloc, mem);
+         return vn_error(dev->instance, result);
+      }
+   }
+
+   if (need_bo && !mem->base_bo) {
+      result = vn_renderer_bo_create_gpu(
+         dev->instance->renderer, mem->size, mem->base.id,
+         mem_type->propertyFlags, export_info ? export_info->handleTypes : 0,
+         &mem->base_bo);
+      if (result != VK_SUCCESS) {
+         vn_async_vkFreeMemory(dev->instance, device, mem_handle, NULL);
+         vk_free(alloc, mem);
+         return vn_error(dev->instance, result);
+      }
+      vn_instance_roundtrip(dev->instance);
+   }
+
+   *pMemory = mem_handle;
+
+   return VK_SUCCESS;
+}
+
+void
+vn_FreeMemory(VkDevice device,
+              VkDeviceMemory memory,
+              const VkAllocationCallbacks *pAllocator)
+{
+   struct vn_device *dev = vn_device_from_handle(device);
+   struct vn_device_memory *mem = vn_device_memory_from_handle(memory);
+   const VkAllocationCallbacks *alloc =
+      pAllocator ? pAllocator : &dev->base.base.alloc;
+
+   if (!mem)
+      return;
+
+   if (mem->base_memory) {
+      vn_device_memory_pool_free(dev, mem->base_memory, mem->base_bo);
+   } else {
+      if (mem->base_bo)
+         vn_renderer_bo_unref(mem->base_bo);
+      vn_async_vkFreeMemory(dev->instance, device, memory, NULL);
+   }
+
+   vn_object_base_fini(&mem->base);
+   vk_free(alloc, mem);
+}
+
+uint64_t
+vn_GetDeviceMemoryOpaqueCaptureAddress(
+   VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo *pInfo)
+{
+   struct vn_device *dev = vn_device_from_handle(device);
+   struct vn_device_memory *mem = vn_device_memory_from_handle(pInfo->memory);
+
+   assert(!mem->base_memory);
+   return vn_call_vkGetDeviceMemoryOpaqueCaptureAddress(dev->instance, device,
+                                                        pInfo);
+}
+
+VkResult
+vn_MapMemory(VkDevice device,
+             VkDeviceMemory memory,
+             VkDeviceSize offset,
+             VkDeviceSize size,
+             VkMemoryMapFlags flags,
+             void **ppData)
+{
+   struct vn_device *dev = vn_device_from_handle(device);
+   struct vn_device_memory *mem = vn_device_memory_from_handle(memory);
+
+   void *ptr = vn_renderer_bo_map(mem->base_bo);
+   if (!ptr)
+      return vn_error(dev->instance, VK_ERROR_MEMORY_MAP_FAILED);
+
+   mem->map_end = size == VK_WHOLE_SIZE ? mem->size : offset + size;
+
+   *ppData = ptr + mem->base_offset + offset;
+
+   return VK_SUCCESS;
+}
+
+void
+vn_UnmapMemory(VkDevice device, VkDeviceMemory memory)
+{
+}
+
+VkResult
+vn_FlushMappedMemoryRanges(VkDevice device,
+                           uint32_t memoryRangeCount,
+                           const VkMappedMemoryRange *pMemoryRanges)
+{
+   for (uint32_t i = 0; i < memoryRangeCount; i++) {
+      const VkMappedMemoryRange *range = &pMemoryRanges[i];
+      struct vn_device_memory *mem =
+         vn_device_memory_from_handle(range->memory);
+
+      const VkDeviceSize size = range->size == VK_WHOLE_SIZE
+                                   ? mem->map_end - range->offset
+                                   : range->size;
+      vn_renderer_bo_flush(mem->base_bo, mem->base_offset + range->offset,
+                           size);
+   }
+
+   return VK_SUCCESS;
+}
+
+VkResult
+vn_InvalidateMappedMemoryRanges(VkDevice device,
+                                uint32_t memoryRangeCount,
+                                const VkMappedMemoryRange *pMemoryRanges)
+{
+   for (uint32_t i = 0; i < memoryRangeCount; i++) {
+      const VkMappedMemoryRange *range = &pMemoryRanges[i];
+      struct vn_device_memory *mem =
+         vn_device_memory_from_handle(range->memory);
+
+      const VkDeviceSize size = range->size == VK_WHOLE_SIZE
+                                   ? mem->map_end - range->offset
+                                   : range->size;
+      vn_renderer_bo_invalidate(mem->base_bo,
+                                mem->base_offset + range->offset, size);
+   }
+
+   return VK_SUCCESS;
+}
+
+void
+vn_GetDeviceMemoryCommitment(VkDevice device,
+                             VkDeviceMemory memory,
+                             VkDeviceSize *pCommittedMemoryInBytes)
+{
+   struct vn_device *dev = vn_device_from_handle(device);
+   struct vn_device_memory *mem = vn_device_memory_from_handle(memory);
+
+   assert(!mem->base_memory);
+   vn_call_vkGetDeviceMemoryCommitment(dev->instance, device, memory,
+                                       pCommittedMemoryInBytes);
+}
+
+VkResult
+vn_GetMemoryFdKHR(VkDevice device,
+                  const VkMemoryGetFdInfoKHR *pGetFdInfo,
+                  int *pFd)
+{
+   struct vn_device *dev = vn_device_from_handle(device);
+   struct vn_device_memory *mem =
+      vn_device_memory_from_handle(pGetFdInfo->memory);
+
+   assert(!mem->base_memory && mem->base_bo);
+   *pFd = vn_renderer_bo_export_dmabuf(mem->base_bo);
+   if (*pFd < 0)
+      return vn_error(dev->instance, VK_ERROR_TOO_MANY_OBJECTS);
+
+   return VK_SUCCESS;
+}
+
+VkResult
+vn_GetMemoryFdPropertiesKHR(VkDevice device,
+                            VkExternalMemoryHandleTypeFlagBits handleType,
+                            int fd,
+                            VkMemoryFdPropertiesKHR *pMemoryFdProperties)
+{
+   struct vn_device *dev = vn_device_from_handle(device);
+
+   struct vn_renderer_bo *bo;
+   VkResult result = vn_renderer_bo_create_dmabuf(dev->instance->renderer, 0,
+                                                  fd, 0, handleType, &bo);
+   if (result != VK_SUCCESS)
+      return vn_error(dev->instance, result);
+
+   /* TODO call into the host with bo->res_id */
+   result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
+
+   vn_renderer_bo_unref(bo);
+
+   return result;
+}
diff --git a/src/virtio/vulkan/vn_device_memory.h 
b/src/virtio/vulkan/vn_device_memory.h
new file mode 100644
index 00000000000..1d980765c59
--- /dev/null
+++ b/src/virtio/vulkan/vn_device_memory.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019 Google LLC
+ * SPDX-License-Identifier: MIT
+ *
+ * based in part on anv and radv which are:
+ * Copyright © 2015 Intel Corporation
+ * Copyright © 2016 Red Hat.
+ * Copyright © 2016 Bas Nieuwenhuizen
+ */
+
+#ifndef VN_DEVICE_MEMORY_H
+#define VN_DEVICE_MEMORY_H
+
+#include "vn_common.h"
+
+struct vn_device_memory_pool {
+   mtx_t mutex;
+   struct vn_device_memory *memory;
+   VkDeviceSize used;
+};
+
+struct vn_device_memory {
+   struct vn_object_base base;
+
+   VkDeviceSize size;
+
+   /* non-NULL when suballocated */
+   struct vn_device_memory *base_memory;
+   /* non-NULL when mappable or external */
+   struct vn_renderer_bo *base_bo;
+   VkDeviceSize base_offset;
+
+   VkDeviceSize map_end;
+};
+VK_DEFINE_NONDISP_HANDLE_CASTS(vn_device_memory,
+                               base.base,
+                               VkDeviceMemory,
+                               VK_OBJECT_TYPE_DEVICE_MEMORY)
+
+void
+vn_device_memory_pool_fini(struct vn_device *dev, uint32_t mem_type_index);
+
+#endif /* VN_DEVICE_MEMORY_H */
diff --git a/src/virtio/vulkan/vn_image.c b/src/virtio/vulkan/vn_image.c
index 0b183f0dbb8..b6b675a97d6 100644
--- a/src/virtio/vulkan/vn_image.c
+++ b/src/virtio/vulkan/vn_image.c
@@ -16,6 +16,7 @@
 #include "venus-protocol/vn_protocol_driver_sampler_ycbcr_conversion.h"
 
 #include "vn_device.h"
+#include "vn_device_memory.h"
 
 /* image commands */
 

_______________________________________________
mesa-commit mailing list
mesa-commit@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-commit

Reply via email to