内容提要
本文介绍在Android Adreno GPU上实现Vulkan与OpenCL直接共享GPU内存的完整流程:通过opaque fd导出/导入内存,缓冲区和线性平铺图像使用通用句柄,最优平铺图像需高通Vulkan opaque fd扩展;同步使用一次性sync fd信号量,每个跨API同步点都需重新导出导入;还需用队列族所有权屏障和OpenCL获取/释放命令转移访问权,并匹配设备与驱动UUID。
延伸解读
内存共享方案的选择依据
文章指出,通用 opaque fd 适用于缓冲区和线性平铺图像,但最优平铺图像的布局由实现定义,仅凭 fd 无法描述,因此需要高通专有的 Vulkan opaque fd 扩展。Android Hardware Buffer 和 DMA-BUF 是其他可选方案,但前者依赖 Android 原生机制,后者更适用于系统底层管线。开发者应根据资源类型和跨平台需求选择,而非默认使用通用句柄。
同步机制的一次性特性
sync fd 是用于单个同步点的 Linux sync-file/Android fence 载荷,导入后不会在 Vulkan 与 OpenCL 信号量对象之间建立永久关联。每次跨 API 交接都必须重新导出和导入 sync fd,这与信号量 opaque fd 的持久关联模型不同。文章强调,若误用持久化假设,可能导致同步失效或未定义行为。
所有权转移与执行顺序的分离
Vulkan 队列族所有权屏障和 OpenCL 的获取/释放命令仅确立接收方 API 对共享资源的访问权,并不保证 Vulkan 与 OpenCL 工作之间的执行先后。外部信号量负责安排执行顺序。开发者需同时处理两者:先通过屏障转移所有权,再通过信号量同步执行,缺一不可。
运行时能力查询的必要性
文章提示,所述配置通常适用于 Snapdragon 8 Elite Gen 5 及后续产品,但实际支持情况取决于设备和驱动。应用应以运行时能力查询结果为准,包括外部内存/信号量扩展支持、句柄类型可用性以及设备与驱动 UUID 匹配。仅匹配设备 UUID 不足以保证 opaque fd 兼容性,还需比较驱动 UUID。
Q&A
在Android Adreno GPU上,Vulkan和OpenCL共享内存时,缓冲区和线性平铺图像应该用哪种句柄?最优平铺图像又该用哪种?
缓冲区和线性平铺图像可以使用通用 opaque fd 句柄(CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR)。最优平铺图像必须使用高通专有的 CL_EXTERNAL_MEMORY_HANDLE_VULKAN_OPAQUE_FD_QCOM,因为通用句柄无法可靠推断最优平铺布局,可能导致未定义行为。
为什么在Adreno上导入最优平铺Vulkan图像时不能使用通用opaque fd句柄?
在Adreno上,通用opaque fd句柄(CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR)通常被列为假设线性图像,OpenCL会将导入的图像视为线性平铺。若用于最优平铺Vulkan图像,Vulkan和OpenCL可能以不同方式解释同一块内存,导致未定义行为。高通Vulkan opaque fd句柄允许OpenCL推断Vulkan图像的格式和内部布局,从而避免不匹配。
Vulkan与OpenCL之间使用sync fd信号量同步时,为什么每个同步点都需要重新导出和导入?
sync fd是一次性载荷,用于单个同步点的Linux sync-file/Android fence。导入它不会在Vulkan和OpenCL的信号量对象之间建立永久关联,而是转移当前的等待/已发出信号状态。一旦导出,导出方应视为已消耗。因此每个跨API同步点都需要导出新的sync fd并重新导入。
在渲染循环中,Vulkan和OpenCL之间转移共享内存访问权需要哪些具体操作?
Vulkan使用队列族所有权屏障:释放时设置srcQueueFamilyIndex为Vulkan队列族,dstQueueFamilyIndex为VK_QUEUE_FAMILY_EXTERNAL;获取时反向设置。OpenCL使用clEnqueueAcquireExternalMemObjectsKHR获取对象,使用后调用clEnqueueReleaseExternalMemObjectsKHR释放。这些操作确立访问权,但执行顺序由外部信号量保证。
如何确保Vulkan和OpenCL指向同一个物理GPU并兼容opaque fd?
需要比较Vulkan的VkPhysicalDeviceIDProperties中的deviceUUID和driverUUID,与OpenCL的cl_khr_device_uuid扩展提供的CL_DEVICE_UUID_KHR和CL_DRIVER_UUID_KHR。仅匹配设备UUID只能确认是同一个GPU,不足以保证opaque fd兼容性,必须同时匹配驱动UUID。
使用高通Vulkan opaque fd扩展导入最优平铺图像时,OpenCL端有哪些特殊规则?
使用CL_EXTERNAL_MEMORY_HANDLE_VULKAN_OPAQUE_FD_QCOM时:cl_image_desc必须与Vulkan图像匹配;行间距和切片间距必须为零;图像类型必须为CL_MEM_OBJECT_IMAGE2D、CL_MEM_OBJECT_IMAGE2D_ARRAY或CL_MEM_OBJECT_IMAGE3D;Vulkan/OpenCL格式配对必须列在扩展规范中;不支持部分驻留的Vulkan图像;创建cl_mem时image_format必须为nullptr。
在Vulkan→OpenCL→Vulkan工作流中,每帧需要执行哪些步骤?
每帧步骤:1) Vulkan提交生产者工作和释放所有权屏障,并发出VK到CL信号量;2) 导出sync fd;3) OpenCL重新导入fd;4) OpenCL等待信号量;5) 获取共享对象;6) 派发内核;7) 释放共享对象;8) 发出CL到VK信号量;9) clFlush;10) 导出CL到VK的sync fd;11) Vulkan导入fd;12) Vulkan提交获取所有权屏障和消费者工作,并等待信号量。