Vulkan 同步

前言

在前面的文章中,我们讲解了Vulkan的多线程设计理念,分析了其底层的机制。我们知道在Vulkan的设计中,尽量避免资源的同步竞争,但是在某些复杂场景和多线程优化过程中难免会遇到资源竞争的问题,这时候就需要同步机制来保证线程访问数据的安全性和一致性。

然而Vulkan认为资源读写所需要做的同步是应用程序的职责,其内部只提供了很少的隐式同步机制,其余的都需要在程序中显式地使用Vulkan中的同步机制来实现。

Vulkan同步基础

在Vulkan代码实现中,使用的同步命令会涉及如下代码:

VkPipelineStageFlags

Vulkan所有的命令都会在Pipeline上执行,只是不同类型的命令,它们的执行阶段是不同的。当我们在Vulkan中使用同步机制时,都是以流水线阶段为单位,即某个流水线阶段上执行的所有命令,会在当前阶段暂停,等待另一个流水线阶段上的所有命令在相应的阶段执行完全后,再开始执行。VkPipelineStageFlags就代表流水线阶段。

VkAccessFlags

Vulkan中的同步不仅控制操作执行的顺序,还要控制缓存的写回,即内存数据的同步,VkAccessFlags是为了控制流水线阶段对于内存的读写操作。

因为在CPU等存储器件为了读写性能都会分为多层缓存。多级缓存就会导致多线程读写数据的一致性问题,就需要有机制保证某一层缓存数据更新了需要同步到其他缓存上,比如MemoryBarrier,而所有的MemoryBarrier中也都会包含VkAccessFlags参数。

Vulkan所有的同步在全局上都应该认为是对一个Queue中的所有命令有效果。

Vulkan同步原语

Vulkan中主要有四种同步原语(synchronization primitives):

  •  Fences
    • 最粗粒度的同步原语,用于同步跨队列或跨粗粒度提交到单个队列的工作,目的是给CPU端提供一种方法,可以知道GPU或者其他Vulkan Device什么时候把提交的工作全部做完。类似Android的显示机制。

  • Semaphores

    • 颗粒度比Fences更小一点,通常用于不同Queue之间的数据同步操作

  • Events

    • 颗粒度更小,可以用于Command Buffer之间的同步工作。

  • Barriers

    • Vulkan流水线(Pipeline)阶段内用于内存访问管理和资源状态移动的同步机制。

Fence

如上介绍Fence是粗粒度的同步,它有两种状态——signaled和unsignaled。

在调用vkQueueSubmit时可以关联一个Fence,这样当Queue中的所有命令都被完成以后,Fence就会被设置成signaled的状态;

通过调用vKResetFences可以让一个Fence恢复成unsignaled的状态;

vkWaitForFences会让CPU原地阻塞,需要等待直到它关联的Fence变为signaled的状态,这样就可以实现在某个渲染队列内的所有任务被完成后,CPU再执行某些操作的同步场景。

Fence也具备内存数据同步的功能,但不需要开发者手动调用。在使用Fence时,如果它一旦被设置成signaled状态,那么使用这个Fence的Queue中的所有的命令如果涉及到了对内存的修改,后续的内存访问就一定会在signaled之前在Device上更新(注意只是在Device上更新,如果确保CPU也能够获取最新的值的话,就需要再用上其他的同步原语)。

Semaphore

Semaphore用于queue每次提交的一批命令之间的同步和Fence一样,它也有两种状态:signaled和unsignaled。

调用vkQueueSubmit提交命令时,会填充VkSubmitInfo结构,而这个结构体中需要设置pWaitSemaphores、pSignalSemaphores、pWaitDstStageMask。程序在执行到pWaitDstStageMask时要阻塞,直到等pWaitSemaphores所指向的所有Semaphore的状态变成signaled时才可以继续执行。本次提交的Command buffer执行结束后,pSignalSemaphores所指向的所有Semaphore的状态都会被设置成signaled。

注:vkQueueSubmit函数本身也隐含了一个内存数据的同步机制:就是CPU上所有的内存修改操作,都会在GPU读写之前,对GPU而言变成available的,并且对于所有后续在GPU上的MemoryAccess,它们都是visible的。

