vkSurface 概述
Vulkan
是一个平台无关的图形 API,这意味着它不能直接与特定的窗口系统 (Windows
,linux
和 macOS
的窗口系统) 进行交互,但是在屏幕上渲染的需求客观存在
为了解决这个问题,Vulkan
引入了窗口系统集成 (Window System Intergration WSI
) 机制,使得 Vulkan
应用程序可以与不同操作系统的窗口系统 (比如 Windows
的 Win32
、Linux
的 X11
或者 Wayland
、Android
的 ANativeWindow
) 进行交互
这些机制运行 Vulkan
应用程序在窗口系统中创建和管理表面(Surface
),并和图形硬件交换图像(Swapchain
)
VK_KHR_surface
是WSI
的核心扩展(instance
扩展),是 Vulkan
中用于渲染表面的对象,是一个平台无关的抽象类型,用于封装与窗口系统相关的表面信息,通过这个对象,Vulkan
可以将渲染结果输出到窗口上
创建窗口表面
VkSurfaceKHR
对象是平台无关的,但是创建VkSurfaceKHR
对象时,不同的窗口系统需要使用不同的 API
:
vkCreateAndroidSurfaceKHR()
vkCreateWaylandSurfaceKHR()
vkCreateWin32SurfaceKHR()
vkCreateXcbSurfaceKHR()
需要注意的是,创建Vulkan
实例的时候需要提前设置好相应的扩展:
std::vector<const char*> instance_extensions;
instance_extensions.push_back("VK_KHR_surface");
instance_extensions.push_back("VK_KHR_win32_surface");//win32
instanceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(instance_extensions.size());
instanceCreateInfo.ppEnabledExtensionNames = instance_extensions.data();
VkResult result = vkCreateInstance(&instanceCreateInfo, nullptr, &instance);
Windows
系统上是借助于glfw
创建出的window
完成 VkSurfaceKHR
的创建:
WSI
Vulkan
与 WSI
(Window System Integration
,窗口系统集成)主要集中在 Surface
,SwapChain
,呈现(Presentation
)和平台适配层等多个部分
-
vkSurfaceKHR
表面属性(支持的格式,大小等),主要用来获取窗口表面的信息 -
VkSwapchainKHR
提供一组vkImage
用于渲染,控制呈现模式(MailBox
orImmedaite
) 并处理窗口大小的变化 -
呈现(
vkQueuePresentKHR
)
用于将SwapChain
中的图像呈现到屏幕
参考代码
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
#define GLFW_EXPOSE_NATIVE_WIN32
#include <GLFW/glfw3native.h>
#include <vulkan/vulkan_win32.h>
void vulkanBasicDemo::vulkanCreateVulkanSurface() {
// 获取 instance extension
uint32_t extensionCount = 0;
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
std::vector<VkExtensionProperties> availableExtensions(extensionCount);
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, availableExtensions.data());
if (!isExtensionSupported("VK_KHR_win32_surface", availableExtensions)) {
throw std::runtime_error("VK_KHR_win32_surface extension not supported");
}
std::cout << "instance support VK_KHR_win32_surface" << std::endl;
glfwInit();
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow* window = glfwCreateWindow(800, 600, "Vulkan window", nullptr, nullptr);
VkWin32SurfaceCreateInfoKHR createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
createInfo.pNext = nullptr;
createInfo.flags = 0;
createInfo.hwnd = glfwGetWin32Window(window);
createInfo.hinstance = GetModuleHandle(nullptr);
VkResult result = vkCreateWin32SurfaceKHR(instance, &createInfo, nullptr, &surface);
if (result != VK_SUCCESS) {
throw std::runtime_error("vkCreateWin32SurfaceKHR failed");
}
vkDestroySurfaceKHR(instance, surface, nullptr);
glfwDestroyWindow(window);
glfwTerminate();
}