显式处理窗口大小改变

尽管许多驱动程序会在窗口大小改变后触发VK_ERROR_OUT_OF_DATE_KHR信息,但这种触发并不可靠,所以我们最好添加一些代码来显式地在窗口大小改变时重建交换链。我们添加一个新的变量来标记窗口大小是否发生改变:

std::vector<VkFence> inFlightFences;
size_t currentFrame = 0;

bool framebufferResized = false;

修改drawFrame函数,检测我们加入的标记:

if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || 
framebufferResized) {
    framebufferResized = false;
    recreateSwapChain();
} else if (result != VK_SUCCESS) {
        ...
}

使用glfwSetFramebufferSizeCallback函数设置处理窗口大小改变的回调函数:

void initWindow() {
    glfwInit();

    glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);

    window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);
    glfwSetFramebufferSizeCallback(window, framebufferResizeCallback);
}

static void framebufferResizeCallback(GLFWwindow* window, int width, int height) {

}

需要注意代码中,我们定义framebufferResizeCallback为静态函数,这样才能将其用作回调函数。 framebufferResizeCallback回调函数有一个GLFWwindow类型的参数,我们可以使用这一参数来引用GLFW窗口。GLFW允许我们将任意的指针使用glfwSetWindowUserPointer函数存储在GLFW窗口相关的数据中:

window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);
glfwSetWindowUserPointer(window, this);
glfwSetFramebufferSizeCallback(window, framebufferResizeCallback);

我们可以通过glfwGetWindowUserPointer函数获取使用glfwSetWindowUserPointer函数存储的指针,在这里我们使用它们来存储应用程序类的this指针:

static void framebufferResizeCallback(GLFWwindow* window, int width, int height) {
    auto app = reinterpret_cast<HelloTriangleApplication*>(glfwGetWindowUserPointer(window));
    app->framebufferResized = true;
}

现在编译运行程序,改变应用程序窗口大小,观察帧缓冲是否随着窗口大小改变而被正确地重新设置。