Ahao's Technical Blog Ahao's Technical Blog
首页
  • 001.基础篇
  • 002.玩转AOSP篇
  • 003.学穿Binder篇
  • 004.基础组件篇
  • 005.系统启动过程分析
  • 006.Hal开发入门与实践
  • 007.显示系统
  • 008.核心系统服务
  • 009.输入系统
  • 010.开发工具
  • Vulkan
  • OpenGL
  • Skia
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

阿豪讲Framework

不积跬步无以至千里
首页
  • 001.基础篇
  • 002.玩转AOSP篇
  • 003.学穿Binder篇
  • 004.基础组件篇
  • 005.系统启动过程分析
  • 006.Hal开发入门与实践
  • 007.显示系统
  • 008.核心系统服务
  • 009.输入系统
  • 010.开发工具
  • Vulkan
  • OpenGL
  • Skia
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Vulkan

    • Vulkan 整体架构
      • 1. Vulkan Application
        • 主要特点
      • 2. Loader
        • 工作原理
        • 主要职责
        • Android 平台实现
        • 系统库位置
        • 驱动查找机制
      • 3. Vulkan Layer
        • 基本概念
        • 工作原理
        • 调用链机制
        • 应用场景
        • 1. 调试与代码验证(最基础的功能)
        • 2. 性能分析与 Profiling(开发者最爱)
        • 3. 渲染增强与视觉修改(玩家与 Modder 最爱)
        • 4. 调试工具与抓帧 (Capture & Replay)
        • 5. 功能模拟与兼容性 (Workarounds)
        • 小结
      • 4. Installable Client Drivers (ICD)
        • 主要职责
        • 多驱动支持
      • 5. Vulkan Physical Device
        • 设备关系
        • 设备枚举
        • 设备类型
      • 架构总结
        • 数据流向
        • 设计优势
      • 参考资料
  • OpenGL

  • Skia

  • Graphic
  • Vulkan
阿豪
2026-01-26
目录

Vulkan 整体架构

# Vulkan 整体架构

在学习 Vulkan 之前,需要对 Vulkan 的整体架构有一定了解,而不是一开始就陷入 Vulkan API 的汪洋大海!

image

Vulkan 是一个分层架构,由 Vulkan Application、Loader、Layer 和 ICDs (Installable Client Drivers) 四个核心组件组成。这种分层设计使得 Vulkan 具有高度的灵活性和可扩展性,同时保持了良好的性能。

# 1. Vulkan Application

Vulkan Application 代表了使用 Vulkan API 的应用程序,例如:

  • 3D 游戏(如《DOOM》、《Quake》等)
  • 渲染引擎(如 Unreal Engine、Unity 等)
  • 计算软件(如机器学习推理、科学计算等)
  • 图形工具(如建模软件、视频编辑器等)

# 主要特点

  • 作用:应用程序通过调用 Vulkan 的 API 函数来发出指令(比如"绘制一个三角形"、"分配显存"或"执行计算着色器")。
  • 交互方式:如图所示,多个应用程序可以同时运行,它们并不直接与硬件对话,而是将指令发送给中间的 Loader。这种设计使得应用程序无需关心底层硬件的具体实现细节。
  • 职责:应用程序负责管理自己的渲染管线、资源分配、命令缓冲区等高级逻辑。

# 2. Loader

Loader 是 Vulkan 架构中的核心调度组件,充当"调度员"的角色。

# 工作原理

Application 在一端直接和 Loader 打交道,Loader 的另一端连接 ICDs。在 Application 和 ICDs 之间,Loader 可以插入一系列可选的 Layers。Loader 负责和各个 Layer 交互,并且支持多 GPUs 和其驱动。

任何一个 Vulkan API 函数调用都会经过 Loader、Layers 和 ICDs 的调用链。Loader 负责将 API 调用分发给合适的 Layers 和 ICDs。Vulkan 对象模型允许 Loader 插入 Layers 层,组成调用链上的一环,并最终将 Vulkan API 调用传递给 ICD。

# 主要职责

Loader 的主要职责包括:

  • 驱动管理:加载和管理一个或多个 ICDs,且保证 ICD 间不相互干扰
  • Layer 支持:支持 Vulkan Layer,Layer 是可选的,可以在运行时动态加载
  • API 分发:管理 API 的入口点,将应用程序的 API 调用分发给正确的 Layer 和驱动程序
  • 性能优化:以尽可能低的方式影响 Vulkan 应用性能,最小化开销
  • 硬件抽象:屏蔽底层不同硬件厂商的差异,让应用程序只需要面对一个统一的接口

# Android 平台实现

在 Android 平台上,Vulkan Loader 的实现位于 frameworks/native/vulkan/libvulkan/ 目录下。在这个目录下,你通常会关注以下几个关键文件:

  • loader.cpp:这是 Loader 的核心逻辑实现,负责查找驱动、加载驱动以及管理 Layer
  • api.cpp / api_gen.cpp:定义了 Vulkan API 的入口点(Entry Points)
  • swapchain.cpp:处理与 Android 显示系统(SurfaceFlinger/ANativeWindow)交互的交换链逻辑(这是 Android 独有的部分)

