在 Vulkan 中,Window Surface(窗口表面,通常对应句柄 VkSurfaceKHR) 是一个连接 Vulkan 图形管道 与 操作系统的窗口系统(OS Window System) 的跨平台抽象层桥梁。
简单来说:Vulkan 本身是一个极其纯粹的硬件渲染 API,它甚至不知道屏幕、窗口、或者“显示”是什么。它只负责在显存里往一片内存(Image)里涂颜色。
而 Window Surface 就是我们向操作系统申请的一块“画布”,有了它,Vulkan 才知道应该把显存里画好的图像投递到屏幕的哪个具体窗口上。
1. 为什么不能直接画在窗口上?(核心痛点)#
在老旧图形 API 比如 OpenGL 中,API 会隐式地处理与操作系统的对接。但 Vulkan 为了追求绝对的平台无关性,把底牌彻底掀开了:
- Vulkan 的世界: 只有物理设备、逻辑设备、命令缓冲区、渲染管线、显存。
- 操作系统的世界: Windows 认的是
HWND(窗口句柄)和HDC;Linux 认的是Window变体(X11 或 Wayland);macOS 认的是CAMetalLayer。
VkSurfaceKHR 就是那个连接两者的中间人。 它把操作系统的原生窗口句柄(比如 Windows 的 HWND)包装起来,变成一个通用的、Vulkan 认识的对象。
2. 名字后面的 KHR 代表什么?#
如果仔细观察,会发现核心的 Vulkan 对象(如 VkDevice、VkImage)后面都没有后缀,而 VkSurfaceKHR 后面跟着 KHR。
其中,KHR 代表 Khronos 官方扩展(Window System Integration, WSI)。
- 因为并不是所有的 Vulkan 程序都需要显示器。比如运行在高性能服务器上的 AI 训练、离线光线追踪渲染器,它们只需要把渲染结果保存为图片,不需要弹出一个窗口。
- 因此,窗口显示功能被剥离出了核心规范,放进了扩展里。
VkSurfaceKHR就是由全局扩展VK_KHR_surface引入的。
3. Window Surface 是如何创建的?#
由于每个操作系统的窗口系统底层实现完全不同,Vulkan 官方针对不同平台提供了专属的“特化创建函数”。
1#if defined(VK_USE_PLATFORM_WIN32_KHR)
2 // Windows 专用的创建表单
3 VkWin32SurfaceCreateInfoKHR createInfo{};
4 createInfo.hwnd = hwnd; // 传入 Win32 的窗口句柄
5 vkCreateWin32SurfaceCreateInfoKHR(...);
6 #elif defined(VK_USE_PLATFORM_XLIB_KHR)
7 // Linux X11 专用
8 VkXlibSurfaceCreateInfoKHR createInfo{};
9 vkCreateXlibSurfaceKHR(...);
10#endif
C++ 现代工程实践(配合 GLFW)#
但是现在几乎没有人会去纯手写上面那些恶心的平台宏。我们通常会使用 GLFW。GLFW 会在内部自动判断当前的操作系统,只需要一行代码,它就能把 VkSurfaceKHR 完美创建出来:
1VkSurfaceKHR surface;
2// GLFW 内部会自动调用 vkCreateWin32SurfaceKHR 或 vkCreateXlibSurfaceKHR
3if (glfwCreateWindowSurface(instance, window, nullptr, &surface) != VK_SUCCESS) {
4 throw std::runtime_error("Failed to create window surface!");
5}
4. 拥有 Surface 之后,下一步做什么?#
创建好 Window Surface 只是第一步。在整个 Vulkan 初始化生命周期里,它是后续两个极为核心的步骤的强依赖参数:
① 筛选硬件队列族(Present Support Check)#
我们在聊“呈现队列”时提过,你需要拿着这个创建好的 surface 去质问物理显卡:“你的哪个队列族,能把画画好之后的图像安全地扔进这个 surface 里显示出来?”
1VkBool32 presentSupport = VK_FALSE;
2vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface, &presentSupport);
② 创建交换链(Swapchain)#
这是 Surface 最重要的归宿。有了 Surface,你才能向显卡申请交换链(Swapchain)。
交换链会在这个 Surface 背后开辟一个“前台缓冲区”和“后台缓冲区”(通常是 2~3 张图形图片,即双重缓冲或三重缓冲)。GPU 在后台缓冲区拼命画画,画完之后,通过交换链,把图片平铺到这个 Surface 上展示给玩家看。