上一次创建了vulkan的实例VkInstance对象。在这里补充一点,需要在SceneWidget类中的UnInit函数,进行资源的清理,即添加代码:
每创建一个对象,在最后都是要清理的。上次忘了清理,在这里补上。
这次要创建vulkan的VkSurfaceKHR对象,还记得KHR是什么意思吗?对,是扩展。vulkan本身是跨平台的图形接口,核心代码是不处理与窗口相关的事务的,所以在这里需要用依赖于平台系统的窗口。
由于我的系统是windows操作系统,所以在这里应该选择与win32的扩展,如果不知道这个怎么写,可以打开头文件vulkan_win32.h这个文件,看一下与CreateSurface相关的函数。
这里用的是vkCreateWin32SurfaceKHR,如果是别的系统,用到的函数就不一样了。
同样,在SceneWidget.h中添加一个protected的函数:bool CreateSurface(),返回值记录是否创建成功。
在CreateSurface()函数中,写创建surface的代码。如果不知道要先写什么,就和之前创建实例一样,先写上vkCreateWin32SurfaceKHR函数,然后补起参数。
第一个参数:VkInstance的实例,这个已经创建完成了,在这里可以直接使用m_instance。
第二个参数:VkWin32SurfaceCreateInfoKHR的指针,所以需要在vkCreateWin32SurfaceKHR的上面定义一个VkWin32SurfaceCreateInfoKHR的实例。即:
VkWin32SurfaceCreateInfoKHR win32Surface = {};同样,={}进行初始化。
可以点开这个结构的定义,看一下它的成员都是什么。
VkStructureType sType表示这个结构是什么类型的,在这里应该是VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR。
const void* pNext 表示这个结构的扩展,不知道怎么赋值时,可以先赋成nullptr,等将来真实需要赋值时再修改也可以。
VkWin32SurfaceCreateFlagsKHR flags,同样不知道怎么赋值时,先赋值为0。
HINSTANCE hinstance,windows系统下的实例句柄,这个值,如果通过代码直接调用系统的窗口时,这个值是一个有效值,是通过系统的函数来获取的。在这里,使用的是Qt的工程,所以在也赋值为nullptr。
HWND hwnd,表示需要绘制的窗口的id。在Window下应该是HWND类型,在Qt中,可以通过QWidget的winId()函数来获取,并通过HWND类型强转来得到。这里赋值为:(HWND)(winId());
第三个参数:VkAllocationCallbacks指针,在这里我们不需要记录分配的地址,所以可以设置为nullptr。
第四个参数:是生成的surface对象。可以和之前的VkInstance一样。定义一个VkSurfaceKHR m_surface;将m_surface写在这个地方。传入的是引用。
同样,vkCreateWin32SurfaceKHR函数有一个VkResult的返回值,成功返回VK_SUCCESS,如果失败则返回一个错误码。
在SceneWidget::Init函数,在创建实例之后,添加调用的代码:
if (!CreateSurface())
{
std::cout << "CreateSurface is return false." << std::endl;
return;
}
在SceneWidget::UnInit函数中,在清理m_instance之前清理资源,清理的顺序正好和创建的顺序相反。代码如下:
vkDestroySurfaceKHR(m_instance, m_surface, nullptr);
头文件的代码完整代码:
Init 和 UnInit的代码:
CreateSurface的代码:
运行的结果:
没有错误的输出。应该是成功了:)