vulkan学习笔记二十二

窗口的大小变化事件处理

在之前的学习中,可以绘抽制出三角形了,但是用鼠标来改变窗口的大小时,可以看到,整个窗口会停顿一秒左右或是黑一秒左右,才会反应在过来。给人的感觉不友好。这就需要在窗口的大小发生变化时,做一些事情来处理这种情况。

《vulkan编程指南》中有说明,vulkan中对于窗口的大小变化是有处理的,即窗口大小发生变化时,会触发VK_ERROR_OUT_OF_DATE_KHR信息。但这种触发是不可靠的。需要显示处理。

所以在SceneWidget.h中添加一个成员变量bool m_resize = false;当窗口大小发生变化时,设置值为true,来记录大小是否发生了变量。在SceneWidget::DrawFrame里,检测这个变量,当m_resize值为true或是vkAcquireNextImageKHR函数和vkQueuePresentKHR返回值为VK_ERROR_OUT_OF_DATE_KHR或是VK_SUBOPTIMAL_KHR时,需要做对应的处理。

VK_ERROR_OUT_OF_DATE_KHR:交换链不能再使用,通常发生在窗口大小变化之后。

VK_SUBOPTIMAL_KHR:交换链仍然可以使用,但surface属性已经不能准确匹配。

所以先在SceneWidget:: resizeEvent函数中,将m_resize的值赋成true。然后在DrawFrame函数修改现有的代码进行处理。

在vkAcquireNextImageKHR函数调用之后,判断是否返回VK_ERROR_OUT_OF_DATE_KHR,如果是,则重建交换链

如果返回的是不是VK_ERROR_OUT_OF_DATE_KHR、VK_SUBOPTIMAL_KHR也不是VK_SUCCESS,输出错误日志。

即把原来的if换成下面的:

if (result == VK_ERROR_OUT_OF_DATE_KHR)

{

    RecreateSwapChain();

}

else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)

{

    std::cout << "vkAcquireNextImageKHR return failed." << std::endl;

}

同样vkQueuePresentKHR的返回值也要判断,如果返回值是VK_ERROR_OUT_OF_DATE_KHR、VK_SUBOPTIMAL_KHR或者m_resize为true时,重建交换链。

添加如下判断的代码:

if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || _bFramebufferResized)

{

    m_resize = false;

    RecreateSwapChain();

}

else if (result != VK_SUCCESS)

{

    std::cout << "failed to present swap chain image!" << std::endl;

}

在SceneWidget.h中添加void RecreateSwapChain()函数,在函数里进行重建操作。

重建交换链调用RecreateSwapChain函数,窗口的大小发生变化,实际上是之前在创建Device时,对物理设备进行检查时,调用:

对m_capabilities中的currentExtent发生了变化。

所以基于这个m_capabilities. currentExtent创建出的对象,都需要删除重建。

在RecreateSwapChain()函数中主要做两个事情。

一:将基于这个m_capabilities. currentExtent创建出的对象删除

二:根据新的m_capabilities. currentExtent的值,把删除的对象再重建出来。

在SceneWidget.h中再添加一个函数,void CleanupSwapchain()进行删除。

然后在RecreateSwapChain()函数中先调用一下vkDeviceWaitIdle(m_device);先等待一下之前的绘制。

调用CleanupSwapchain(),删除之前创建的与m_capabilities. currentExtent相关的对象。

改写之前的SceneWidget::UnInit函数,将其中删除的与m_capabilities. currentExtent相关的对象,放入到CleanupSwapchain()里,并在SceneWidget::UnInit中调用CleanupSwapchain(),调用完成后,再生成这些被删除的对象。

与m_capabilities. currentExtent相关的对象,有:

VkSwapchainKHR、VkSwapchainKHR相关的VkImage和VkImageView、VkRenderPass、VkFrameBuffer、VkGraphicsPipeline(与renderPass相关,还创建了VkGraphicsPipelineLayout)、VkFrameBuffer、深度和颜色相关的VkImage和VkImageView。

运行结果:

vulkan学习笔记二十二_第1张图片

改变窗口大小时,就好多了。

你可能感兴趣的:(c++,开发语言)