diff --git a/src/gallium/frontends/lavapipe/lvp_android.c b/src/gallium/frontends/lavapipe/lvp_android.c new file mode 100644 index 00000000000..cc5cbb655de --- /dev/null +++ b/src/gallium/frontends/lavapipe/lvp_android.c @@ -0,0 +1,177 @@ +/* + * 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 +#include + +#if ANDROID_API_LEVEL >= 26 +#include +#endif + +#include +#include + +#include "util/libsync.h" +#include "util/os_file.h" +#include "util/libsync.h" + +#include "vk_fence.h" +#include "vk_semaphore.h" + +static int +lvp_hal_open(const struct hw_module_t *mod, + const char *id, + struct hw_device_t **dev); +static int +lvp_hal_close(struct hw_device_t *dev); + +static_assert(HWVULKAN_DISPATCH_MAGIC == ICD_LOADER_MAGIC, ""); + +struct hw_module_methods_t HAL_MODULE_METHODS = { + .open = lvp_hal_open, +}; + +PUBLIC struct hwvulkan_module_t HAL_MODULE_INFO_SYM = { + .common = + { + .tag = HARDWARE_MODULE_TAG, + .module_api_version = HWVULKAN_MODULE_API_VERSION_0_1, + .hal_api_version = HARDWARE_MAKE_API_VERSION(1, 0), + .id = HWVULKAN_HARDWARE_MODULE_ID, + .name = "Lavapipe Vulkan HAL", + .author = "Mesa3D", + .methods = &HAL_MODULE_METHODS, + }, +}; + +static int +lvp_hal_open(const struct hw_module_t *mod, + const char *id, + struct hw_device_t **dev) +{ + assert(mod == &HAL_MODULE_INFO_SYM.common); + assert(strcmp(id, HWVULKAN_DEVICE_0) == 0); + + hwvulkan_device_t *hal_dev = (hwvulkan_device_t *) malloc(sizeof(*hal_dev)); + if (!hal_dev) + return -1; + + *hal_dev = (hwvulkan_device_t){ + .common = + { + .tag = HARDWARE_DEVICE_TAG, + .version = HWVULKAN_DEVICE_API_VERSION_0_1, + .module = &HAL_MODULE_INFO_SYM.common, + .close = lvp_hal_close, + }, + .EnumerateInstanceExtensionProperties = + lvp_EnumerateInstanceExtensionProperties, + .CreateInstance = lvp_CreateInstance, + .GetInstanceProcAddr = lvp_GetInstanceProcAddr, + }; + + *dev = &hal_dev->common; + return 0; +} + +static int +lvp_hal_close(struct hw_device_t *dev) +{ + /* hwvulkan.h claims that hw_device_t::close() is never called. */ + return -1; +} + +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; +} diff --git a/src/gallium/frontends/lavapipe/lvp_device.c b/src/gallium/frontends/lavapipe/lvp_device.c index 7b9a61bca71..844ffb644c2 100644 --- a/src/gallium/frontends/lavapipe/lvp_device.c +++ b/src/gallium/frontends/lavapipe/lvp_device.c @@ -50,6 +50,10 @@ #include #endif +#if DETECT_OS_ANDROID +#include "vk_android.h" +#endif + #if defined(VK_USE_PLATFORM_WAYLAND_KHR) || \ defined(VK_USE_PLATFORM_WIN32_KHR) || \ defined(VK_USE_PLATFORM_XCB_KHR) || \ @@ -249,6 +253,9 @@ static const struct vk_device_extension_table lvp_device_extensions_supported = .EXT_line_rasterization = true, .EXT_robustness2 = true, .AMDX_shader_enqueue = true, +#if DETECT_OS_ANDROID + .ANDROID_native_buffer = true, +#endif .GOOGLE_decorate_string = true, .GOOGLE_hlsl_functionality1 = true, .NV_device_generated_commands = true, @@ -1271,12 +1278,14 @@ lvp_physical_device_init(struct lvp_physical_device *device, lvp_get_features(device, &device->vk.supported_features); lvp_get_properties(device, &device->vk.properties); +#ifdef LVP_USE_WSI_PLATFORM result = lvp_init_wsi(device); if (result != VK_SUCCESS) { vk_physical_device_finish(&device->vk); vk_error(instance, result); goto fail; } +#endif return VK_SUCCESS; fail: @@ -1286,7 +1295,9 @@ lvp_physical_device_init(struct lvp_physical_device *device, static void VKAPI_CALL lvp_physical_device_finish(struct lvp_physical_device *device) { +#ifdef LVP_USE_WSI_PLATFORM lvp_finish_wsi(device); +#endif device->pscreen->destroy(device->pscreen); vk_physical_device_finish(&device->vk); } @@ -1342,6 +1353,10 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateInstance( // VG(VALGRIND_CREATE_MEMPOOL(instance, 0, false)); +#if DETECT_OS_ANDROID + vk_android_init_ugralloc(); +#endif + *pInstance = lvp_instance_to_handle(instance); return VK_SUCCESS; @@ -1356,6 +1371,10 @@ VKAPI_ATTR void VKAPI_CALL lvp_DestroyInstance( if (!instance) return; +#if DETECT_OS_ANDROID + vk_android_destroy_ugralloc(); +#endif + pipe_loader_release(&instance->devs, instance->num_devices); vk_instance_finish(&instance->vk); @@ -2231,6 +2250,11 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_BindImageMemory2(VkDevice _device, VkBindMemoryStatusKHR *status = (void*)vk_find_struct_const(&pBindInfos[i], BIND_MEMORY_STATUS_KHR); bool did_bind = false; + if (!mem) { + continue; + } + +#ifdef LVP_USE_WSI_PLATFORM vk_foreach_struct_const(s, bind_info->pNext) { switch (s->sType) { case VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR: { @@ -2256,6 +2280,7 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_BindImageMemory2(VkDevice _device, break; } } +#endif if (!did_bind) { uint64_t offset_B = 0; diff --git a/src/gallium/frontends/lavapipe/lvp_formats.c b/src/gallium/frontends/lavapipe/lvp_formats.c index 3a80dbd2950..132c34376ce 100644 --- a/src/gallium/frontends/lavapipe/lvp_formats.c +++ b/src/gallium/frontends/lavapipe/lvp_formats.c @@ -467,7 +467,7 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_GetPhysicalDeviceImageFormatProperties2( } } - if (external_info && external_info->handleType != 0) { + if (external_info && external_info->handleType != 0 && external_props) { VkExternalMemoryFeatureFlagBits flags = 0; VkExternalMemoryHandleTypeFlags export_flags = 0; VkExternalMemoryHandleTypeFlags compat_flags = 0; diff --git a/src/gallium/frontends/lavapipe/lvp_image.c b/src/gallium/frontends/lavapipe/lvp_image.c index bd994f7cb2b..0522ed17f97 100644 --- a/src/gallium/frontends/lavapipe/lvp_image.c +++ b/src/gallium/frontends/lavapipe/lvp_image.c @@ -27,6 +27,7 @@ #include "util/u_surface.h" #include "pipe/p_state.h" #include "frontend/winsys_handle.h" +#include "vk_android.h" static VkResult lvp_image_create(VkDevice _device, @@ -36,12 +37,14 @@ lvp_image_create(VkDevice _device, { LVP_FROM_HANDLE(lvp_device, device, _device); struct lvp_image *image; - + VkResult result = VK_SUCCESS; + bool android_surface = false; + const VkSubresourceLayout *layouts = NULL; + uint64_t modifier; assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO); #ifdef HAVE_LIBDRM unsigned num_layouts = 1; - const VkSubresourceLayout *layouts = NULL; enum pipe_format pipe_format = lvp_vk_format_to_pipe_format(pCreateInfo->format); const VkImageDrmFormatModifierExplicitCreateInfoEXT *modinfo = (void*)vk_find_struct_const(pCreateInfo->pNext, IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT); @@ -59,6 +62,8 @@ lvp_image_create(VkDevice _device, mesa_loge("lavapipe: planar drm formats are not supported"); return VK_ERROR_OUT_OF_DEVICE_MEMORY; } + + modifier = DRM_FORMAT_MOD_LINEAR; #endif image = vk_image_create(&device->vk, pCreateInfo, alloc, sizeof(*image)); @@ -73,6 +78,20 @@ lvp_image_create(VkDevice _device, image->disjoint = image->plane_count > 1 && (pCreateInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT); + /* This section is removed by the optimizer for non-ANDROID builds */ + VkImageDrmFormatModifierExplicitCreateInfoEXT eci; + VkSubresourceLayout a_plane_layouts[LVP_MAX_PLANE_COUNT]; + if (vk_image_is_android_native_buffer(&image->vk)) { + result = vk_android_get_anb_layout( + pCreateInfo, &eci, a_plane_layouts, LVP_MAX_PLANE_COUNT); + if (result != VK_SUCCESS) + goto fail; + + modifier = eci.drmFormatModifier; + layouts = a_plane_layouts; + android_surface = true; + } + const struct vk_format_ycbcr_info *ycbcr_info = vk_format_get_ycbcr_info(pCreateInfo->format); for (unsigned p = 0; p < image->plane_count; p++) { @@ -141,7 +160,7 @@ lvp_image_create(VkDevice _device, template.nr_storage_samples = pCreateInfo->samples; #ifdef HAVE_LIBDRM - if (modinfo && pCreateInfo->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) { + if (android_surface || (modinfo && pCreateInfo->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)) { struct winsys_handle whandle; whandle.type = WINSYS_HANDLE_TYPE_UNBACKED; whandle.layer = 0; @@ -152,7 +171,7 @@ lvp_image_create(VkDevice _device, whandle.image_stride = layouts[p].depthPitch; image->offset = layouts[p].offset; whandle.format = pCreateInfo->format; - whandle.modifier = DRM_FORMAT_MOD_LINEAR; + whandle.modifier = modifier; image->planes[p].bo = device->pscreen->resource_from_handle(device->pscreen, &template, &whandle, @@ -172,9 +191,23 @@ lvp_image_create(VkDevice _device, image->size += image->planes[p].size; } + + /* This section is removed by the optimizer for non-ANDROID builds */ + if (vk_image_is_android_native_buffer(&image->vk)) { + result = vk_android_import_anb(&device->vk, pCreateInfo, alloc, + &image->vk); + if (result != VK_SUCCESS) { + mesa_logw("Failed to import memory"); + goto fail; + } + } + *pImage = lvp_image_to_handle(image); return VK_SUCCESS; +fail: + vk_image_destroy(&device->vk, alloc, &image->vk); + return result; } struct lvp_image * @@ -216,11 +249,13 @@ lvp_CreateImage(VkDevice device, const VkAllocationCallbacks *pAllocator, VkImage *pImage) { +#if !DETECT_OS_ANDROID const VkImageSwapchainCreateInfoKHR *swapchain_info = vk_find_struct_const(pCreateInfo->pNext, IMAGE_SWAPCHAIN_CREATE_INFO_KHR); if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE) return lvp_image_from_swapchain(device, pCreateInfo, swapchain_info, pAllocator, pImage); +#endif return lvp_image_create(device, pCreateInfo, pAllocator, pImage); } diff --git a/src/gallium/frontends/lavapipe/lvp_private.h b/src/gallium/frontends/lavapipe/lvp_private.h index 0c3f2596d6a..1d0fc14feeb 100644 --- a/src/gallium/frontends/lavapipe/lvp_private.h +++ b/src/gallium/frontends/lavapipe/lvp_private.h @@ -100,6 +100,8 @@ extern "C" { #define MAX_PER_STAGE_DESCRIPTOR_UNIFORM_BLOCKS 8 #define MAX_DGC_STREAMS 16 #define MAX_DGC_TOKENS 16 +/* Currently lavapipe does not support more than 1 image plane */ +#define LVP_MAX_PLANE_COUNT 1 #ifdef _WIN32 #define lvp_printflike(a, b) @@ -775,6 +777,7 @@ bool lvp_nir_lower_sparse_residency(struct nir_shader *shader); enum vk_cmd_type lvp_nv_dgc_token_to_cmd_type(const VkIndirectCommandsLayoutTokenNV *token); + #ifdef __cplusplus } #endif diff --git a/src/gallium/frontends/lavapipe/meson.build b/src/gallium/frontends/lavapipe/meson.build index 67e78b0c1cb..06adc5aa8ca 100644 --- a/src/gallium/frontends/lavapipe/meson.build +++ b/src/gallium/frontends/lavapipe/meson.build @@ -37,6 +37,10 @@ liblvp_files = files( 'lvp_ray_tracing_pipeline.c', 'lvp_wsi.c') +if with_platform_android + liblvp_files += 'lvp_android.c' +endif + lvp_deps = [] lvp_flags = []