异步场景加载基本流程验证完成。
此方法理论上只需要使用3个Vulkan的指令队列。
对于移动平台上的Vulkan,指令队列数量极少,比如Adreno640只有3个指令队列可用。所以理论上这一设计也适合目前的移动平台使用。
(1) graphic_queue:用于完成当前场景的渲染。
(2) load_queue:用于在当前场景异步加载结点,或更新结点资源,比如ui贴图,文本。
(3) back_load_queue:用于在独立的线程中异步加载完整场景。
加载场景分别使用load_queue和back_load_queue两个队列的原因是,在back_load_queue加载场景时,当前场景可能需要load_queue来异步更新ui之类的资源。
graphic_queue只进行渲染相关或耗时较短的工作,对于耗时可能跨越多帧的操作,比如ui贴图更新,文本更新,通过异步任务队列,交由load_queue处理,load_queue处理完成后,通过同步任务通知graphic_queue,完成资源切换。
graphic_queue使用线程池中的多个用于执行单帧任务(Frame Graph)的线程并行记录渲染指令。
视频解释:
(1)
对于异步加载一个完整的场景
通过按钮广播点击消息给脚本管线对象
脚本管线对象调用脚本,通过viewer对象创建新线程加载场景。
新线程加载场景完成后,通过无锁队列添加同步任务到同步任务队列。
在同步任务中反转场景(反转场景实际上只是管线对象内部很少几个变量的交换,耗时极小),进入刚刚加载的场景。(同步任务,确保线程安全,并且如果没有需要执行的同步任务,几乎不存在计算代价)
(2)
对于同一场景添加单个或少量结点,载入量较小,没必要单独开一个线程,将加载任务放入viewer对象初始化时创建的用于执行跨越多帧的小任务的异步任务队列,加载结点完成后,通过无锁队列添加同步任务到同步任务队列 ,在同步任务(只是简单的几个变量交换,耗时极小)中将结点安全地放入当前场景。
对于类似UI贴图或文本的更新,通过方法2进行。
https://www.zhihu.com/video/1174439628005359616