Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android demo 6 HardwareImage对应的Image(绑定到openGL ES的纹理)是如何更新的 #8

Closed
paul1992li opened this issue Feb 22, 2022 · 3 comments

Comments

@paul1992li
Copy link

paul1992li commented Feb 22, 2022

本人的理解是 VkOutputLayer的inTex[0] 作为输入的Vulkan管线的绘制结果,需要1. blit到HardwareImage的image用于OpenGL ES对应的surfaceView的展示 2. bilt到vulkan SurfaceView对应的ANativeWindow的present的Image
第2步的逻辑已经清楚了,不知道第1步怎么做的 我看到OnCommand的blit不是每次都调用但是Opengl ES对应的SurfaceView上屏结果每次都有更新,希望解答下这块儿逻辑
非常感谢 ,学习中,这个工程很强大!!!

@paul1992li paul1992li changed the title demo 6 HardwareImage对应的Image(绑定到openGL ES的纹理)是如何更新的 Android demo 6 HardwareImage对应的Image(绑定到openGL ES的纹理)是如何更新的 Feb 22, 2022
@xxxzhou
Copy link
Owner

xxxzhou commented Feb 23, 2022

@paul1992li 你看下https://zhuanlan.zhihu.com/p/302285687 这里能帮你不.
其opengl es在android现阶段有更完善的UI界面支持,在android界面GLVideoRender继承于GLSurfaceView.Renderer,在每次onDrawFrame阶段会去把vulkan管线计算结果通过HardwareImage复制给对应的opengl es texture.

@paul1992li
Copy link
Author

paul1992li commented Feb 23, 2022

好像有点理解了,VulkanWindow和VkpipeGraph用了同一个环境,但是渲染和上屏处理是隔离的(各自vkQueueSubmit执行指令),所以两部分又是独立的,实际的渲染处理在VkpipeGraph中。
VkpipeGraph创建OpenGL ES和Vulkan的共享:

  1. VKVideoRender绑定的SurfaceView的surface获取对应的ANativeWindow,并以此创建Vulkan的渲染环境
  2. VkOutputLayer创建HardwareImage,申请Android的AHardwareBuffer,并以此创建VkBuffer同时新建VkImage(类型为VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID而非Linux的VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT)
  3. 通过eglMakeCurrent获取当前vulkan渲染环境对应的eglContext及其display等,并基于该context创建EGLImage(EGLImageKHR),也即将VkpipeGraph的绘制结果最终输出到
  4. GLVideoRender将其申请的textureId(有绑定到业务层的FBO),通过bindGL调用glEGLImageTargetTexture2DOES绑定到3中生成的EGLImageKHR,使得当前EGL & vulkan渲染环境下存在vkImage-AHardwareBuffer-openglES texture的共享关系

GLVideoRender绑定的SurfaceView的Surface上屏:

  1. FFmpeg获取一帧后执行一次VkpipeGraph的指令执行周期
  2. 指令执行完成后,绘制结果渲染到EGLImageKHR绑定的AHardwareBuffer上,也即渲染到GLVideoRender传入的纹理上
  3. GLVideoRender(实现GLSurfaceView.Renderer接口)已经将自己注册到GLSurfaceView,也即Android系统的绘制周期会触发GLVideoRender的onDrawFrame回调实现(理论上频率是系统的FPS,和解帧频率不一致),回调内将会将2.中纹理对应的的FBO glBlitFramebuffer到SurfaceView对应的FBO上,后续Android系统具体调度合成SurfaceView数据完成上屏

VKVideoRender绑定的SurfaceView的surface数据上屏:

  1. FFmpeg获取到一帧后,执行一次VulkanWindow的指令执行周期
  2. 该周期内将VkpipeGraph渲染执行中间结果(VKOutputLayer的intexs[0].vkImage)blit到ANativeWindow绑定的即将上屏的vkImage上(Surface通常持有Android三缓冲GraphicsBuffer)
  3. 指令提交后有执行 vkQueuePresentKHR, 从而将刚才完成渲染的帧上屏

最后有个问题点需要确认下
1. VkpipeGraph每次执行完vkQueueSubmit后,绘制结果是写入到vkImage-AHardwareBuffer-openglES吗?对EGL和Vulkan的关系有点懵
2. 为什么在bindVk函数内initContext后,在makeCurrent之前调用saveContext,理论上初始化context和后续eglCreateImageKHR都在一个线程调用,不存在context切换的问题吧
image

@xxxzhou
Copy link
Owner

xxxzhou commented Feb 24, 2022

@paul1992li 其实你应该把渲染给vulkan/opengl es分开看,在win平台,还有渲染给dx11了,后面的几个android大demo,我都是直接只渲染给opengl es,没有vulkan窗口了.
渲染给vulkan窗口,就是你看到的VulkanWindow那些,和HardwareImage无关,ffmpeg解码后运算得到结果,然后等到VulkanWindow窗口刷新拿到这个结果,注意这个结果在解码线程与窗口刷新线程相关的barrier就行,如果不需要渲染给vulkan窗口,这些逻辑都是不执行的.
而渲染给opengl es,就需要用HardwareImage里的那一套,相关的EGL也只在这用,如果不渲染给opengl es,就不需要,EGL创建一个opengl es窗口环境,一样是解码一个线程,EGL自身窗口刷新一个线程,二者通过HardwareImage负责vulkan/opengl es纹理交互.
makeCurrent/saveContext 这些是我集成到UE4的一个尝试,尝试用纹理交互方式直接写到UE4里的纹理 ,但是现在只在win平台/dx11成功了,android下还是不行,是一次失败的尝试,demo里可以不要的,但是代码先放这里,注释掉在所有demo也是正常的.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants