mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-29 03:40:10 +01:00
lavapipe: Add android platform integration
Allow lavapipe to be loaded by the Android vulkan loader. Also provides window system integration through the `VK_ANDROID_native_buffer` extension. Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29344>
This commit is contained in:
parent
cfd897bae0
commit
0dce939e6d
6 changed files with 249 additions and 5 deletions
177
src/gallium/frontends/lavapipe/lvp_android.c
Normal file
177
src/gallium/frontends/lavapipe/lvp_android.c
Normal file
|
|
@ -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 <lvp_private.h>
|
||||
#include <hardware/gralloc.h>
|
||||
|
||||
#if ANDROID_API_LEVEL >= 26
|
||||
#include <hardware/gralloc1.h>
|
||||
#endif
|
||||
|
||||
#include <hardware/hardware.h>
|
||||
#include <hardware/hwvulkan.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
|
@ -50,6 +50,10 @@
|
|||
#include <sys/resource.h>
|
||||
#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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 = []
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue