Skip to content

第一章 · Vulkan 架构与核心概念

1.1 Vulkan 是什么

Vulkan(Khronos Group 于 2016 年发布)是一个低级、跨平台的图形 API,专为高性能 3D 图形和计算设计。

核心设计哲学

原则说明
显式控制一切由开发者管理,Driver 几乎不干预
低开销减少 CPU 驱动层开销,CPU/GPU 并行
多线程优化原生支持多线程命令提交
精确同步开发者完全控制资源访问时序
硬件抽象层面向现代 GPU 架构直接映射

为什么选择 Vulkan?

OpenGL:                    Vulkan:
───────────               ───────────

Driver 帮你做决定          你决定一切
"画一个三角形"             "请给我 1000 字节,一个命令缓冲..."

CPU 开销大(~50-100%)    CPU 开销小(~10-20%)
GPU 利用率低(~40%)      GPU 利用率高(~90%)

容易上手                   难上手

适合中小项目                适合高性能项目

1.2 Vulkan 架构总览 🔥

1.2.1 分层架构

┌─────────────────────────────────────────────────┐
│               Your Application                   │
│           (你的游戏/渲染器)                       │
│   ┌───────────────────────────────────────────┐  │
│   │           Vulkan API (C/C++)              │  │
│   │  vkCreateInstance → vkQueueSubmit → ...  │  │
│   └───────────────────────────────────────────┘  │
├─────────────────────────────────────────────────┤
│           Vulkan Driver (Vendor)                │
│   ┌───────────────────────────────────────────┐  │
│   │           Driver Layer                      │  │
│   │  OpenGL ES → Vulkan (通过翻译层)           │  │
│   │  Metal → Vulkan (通过 MoltenVK)            │  │
│   │  Native Vulkan → Hardware                 │  │
│   └───────────────────────────────────────────┘  │
├─────────────────────────────────────────────────┤
│              GPU / Hardware                      │
│   ┌─────────────┐  ┌─────────────┐              │
│   │ Compute Unit │  │Graphics Unit│              │
│   │  (Shader)    │  │  (Shader)   │              │
│   └─────────────┘  └─────────────┘              │
└─────────────────────────────────────────────────┘

1.2.2 核心对象模型

Instance (实例)

    ├── Physical Device (物理设备)
    │   ├── GPU (GPU 0)
    │   ├── GPU (GPU 1)
    │   └── ...

    └── Device (逻辑设备)
        ├── Queue Family (队列族)
        │   ├── Queue 0 (Graphics)
        │   ├── Queue 1 (Compute)
        │   └── Queue 2 (Transfer)

        ├── Memory (内存管理)
        │   ├── Memory Type 0
        │   ├── Memory Type 1
        │   └── ...

        ├── Resources (资源)
        │   ├── Buffers
        │   ├── Images
        │   ├── Samplers
        │   └── Pools

        ├── Pipelines (管线)
        │   ├── Graphics Pipeline
        │   ├── Compute Pipeline
        │   └── Ray Tracing Pipeline

        ├── Descriptor Sets (描述符)
        │   ├── Uniform Buffers
        │   ├── Storage Buffers
        │   └── Texture Views

        └── Render Passes (渲染通道)
            └── Framebuffers

1.3 核心概念详解 🔥

1.3.1 Instance(实例)

概念:一个 Vulkan 实例代表你与 Vulkan 驱动的"连接"
类比:数据库连接

创建流程:
1. 创建 Application Info(应用名称、版本)
2. 创建 Instance (指定需要的扩展)
3. 枚举物理设备 (Physical Devices)

关键 API:
- vkCreateInstance()
- vkEnumeratePhysicalDevices()
- vkDestroyInstance()

1.3.2 Physical Device(物理设备)

概念:实际的 GPU 硬件
类比:计算机中的显卡

每个 GPU 是一个 Physical Device,需要:
- 查询其能力(支持的 Vulkan 版本、特性)
- 查询其队列族(Queue Families)
- 查询其内存类型(Memory Types)

关键 API:
- vkGetPhysicalDeviceProperties()
- vkGetPhysicalDeviceFeatures()
- vkGetPhysicalDeviceQueueFamilyProperties()

1.3.3 Logical Device(逻辑设备)

概念:从 Physical Device 创建的"虚拟连接"
类比:SQLAlchemy Session(从数据库连接创建的会话)

创建时指定:
- Queue 要求(Graphics/Compute/Transfer)
- 扩展(Extensions)
- 设备特性(Features)

关键 API:
- vkCreateDevice()
- vkGetDeviceQueue()
- vkDestroyDevice()

1.3.4 Queue(队列)

概念:GPU 执行命令的队列
类比:打印机队列(但 GPU 可以有多个队列)

Queue Family 类型:
- VK_QUEUE_GRAPHICS_BIT     — 图形渲染
- VK_QUEUE_COMPUTE_BIT       — 计算任务
- VK_QUEUE_TRANSFER_BIT      — 数据传输
- VK_QUEUE_SPARSE_BINDING_BIT — 稀疏绑定
- VK_QUEUE_PROTECTED_BIT     — 保护队列

一个物理设备可以有多个 Queue Family
每个 Queue Family 可以有多个 Queue

关键 API:
- vkGetDeviceQueue()
- vkQueueSubmit() — 提交命令缓冲
- vkQueueWaitIdle() — 等待队列空闲

1.3.5 Command Buffer(命令缓冲)

概念:记录渲染命令的"回放"
类比:视频带的"录制"功能

流程:
1. 创建 Command Pool(命令池)
2. 从 Pool 分配 Command Buffer
3. 开始记录命令(vkCmdBeginRenderPass → vkCmdDraw → vkCmdEndRenderPass)
4. 停止记录
5. 提交到 Queue 执行
6. 重置并复用

关键 API:
- vkAllocateCommandBuffers()
- vkBeginCommandBuffer()
- vkCmdBindPipeline()
- vkCmdDraw()
- vkEndCommandBuffer()
- vkQueueSubmit()

1.3.6 Memory(内存)

概念:Vulkan 显式管理 GPU 内存
类比:C/C++ 的 malloc/free(但更复杂)

Vulkan 内存管理三层模型:

Physical Memory → Memory Type → Device Memory

Physical Memory Types (驱动定义):
  VK_MEMORY_TYPE_DEVICE_LOCAL_BIT    — GPU 本地显存(最快)
  VK_MEMORY_TYPE_HOST_VISIBLE_BIT    — 主机可访问
  VK_MEMORY_TYPE_HOST_COHERENT_BIT   — 自动同步
  VK_MEMORY_TYPE_HOST_NON_COHERENT_BIT — 需要手动同步

Memory Allocation:
  1. 查询 Physical Device 支持的 Memory Types
  2. 选择合适类型(考虑性能和可用性)
  3. 分配 Device Memory
  4. 绑定到 Buffer/Image

关键 API:
- vkGetPhysicalDeviceMemoryProperties()
- vkAllocateMemory()
- vkBindBufferMemory() / vkBindImageMemory()
- vkFreeMemory()

1.4 渲染管线(Render Pipeline)🔥

1.4.1 整体流程

Application

    ├── 1. Instance (实例)
    │       └── 创建 Vulkan 连接

    ├── 2. Physical Device (物理设备)
    │       └── 查询 GPU 能力

    ├── 3. Logical Device (逻辑设备)
    │       └── 创建虚拟连接

    ├── 4. Surface (表面)
    │       └── 窗口系统绑定

    ├── 5. Swap Chain (交换链)
    │       └── 帧缓冲管理

    ├── 6. Command Buffer (命令缓冲)
    │       └── 记录渲染命令

    ├── 7. Render Pass (渲染通道)
    │       └── 定义渲染结构

    ├── 8. Pipeline (管线)
    │       └── 渲染状态

    ├── 9. Resources (资源)
    │       ├── Buffers (顶点、Uniform)
    │       ├── Images (纹理)
    │       └── Samplers (采样)

    ├── 10. Render (渲染)
    │        └── vkQueueSubmit → GPU 执行

    └── 11. Present (呈现)
             └── 图像显示到屏幕

1.4.2 Render Pass 详解

Render Pass 定义"如何渲染":

1. 渲染通道 (Render Pass)
   ├── 附件 (Attachments)
   │   ├── Color Attachment (颜色附件)
   │   ├── Depth Attachment (深度附件)
   │   └── Stencil Attachment (模板附件)

   └── 子通道 (Subpasses)
       ├── Subpass 0 (主渲染)
       │   ├── 输入附件 (Input Attachments)
       │   ├── 颜色附件 (Color Attachments)
       │   ├── 深度附件 (Depth Attachment)
       │   └── 输出附件 (Output Attachments)
       └── ...

2. Framebuffer (帧缓冲)
   └── 绑定具体资源到 Attachments

3. Pipeline (管线)
   └── 绑定到 Render Pass

1.4.3 Pipeline 状态

Graphics Pipeline 由多个阶段组成:

Input Assembly (顶点组装)

    ├── Vertex Input (顶点输入)
    │   ├── Vertex Buffer (顶点缓冲)
    │   └── Vertex Attribute Description

    ├── Vertex Shader (顶点着色器)
    │   └── GLSL Shader Module

    ├── Tessellation (可选)
    ├── Geometry Shader (可选)

    ├── Rasterization (光栅化)
    │   ├── Front Face (正面)
    │   ├── Polygon Mode (多边形模式)
    │   ├── Cull Mode (剔除模式)
    │   └── Depth Bias (深度偏置)

    ├── Multisample (多重采样)

    ├── Fragment Shader (片元着色器)
    │   └── GLSL Shader Module

    ├── Color Blend (颜色混合)
    │   ├── Blend Enable (混合启用)
    │   ├── Blend Factor (混合因子)
    │   └── Color Mask (颜色掩码)

    ├── Depth Test (深度测试)
    │   ├── Depth Compare (比较方式)
    │   └── Depth Write (深度写入)

    └── Stencil Test (模板测试)
        ├── Compare Op (比较操作)
        └── Stencil Op (模板操作)

1.5 核心对象关系图

    Instance

       ├── Physical Device
       │   ├── GPU Info
       │   ├── Memory Types
       │   └── Queue Families

       ├── Logical Device
       │   ├── Queue
       │   │   ├── Command Pool
       │   │   │   ├── Command Buffer
       │   │   │   └── ...
       │   │   └── Command Buffer
       │   │
       │   ├── Memory
       │   │   └── Device Memory
       │   │       ├── Buffer
       │   │       └── Image
       │   │
       │   ├── Pipeline
       │   │   ├── Shader Module
       │   │   └── Shader Stage
       │   │
       │   ├── Render Pass
       │   │   └── Framebuffer
       │   │       └── Image View
       │   │
       │   ├── Descriptor Set Layout
       │   │   ├── Uniform Buffer
       │   │   ├── Storage Buffer
       │   │   └── Sampler
       │   │
       │   └── Swap Chain
       │       ├── Image (xN)
       │       ├── Image View (xN)
       │       └── Allocator

       └── Surface
           └── Window/System

1.6 关键术语速查

术语说明类比
InstanceVulkan 实例,与驱动的连接HTTP 客户端
Physical Device实际的 GPU 硬件物理显卡
Logical Device从 Physical Device 创建的虚拟连接数据库连接
QueueGPU 执行命令的队列打印机队列
Command Buffer记录命令的缓冲录制视频
Render Pass定义渲染结构烹饪步骤
Pipeline渲染状态烹饪配方
Buffer线性内存(顶点、Uniform)数组
Image纹理资源图像文件
Sampler纹理采样配置放大镜设置
Frame Buffer帧缓冲(附件绑定)画布
Swap Chain帧缓冲管理电影胶片
Fence驱动完成信号(CPU/GPU 同步)
SemaphoreGPU/GPU 同步信号灯
MemoryGPU 显存管理malloc
Descriptor Set描述符绑定(UBO、SRV)变量绑定

1.7 Vulkan vs OpenGL 核心差异

OpenGL (Fixed Function):         Vulkan (Explicit):
─────────────────────            ────────────────────

glVertexPointer()              →  手动绑定 Buffer

glEnable(GL_DEPTH_TEST)        →  创建 Pipeline 时指定

glUniformMatrix4fv(...)        →  创建 Uniform Buffer + Descriptor

glDrawArrays(GL_TRIANGLES, ...)→  vkCmdDraw(..., commandBuffer)

glTexImage2D(...)              →  vkCreateImage + vkAllocateMemory + vkBind...

glUseProgram(program)          →  创建 Pipeline + vkCmdBindPipeline(...)

glGetError()                   →  vkGetResult() / vkGetResultCallback()

自动内存管理                    →  手动内存管理

状态机(隐式状态)              →  显式状态

1.8 渲染循环(Render Loop)

python
# 典型的 Vulkan 渲染循环
while not should_terminate:
    # 1. 获取下一帧
    image_index = swap_chain.acquire_next_image()
    
    # 2. 等待之前的命令完成
    wait_for_fence(fences[image_index])
    
    # 3. 重置命令缓冲
    reset_command_buffer(command_buffers[image_index])
    
    # 4. 开始记录命令
    vkCmdBeginRenderPass(command_buffer)
        vkCmdBindPipeline(command_buffer, pipeline)
        vkCmdBindDescriptorSets(command_buffer, descriptor_sets)
        vkCmdBindVertexBuffers(command_buffer, vertex_buffers)
        vkCmdDraw(command_buffer, vertex_count, instance_count)
    vkCmdEndRenderPass(command_buffer)
    
    # 5. 提交命令
    submit_command_buffer(command_buffer)
    
    # 6. 呈现图像
    swap_chain.present_image(image_index)

1.9 核心 API 分类速查

类别函数
初始化vkCreateInstance(), vkCreateDevice()
枚举vkEnumeratePhysicalDevices(), vkEnumerateInstanceExtensionProperties()
资源vkCreateBuffer(), vkCreateImage(), vkCreateSampler()
内存vkAllocateMemory(), vkBindBufferMemory()
命令vkAllocateCommandBuffers(), vkCmdDraw(), vkQueueSubmit()
同步vkCreateFence(), vkCreateSemaphore(), vkWaitForFences()
渲染vkCreateRenderPass(), vkCreateFramebuffer()
管线vkCreateGraphicsPipelines()
呈现vkAcquireNextImageKHR(), vkQueuePresentKHR()
交换链vkCreateSwapchainKHR(), vkDestroySwapchainKHR()