298 lines
8.5 KiB
Markdown
298 lines
8.5 KiB
Markdown
# Vulkan Widget 集成总结
|
||
|
||
## 概述
|
||
|
||
本项目已成功集成了一个基于 Vulkan 的渲染组件 `VulkanWidget`,该组件使用 Qt 的 native window 属性来创建 Vulkan Surface,并通过 volk 机制动态加载 Vulkan 函数。
|
||
|
||
## 主要特性
|
||
|
||
### 1. VulkanWidget 组件
|
||
- **文件位置**: `src/vulkanwidget.h`, `src/vulkanwidget.cpp`
|
||
- **功能**: 使用 Vulkan API 进行硬件加速渲染
|
||
- **特点**:
|
||
- 使用 Qt Native Window 属性创建平台特定的 Vulkan Surface
|
||
- 支持跨平台(Windows、Linux、macOS)
|
||
- 自动管理 Swapchain 生命周期
|
||
- 窗口大小变化时自动重建 Swapchain
|
||
- 帧同步机制(使用 Semaphore 和 Fence)
|
||
- 简单的颜色循环渲染演示
|
||
|
||
### 2. Volk 集成
|
||
- **版本**: 1.3.295
|
||
- **位置**: `third_party/volk/`
|
||
- **特点**:
|
||
- 动态加载 Vulkan 函数,无需链接 Vulkan 库
|
||
- 支持实例级和设备级函数加载
|
||
- 以静态库形式嵌入项目
|
||
- 避免了 Vulkan SDK 版本冲突问题
|
||
|
||
### 3. 条件编译支持
|
||
- 使用 `ENABLE_VULKAN_WIDGET` 宏控制 Vulkan 功能的编译
|
||
- 如果系统没有安装 Vulkan SDK,项目仍可正常编译和运行
|
||
- CMake 选项 `ENABLE_VULKAN` 可以手动控制是否启用 Vulkan 支持
|
||
|
||
## 技术实现细节
|
||
|
||
### Qt Native Window 属性设置
|
||
|
||
```cpp
|
||
setAttribute(Qt::WA_NativeWindow); // 创建原生窗口句柄
|
||
setAttribute(Qt::WA_PaintOnScreen); // 直接在屏幕上绘制
|
||
setAttribute(Qt::WA_OpaquePaintEvent); // 组件不透明
|
||
```
|
||
|
||
这些属性确保:
|
||
- Qt 创建可通过 `windowHandle()` 访问的原生窗口句柄
|
||
- Qt 不会干扰 Vulkan 渲染
|
||
- 组件拥有自己的绘制表面
|
||
|
||
### Vulkan 初始化流程
|
||
|
||
1. **初始化 Volk**: `volkInitialize()` 加载 Vulkan 加载器
|
||
2. **创建 Instance**: 创建 Vulkan 实例,包含必需的 Surface 扩展
|
||
3. **创建 Surface**: 从原生窗口句柄创建平台特定的 Surface
|
||
4. **选择物理设备**: 查找支持图形和呈现的 GPU
|
||
5. **创建逻辑设备**: 创建带有 Swapchain 扩展的设备
|
||
6. **创建 Swapchain**: 设置适当格式和呈现模式的交换链
|
||
7. **创建命令对象**: 分配命令池和命令缓冲区
|
||
8. **创建同步对象**: 创建用于帧同步的 Semaphore 和 Fence
|
||
|
||
### 平台特定 Surface 创建
|
||
|
||
#### Windows (Win32)
|
||
```cpp
|
||
VkWin32SurfaceCreateInfoKHR createInfo = {};
|
||
createInfo.hwnd = reinterpret_cast<HWND>(window->winId());
|
||
createInfo.hinstance = GetModuleHandle(nullptr);
|
||
vkCreateWin32SurfaceKHR(m_instance, &createInfo, nullptr, &m_surface);
|
||
```
|
||
|
||
#### Linux (Xlib)
|
||
```cpp
|
||
VkXlibSurfaceCreateInfoKHR createInfo = {};
|
||
createInfo.dpy = qApp->platformNativeInterface()->nativeResourceForWindow("display", window);
|
||
createInfo.window = static_cast<Window>(window->winId());
|
||
vkCreateXlibSurfaceKHR(m_instance, &createInfo, nullptr, &m_surface);
|
||
```
|
||
|
||
#### macOS (Metal)
|
||
```cpp
|
||
VkMetalSurfaceCreateInfoEXT createInfo = {};
|
||
createInfo.pLayer = nullptr; // 需要正确的 Metal 层设置
|
||
vkCreateMetalSurfaceEXT(m_instance, &createInfo, nullptr, &m_surface);
|
||
```
|
||
|
||
### 渲染循环
|
||
|
||
渲染循环以约 60 FPS(16ms 间隔)运行:
|
||
|
||
1. 等待上一帧的 Fence
|
||
2. 获取下一个 Swapchain 图像
|
||
3. 重置并记录命令缓冲区
|
||
4. 使用 Semaphore 同步提交命令缓冲区
|
||
5. 将图像呈现到屏幕
|
||
6. 必要时处理 Swapchain 重建
|
||
|
||
## 项目结构
|
||
|
||
```
|
||
ScreenLockDetector/
|
||
├── src/
|
||
│ ├── vulkanwidget.h # VulkanWidget 类声明
|
||
│ ├── vulkanwidget.cpp # VulkanWidget 实现
|
||
│ ├── mainwindow.h # 已更新:集成 VulkanWidget
|
||
│ └── mainwindow.cpp # 已更新:添加 VulkanWidget Tab
|
||
├── third_party/
|
||
│ └── volk/ # Volk 元加载器源码
|
||
│ ├── volk.h # Volk 头文件
|
||
│ ├── volk.c # Volk 实现
|
||
│ └── ...
|
||
├── CMakeLists.txt # 已更新:Vulkan/volk 支持
|
||
├── VULKAN_INTEGRATION.md # Vulkan 集成详细文档
|
||
└── VULKAN_WIDGET_SUMMARY.md # 本文件
|
||
```
|
||
|
||
## 用户界面
|
||
|
||
主窗口现在包含两个 Tab:
|
||
|
||
1. **QPainter Widget Tab**:
|
||
- 原有的自定义组件,使用 Qt 的 QPainter
|
||
- 显示动态动画效果
|
||
|
||
2. **Vulkan Widget Tab**:
|
||
- 新的 Vulkan 渲染组件
|
||
- 显示颜色循环效果
|
||
- 控制按钮:
|
||
- Enable Rendering: 初始化 Vulkan(如需)并开始渲染
|
||
- Disable Rendering: 停止渲染循环
|
||
- Reset Frame Count: 重置帧计数器
|
||
- 状态信息:
|
||
- Vulkan Status: 初始化状态和错误消息
|
||
- Rendering Status: 渲染是否激活
|
||
- Frame Count: 已渲染的总帧数
|
||
|
||
## 构建说明
|
||
|
||
### 前提条件
|
||
|
||
**启用 Vulkan 支持时**:
|
||
- Vulkan SDK (LunarG)
|
||
- Qt5 (5.15 或更高版本)
|
||
- X11 开发库(仅 Linux): `sudo apt install libx11-dev`
|
||
|
||
**禁用 Vulkan 支持时**:
|
||
- 仅需 Qt5
|
||
|
||
### 构建命令
|
||
|
||
```bash
|
||
cd ScreenLockDetector
|
||
mkdir -p build
|
||
cd build
|
||
|
||
# 启用 Vulkan 支持(默认)
|
||
cmake ..
|
||
|
||
# 或禁用 Vulkan 支持
|
||
cmake -DENABLE_VULKAN=OFF ..
|
||
|
||
make
|
||
```
|
||
|
||
### CMake 配置选项
|
||
|
||
- `ENABLE_VULKAN`: 启用/禁用 Vulkan 支持(默认: ON)
|
||
- 如果找不到 Vulkan SDK,将自动禁用 Vulkan 支持
|
||
- 如果 volk 源码不存在,将自动禁用 Vulkan 支持
|
||
|
||
## 运行说明
|
||
|
||
### 启用 Vulkan 支持的版本
|
||
|
||
```bash
|
||
./build/bin/ScreenLockDetector
|
||
```
|
||
|
||
应用启动后:
|
||
1. 切换到 "Vulkan Widget" Tab
|
||
2. 点击 "Enable Rendering" 按钮
|
||
3. 观察颜色循环效果
|
||
4. 查看状态信息了解渲染状态
|
||
|
||
### 禁用 Vulkan 支持的版本
|
||
|
||
应用将正常运行,但不显示 "Vulkan Widget" Tab,仅显示 "QPainter Widget" Tab。
|
||
|
||
## 故障排除
|
||
|
||
### Vulkan 初始化失败
|
||
|
||
**问题**: "Failed to initialize volk" 或 "Failed to create Vulkan instance"
|
||
|
||
**解决方案**:
|
||
- 确保已安装 Vulkan SDK 和最新的 Vulkan 驱动
|
||
- 运行 `vulkaninfo` 或 `vkcube` 验证 Vulkan 环境
|
||
- 检查环境变量 `VK_LOADER_DEBUG=all` 查看加载器活动
|
||
|
||
### Surface 创建失败
|
||
|
||
**问题**: "Failed to create Vulkan surface"
|
||
|
||
**Linux 解决方案**:
|
||
- 确保已安装 X11 开发库
|
||
- 确认应用在 X11 下运行(非 Wayland)
|
||
- 验证 DISPLAY 环境变量已设置
|
||
|
||
**macOS 解决方案**:
|
||
- 确保 MoltenVK 已正确安装
|
||
- 检查设备是否支持 Metal
|
||
|
||
### 黑屏或无渲染
|
||
|
||
**问题**: 组件显示但无内容渲染
|
||
|
||
**解决方案**:
|
||
- 检查状态消息是否有初始化错误
|
||
- 确认已点击 "Enable Rendering"
|
||
- 查看控制台输出是否有 Vulkan 错误
|
||
- 确保窗口可见且大小非零
|
||
|
||
## volk 源码获取
|
||
|
||
如果 `third_party/volk/` 目录为空,可以通过以下方式获取 volk 源码:
|
||
|
||
### 方法 1: 从 GitHub 下载
|
||
|
||
```bash
|
||
cd third_party/volk
|
||
curl -L https://github.com/zeux/volk/archive/refs/tags/1.3.295.tar.gz -o volk.tar.gz
|
||
tar xzf volk.tar.gz --strip-components=1
|
||
rm volk.tar.gz
|
||
```
|
||
|
||
### 方法 2: 使用 Git 子模块
|
||
|
||
```bash
|
||
cd third_party
|
||
git submodule add https://github.com/zeux/volk.git
|
||
git submodule update --init --recursive
|
||
```
|
||
|
||
### 方法 3: 手动复制
|
||
|
||
如果已有 volk 源码(例如在 `$HOME/sdk/volk-1.4.304`):
|
||
|
||
```bash
|
||
cp -r $HOME/sdk/volk-1.4.304/* third_party/volk/
|
||
```
|
||
|
||
## 与锁屏检测的集成
|
||
|
||
虽然当前 VulkanWidget 可以独立工作,但可以轻松集成锁屏检测功能:
|
||
|
||
```cpp
|
||
// 在 MainWindow::onLockStateChanged() 中添加
|
||
if (m_vulkanWidget) {
|
||
m_vulkanWidget->setRenderingEnabled(!locked);
|
||
}
|
||
```
|
||
|
||
这样,当屏幕锁定时,Vulkan 渲染会自动暂停,节省 GPU 资源。
|
||
|
||
## 扩展建议
|
||
|
||
### 短期改进
|
||
- [ ] 添加调试模式的验证层
|
||
- [ ] 实现完整的渲染通道和帧缓冲
|
||
- [ ] 添加图形管线和着色器
|
||
- [ ] 实现几何体渲染
|
||
- [ ] 与锁屏检测集成(锁定时暂停渲染)
|
||
|
||
### 长期改进
|
||
- [ ] 添加纹理支持
|
||
- [ ] 实现多线程命令缓冲区录制
|
||
- [ ] 添加性能指标(FPS、帧时间)
|
||
- [ ] 支持 Linux Wayland
|
||
- [ ] 改进 macOS Metal 层设置
|
||
- [ ] 添加高级渲染效果(光照、阴影等)
|
||
|
||
## 参考资源
|
||
|
||
- **Vulkan 教程**: https://vulkan-tutorial.com/
|
||
- **Vulkan 规范**: https://www.khronos.org/registry/vulkan/
|
||
- **Volk 仓库**: https://github.com/zeux/volk
|
||
- **Qt Native Interface**: https://doc.qt.io/qt-5/qpa.html
|
||
- **Vulkan SDK**: https://vulkan.lunarg.com/
|
||
|
||
## 许可证
|
||
|
||
此 Vulkan 集成遵循主项目的许可证。Volk 使用 MIT 许可证。
|
||
|
||
## 贡献者
|
||
|
||
- 实现了 VulkanWidget 类及其完整的 Vulkan 渲染管线
|
||
- 集成了 volk 元加载器以实现动态 Vulkan 加载
|
||
- 添加了条件编译支持,使 Vulkan 成为可选功能
|
||
- 更新了 MainWindow 以支持 Tab 式界面
|
||
- 提供了详细的文档和故障排除指南 |