# 系统库位置

当 Android 系统编译完成后,Vulkan Loader 会被编译成一个动态链接库文件 libvulkan.so。在手机文件系统中的位置:

  • 64位系统:/system/lib64/libvulkan.so
  • 32位系统:/system/lib/libvulkan.so

应用程序在调用 Vulkan API 时,链接的就是这个系统库。

# 驱动查找机制

Loader 会在以下目录下寻找符合特定命名规则的动态库(驱动):

  • 64位系统:/vendor/lib64/hw/
  • 32位系统:/vendor/lib/hw/

文件名通常是 vulkan.<platform>.so。例如:

  • 在高通骁龙设备上,驱动通常是 vulkan.adreno.so 或 vulkan.qcom.so
  • 在 Mali GPU 设备上,驱动通常是 vulkan.mali.so
  • 在 PowerVR GPU 设备上,驱动通常是 vulkan.pvr.so

# 3. Vulkan Layer

Vulkan Layer 是 Vulkan 架构中的可选组件,可以增强 Vulkan 系统的功能。

# 基本概念

Layers 是可选组件,可以拦截、修改 Vulkan API 调用。Layers 是作为动态库(lib)实现的,可以通过不同方式启用,并且在 vkCreateInstance 调用时被加载。

每个 Layer 可以选择拦截任何 Vulkan API 函数。一个 Layer 不需要拦截所有 Vulkan API 函数,Layer 可以选择拦截所有已知的 Vulkan API,也可以只拦截一条特定的 Vulkan API。

# 工作原理

Layer 处于应用程序和显卡驱动之间,能够拦截、查看、甚至修改流经它的所有 Vulkan API 指令。这意味着,通过自定义 Layer,不需要修改应用程序的一行源代码,也不需要重新编译应用,你就可以通过挂载 Layer 来改变程序的行为。

# 调用链机制

当应用程序调用 Vulkan API 时,调用顺序通常是:

Application → Layer 1 → Layer 2 → ... → Layer N → ICD → GPU
1

每个 Layer 都可以:

  • 前处理:在 API 调用传递给下一个 Layer 或 ICD 之前进行处理
  • 后处理:在 API 调用返回给上一个 Layer 或 Application 之后进行处理

# 应用场景

通过自定义 Layer 可以实现非常多的特性,这里举几个例子:

# 1. 调试与代码验证(最基础的功能)

这是 Layer 机制诞生的初衷。

  • API 参数检查:这是官方 VK_LAYER_KHRONOS_validation 做的事。你可以写一个 Layer 来检查应用是否传递了非法的枚举值、空指针,或者是否在未绑定管线的情况下绘制。
  • 内存泄漏检测:拦截所有的 vkAllocateMemory 和 vkFreeMemory,记录分配堆栈。如果程序退出时还有未释放的内存,Layer 就可以报警。
  • 对象生命周期追踪:确保应用没有使用已经被销毁的 Buffer 或 Image。

# 2. 性能分析与 Profiling(开发者最爱)

你可以通过 Layer 深入了解应用的性能瓶颈。

  • FPS 统计与显示:计算 vkQueuePresentKHR 的调用间隔,实时计算帧率。
  • API 调用统计:统计一帧内调用了多少次 vkCmdDraw(绘制指令),如果数量过多(比如几千次),提示开发者使用 Instance Rendering(实例化渲染)进行优化。
  • 耗时分析:在 API 调用前后打点计时,找出哪个 Vulkan 函数最耗时(主要针对 CPU 端耗时)。
  • GPU 时间戳插入:自动在 Command Buffer 中插入 vkCmdWriteTimestamp,精确测量 GPU 执行某段渲染指令的时间。

# 3. 渲染增强与视觉修改(玩家与 Modder 最爱)

这是很多游戏工具和"外挂"的原理。

  • OSD (On-Screen Display) 叠加层:像 Steam 游戏内覆盖、Discord 浮窗、MSI Afterburner,本质上都是通过 Layer 在每一帧渲染结束前(Present 之前),向 Command Buffer 中插入绘制 UI 的指令。
  • 后处理注入 (ReShade 原理):拦截呈现操作,获取当前帧的图像,应用自定义的 Shader(如色彩校正、锐化、Bloom 泛光),然后再显示出来。
  • 线框模式 (Wireframe):强制修改光栅化状态(Rasterization State),将填充模式改为线框模式,用于查看模型结构(或者被用作透视作弊)。

# 4. 调试工具与抓帧 (Capture & Replay)

  • 截帧工具 (RenderDoc):RenderDoc 的核心就是一个复杂的 Layer。它拦截并记录一帧内所有的 API 调用和资源数据,保存下来。之后可以在另一台机器上"回放"这些指令,完美复现渲染过程。
  • 截图与录屏:在 Swapchain 展示之前,将图像数据拷贝到 CPU 内存并保存为图片或视频。

