Opengles(android)and vulkan(unity) interoperation

809 阅读2分钟

背景

android(gles)侧的OES纹理内容如何同步到Unityvulkan)的Texture2D里

oes纹理是gles的概念,当untiy的渲染实现为vulkan时,Texture2D.GetNativePtr()返回的是VKImage,不再是gles的GLuint(TextureObject)。

问题归纳为如何把gles的Texture绘制到Unity vulkan上(VKImage 作为 gles的RT)。

交互原理

本质是共享内存的方式,按业务需求,流程梳理为:

  • vulkan侧创建纹理的内存,然后export
  • gles侧import vulkan的memory object
  • gles侧写入内容到共享内存。

原理概念图:

image.png

关键障碍点

  • 确认gles的EXT_external_objects,对android os,ndk版本等要求是否符合 pico

  • 确认unity的vulkan实现是否开启了扩展能力:VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME等

  • 目前unity c#层的Texture2D,只能拿到VKImage, 需要确认是否能拿到VkDeviceMemory等

任务拆分:

  • Unity 开启vulkan的扩展VK_KHR_external_memory(技术手段为调用hook的vkCreateDevice,把扩展塞进去)

    • 需要hook vkCreateDevice,unity editor测试通过
    • hook vkCreateDevice,编译so,真机设备测试
  • unity侧export vkDeviceMemory(binded with vkImage)

  • gles侧import mem obj。

  • 上一步的Texture作为RT,把anroid oes纹理绘制上去。

一些记录

unity默认,一些扩展未开启:

image

坑1:

不要完全相信unity文档,2021文档如下:

image

实际测试,跟前缀没有关系(2021),只跟startup onload,和编辑器重开有关。

坑2:

测试发现aar勾选load on startup,并不会预加载so,只有把aar中的so裸露出来,勾选load on startup才生效。

因此目前测试流程:

  1. 编译aar

  2. copy到unity plugin下,解开aar

  3. 勾选so的load on startup

  4. 导出gradle 工程

  5. Copy .mp4到 gradle工程的asset目录下

  6. 打包

技术demo

android上播放一个mp4的视频流,输出到unity的vulkan app里

Ref:

VK_KHR_external_memory: registry.khronos.org/vulkan/spec…

EXT_external_objects: registry.khronos.org/OpenGL/exte…

Unity vulkan扩展关闭?:github.com/asus4/tf-li…

Android api 28,os9.0:

gl & vulkan interop: eleni.mutantstargoat.com/hikiko/vk-g…

Unity NativeRenderingPlugin: github.com/Unity-Techn…

Unity vulkan开启扩展VK_KHR_external_memory:forum.unity.com/threads/ena…

Vulkan specs: registry.khronos.org/vulkan/spec…

External Memory and Synchronization:github.com/KhronosGrou…

Vulkan to gles: github.com/keith2018/S…

AHardwareBuffer:stackoverflow.com/questions/5…

Opencl interop vulkan for android: github.com/KhronosGrou…