Edit

IABSD.fr/xenocara/lib/mesa/src/vulkan/runtime/vk_device_memory.c

Branch :

  • Show log

    Commit

  • Author : jsg
    Date : 2025-06-05 11:23:11
    Hash : 67d6f117
    Message : Import Mesa 25.0.7

  • lib/mesa/src/vulkan/runtime/vk_device_memory.c
  • /*
     * Copyright © 2023 Collabora, Ltd.
     *
     * Permission is hereby granted, free of charge, to any person obtaining a
     * copy of this software and associated documentation files (the "Software"),
     * to deal in the Software without restriction, including without limitation
     * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     * and/or sell copies of the Software, and to permit persons to whom the
     * Software is furnished to do so, subject to the following conditions:
     *
     * The above copyright notice and this permission notice (including the next
     * paragraph) shall be included in all copies or substantial portions of the
     * Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     * IN THE SOFTWARE.
     */
    
    #include "vk_device_memory.h"
    
    #include "vk_android.h"
    #include "vk_common_entrypoints.h"
    #include "vk_util.h"
    
    #if DETECT_OS_ANDROID && ANDROID_API_LEVEL >= 26
    #include <vndk/hardware_buffer.h>
    #endif
    
    void *
    vk_device_memory_create(struct vk_device *device,
                            const VkMemoryAllocateInfo *pAllocateInfo,
                            const VkAllocationCallbacks *alloc,
                            size_t size)
    {
       struct vk_device_memory *mem =
          vk_object_zalloc(device, alloc, size, VK_OBJECT_TYPE_DEVICE_MEMORY);
       if (mem == NULL)
          return NULL;
    
       assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
    
       mem->size = pAllocateInfo->allocationSize;
       mem->memory_type_index = pAllocateInfo->memoryTypeIndex;
    
       vk_foreach_struct_const(ext, pAllocateInfo->pNext) {
          switch (ext->sType) {
          case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO: {
             const VkExportMemoryAllocateInfo *export_info = (void *)ext;
             mem->export_handle_types = export_info->handleTypes;
             break;
          }
    
          case VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID: {
    #if DETECT_OS_ANDROID && ANDROID_API_LEVEL >= 26
             const VkImportAndroidHardwareBufferInfoANDROID *ahb_info = (void *)ext;
    
             assert(mem->import_handle_type == 0);
             mem->import_handle_type =
                VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
    
             /* From the Vulkan 1.3.242 spec:
              *
              *    "If the vkAllocateMemory command succeeds, the implementation
              *    must acquire a reference to the imported hardware buffer, which
              *    it must release when the device memory object is freed. If the
              *    command fails, the implementation must not retain a
              *    reference."
              *
              * We assume that if the driver fails to create its memory object,
              * it will call vk_device_memory_destroy which will delete our
              * reference.
              */
             AHardwareBuffer_acquire(ahb_info->buffer);
             mem->ahardware_buffer = ahb_info->buffer;
             break;
    #else
             unreachable("AHardwareBuffer import requires Android >= 26");
    #endif /* DETECT_OS_ANDROID && ANDROID_API_LEVEL >= 26 */
          }
    
          case VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR: {
             const VkImportMemoryFdInfoKHR *fd_info = (void *)ext;
             if (fd_info->handleType) {
                assert(fd_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
                       fd_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
                assert(mem->import_handle_type == 0);
                mem->import_handle_type = fd_info->handleType;
             }
             break;
          }
    
          case VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT: {
             const VkImportMemoryHostPointerInfoEXT *host_ptr_info = (void *)ext;
             if (host_ptr_info->handleType) {
                assert(host_ptr_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT ||
                       host_ptr_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT);
    
                assert(mem->import_handle_type == 0);
                mem->import_handle_type = host_ptr_info->handleType;
                mem->host_ptr = host_ptr_info->pHostPointer;
             }
             break;
          }
    
          case VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR: {
    #ifdef VK_USE_PLATFORM_WIN32_KHR
             const VkImportMemoryWin32HandleInfoKHR *w32h_info = (void *)ext;
             if (w32h_info->handleType) {
                assert(w32h_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT ||
                       w32h_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT ||
                       w32h_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT ||
                       w32h_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT ||
                       w32h_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT ||
                       w32h_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT);
                assert(mem->import_handle_type == 0);
                mem->import_handle_type = w32h_info->handleType;
             }
             break;
    #else
             unreachable("Win32 platform support disabled");
    #endif
          }
    
          case VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO: {
             const VkMemoryAllocateFlagsInfo *flags_info = (void *)ext;
             mem->alloc_flags = flags_info->flags;
             break;
          }
    
          default:
             break;
          }
       }
    
       /* From the Vulkan Specification 1.3.261:
        *
        *    VUID-VkMemoryAllocateInfo-allocationSize-07897
        *
        *   "If the parameters do not define an import or export operation,
        *   allocationSize must be greater than 0."
        */
       if (!mem->import_handle_type && !mem->export_handle_types)
          assert(pAllocateInfo->allocationSize > 0);
    
       /* From the Vulkan Specification 1.3.261:
        *
        *    VUID-VkMemoryAllocateInfo-allocationSize-07899
        *
        *    "If the parameters define an export operation and the handle type is
        *    not VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
        *    allocationSize must be greater than 0."
        */
        if (mem->export_handle_types &&
            mem->export_handle_types !=
              VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
          assert(pAllocateInfo->allocationSize > 0);
    
       if ((mem->export_handle_types &
            VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) &&
           mem->ahardware_buffer == NULL) {
          /* If we need to be able to export an Android hardware buffer but none
           * is provided as an import, create a new one.
           */
          mem->ahardware_buffer = vk_alloc_ahardware_buffer(pAllocateInfo);
          if (mem->ahardware_buffer == NULL) {
             vk_device_memory_destroy(device, alloc, mem);
             return NULL;
          }
       }
    
       return mem;
    }
    
    void
    vk_device_memory_destroy(struct vk_device *device,
                             const VkAllocationCallbacks *alloc,
                             struct vk_device_memory *mem)
    {
    
    #if DETECT_OS_ANDROID && ANDROID_API_LEVEL >= 26
       if (mem->ahardware_buffer)
          AHardwareBuffer_release(mem->ahardware_buffer);
    #endif /* DETECT_OS_ANDROID && ANDROID_API_LEVEL >= 26 */
    
       vk_object_free(device, alloc, mem);
    }
    
    #if DETECT_OS_ANDROID && ANDROID_API_LEVEL >= 26
    VkResult
    vk_common_GetMemoryAndroidHardwareBufferANDROID(
       VkDevice _device,
       const VkMemoryGetAndroidHardwareBufferInfoANDROID *pInfo,
       struct AHardwareBuffer **pBuffer)
    {
       VK_FROM_HANDLE(vk_device_memory, mem, pInfo->memory);
    
       /* Some quotes from Vulkan spec:
        *
        *    "If the device memory was created by importing an Android hardware
        *    buffer, vkGetMemoryAndroidHardwareBufferANDROID must return that same
        *    Android hardware buffer object."
        *
        *    "VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
        *    must have been included in VkExportMemoryAllocateInfo::handleTypes
        *    when memory was created."
        */
       if (mem->ahardware_buffer) {
          *pBuffer = mem->ahardware_buffer;
          /* Increase refcount. */
          AHardwareBuffer_acquire(*pBuffer);
          return VK_SUCCESS;
       }
    
       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
    }
    #endif