# 5. 功能模拟与兼容性 (Workarounds)

  • 功能降级或模拟:如果某个旧显卡不支持某个 Vulkan 扩展,你可以写一个 Layer 来用其他指令模拟这个功能,让应用以为显卡支持该扩展。
  • 跨平台转换:虽然不是典型的 Layer,但类似 MoltenVK 的逻辑也可以通过 Layer 实现——将 Vulkan 指令动态翻译成 Metal (macOS) 或 DX12 指令。

# 小结

自定义 Layer 赋予了你**"中间人攻击" (Man-in-the-Middle)** 的能力:

  • 观察 (Observe):看应用发了什么指令
  • 拦截 (Intercept):阻止某些指令发送给驱动
  • 修改 (Modify):偷梁换柱,修改指令参数
  • 注入 (Inject):无中生有,插入额外的渲染或计算指令

# 4. Installable Client Drivers (ICD)

ICD (Installable Client Drivers) 指的是可安装客户端驱动程序,也就是我们通常说的显卡驱动(由 NVIDIA、AMD、Intel、Qualcomm、ARM 等厂商提供)。

# 主要职责

  • 指令翻译:Loader 将经过筛选或验证的指令传递给 ICD。ICD 负责将这些标准的 Vulkan 指令翻译成特定 GPU 能够理解的机器指令。
  • 硬件抽象:ICD 封装了底层硬件的具体实现细节,向上提供统一的 Vulkan 接口。

# 多驱动支持

Vulkan 允许系统中有多个 ICD,每个 ICD 支持 1 个或者多个设备(VkPhysicalDevice)。这意味着系统里可以同时安装不同厂商的驱动,例如:

  • 桌面平台:既有集显(Intel HD Graphics)也有独显(NVIDIA GeForce 或 AMD Radeon)
  • 移动平台:可能同时存在多个 GPU(如 ARM Mali + 其他协处理器)

Loader 负责发现可用的 Vulkan ICDs。给定一系列可用 ICDs,Loader 会枚举所有 Physical Device,应用程序可以通过 vkEnumeratePhysicalDevices 获取所有可用的物理设备。

# 5. Vulkan Physical Device

Vulkan Physical Device 代表实际的物理硬件设备(GPU)。每个 ICD 可以控制一个或多个物理设备。

# 设备关系

  • 一对一关系:一个 ICD 控制一个物理设备(最常见的情况)
  • 一对多关系:一个 ICD 控制多个物理设备(例如双显卡交火、SLI/CrossFire 配置)

图中右上角展示了一个 ICD 控制两个物理设备的情况(例如双显卡交火),而右下角展示了一个 ICD 控制一个设备。

# 设备枚举

应用程序可以通过以下方式获取物理设备信息:

  • vkEnumeratePhysicalDevices:枚举所有可用的物理设备
  • vkGetPhysicalDeviceProperties:获取物理设备的属性(名称、类型、驱动版本等)
  • vkGetPhysicalDeviceFeatures:查询物理设备支持的功能
  • vkGetPhysicalDeviceQueueFamilyProperties:获取队列族属性

# 设备类型

物理设备可以是以下类型之一:

  • VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:集成 GPU(如 Intel HD Graphics)
  • VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:独立 GPU(如 NVIDIA GeForce、AMD Radeon)
  • VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:虚拟 GPU
  • VK_PHYSICAL_DEVICE_TYPE_CPU:CPU(软件渲染)
  • VK_PHYSICAL_DEVICE_TYPE_OTHER:其他类型

# 架构总结

Vulkan 的整体调用流程如下:

Application 
  ↓ (发出 Vulkan API 调用)
Loader 
  ↓ (可选:通过 Layer 进行校验、分析、修改)
ICD (厂商驱动)
  ↓ (翻译成 GPU 指令)
Physical Device (GPU)
  ↓ (执行渲染或计算)
1
2
3
4
5
6
7
8

# 数据流向

  1. Application 发出指令(如 vkCmdDraw、vkAllocateMemory 等)
  2. Loader 接收指令,可能通过 Layer 进行校验、分析或修改
  3. Loader 将指令分发给对应的厂商驱动 ICD
  4. ICD 将标准的 Vulkan 指令翻译成特定 GPU 能够理解的机器指令
  5. Physical Device (GPU) 执行渲染或计算任务

# 设计优势

这种分层架构的设计带来了以下优势:

  • 硬件抽象:应用程序无需关心底层硬件的具体实现
  • 灵活扩展:通过 Layer 机制可以灵活扩展功能
  • 多驱动支持:系统可以同时支持多个厂商的 GPU 驱动
  • 性能优化:Loader 和 Layer 的开销被控制在最低水平
  • 调试友好:Layer 机制使得调试和性能分析变得容易

# 参考资料

  • VULKAN入门学习(一)--- Loader和Layer (opens new window)
  • 《The Modern Vulkan CookBook》
  • 《Vulkan学习指南》
  • Vulkan 官方文档 (opens new window)
  • Vulkan Loader 源码 (opens new window)
最近更新
01
跨进程通信
11-24
02
Scheduler 初始化
11-24
03
显示设备初始化
10-17
更多文章>
Theme by Vdoing | Copyright © 2020-2026 AHao Framework | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式