0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Vulkan图形处理过程中遇到的问题

Dbwd_Imgtec 来源:Imagination Tech 作者:Imagination Tech 2020-09-04 11:45 次阅读

利用乒乓机制的交错队列减少风险

在本篇文章中,我们将提到Vulkan 图形处理过程中夹杂计算任务时遇到的各式问题。为更准确地了解我们的话题,可查看文章第一部分。

第一部分概述了在Vulkan中如何使用barrier;具体来说,涉及图形→计算barrier,随后是一个中间帧计算→图形barrier。这会严重削弱GPU任务调度能力,并导致暂停,降低性能。为此我们给出了在多种资源配置情况下的不同解决方案。

体系架构级方法

"算法"优先的方法是手动使任务交错:也就是说,以我们希望的顺序提交任务,并使它们在GPU 上执行。这会生成正确结果,也为我们提供足够的可控性。在该情况下,首先为上一"逻辑"帧提交计算任务BN-1(注意缺少早期图形任务),然后提交当前帧AN的早期图形任务。随后,将提交计算/图形Barrier,接下来提交上一帧CN-1的后期图形任务,最后提交图形/计算Barrier。

这种方法会产生良好的结果,但会有损帧分离性,使维护更加困难。它对逻辑资源的需求将加倍,因为至少部分后期帧的操作代码需要比早期帧操作先调度。此外,会引入一个额外的滞后帧。 其执行过程如下: 帧N: BN-1→AN→ 计算/图形barrier→CN-1→图形/计算barrier→提交N-1 帧N+1: BN→ AN+1→ 计算/图形barrier→CN→图形/计算barrier→提交N 这将允许BN-1/AN重叠。 听起来很复杂,而且也确实如此:计算多个帧操作通常需要大量的记录。但是,如果在此方案中任务封装的不错,至少一定程度上会缓解该问题。但是,如果复杂性更高时(即更复杂的猜测计算→barrier→图形→barrier→计算→barrier→图形工作负载),它仍然可能崩溃。在任何情况下,为降低不断增加的CPU 端复杂性成本,可以定制解决方案。

每个任务使用不同队列

另一个有效的解决方案是使用不同的队列,并在每个队列提交帧的不同部分:每个早期计算、后期计算、早期图形和后期图形提交到自己的队列,任务间连接使用信号量而非barrier。例如 ,PowerVR开发套件中的Vulkan粒子系统就是采用该方法,在对应的专用队列中提交所有计算。

但在我看来,该方案有其挑战性,它比交错帧更好,因为它允许 GPU 处理自己的问题,而不会弄乱引擎的非 API 部分。在我看来,它也是第一个"真正的"解决方案。类似于上述方案,它至少会缓解部分问题。在讨论其自身体系结构上的计算后处理时,Arm 在其社区网站上也将目光投向该方案。但是,它又取决于某些特定任务的重叠,一般来说,需要仔细生成大量的信号量,并且借助于队列优先级,这些增加了部分复杂性,但也为您提供了另一个控制向量。在多个交错计算/图形任务的情况下,它也可能不能完全按照我们预期的方式工作。该方案非常有效,可能将其与别的方案结合是个好思路。 我们已经找到了值得推荐的不同方案。

更简单、通用的方案:乒乓机制的交错队列

我们相信我们可以更简单、更有效的方式来完成计算。为此,我们需要从全局上考虑我们的最终目标:我们需要在没有Vulkan 规范介入的前提下,使 GPU 能够在连续两个帧中交替工作。

Vulkan 规范团队中的精明者可能已经意识到,barrier是始终指向单个队列的构造器。 PowerVR(和许多其它设备)设备可能会暴露多个相同/可互换的通用队列(图形+计算以及可能的呈现)。 因此,在这种情况下,为在不重新调整帧前提下避免跨帧同步,我们可以在不同队列中为每个帧提交负载。这将允许一个帧中的任何负载与下一帧中的任何负载交错执行,即使具有多个不同的图形、顶点和计算任务,因为它们在不同队列上显式执行,可以不受制于彼此的barrier。 简单来说:从同一队列源中创建两个相同的队列,然后对于每个帧,您提交负载到与上一队列不同的队列上。队列源很重要,因为它可以使您不必担心资源队列所有权等问题。 因此,帧提交过程如下: 帧 0:获取下一个图像→渲染 0(A0)→图形/计算barrier→计算0(B0)→计算/图形barrier→渲染0′(C0)→提交到队列0 →呈现到队列 0 帧 1:获取下一个图像→渲染 1A1→图形/计算barrier→计算1B1→计算/图形barrier→渲染1′C1→提交到队列1→呈现到队列1 帧 2:获取下一个图像→渲染2 A2→图形/计算barrier→计算2B2→计算/图形barrier→渲染2′C2→提交到队列0 →呈现到队列 0 帧 3:获取下一个图像→渲染 3A3→图形/计算barrier→计算3B3→计算/图形barrier→渲染3′C3→提交到队列1→呈现到队列1 ...等等。 那么,这行得通吗?而且,如果可以,其原因是什么? 确实可行。BN(当前帧计算)和 CN(当前帧的后期图形)之间的barrier将阻止 CN在BN完成之前启动,但不会阻止 AN+1(下一帧的早期图形)启动,因为它在与Barrier不同的队列上提交(一个额外的好处,由于队列不同,AN+1与CN不需要强制排序)。 此技术解决了问题的核心:应用程序设置的barrier,旨在在单个帧中等待风险的发生,不会导致后续帧之间的任务间等待。我发现它相当令人欣喜,而且是迄今为止最简单的可实现方案——只要您的通用队列源中有多个队列,就可以使用单个计数器(甚至是布尔类型)并交换每一帧,此时无需进一步修改:只要我们确保 CPU 资源得到正确管理(与单个队列相同),不须施加额外同步。 简而言之,由于每个连续帧都在不同的队列中提交,因此 GPU 可以自由地在帧之间并行调度任务,预期结果为 (CN+1) 在(AN) 完成之后开始执行。它可确保渲染器及其相应的调度程序始终繁忙,并且中间的计算不会串行化帧。 —————– 计算工作负载:B0B1 B2B3 B4B5 图形工作负载:A0 A1 C0 C1 A2 A3 C2 C3 A4 A5 C4 C5 ... 或(基本相同的效果)如下: 计算工作负载:B0 B1 B2 B3 B4 B5 图形工作负载:A0 A1 C0 A2 C1 A3 C2 A4 C3 A5 C4 C5 ...

解决方案:通过使用多个队列,可以在上一帧的早期任务之后安排下一帧的早期片段任务,与计算任务重叠以获得出色的效率增益 乍一看,这看起来可能很复杂,但实际很简单。无论如何,该图示告诉我们,GPU 正在处理一个帧(N)的计算,同时处理下一帧 (N+1) 的早期图形或上一帧的后期图形。

完全封装的情况是"相当不可能",它甚至没有必要达到这种水平的封装。但是,您应具备类似的特征,计算与顶点/片段任务一起调度,允许USC 加载使用尽可能多的容量。

其他的适用方案

通常,在任何存在barrier的情况下(而不仅仅是图形/计算/图形)时使用此技术是一个好思路。在任何情况下,它都不会有损性能,并且在--任何情况下调度器都具备更好的灵活性。调度器可能不需要额外的灵活性,但在任何情况下它都不会有损性能,而且增加的复杂性微不足道。

任何类型的barrier(包括图形/图形)都有可能损害 GPU 调度不同帧负载的能力并会导致暂停(顺便说一下,这是考虑使用barrier一个非常重要的原因,如果不考虑该因素,可以使用子类依赖性而非barrier)。计算示例非常重要,因为即使它们共享 PowerVR 上的执行内核、图形和计算部件,它们也在不同的数据主设备上工作,因此始终有些任务要并行执行,因此,如果可能,我们总是希望它们尽量重叠工作。但是,即使只是不同帧的图形负载交错执行,也通常允许您在顶点和片段任务之间获得更多的重叠,并确保 GPU 更好的饱和性。

