mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-22 08:48:07 +02:00
AHB image layout initialization is deferred until dedicated memory import time. During vkCreateImage, only a stub is created just like aliased ANB image since the layout has to be retrieved from the AHB. Reviewed-by: Lucas Fryzek <lfryzek@igalia.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40426>
220 lines
7.6 KiB
C
220 lines
7.6 KiB
C
/*
|
|
* Copyright © 2024, Google Inc.
|
|
*
|
|
* 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 <hardware/gralloc.h>
|
|
|
|
#if ANDROID_API_LEVEL >= 26
|
|
#include <hardware/gralloc1.h>
|
|
#include <vndk/hardware_buffer.h>
|
|
#endif
|
|
|
|
#include <vulkan/vk_android_native_buffer.h>
|
|
|
|
#include "util/libsync.h"
|
|
#include "util/os_file.h"
|
|
#include "util/libsync.h"
|
|
|
|
#include "vk_fence.h"
|
|
#include "vk_semaphore.h"
|
|
#include "vk_android.h"
|
|
|
|
#include "lvp_private.h"
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
|
lvp_GetSwapchainGrallocUsageANDROID(VkDevice device_h,
|
|
VkFormat format,
|
|
VkImageUsageFlags imageUsage,
|
|
int *grallocUsage)
|
|
{
|
|
*grallocUsage = GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_OFTEN;
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
#if ANDROID_API_LEVEL >= 26
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
|
lvp_GetSwapchainGrallocUsage2ANDROID(VkDevice device_h,
|
|
VkFormat format,
|
|
VkImageUsageFlags imageUsage,
|
|
VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,
|
|
uint64_t *grallocConsumerUsage,
|
|
uint64_t *grallocProducerUsage)
|
|
{
|
|
*grallocConsumerUsage = 0;
|
|
*grallocProducerUsage = GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN | GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN;
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
#endif
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
|
lvp_AcquireImageANDROID(VkDevice _device,
|
|
VkImage image,
|
|
int nativeFenceFd,
|
|
VkSemaphore semaphore,
|
|
VkFence fence)
|
|
{
|
|
VK_FROM_HANDLE(vk_device, vk_device, _device);
|
|
VkResult result = VK_SUCCESS;
|
|
|
|
if(nativeFenceFd >= 0)
|
|
{
|
|
sync_wait(nativeFenceFd, -1);
|
|
close(nativeFenceFd);
|
|
}
|
|
|
|
if(fence != VK_NULL_HANDLE)
|
|
{
|
|
VK_FROM_HANDLE(vk_fence, vk_fence, fence);
|
|
result = vk_sync_signal(vk_device, &vk_fence->permanent, 0);
|
|
}
|
|
|
|
if(result == VK_SUCCESS && semaphore != VK_NULL_HANDLE)
|
|
{
|
|
VK_FROM_HANDLE(vk_semaphore, vk_semaphore, semaphore);
|
|
result = vk_sync_signal(vk_device, &vk_semaphore->permanent, 0);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
|
lvp_QueueSignalReleaseImageANDROID(VkQueue _queue,
|
|
uint32_t waitSemaphoreCount,
|
|
const VkSemaphore *pWaitSemaphores,
|
|
VkImage image,
|
|
int *pNativeFenceFd)
|
|
{
|
|
VK_FROM_HANDLE(vk_queue, queue, _queue);
|
|
struct vk_device *device = queue->base.device;
|
|
|
|
device->dispatch_table.QueueWaitIdle(_queue);
|
|
|
|
*pNativeFenceFd = -1;
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
VkResult
|
|
lvp_import_ahb_memory(struct lvp_device *device,
|
|
const VkMemoryAllocateInfo *alloc_info,
|
|
struct lvp_device_memory *mem)
|
|
{
|
|
const VkMemoryDedicatedAllocateInfo *dedicated_info =
|
|
vk_find_struct_const(alloc_info->pNext, MEMORY_DEDICATED_ALLOCATE_INFO);
|
|
if (dedicated_info && dedicated_info->image != VK_NULL_HANDLE) {
|
|
VK_FROM_HANDLE(lvp_image, image, dedicated_info->image);
|
|
VkResult result;
|
|
|
|
VkImageDrmFormatModifierExplicitCreateInfoEXT eci;
|
|
VkSubresourceLayout layouts[LVP_MAX_PLANE_COUNT];
|
|
result = vk_android_get_ahb_layout(mem->vk.ahardware_buffer, &eci,
|
|
layouts, LVP_MAX_PLANE_COUNT);
|
|
if (result != VK_SUCCESS)
|
|
return result;
|
|
|
|
image->vk.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
|
|
const uint32_t queue_family_index = 0;
|
|
const VkImageCreateInfo create_info = {
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
|
.pNext = &eci,
|
|
.flags = image->vk.create_flags,
|
|
.imageType = image->vk.image_type,
|
|
.format = image->vk.format,
|
|
.extent = image->vk.extent,
|
|
.mipLevels = image->vk.mip_levels,
|
|
.arrayLayers = image->vk.array_layers,
|
|
.samples = image->vk.samples,
|
|
.tiling = image->vk.tiling,
|
|
.usage = image->vk.usage,
|
|
.sharingMode = image->vk.sharing_mode,
|
|
.queueFamilyIndexCount = 1,
|
|
.pQueueFamilyIndices = &queue_family_index,
|
|
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
|
};
|
|
result = lvp_image_init(device, image, &create_info);
|
|
if (result != VK_SUCCESS)
|
|
return result;
|
|
}
|
|
|
|
const native_handle_t *handle =
|
|
AHardwareBuffer_getNativeHandle(mem->vk.ahardware_buffer);
|
|
int dma_buf = (handle && handle->numFds) ? handle->data[0] : -1;
|
|
if (dma_buf < 0)
|
|
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
|
|
|
|
uint64_t size;
|
|
if (!device->pscreen->import_memory_fd(device->pscreen, dma_buf, &mem->pmem,
|
|
&size, true))
|
|
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
|
|
|
|
mem->vk.size = size;
|
|
mem->map = device->pscreen->map_memory(device->pscreen, mem->pmem);
|
|
mem->memory_type = LVP_DEVICE_MEMORY_TYPE_DMA_BUF;
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
VkResult
|
|
lvp_bind_anb_memory(struct lvp_device *device,
|
|
const VkBindImageMemoryInfo *bind_info)
|
|
{
|
|
VK_FROM_HANDLE(lvp_image, image, bind_info->image);
|
|
|
|
/* ANB info is the only addition here. Fish it out and strip the pNext. */
|
|
const VkNativeBufferANDROID *anb_info =
|
|
vk_find_struct_const(bind_info->pNext, NATIVE_BUFFER_ANDROID);
|
|
assert(anb_info);
|
|
VkNativeBufferANDROID local_anb_info = *anb_info;
|
|
local_anb_info.pNext = NULL;
|
|
|
|
/* We can use the common vk_image info to reconstruct the VkImageCreateInfo
|
|
* for deferred layouting and the ANB memory import. This step can be lossy
|
|
* for some hw drivers but is fine for lavapipe.
|
|
*/
|
|
const uint32_t queue_family_index = 0;
|
|
const VkImageCreateInfo create_info = {
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
|
.pNext = &local_anb_info,
|
|
.flags = image->vk.create_flags,
|
|
.imageType = image->vk.image_type,
|
|
.format = image->vk.format,
|
|
.extent = image->vk.extent,
|
|
.mipLevels = image->vk.mip_levels,
|
|
.arrayLayers = image->vk.array_layers,
|
|
.samples = image->vk.samples,
|
|
.tiling = image->vk.tiling,
|
|
.usage = image->vk.usage,
|
|
.sharingMode = image->vk.sharing_mode,
|
|
.queueFamilyIndexCount = 1,
|
|
.pQueueFamilyIndices = &queue_family_index,
|
|
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
|
};
|
|
|
|
VkResult result = lvp_image_init(device, image, &create_info);
|
|
if (result != VK_SUCCESS)
|
|
return result;
|
|
|
|
return vk_android_import_anb(&device->vk, &create_info, &device->vk.alloc,
|
|
&image->vk);
|
|
}
|