Vulkan的Execution Model


vulkan执行中涉及的几个组件

Device

为了渲染图形,计算机中必须有显卡,或者独立显卡或者集成显卡,这些都是PhysicalDeivce,而在vulkan的术语环境下,这个PhysicalDeivce指的是支持vulkan的具体的物理设备。

同样地,为了在各种应用中表示该PhysicalDevice,vulkan中引入Device的概念,它是一个抽象的logical representation。

对于在应用中使用时,对于vulkan兼容的PhysicalDeivce(指的是通过vulkan的API可以操作该设备),我们要find;对于Device,我们要create。

Queue

Queue在数据结构中是先入先出的特性。根据这一点,在很多的消息队列中广泛使用,比如:生产者-消费者模型,尤其是多线程的环境下。如果你了解这一点,对于vulkan中Queue发挥的作用,就不会陌生了。

在vulkan中,Queue是execution engine和application之间的interface:

  • application是command的生产者;
  • execution engine是command的消费者;

具体来说,Queue的责任在于收集所有来自应用的commands,application将command提交到Queue,然后execution engine取走调度执行。

一个PhysicalDevice包含很多的Queue,每个Queue可能有不同的功能,这里的功能不同,我理解是:特定的Queue只能接受特定的command,比如:内存操作、并行计算等。

Family

按照功能不同,这些Queue并划分到Family,这样一组Queue内形成的Family内,支持多种功能的Queue

  • video decode;
  • video encode;
  • graphics(重点使用);
  • compute(并行计算,深度学习模型等);
  • transfer;
  • sparse memory management;

Command

Command即application发出的,用来命令GPU执行的操作指令。一般可以分为3种类型:

  • action

    这是真正要工作的Command,利用GPU等绘制图形,拷贝buffer等。

  • state

    这种类型的command,是用来对一些状态进行管理的,比如一些descriptor sets、buffers等。

    对descriptor sets、buffers等不了解很正常,提一下,后续会深入学习,学一个东西总是不断有新的名词冒出来,开始时很恼火,不过后来就习惯了。

  • synchronization

    这种command更多的是用来协调各种Action command,尤其是这些command对一些公共资源竞争时,或者彼此之间存在依赖关系,需要对它们进行排布,以更好地完成工作。

Command buffer

  • a collection of commands
  • records the commands and submit them to queues

vulkan执行模型

简要过程

vulkan中简要的执行过程如下图所示:

vulkan的执行模型

  1. application选择支持vulkan API的PhysicalDevice
  2. application创建Device来代表选择的PhysicalDevice
  3. 根据自己的需求,选择PhysicalDevice中包含的特定Queue
  4. application发出的Command被记录在Command Buffer中;
  5. 之后,这些Command buffer被提交到Queue中;
  6. PhysicalDevice消费这些command,命令GPU执行对应的操作;
  7. 最后,PhysicalDevice将处理的结果显示到屏幕上,或者返回给application。

一些注意事项

command buffer construction is expensive

在这个过程中,command buffer要接受application提交的command,之后再submit给对应的queue。但是command buffer的构造是昂贵的,这里中的昂贵一般指时间占用或者资源使用上的,因此要缓存下来重用。而且,很多的command buffer可以通过多线程并发构造。

application是execution顺利进行的主要责任人

在之前说到Vulkan与OpenGL等的一个重要的不同在于——驱动的很大一部分工作交给了application完成,具体有:

  • command的顺利执行准备必要的条件;
    • prepare resources
    • precompile shaders
    • attach the resources to shaders
    • specify render states
    • build a pipeline
    • call draw operations
  • memory management
  • synchronization
    • 在不同的queue之间同步;
  • Error checking

Queue的实际执行过程

作为command bufferPhysicalDevice的中介,负责沟通application和实际的GPU,Queue的实际执行过程影响了GPU的执行。

对于记录到command buffer中的一系列command,可以提交到:

  • single queue

    对于提交到一个queue的多个command buffer,它们后续执行的顺序与它们提交的顺序保持一致,严格恪守先入先出的规则;

  • multiple queue

    但是当多个command buffer同时提交到多个queue时,它们的执行顺序默认情况下,是没有保证的。如果application想要控制它们的执行顺序,需要自己完成同步的操作。

Vulkan中有多种保证同步的primitives,可以保证一个或者多个queuecommand buffer的执行顺序:

  • Semaphore
  • Events
  • Fences
  • Pipeline barriers

这些同步机制在后续的学习中可能会有深入地阐述。

参考资料

  1. https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap3.html#fundamentals-execmodel

  2. Learning Vulkan - Chapter 1 - Learning the fundamentals of Vulkan


文章作者: alex Li
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 alex Li !
  目录