交换链不完全匹配和交换链过期

现在我们只需要在交换链必须被重建时调用recreateSwapChain函数重建交换链即可。我们可以根据vkAcquireNextImageKHR和vkQueuePresentKHR函数返回的信息来判定交换链是否需要重建:

  • VK_ERROR_OUT_OF_DATE_KHR:交换链不能继续使用。通常发生在窗口大小改变后。

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

VkResult result = vkAcquireNextImageKHR(device, swapChain, std::numeric_limits<uint64_t>::max(),
imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);

if (result == VK_ERROR_OUT_OF_DATE_KHR) {
recreateSwapChain();
return;
} else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
throw std::runtime_error("failed to acquire swap chain image!");
}
recreateSwapChain();
return;
} else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
throw std::runtime_error("failed to acquire swap chain image!");
}

当交换链过期时,我们就不能再使用它,必须重建交换链。

但是,如果在获取交换链不可继续使用后,立即跳出这一帧的渲染,会导致我们使用的栅栏(fence)处于我们不能确定得状态。所以,我们应该在重建交换链时,重置栅栏(fence)对象,这可以通过调用vkResetFences函数完成:

vkResetFences(device, 1, &inFlightFences[currentFrame]);

if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]) != VK_SUCCESS) {
    throw std::runtime_error("failed to submit draw command buffer!");
}

我们可以在交换链不完全匹配时进行一些处理,在这里,我们没有选择在交换链不完全匹配时中断这一帧的渲染,毕竟,这种情况下,我们实际取得了可以用来绘制的交换链的图像。可以认为VK_SUCCESS和VK_SUBOPTIMAL_KHR都说明成功获取到了交换链图像:

result = vkQueuePresentKHR(presentQueue, &presentInfo);

if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
    recreateSwapChain();
} else if (result != VK_SUCCESS) {
    throw std::runtime_error("failed to present swap chain image!");
}

currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;

vkQueuePresentKHR函数的返回值与vkAcquireNextImageKHR函数的返回值有着相同的意义。在这里,为了保证最佳渲染效果,我们选择在交换链不完全匹配时也重建交换链。