部分相关代码示例:

vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]);

Event

Event同样也具有两种状态——signaled和unsignaled,与Fence不同的是,它的状态改变既可以在CPU上完成,也可以在GPU上完成,并且它是一种细粒度的同步机制。注意:Event只能用在同队列的Command buffer间的同步。

在CPU侧可以调用vkSetEvent来使一个Event变成Signaled的状态;调用vkResetEvent来使一个Event恢复成Unsignaled的状态;调用vkGetEventStatus获取一个Event的当前状态,根据Event状态阻塞CPU运行。

GPU侧:通过vkCmdSetEvent命令来使得一个Event变成Signaled状态,此时该命令附加了一个操作执行同步:根据提交顺序,在该命令之前的所有命令都必须在Event设置Signaled状态之前完成。

通过vkCmdResetEvent命令来使得一个Event变成Unsignaled状态,此时该命令同样附加了一个操作执行同步:根据提交顺序,在该命令之前的所有命令都必须在Event设置Unsignaled状态之前完成。

相关代码:

Barrier

所有的同步原语中,Barrier的使用成本最高。Barrier用于显式地控制buffer或者image的访问范围,避免hazards(RaW,WaR,and WaW),保证数据一致性。

Barrier又分为pipeline barrier和memory barrier。

pipeline barrier

要开发者了解渲染管线的各个阶段,能清晰地把握管线中每个步骤对资源的读写顺序。

Vulkan中Pipline各阶段的定义:

  • TOP_OF_PIPE_BIT
  • DRAW_INDIRECT_BIT

  • VERTEX_INPUT_BIT

  • VERTEX_SHADER_BIT

  • TESSELLATION_CONTROL_SHADER_BIT

  • TESSELLATION_EVALUATION_SHADER_BIT

  • GEOMETRY_SHADER_BIT

  • FRAGMENT_SHADER_BIT

  • EARLY_FRAGMENT_TESTS_BIT

  • LATE_FRAGMENT_TESTS_BIT

  • COLOR_ATTACHMENT_OUTPUT_BIT

  • TRANSFER_BIT

  • COMPUTE_SHADER_BIT

  • BOTTOM_OF_PIPE_BIT

举一个简单的例子:

场景中有两个渲染管线P1 和 P2,P1会通过Vertex Shader往Command buffer写入顶点数据,P2需要在Compute Shader中使用这些数据。如果使用fence,P1的command提交后,P2通过fence确保P1的操作已经被全部执行完,再开始工作。但理论上P2只需要在Compute Shader阶段等待P1的顶点数据即可。

该场景优化可以用Barrier,只需要告诉Vulkan,我们在P2的Compute Shader阶段才需要等待P1 Vertex Shader里面的数据,其他阶段可以并行。

Memory Barrier

内存数据的同步需要使用Memory Barrier完成,Vulkan中有三种MemoryBarrier。

所有的MemoryBarrier都需要搭配PipelineBarrier或者Event使用。

隐藏的执行顺序

Vulkan是显式的,号称“没有秘密的API”。但是在多线程同步时,还是存在一些潜规则。在提隐式执行前,先来了解下提交顺序,它是Vulkan的隐式同步及用户的显式同步的前提。

  • 在CPU上通过多次vkQueueSubmit提交了一系列命令,这些命令的提交顺序为先提交的先行。
  • 同一个Queue中,一起提交的多个Command Buffer,按照下标顺序提交。

  • 同一个Command Buffer的操作,先提交的先行

了解了提交顺序后,我们来看下Vulkan中隐式的执行顺序,

  • Command Buffer中的Command,严格遵循提交顺序的,先记录的先执行。
  • ImageLayout的转移是通过ImageMemoryBarrier实现的,严格按照提交顺序执行。

  • 同一个Queue中,一起提交的多个Command Buffer,严格按照提交顺序执行

  • 先提交的Command Buffer先执行

总结

本篇文章讲了Vulkan中的同步机制,包含显示和隐藏的同步控制,只能感叹Vulkan的操作是真的繁琐,希望大家能在了解同步机制的情况下,实现出性能更极致的程序。

