对象类型和函数约定
事实上,Vulkan中的所有内容都被表示为一个由句柄引用的对象。句柄分为两大类:可分派对象和不可分散对象。在大多数情况下,这与应用程序无关,仅影响API的结构以及系统级组件(如Vulkan加载器和层)与这些对象的互操作性。
可分派对象是内部包含调度表的对象。这是各种组件使用的功能表,用于确定当您的应用程序调用Vulkan时要执行的代码部分。这些类型的对象通常是较大较复杂的结构,目前由实例(VkInstance),物理设备(VkPhysicalDevice),逻辑设备(VkDevice),命令缓冲区(VkCommandBuffer)和队列(VkQueue)组成)构成。所有其他对象被认为是不可分散的。
任何Vulkan函数的第一个参数总是一个可调度的对象。此规则的唯一例外是与实例的创建和初始化相关的功能。
管理内存
Vulkan提供两种类型的内存:主机内存和设备内存。由Vulkan API创建的对象通常需要一定数量的主机内存。这就是Vulkan实现将存储对象状态以及实现Vulkan API所需的任何数据。资源对象(如缓冲区和图像)需要一定量的设备内存。这是存储在资源中的数据的存储器。
您的应用程序可以管理Vulkan实现的主机内存,并且需要您的应用程序管理设备内存。为此,您将需要创建一个设备内存管理子系统。您可以查询您创建的每个资源,以获得支持所需的内存量和类型。应用程序将分配正确的内存量并将其附加到资源对象,然后才能使用它。在诸如OpenGL这样的更高级别的API中,这个“魔术”是由驱动程序代表你的应用程序执行的。然而,一些应用程序需要非常大量的小资源,而其他应用程序需要较少数量的非常大的资源。一些应用程序在执行过程中创建和销毁资源,而其他应用程序在启动时创建所有资源,并且在终止之前不释放它们。
在这些情况下使用的分配策略可能会有很大的不同。没有一刀切的策略。 OpenGL驱动程序不知道您的应用程序将如何运行,因此必须调整分配策略以尝试适应您的使用模式。另一方面,您,应用程序开发人员,您的应用程序的行为准确无误。您可以将资源分成长期和短暂的组。您可以将将一起使用的资源分成少量池化分配。您可以决定应用程序使用的分配策略
重要的是要注意,每个“实时”内存分配会给系统带来一些成本。因此,将分配对象的数量保持在最小值是很重要的。建议设备内存分配器以大块分配内存。许多小资源可以放置在少得多的设备内存块内。第2章“内存和资源”中讨论了设备内存分配器的一个例子,它们更详细地讨论了内存分配。
Vulkan的多线程
支持多线程应用程序是Vulkan设计的一个组成部分。 Vulkan通常假定应用程序将确保没有两个线程同时在同一对象上进行变异。这被称为外部同步。在Vulkan的性能关键部分(如构建命令缓冲区)中的绝大多数Vulkan命令根本不提供同步。
为了具体定义各种Vulkan命令的线程命令,必须保护不受主机并发访问的每个参数被标记为外部同步。在某些情况下,对象或其他数据的句柄将被包含在数据结构中,包含在数组中,或以其他方式传递给命令。这些参数也必须是外部同步的。
这样做的意图是,Vulkan实现不需要在内部采用互斥体或使用其他同步原语来保护数据结构。这意味着多线程程序很少停止或跨线程阻塞。
除了要求主机在线程间使用共享对象的同时访问之外,Vulkan还提供了许多更高级别的功能,专门用于允许线程执行工作而不会相互阻止。这些包括以下内容:
•主机内存分配可以通过传递给对象创建功能的主机内存分配结构来处理。通过使用每个线程的分配器,该分配器中的数据结构不需要被保护。主机内存分配器在第2章“内存和资源”中有介绍。
•命令缓冲区是从池分配的,对池的访问是外部同步的。如果应用程序每个线程使用单独的命令池,则可以从这些池中分配命令缓冲区,而不会相互阻止。命令缓冲区和池在第3章“队列和命令”中有介绍。
•描述符按描述符池分配。描述符是在设备上运行的着色器使用的资源的表示。它们在第6章“着色器和管道”中有详细描述。如果每个线程都使用单独的池,则可以从这些池中分配描述符集,而不会使线程相互阻塞。
•二级命令缓冲区允许并行生成大型renderpass(必须包含在单个命令缓冲区中)的内容,然后在从主命令缓冲区调用时分组。第13章“Multipass Rendering”中详细介绍了二级命令缓冲区。
当您构建一个非常简单的单线程应用程序时,创建从其分配对象的池的需求可能看起来很多不必要的间接。然而,随着应用程序在线程数量上的扩展,这些对象是实现高性能的必不可少的。
在本书的其余部分中,关于线程的任何特殊要求将在引入命令时注明。
数学概念
计算机图形学和大多数异构计算应用程序都是以数学作为基础。 大多数Vulkan设备都是基于非常强大的计算处理器。 在撰写本文时,即使是适中的移动处理器也能够提供许多千兆位的处理能力,而高端桌面和工作站处理器则提供了数千倍的数字处理能力。 因此,真正有趣的应用程序将建立在偏重数学的着色器上。 此外,Vulkan处理管道的几个固定功能部分建立在硬连接到设备和规范中的数学概念上。
向量和矩阵
任何图形应用程序的基本构建块之一是向量。无论它们是位置,方向,颜色还是其他数量的表示,在整个图形文献中都使用向量。向量的一种常见形式是均匀矢量,它是一个空间中的矢量,该空间的一维高于其所代表的数量。这些向量用于存储投影坐标。将均匀矢量乘以任何标量产生表示相同投影坐标的新矢量。要投射一个点矢量,通过其最后一个分量进行分割,产生x,y,z,1.0形式的向量(对于四分量矢量)。
要将矢量从一个坐标空间转换到另一个坐标空间,将该矢量乘以一个矩阵。正如3D空间中的一点被表示为四分量均匀矢量,在3D均匀矢量上运行的变换矩阵是4×4矩阵。
3D空间中的点通常表示为常规称为x,y,z和w的四个分量的均匀矢量。对于一个点,w分量通常以1.0开始,并且随着向量通过投影矩阵变换而改变。在通过w分量分配之后,该点通过以下变量进行投影:如果没有一个变换是投影变换,则w保持为1.0,除以1.0对矢量没有影响。如果矢量进行投影变换,则w不等于1.0,但是通过它将会投射点并将w返回到1.0。
同时,3D空