背景
android(gles)侧的OES纹理内容如何同步到Unity(vulkan)的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侧写入内容到共享内存。
原理概念图:
关键障碍点
-
确认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默认,一些扩展未开启:
坑1:
不要完全相信unity文档,2021文档如下:
实际测试,跟前缀没有关系(2021),只跟startup onload,和编辑器重开有关。
坑2:
测试发现aar勾选load on startup,并不会预加载so,只有把aar中的so裸露出来,勾选load on startup才生效。
因此目前测试流程:
-
编译aar
-
copy到unity plugin下,解开aar
-
勾选so的load on startup
-
导出gradle 工程
-
Copy .mp4到 gradle工程的asset目录下
-
打包
技术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…