因此,任何barrier情况都存在潜在风险,所以使用多个队列是备选。

注意事项:如何采用交错队列防止乱序

我们未能发现任何严重的不利条件。在不同帧之间使用不同的队列没有额外开销。我们确定的唯一限制很明显:同一队列源必须支持多个图形计算队列,不过,所有 PowerVR 设备都支持该特性。

我们能够识别的另一潜在问题是确保正确的呈现顺序。但是,交换链对象本身将确保这一点,因为图像以 FIFO 和邮箱呈现模式调用的 vkQueuePresent 顺序呈现。对于其它模式(例如即时),您可能需要确保当前操作正确同步,以便按顺序执行; 这也相当容易实现。 最后,如果设备强制采用单个呈现队列,您可以修改如下,最终只在单个队列上呈现: 帧 0:获取下一个图像→渲染 0→记录图形/计算barrier→计算0 →计算/图形barrier→渲染0′→提交到队列0 →呈现到队列 0 帧 1:获取下一个图像→渲染 1→记录图形/计算barrier→计算1→计算/图形barrier→渲染1′→提交到队列1 →呈现到队列0 帧 2:获取下一个图像→渲染2→记录图形/计算barrier→计算2→计算/图形barrier→渲染2′→提交到队列0 →呈现到队列 0 帧 3:获取下一个图像→渲染 3→记录图形/计算barrier→计算3→计算/图形barrier→渲染3′→提交到队列1 →呈现到队列0 ...等等。 它不仅利用了并行性,还确保了具有交换链"特殊"实现的驱动程序不会出现乱序帧呈现的风险。 简言之,我们完全可以放心的使用该技术。如果你发现了潜在的问题,请告诉我们。重要性能说明

需要提醒的是,PowerVR 调度时与 CPU 线程调度工作方式不同,因为后者需要昂贵的上下文切换并保存到主存——如果调度器在同一 USC 上并行执行两个任务,在大多数情况下,它们之间切换成本为零,因此每当需要等待操作时(例如内存访问),调度器都可以切换到另一个任务并隐藏内存操作延迟。这是我们性能得以提升的重要部分。

下面是我们需要澄清的:该技术主要不是填充可能出现空闲的不同硬件部分负载,我们试图做的是指导驱动程序正确调度负载,减少开销并隐藏延迟。PowerVR 是一个统一的体系结构,顶点、图形和计算任务都在同一个 USC 上执行。与在不同顶点和片段着色器内核单独执行的早期图形设备不同,100%性能提升是无法实现的。我们不是要填充空闲内核;只是要 GPU非空闲时, 所有USC 都在运行(不排除一些意外状况发生)。 最后,在仅有图形的负载中,还可能会遇到这样的情况,barrier会阻止不同帧之间的重叠。

未来工作

当您希望将不同的任务提交到不同的队列类型/源情况下,此技术可以而且将起作用。一个重要的免责声明是,该技术不会取代帧的不同负载使用不同队列的潜在好处——如本文及其他文章中所讨论到的,使用不同的专用队列(特别是使用不同的队列优先级来最小化帧延迟)。

