ScreenLockDetector/docs/VULKAN_WIDGET_SUMMARY.md

8.5 KiB
Raw Permalink Blame History

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 属性设置

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)

VkWin32SurfaceCreateInfoKHR createInfo = {};
createInfo.hwnd = reinterpret_cast<HWND>(window->winId());
createInfo.hinstance = GetModuleHandle(nullptr);
vkCreateWin32SurfaceKHR(m_instance, &createInfo, nullptr, &m_surface);

Linux (Xlib)

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)

VkMetalSurfaceCreateInfoEXT createInfo = {};
createInfo.pLayer = nullptr; // 需要正确的 Metal 层设置
vkCreateMetalSurfaceEXT(m_instance, &createInfo, nullptr, &m_surface);

渲染循环

渲染循环以约 60 FPS16ms 间隔)运行:

  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

构建命令

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 支持的版本

./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 驱动
  • 运行 vulkaninfovkcube 验证 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 下载

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 子模块

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

cp -r $HOME/sdk/volk-1.4.304/* third_party/volk/

与锁屏检测的集成

虽然当前 VulkanWidget 可以独立工作,但可以轻松集成锁屏检测功能:

// 在 MainWindow::onLockStateChanged() 中添加
if (m_vulkanWidget) {
    m_vulkanWidget->setRenderingEnabled(!locked);
}

这样当屏幕锁定时Vulkan 渲染会自动暂停,节省 GPU 资源。

扩展建议

短期改进

  • 添加调试模式的验证层
  • 实现完整的渲染通道和帧缓冲
  • 添加图形管线和着色器
  • 实现几何体渲染
  • 与锁屏检测集成(锁定时暂停渲染)

长期改进

  • 添加纹理支持
  • 实现多线程命令缓冲区录制
  • 添加性能指标FPS、帧时间
  • 支持 Linux Wayland
  • 改进 macOS Metal 层设置
  • 添加高级渲染效果(光照、阴影等)

参考资源

许可证

此 Vulkan 集成遵循主项目的许可证。Volk 使用 MIT 许可证。

贡献者

  • 实现了 VulkanWidget 类及其完整的 Vulkan 渲染管线
  • 集成了 volk 元加载器以实现动态 Vulkan 加载
  • 添加了条件编译支持,使 Vulkan 成为可选功能
  • 更新了 MainWindow 以支持 Tab 式界面
  • 提供了详细的文档和故障排除指南