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