因此,在这些情况下,可以使用相同的逻辑——唯一的区别是,您不会将一个队列分裂为两个队列,而是将所有(或大多数)使用barrier的队列复用。这可能并非所有队列,因此不能替代常识和良好设计。在某些体系结构中,您可能使用三个不同的队列,并且只需要将其中一个或者多个中的两个队列复用并进行乒乓操作。最重要的是在barrier旁边至少增加一个队列。 例如,假设一个专用计算队列与多个通用队列并存,此技术可能仍然有用。事实上,在多数的有趣场景下,拥有多组具有不同优先级的不同队列并且帧之间交换集,这可以提供惊人的精细控制和灵活性。 这种情况可能工作如下: (此处的队列 C2 是一个专用计算队列,队列 0 和队列 1 是我们要复用的通用队列): 帧 0:获取下一个图像→渲染 0 →提交到队列 0 →信号量给队列 2 →计算 0,提交到队列 C2→信号量给队列 0 →渲染0′→提交到队列 0→呈现给队列 0 帧1:获取下一个图像→渲染1→提交到队列 1→信号量给队列 2→计算 1,提交到队列 C2→信号量给队列 1→渲染1′→提交到队列 1→呈现给队列 1 帧2:获取下一个图像→渲染2→提交到队列 0 →信号量给队列 2 →计算 2,提交到队列 C2→信号量给队列 0 →渲染2′→提交到队列 0→呈现给队列 0 帧 3:获取下一个图像→渲染3→提交到队列1→信号量给队列 2 →计算 3,提交到队列 C2→信号量给队列 1→渲染3′→提交到队列 1→呈现给队列 1 帧 4:获取下一个图像→渲染4→提交到队列 0 →信号量给队列 2 →计算 4,提交到队列 C2→信号量给队列 0 →渲染4′→提交到队列 0→呈现给队列 0

同样,此处的多个图形队列是必要的,以允许在当前帧的第二次渲染之前调度连续帧的第一次渲染。

结论

我们向您展现了一个非常完整和通用的解决方案,用以解决常见但现实的难题。无论何时,尽可能为每帧使用多个队列,您可以无风险、更简单地获得惊人的性能提升。希望这将对您的项目有帮助!如果该技术确实帮助到您,欢迎向我们分享您的故事。

我们在 PowerVR SDK中的许多演示中都使用此技术,而且我们在编写后处理演示时也受到了启发,并使用了该技术。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • cpu
    cpu
    +关注

    关注

    68

    文章

    10442

    浏览量

    206564
  • 图形处理
    +关注

    关注

    0

    文章

    40

    浏览量

    13674
  • Vulkan
    +关注

    关注

    0

    文章

    28

    浏览量

    5644

原文标题:Vulkan同步机制和图形-计算-图形转换的风险(二)

