跳转至

项目介绍

Vulkan 技术概览

Vulkan是什么

Vulkan 是 Khronos Group 推出的现代图形与计算 API。与传统 API (如OpenGLDirect3D)相比,它为显卡提供了更好的抽象,使你可以更好的描述应用程序的行为,从而带来更好的性能和减少意外的驱动程序行为。

与传统API的关键差异

维度 OpenGL/D3D11 Vulkan
驱动开销 高(由驱动隐式管理状态) 低(需开发者显式声明)
线程模型 单线程主导 原生多线程支持
着色器编译 运行时GLSL编译 预编译SPIR-V字节码
内存管理 驱动自动分配 开发者控制内存类型

这些好处的代价是你必须使用更细致的 API,每个细节都需要由您的应用程序从头开始设置,这意味着您必须在应用程序中执行更多工作以确保正确的行为。

什么人适合Vulkan

Vulkan 并不适合所有人。它针对的是热衷于高性能计算机图形学并愿意投入一些工作的程序员。

如果您主要对游戏开发感兴趣,那么 OpenGL 或 Direct3D 可能更适合您,因为它们的上手难度相对较低,且在多数场景下仍然能够满足需求。

另一种选择是使用 Unreal EngineUnity 这样的游戏引擎。这些引擎可以利用 Vulkan 的高性能特性,同时为开发者提供更易用的高级 API,从而在不牺牲太多性能的前提下显著降低开发难度。

学习前提

硬件要求

  • 支持 Vulkan 的显卡(NVIDIA/AMD/Intel/Apple Silicon)
  • 较新的显卡驱动

软件技能

  • 熟练的现代 C++ 编程能力(RAII、初始化列表等)
  • CMake 和 vcpkg 基础使用经验

专业知识

  • 线性代数,微积分等数学基础
  • 3D 图形学基础知识

本教程不会教你 OpenGL 或 Direct3D 的概念,但它确实要求您了解 计算机图形学 的基础知识。例如,它不会解释透视投影背后的数学原理。

强烈推荐先修课程: GAMES101-现代计算机图形学入门

绘制三角形

在编程语言中,常常将打印Hello World!作为学习的开始。而图形引擎的学习将从第一个三角形的绘制开始。

绘制三角形需要什么

绘制一个三角形远比你想象的复杂,初学者很难快速理解各组件的作用。 作者为此设计了一个“比喻”,它并不精准,但有助于初学者的理解。

思考这样一个场景:

我们现在在玩一款沙盒游戏,我们的目标是让一些机器人自动画画并提交画作。

  1. 首先我们需要创建一个新世界,初始化天空地面和机器人之类的设置。这就是实例 VkInstance

  2. 我们希望有东西在开发时帮我们检查错误,这就是验证层 Validation Layer

  3. 然后我们需要找一些合适的机器人帮我们画画,也就是物理设备 VkPhysicalDevice ,常代指GPU。

  4. 这些机器人有的支持画画有的不支持,所以我们需要检查机器人(GPU)的特征。

  5. 机器人有很多机械臂,有的机械臂可以画画,有的不仅能画画还能扫地。我们需要选择合适的机械臂去完成任务。一个机械臂对应一个队列 VkQueue ,它表示GPU的功能。一组支持特定功能的机械臂称为队列族 VkQueueFamily ,比如绘画队列族。

  6. 机器人(GPU)的型号不一样,但你希望操作的方式都一样,于是设计了统一的接口,这就是逻辑设备 VkDevice ,用于抽象物理设备。

  7. 你希望通过一个屏幕看画(实时渲染),这个屏幕就是第三方的窗口系统,我们使用 GLFW

  8. 我们需要一个工具,将画作扫描进屏幕,这个扫描仪就是窗口表面 VkSurfaceKHR

  9. 你看画的速度和机器人画画速度不一样,为了提高效率,可以用一个盒子作为缓冲。机器人往盒子里放画,扫描仪从盒子里拿画。这个盒子就是交换链 VkSwapchainKHR

  10. 特别的是,这些画画的纸可以重复使用,所以盒子里的纸的总数是固定的。这些纸就是图像 VkImage ,交换链中的图像总数固定。

  11. 不同的纸可能有不同的材质和大小,所以我们需要给每个纸写一个标签。这个标签就是图像视图 VkImageView ,描述图像的基本信息。

  12. 现在机器人终于可以画画了,我们要为他准备一个画架,用来放画纸。这个画架就是帧缓冲 VkFrameBuffer ,一帧代指一副图像。

  13. 我们还要为机器人设计一个房子,房子里放着画笔、颜料等工具,还有一台用于清洗(重置)画纸的机器。这个房子就是渲染通道 VkRenderPass ,而画笔和机器等工具就是附件 Attachments

  14. 当画作变得更加复杂,我们可以在一个房子里放多个小房间,每个房间干不同的事情,这些小房间就是子通道 VkSubpass

  15. 机器人很笨,只能看着流程图画画,所以你需要在房间中放置一些流程图,可以是一张,也可以是多张。这个流程图就是图形管线 VkPipeline

  16. 我们有一份流程图的模版,只需要修改它的部分内容就可以变成新的流程图。其中某几个部分是可编程的,这里就用到了我们熟悉的着色器模块 Shader Model

  17. 这些机器人很呆,需要你写信告诉他该画一幅画了,要在哪个房子的哪些房间根据哪些流程图画画。这个信就是命令缓冲VkCommandBuffer。你需要先写信才能寄信,我们也必须先录制完命令,然后才能提交。

  18. 特殊的是,这些信可以重用,所以我们使用一个命令池 VkCommandPool 管理这些资源。

  19. 事情一多,机器人做起来就乱了。要保证他先画画,画完才能把画拿出去,所以我们用信号量 Semaphore 处理GPU自身的同步。还要保证机器人先完成一张画,我们再寄出新的信,所以我们使用围栏 Fence 处理CPU和GPU之间的同步。

  20. 显然你写信和机器人画画可以同时进行,所以实际可能有两幅甚至更多的画被同时制作。这些画被称为飞行中的帧 frames in flight ,指代处于流水线不同阶段但都在工作中的帧。

绘制第一个三角形大致就是这些内容,你目前不需要记住,在后面的学习中随时可以回顾此内容。

注意

上面的描述是非常简化的,与各个模块具体的功能并不完全一致。 这有助于初学者的理解,但当你学完具体内容,应当去理解他们更加准确的意义。

最后

由于大量的初始化工作,仅仅是绘制一个三角形就需要约700行代码。 但在后续的过程中,你会逐渐理解以及这些繁琐步骤的巨大意义。 且在完成了第一个三角形后,后续扩展纹理和 3D 模型不再需要那么多重复工作。


准备好投入高性能图形API的未来了吗?让我们开始吧!