Linux下GLFW创建Vulkan Surface报错 GLFW_NO_API设置未生效
根本原因
你遇到的Surface创建报错、关闭事件响应异常都不是GLFW本身的缺陷,是代码里的3个逻辑错误导致的:
- 核心错误:
initWindow函数的窗口参数为值传递,有效窗口指针丢失
C++中形参GLFWwindow *window是函数内的局部副本,你在函数内给window赋值glfwCreateWindow返回值时,仅修改了局部变量,不会改变外部app->window的值。你调用glfwWindowHint设置的GLFW_NO_API属性确实生效了,但配置正确的窗口指针只存在于initWindow的局部作用域,函数返回后就丢失了。后续所有操作拿到的app->window是未初始化的野指针,GLFW检测到传入的非法窗口对象没有配置NO_API,就会抛出65540错误,glfwWindowShouldClose无法正常工作也是同一个原因。 - 验证层检测逻辑写反
checkValidationLayerSupport函数中对strcmp的返回值判断错误:strcmp返回0代表两个字符串完全相等,你当前的写法是字符串不相等时才标记层为已找到,完全颠倒了判断逻辑,会导致验证层检测结果异常。 - 资源清理顺序错误
现有清理逻辑先销毁GLFW窗口、终止GLFW,再销毁Vulkan Surface,而Vulkan Surface是依赖GLFW窗口创建的资源,逆序销毁会触发资源泄漏或运行时错误。
修复方法
按以下步骤修改代码即可解决所有问题:
- 修改
initWindow的参数传递逻辑,保证窗口指针正确写回Application结构体
把initWindow的形参从GLFWwindow *window改为Application *app,直接在函数内给app的window成员赋值:
static void initWindow(Application *app) { glfwInit(); glfwSetErrorCallback(glfwErrorCallback); glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); app->window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Vulkan", nullptr, nullptr); if (app->window == NULL) { throw std::runtime_error("Failed to create window!\n"); } printf("Created window.\n"); glfwSetWindowCloseCallback(app->window, windowCloseCallback); glfwSetKeyCallback(app->window, keyCallback); RUNNING = true; }
对应修改runApplication中的调用为initWindow(app);即可。
- 修正验证层匹配逻辑
把checkValidationLayerSupport中的strcmp判断改为相等时才标记找到:
for (const auto &layer_properties : available_layers) { // strcmp返回0代表字符串相等 if (strcmp(layer_name, layer_properties.layerName) == 0) { found = true; break; } }
- 调整资源清理顺序
先销毁所有Vulkan资源,再销毁GLFW窗口、终止GLFW,修改cleanUp函数:
static void cleanUp(Application *app) { printf("Cleaning up!\n"); // 先销毁Vulkan相关资源 vkDestroySurfaceKHR(app->vk_instance, app->vk_surface, nullptr); vkDestroyDevice(app->vk_device, nullptr); vkDestroyInstance(app->vk_instance, nullptr); // 再销毁GLFW资源 glfwDestroyWindow(app->window); glfwTerminate(); }
对应修改runApplication中的cleanUp调用为cleanUp(app);。
修复完成后,你之前用来绕过关闭事件问题的全局RUNNING变量可以正常工作,也可以直接删除该全局变量,在主循环中直接用glfwWindowShouldClose(app->window)作为循环判断条件,不需要额外的变通方案。
内容的提问来源于stack exchange,提问作者Mr. Vermeer
相关产品推荐
相关产品推荐