文章出处:【微信号:Imgtec,微信公众号:Imagination Tech】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    使用FreeRTOS过程中如何退出Tickless?

    在使用FreeRTOS过程中,如果设置Tickless,那要怎么退出呢?进入Tickless模式的话应该是吧系统滴答中断给关闭了,如果我在没有外部中断的情况下,那系统是不是就不会唤醒了,百思不得其解,还望高人指点一二
    发表于 04-17 06:26

    ADC处理过程中的各个步骤

    在现实世界中,模拟信号具有不断变化的值,这些值来自各种来源和传感器,可以测量声音,光,温度或运动,许多数字系统通过测量来自这些传感器的模拟信号与环境相互作用。
    的头像 发表于 01-23 16:46 917次阅读
    ADC<b class='flag-5'>处理过程中</b>的各个步骤

    使用ADXL362的过程中遇到了ODR不准确的问题怎么解决?

    在使用ADXL362的过程中遇到了ODR不准确的问题,具体为: 1、3V电源供电,系统设置ADXL362 ODR为50Hz,采用FIFO Triggered Mode模式,64个点的FIFO
    发表于 12-29 07:05

    使用AD5293的过程中遇到的几个问题求解

    我在使用AD5293的过程中遇到了以下几个问题: 1.AD5293的VDD,VSS,VLOGIC引脚所连接的10uf的电容是有极性还是无极性的? 2.EXT_CAP引脚,在上电时对地电压应该是
    发表于 12-11 08:21

    在使用AD4114过程中遇到的问题,请帮忙解答

    哈罗 在使用AD4114的过程中遇到问题,请帮忙解答。多谢! 1.设置AD4114为Continuous Conversion Mode和Continuous Read Mode时,连续读回来通道数
    发表于 12-04 08:06

    PCB设计过程中常见问题汇总

    ;0.3mm,PCB制造过程中图形转移工序在显影后产生碎膜造成断线,提高加工难度。 8、多层板内层走线不合理。散热焊盘放到隔离带上,钻孔后容易出现不能连接的情况,隔离带设计有缺口,容易误解,隔离带设计太窄
    发表于 11-16 16:43

    矩阵按键在识别的过程中是否要进行消抖处理

    矩阵按键在识别的过程中是否要进行消抖处理
    发表于 10-11 06:30

    由Java改为 Kotlin过程中遇到的坑

    Kotlin 过程中遇到的坑和 Kotlin 的优缺点。 环境和版本 Eclipse Oxygen JDK 8 Kotlin 1.3.0 Gradle 4.6 SpringCloud
    的头像 发表于 09-30 16:51 455次阅读
    由Java改为 Kotlin<b class='flag-5'>过程中</b><b class='flag-5'>遇到</b>的坑

    工业一体机在安装过程中可能会遇到的问题

    工业一体机的安装并非只是一个简单的物理接口连接过程,我们可能会遇到以下几类问题:
    的头像 发表于 08-22 15:00 290次阅读
    工业一体机在安装<b class='flag-5'>过程中</b>可能会<b class='flag-5'>遇到</b>的问题

    在高频变压器生产过程中可能会遇到的问题及其解决办法

    在高频变压器生产过程中可能会遇到以下问题,并提供解决方法
    的头像 发表于 08-15 09:44 644次阅读

    如何在pcb设计过程中处理好扇热问题?

    介绍在PCB设计过程中处理扇热问题的方法和技巧,以帮助大家提高设计质量和性能。 首先,在处理扇热问题之前, 首先需要准确定义和确定热量产生源 。例如,处理器、功放器等特定组件通常会产生
    的头像 发表于 08-06 07:35 3161次阅读
    如何在pcb设计<b class='flag-5'>过程中</b><b class='flag-5'>处理</b>好扇热问题?

    SMT贴片加工过程中立碑现象的处理

    在PCBA加工行业中多数的pcba加工厂家都会遇到的不良现象,比如SMT贴片加工过程中片式元器件一端抬起,这种情况多有发生在小尺寸片式阻容元器件
    的头像 发表于 07-10 10:48 812次阅读

    利用3D可视化技术将污水处理过程以立体、形象的方式呈现

    随着科技的不断发展,3D可视化技术在各个领域得到了广泛应用。污水处理工艺流程展示是一个重要的环节,它可以让公众更加直观地了解污水处理过程,提高透明度并增加信任度。将3D可视化技术应用到污水处理
    的头像 发表于 06-16 15:16 334次阅读

    smt贴片加工过程中,误印锡膏如何妥善处理

    在smt贴片加工过程中,难免会遇到各种各样的问题。如果在加工过程中误印锡膏,如何妥善处理?以下是佳金源锡膏厂家讲解一下常用的锡膏清洗方法:出现误印锡膏后很多人第一反应是赶紧用刮板清除掉
    的头像 发表于 05-22 10:28 381次阅读
    smt贴片加工<b class='flag-5'>过程中</b>,误印锡膏如何妥善<b class='flag-5'>处理</b>?

    垃圾填埋场渗滤液厌氧处理过程中甲烷/硫化氢有毒气体监测

    少量的H2、H2S、NH3、硫醇、硫醚和微量的不饱和烃垃圾渗滤液处理厌氧工艺过程中会产生大量的沼气,通常1m³垃圾渗滤液会产生15~30m³的沼气。 由于垃圾渗滤液水质复杂,含有大量有机污染物,在垃圾渗滤液的处理过程中,为了保证
    的头像 发表于 05-19 10:17 640次阅读
    垃圾填埋场渗滤液厌氧<b class='flag-5'>处理过程中</b>甲烷/硫化氢有毒气体监测