参考

Vulkan Specification

Yet another blog explaining Vulkan synchronization

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1540.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android 生成pdf文件

Android 生成pdf文件 1.使用官方的方式 使用官方的方式也就是PdfDocument类的使用 1.1 基本使用 /**** 将tv内容写入到pdf文件*/RequiresApi(api Build.VERSION_CODES.KITKAT)private void newPdf() {// 创建一个PDF文本对象PdfDocument document new PdfDocument();//创建…

SpringCloud(二)Eureka简介与依赖导入

一、Eureka Eureka能够自动注册并发现微服务,然后对服务的状态、信息进行集中管理,这样当我们需要获取其他服务的信息时,我们只需要向Eureka进行查询就可以了。 像这样的话,服务之间的强关联性就会被进一步削弱。 二、服务注册与…

详解GPT技术发展脉络

文章目录 前言关于本篇的分享内容大语言模型大模型语言模型 百花齐放TransformerAuto-RegressiveResnetLayer-NormMaskScaled Dot-Product AttentionMulti-Head AttenionSelf-AttentionPositional Encoding关于并行计算关于长程依赖Transformer演化 GPT SeriesGPT-1GPT-2GPT-3 …

aidl的学习(1)aidl中java.lang.RuntimeException: Didn‘t create service “XXX“

1、build中版本号为30及以上时&#xff0c;aidl无效&#xff0c;解决方案 ①在客户端的manifest.xml中添加一下代码&#xff0c;其中代码中的包名为服务端的包名 <manifest> ... <application> ....</application> <queries ><package android:na…

如何在 Ubuntu 20.04 桌面上启用/禁用 wayland

Wayland 是一种通信协议&#xff0c;指定显示服务器与其客户端之间的通信。 默认情况下&#xff0c;Ubuntu 20.04 桌面不会启动 Wayland&#xff0c;而是加载 Xorg 显示服务器X11。 在本教程中您将学习&#xff1a; 如何启用 Wayland如何禁用 Wayland 类别要求、约定或使用的…

【自动驾驶汽车量子群粒子过滤器】用于无人驾驶汽车列车定位的量子粒子滤波研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

web前端项目使用electron打包成跨平台桌面端程序(Windows)

文章目录 Electron是什么&#xff1f;快速入门基本使用要求从github下载一个开源项目执行启动脚本运行项目安装electron依赖包编写electron入口文件&#xff0c;在package.json中配置入口文件路径和electron执行脚本启动electron脚本&#xff0c;运行electron应用 应用打包Wind…

1.监控分布式--zabbix

文章目录 监控分布式-zabbix、prometheus概念工作原理功能组件部署zabbix安装Nginx和PHP环境部署数据库编码安装zabbix编译安装zabbix server客户端安装zabbix agent服务 监控分布式-zabbix、prometheus 利用一个优秀的监控软件&#xff0c;我们可以: 通过一个友好的界面进行…

简单爬虫项目练习

爬虫项目练习 前言任务基本爬虫框架URL管理器Html 下载器HTML 解析器数据存储器爬虫调度器效果分析 前言 自学&#xff0c;参考书籍为 Python爬虫开发与项目实战 &#xff0c;具体参考了该书的第六章。过程中出现两个问题&#xff1a; 在 Pycharm 上实现时发现有些库名更改及…

计算机网络——数据链路层

文章目录 **1 数据链路层的功能****1.1 为网络层提供服务****1.2 链路管理****1.3 帧定界&#xff0c;帧同步与透明传输****1.4 流量控制****1.5 差错控制** **2 组帧****2.1 字符计数法****2.2 字符填充的首尾定界符法****2.3 零比特填充的首尾标志法****2.4 违规编码法** **3…

10.6.5 【Linux】分区命令: split

如果你有文件太大&#xff0c;导致一些携带式设备无法复制的问题&#xff0c;split可以将一个大文件&#xff0c;依据文件大小或行数来分区&#xff0c;可以将大文件分区成为小文件&#xff0c;快速有效。 将文件分区的话&#xff0c;使用-b size来将一个分区的文件限制其大小&…

YOLOv8的目标对象的分类,分割,跟踪和姿态估计的多任务检测实践(Netron模型可视化)

YOLOv8是目前最新版本&#xff0c;在以前YOLO版本基础上建立并加入了一些新的功能&#xff0c;以进一步提高性能和灵活性&#xff0c;是目前最先进的模型。YOLOv8旨在快速&#xff0c;准确&#xff0c;易于使用&#xff0c;使其成为广泛的目标检测和跟踪&#xff0c;实例分割&a…

模拟行走机器人-python

leetcode第874题 链接https://leetcode.cn/problems/walking-robot-simulation 机器人在一个无限大小的 XY 网格平面上行走&#xff0c;从点 (0, 0) 处开始出发&#xff0c;面向北方。该机器人可以接收以下三种类型的命令 commands &#xff1a; -2 &#xff1a;向左转 90 度…

Hadoop——大数据生态体系详解

一.大数据概论 1.1 大数据概念 大数据&#xff08;big data&#xff09;&#xff1a;指无法在一定时间范围内用常规软件工具进行捕捉、管理 和处理的数据集合&#xff0c;是需要新处理模式才能具有更强的决策力、洞察发现力和流程 优化能力的海量、高增长率和多样化的信息资产…

【无标题】使用html2canvas和jspdf生成的pdf在不同大小的屏幕下文字大小不一样

问题&#xff1a;使用html2canvas和jspdf生成的pdf在不同大小的屏幕下文字大小不一样&#xff0c;在mac下&#xff0c;一切正常&#xff0c;看起来很舒服&#xff0c;但是当我把页面放在扩展屏幕下&#xff08;27寸&#xff09;&#xff0c;再生成一个pdf&#xff0c;虽然排版一…

ARM Coresight 系列文章 8 - ARM Coresight 通过 APBIC 级联使用

文章目录 APBIC 回顾APBIC 级联 上篇文章&#xff1a;ARM Coresight 系列文章 7 - ARM Coresight 通过 AHB-AP 访问 异构 cpu 内部 coresight 组件 APBIC 回顾 APBIC 可以连接一个或者多个APB BUS masters&#xff0c; 例如连接一个 APB-AP 组件和带有 APB 接口的 Processor&…

【C++】STL——vector的使用、 vector增删查改函数的介绍和使用、push_back和pop_back、operator[]

文章目录 1.vector的使用2.vector的增删查改&#xff08;1&#xff09;push_back 尾插&#xff08;2&#xff09;pop_back 尾删&#xff08;3&#xff09;find 查找&#xff08;4&#xff09;insert 在position之前插入val &#xff08;5&#xff09;erase 删除指定位置的数据&…

手搓GPT系列之 - 通过理解LSTM的反向传播过程,理解LSTM解决梯度消失的原理 - 逐条解释LSTM创始论文全部推导公式,配超多图帮助理解(中篇)

近期因俗事缠身&#xff0c;《通过理解LSTM的反向传播过程&#xff0c;理解LSTM解决梯度消失的原理 - 逐条解释LSTM创始论文全部推导公式&#xff0c;配超多图帮助理解》的中下篇鸽了实在太久有些不好意思了。为了避免烂尾&#xff0c;还是抽时间补上&#xff08;上篇在此&…

带你用Python制作7个程序,让你感受到端午节的快乐

名字:阿玥的小东东 学习:Python、C/C++ 主页链接:阿玥的小东东的博客_CSDN博客-python&&c++高级知识,过年必备,C/C++知识讲解领域博主 目录 前言 程序1:制作粽子

Spring Boot进阶(57):Spring中什么时候不要用@Autowired注入 | 超级详细,建议收藏

1. 前言&#x1f525; 注解Autowired&#xff0c;相信对于我们Java开发者而言并不陌生吧&#xff0c;在SpringBoot或SpringCloud框架中使用那是非常的广泛。但是当我们使用IDEA编辑器开发代码的时候&#xff0c;经常会发现Autowired 注解下面提示小黄线警告&#xff0c;我们把小…