atw算法为啥是做vr的核心呢听说oculus因为atw算法很棒而获得高额收购和三星的合作。( 二 )


解决什么问题呢?
ATW主要用来解决画面剧烈颤动(Judder)的问题。
为了生成一个感知真实的虚拟世界,显示屏上显示的图像必须在每一个VSYNC刷新时及时更新。可是,如果渲染图像花的时间太长,那么就会发生丢帧的现象,这时就会产生显示画面颤动。因为当没有新的图像渲染出来时,视频适配器就会把一次的图像显示在显示屏上。如果这时画面相对于眼睛是移动的,那么就会感觉的画面显示在了错误的位置。
ATW可以解决上述的画面颤动问题:如果渲染线程没有在VSYNC前及时提交被渲染的游戏帧,时间扭曲线程将中断渲染线程的渲染并扭曲上一次渲染线程提交的游戏帧;虽然时间扭曲线程新生成的游戏帧并不完全正确,但是它根据头部的旋转做了调整,所以相对于直接显示原来的游戏帧而言减少了颤动。
下面看一下如何实现ATW。
实现ATW有两个难点:
需要GPU硬件支持合理粒度的抢占需要操作系统和驱动支持GPU的抢占 【atw算法为啥是做vr的核心呢听说oculus因为atw算法很棒而获得高额收购和三星的合作。】 先来看一下第一点,为什么需要GPU硬件支持合理粒度的抢占呢?
ATW线程需要确保每一个VSYNC都要生成一个新的时间扭曲的帧;那么,倘若Rendering Thread没有及时渲染完成一帧画面,ATW 线程就需要中断Rendering Thread的渲染。
所以GPU硬件要提供两点:
1)支持抢占,就是ATW线程的优先级要高于 Rendering Thread的优先级;
2)粒度要尽可能的小;
目前一些GPU厂商和驱动支持 Batch 或 Drawcall 粒度的抢占。这种抢占粒度不够好,例如在极端的情况下,一个Drawcall伴随这复杂Shader运算很用以花费10ms的时间。其他一些GPU厂商和驱动支持 计算着色器的抢占,但需要厂商的特定扩展,以支持渲染与计算的抢占。如果ATW线程不能及时的抢占,将导致它不能在VSYNC之前扭曲生成一个新的帧,这样上一帧会显示出来,就会导致颤动现象。理想情况下,ATW线程能够任意的抢占并启动渲染,而不必关心渲染管线的状态。理论上,三角形的粒度抢占也是不够好的,因为我们不知道渲染一个三角形时使用一个复杂的shader需要花费多长时间。所以,GPU厂商一致在致力于实现更好的抢占。
然后看一下第二点,操作系统和驱动需要支持渲染抢占。
在Window8之前,WDDM(Windows Display Driver Model)支持“Batch Queue”粒度的有限制的抢占,“Batchs”是有图形驱动生成的。不幸的是,图形驱动倾向于积累大的批次从而提高渲染效率,这样对ATW线程的抢占就非常不好。
在Window8之后,WDDM1.2开始支持更好粒度的抢占。但是,目前这种抢占模式还没有被图形驱动普遍支持。渲染管线管理在Window10 和 DirectX12时有重要的提高,此时向开发者提供更底层的渲染控制。所以,ATW一段时间内仍然需要GPU厂商定制的驱动扩展。
下面的实现是个人推理的,如果有错误还请指正,哈!!! TODO:这里有张图片上传不上去,看我头像吧。悲剧
atw算法为啥是做vr的核心呢听说oculus因为atw算法很棒而获得高额收购和三星的合作。

如上图,Rendering Thread 在R1处开始渲染,到R2处渲染完成。ATW Thread 从A1处等待 Rendering Thread渲染,最迟在A2处开始执行渲染,在A3时渲染完成。
那么这里有几个问题:1. ATW Thread如何确保自己最迟在A2时开始渲染?
2. A2 到 A3 这段时间应该是多少比较合理?
解答问题:
1. ATW Thread 在 A1点调用 eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout) ; timeout 设置成 执行TW渲染所需要的时间(一般为2~3ms)。
ATW Thread 调用此函数之后,ATW Thread就会挂起,直到 timeout 超时或 被 Rendering Thread 调用 eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) 函数唤醒。


推荐阅读