Vulkan。开发人员指南

我是伊热夫斯克IT公司CG Tribe的技术翻译,该公司邀请我为社区做出贡献并开始出版有趣的文章和指南的翻译。



在这里,我将发布Vulkan API手册的翻译。源链接-vulkan-tutorial.com由于另一个Habr用户kiwhy(https://habr.com/ru/users/kiwhy/)从事同一指南的翻译工作,因此我们同意在

彼此之间分享经验教训。在我的出版物中,我将提供指向kiwhy翻译的章节的链接。



内容
1.



2.



3.



4.



  1. (pipeline)


5.



  1. Staging


6. Uniform-



  1. layout
  2. sets


7.



  1. Image view image sampler
  2. image sampler


8.



9.



10. -



11. Multisampling



FAQ







1.简介



参见作者kiwhy的文章-habr.com/ru/post/462137



2.概述



Vulkan背景



如何绘制三角形?



  1. 步骤1-实例和物理设备
  2. 第2步-逻辑单元和队列系列
  3. 步骤3-窗户表面和交换链
  4. 第4步-图像视图和帧缓冲区
  5. 第5步-渲染通行证
  6. 第6步-图形管道
  7. 步骤7-命令池和命令缓冲区
  8. 第8步-主循环
  9. 结论


API概念



  1. 代码格式化标准
  2. 验证层


在本章中,我们将开始使用Vulkan,并查看它可以解决什么问题。我们将描述创建第一个三角形所需的步骤。这将为您提供标准的概述,并让您了解后面各章的内容背后的逻辑。我们以Vulkan API结构和典型用例为结尾。



Vulkan的先决条件



像以前的图形API一样,Vulkan被认为是GPU上的跨平台抽象。这些API中的大多数的主要问题是在其开发过程中使用了图形硬件,但仅限于固定功能。开发人员必须以标准格式提供顶点数据,并且完全依赖GPU制造商提供照明和阴影。



随着视频卡体系结构的发展,越来越多的可编程功能开始出现在其中。所有新功能都需要以某种方式与现有API结合。这导致图形驱动程序方面的抽象概念不完善,并提出了许多关于如何将程序员的意图转换为现代图形体系结构的假设。因此,发布了大量驱动程序更新以提高游戏性能。由于此类驱动程序的复杂性,因此供应商之间经常存在差异,例如,着色器采用的语法...除此之外,过去十年来还涌现了具有强大图形硬件的移动设备。这些移动GPU的架构可能会因尺寸和功耗要求而有很大差异。这样的例子之一就是基于图块的渲染,它可以通过更好地控制功能来提供更好的性能。由于API的使用年限,另一个限制是对多线程的有限支持,这可能会导致CPU方面的瓶颈。



Vulkan是为现代图形体系结构完全构建的,因此可以帮助解决这些问题。通过允许开发人员使用详细的API清楚地描述其目标,可以减少驱动程序方面的开销。Vulkan允许您在多个线程中并行创建和发送命令。通过移至标准字节码格式并使用单个编译器,还可以减少着色器之间的编译差异。最后,Vulkan通过将图形和计算功能集成到单个API中,将当今图形卡的核心功能整合在一起。



如何绘制三角形?



我们将快速浏览绘制三角形所需的步骤。这将为您提供该过程的概述。在以下各章中将对每个概念进行详细说明。



步骤1-实例和物理设备



使用Vulkan的过程首先通过VkInstance配置Vulkan API 。使用您的程序说明和要使用的任何扩展名创建一个实例。实例化之后,您可以查询Vulkan支持的硬件并选择一个或多个VkPhysicalDevices来执行操作。如果您喜欢使用专用的图形卡,则可以查询诸如VRAM大小和设备功能之类的参数以选择所需的设备。



步骤2-逻辑设备和队列系列



选择合适的硬件设备后,您需要创建一个VkDevice(逻辑设备),在其中将更详细地描述您将使用哪些功能(VkPhysicalDeviceFeatures),例如渲染到多个视口。 s(多视口渲染)和64位浮点型。您还需要确定要使用的队列系列。使用Vulkan完成的许多操作(例如绘图命令和内存中操作)在发送到VkQueue之后都是异步执行的...队列是从一组队列中分配的,每个队列都支持一组特定的操作。例如,可能存在单独的队列系列,用于图形操作,计算操作和内存数据传输。此外,在选择物理设备时,它们的可用性可以用作关键参数。一些支持Vulkan的设备不提供任何图形功能,但是,所有支持Vulkan的现代图形卡通常都支持我们需要的所有排队操作。



第3步-窗口表面和交换链



如果您不仅对屏幕外渲染感兴趣,还需要创建一个窗口来显示渲染的图像。可以使用本地平台API或库(例如GLFWSDL)创建Windows 。在本教程中,我们将使用GLFW,我们将在下一章中对其进行详细介绍。



我们还需要两个组件来渲染应用程序窗口:窗口表面(VkSurfaceKHR)和显示链(VkSwapchainKHR)。注意后缀KHR表示这些对象是Vulkan扩展的一部分。 Vulkan API完全独立于平台,因此我们需要使用WSI(窗口系统接口)标准化扩展与窗口管理器进行交互。 Surface是用于渲染的跨平台窗口抽象,通常是通过引用本机窗口句柄(例如HWND在Windows上)创建的。幸运的是,GLFW库具有用于处理特定于平台的详细信息的内置功能。



显示链是一组渲染目标。其任务是确保当前渲染的图像与屏幕上显示的图像不同。这使您可以跟踪仅显示渲染的图像。每次我们需要创建框架时,都必须请求显示链为我们提供要渲染的图像。创建框架后,图像将返回到显示链,以在某个时刻显示在屏幕上。在屏幕上显示完成图像的渲染目标的数量和条件取决于当前模式。这些模式包括双缓冲(vsync)和三缓冲。我们将在创建展示链的章节中介绍它们。



一些平台允许通过扩展直接渲染到屏幕,VK_KHR_displayVK_KHR_display_swapchain无需与任何窗口管理器进行交互。这样,您就可以创建一个代表整个屏幕的表面,并且可以用于实现自己的窗口管理器。



第4步-图像视图和帧缓冲区



为了绘制从显示链获得的图像,我们必须将其包装在VkImageViewVkFramebuffer中。图像视图是指正在使用的图像的特定部分,而帧缓冲区是指用作颜色,深度和模板缓冲区的图像视图。由于显示链中可能有许多不同的图像,因此我们将为每个图像预先创建一个图像视图和一个帧缓冲区,并在绘制过程中选择所需的图像。



第5步-渲染过程



Vulkan的渲染过程描述了渲染操作期间使用的图像类型,如何使用图像以及如何处理其内容。在绘制三角形之前,我们将告诉Vulkan我们要使用单个图像作为颜色缓冲区,并且需要在绘制之前清除它。如果渲染过程仅描述用作缓冲区的图像类型,则VkFramebuffer实际上会将特定图像与那些插槽关联。



第6步-图形管道



Vulkan中图形管道是通过创建VkPipeline对象配置的。它描述了视频卡的可配置状态,例如视口大小或深度缓冲区操作,以及使用VkShaderModule对象的可编程状态VkShaderModule对象是从着色器字节码创建的。驱动程序还需要指定在管道中使用哪些渲染目标。我们通过引用渲染过程来设置它们。



与现有API相比,Vulkan最具特色的功能之一是,几乎所有系统图形管道设置都必须预先配置。这意味着,如果要切换到其他着色器或略微更改顶点布局,则需要完全重新创建图形管线。因此,必须为渲染操作所需的所有组合预先创建许多VkPipeline对象。只能动态更改某些基本设置,例如视口大小和纯色。必须明确描述所有状态。因此,例如,没有默认的颜色混合状态。



幸运的是,由于该过程更像是预先进行编译,而不是即时进行编译,因此驱动程序具有更多的优化机会,并且由于显着地指定了重要的状态更改(例如切换到不同的图形管线),因此性能更加可预测。



步骤7-命令池和命令缓冲区



如上所述,Vulkan中的许多操作(例如绘图操作)必须排队。在发送操作之前,必须将它们写入VkCommandBuffer命令缓冲区来自与特定队列系列相关联VkCommandPool要绘制一个简单的三角形,我们需要使用以下操作编写命令缓冲区:



  • 开始渲染过程
  • 绑定图形管道
  • 绘制3个顶点
  • 结束渲染过程


由于帧缓冲区中图像的实例取决于显示链将提供给我们的图像,因此我们需要为每个可能的图像编写一个命令缓冲区,并在绘制过程中选择所需的图像。我们可以每次为每帧写入命令缓冲区,但这效率较低。



步骤8-主循环



将绘图命令发送到命令缓冲区后,主循环似乎很简单。首先,我们使用来从展示链中获取图像vkAcquireNextImageKHR然后,我们可以为此图像选择适当的命令缓冲区,并使用vkQueueSubmit运行它最后,我们使用将图像返回到显示链以进行显示vkQueuePresentKHR



发送到队列的操作是异步执行的。因此,我们必须使用同步对象-信号量-以确保正确的启动顺序。必须以仅在从显示链中获取图像之后才执行绘制命令缓冲区的方式来配置执行命令,否则,当我们开始渲染仍在读取的图像以显示在屏幕上时,可能会出现这种情况。vkQueuePresentKHR反过来,调用必须等待渲染完成,为此,我们将使用第二个信号量。它将通知渲染结束。



结论



此快速概述为您提供了绘制第一个三角形之前的工作概述。实际上,还有更多步骤。这些包括分配顶点缓冲区,创建统一缓冲区以及加载纹理图像-所有这些我们将在下一章中介绍,但现在让我们开始简单。我们移动得越远,材料就会越困难。请注意,我们决定采用棘手的方法,方法是先将顶点坐标嵌入到顶点着色器中,而不使用顶点缓冲区。该决定是由于要管理顶点缓冲区,您首先需要熟悉命令缓冲区。



让我们简要地总结一下。要绘制第一个三角形,我们需要:



  • 创建VkInstance
  • 选择支持的视频卡(VkPhysicalDevice
  • 创建VkDeviceVkQueue进行绘制和显示
  • 创建窗口,窗口表面并显示链
  • VkImageView中包装显示链图像
  • 创建一个定义渲染目标及其用法的渲染过程
  • 创建帧缓冲区以进行渲染
  • 配置图形管道
  • 为显示链中的每个图像分配绘图命令并将其写入缓冲区
  • 通过发送正确的命令缓冲区并将图像返回到显示链,将帧渲染为接收的图像


尽管存在许多步骤,但以下各章将清楚说明每个步骤的含义。如果您无法找出步骤,请返回本章。



API概念



本章将简要概述Vulkan API的底层结构。



编码标准



所有Vulkan功能,枚举和结构均在LunarG开发vulkan.hVulkan SDK中包含的标题下标记。下一章将介绍如何安装SDK。



函数以vk小写字母为前缀,枚举类型(枚举)和结构为前缀Vk,枚举值为前缀VK_。 API广泛使用结构来为函数提供参数。例如,通常根据以下模式创建对象:



图片



Vulkan中的许多结构都要求您在member中显式指定结构类型sType。成员pNext可以指向扩展结构,并且永远是类型nullptr...创建或销毁对象的函数将具有VkAllocationCallbacks参数,该参数允许您使用自己的内存分配器,并且在本教程中也将属于此类nullptr



几乎所有函数都返回VkResult,这VK_SUCCESS可能是错误代码。规范说明了每个函数可以返回的错误代码及其含义。



验证层



如前所述,Vulkan旨在在低驱动程序负载下提供高性能。因此,它包括非常有限的自动错误检测和纠正功能。如果输入错误,驱动程序将崩溃或变得更糟,继续在您的图形卡上工作,但在其他图形卡上失败。



因此,Vulkan允许您使用称为验证层的功能运行高级验证...验证层是可以插入API和图形驱动程序之间的代码段,以对功能参数执行附加验证并跟踪内存管理问题。这很方便,因为您可以在开发过程中启动它们,然后在启动程序时完全禁用它们,而无需支付额外费用。任何人都可以编写自己的验证层,但是LunarG的Vulkan SDK提供了我们将在整个教程中使用的标准集。您还需要注册一个回调函数以接收来自层的调试消息。



由于Vulkan中的操作非常详细,并且验证层非常广泛,因此与OpenGL和Direct3D相比,您更容易确定黑屏的原因。



在我们开始编码之前,只剩下一个步骤,那就是设置开发环境。



All Articles