Vulkan 创建 VK_KHR_surface 时出错:VK_ERROR_EXTENSION_NOT_PRESENT(扩展不存在)

Number of views 27

我正在通过这个教程学习 Vulkan。我已经用 GLFW 创建了窗口,并且成功初始化了 Vulkan 实例,没有出现错误。但 Vulkan 在创建 VKSurfaceKHR 时失败了。

bool CreateRenderContext(RenderContext* contextOut)
{
  glfwInit();
  glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
  glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
  contextOut->window = glfwCreateWindow(contextOut->width, contextOut->height, "Vulkan", NULL, NULL);

  if(!CreateVulkanInstance(contextOut->instance))
  {
    printf("failed creating vulkan instance\n");
  }

  if(!glfwVulkanSupported())
  {
    return false;
  }

  VkResult err = glfwCreateWindowSurface(contextOut->instance, contextOut->window,nullptr, &contextOut->surface);
  if (err != VK_SUCCESS)
  {
    // 窗口表面创建失败
    printf("failed to create surface");
    return false;
  }
  return true;
}

CreateVulkanInstance() 函数如下:

bool CreateVulkanInstance(VkInstance  instanceOut)
{
  VkApplicationInfo appInfo = {};
  appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
  appInfo.pApplicationName = "Hello Triangle";
  appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
  appInfo.pEngineName = "No Engine";
  appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
  appInfo.apiVersion = VK_API_VERSION_1_0;

  VkInstanceCreateInfo createInfo = {};
  createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  createInfo.pApplicationInfo = &appInfo;

  uint32_t glfwExtensionCount = 0;
  const char** glfwExtensions = nullptr;
  glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);

  createInfo.enabledExtensionCount = glfwExtensionCount;
  createInfo.ppEnabledExtensionNames = glfwExtensions;
  createInfo.enabledLayerCount = 0;

  if (vkCreateInstance(&createInfo, nullptr, &instanceOut) != VK_SUCCESS)
  { 
    return false;
  }

  return true;
}

GLFW 返回了以下所需的扩展:

VK_KHR_surface
VK_KHR_xcb_surface

VkResult err = glfwCreateWindowSurface(contextOut->instance, contextOut->window,nullptr, &contextOut->surface); 返回了 VK_ERROR_EXTENSION_NOT_PRESENT

为什么表面创建会失败?

我的系统:Ubuntu 18.04 64位,NVIDIA RTX 3000,GPU 驱动 NVIDIA 430。

2 Answers

这边错了:

bool CreateVulkanInstance(VkInstance  instanceOut) {
   vkCreateInstance(&createInfo, nullptr, &instanceOut)
}

这里应该是 VkInstance&

在你的代码中,VK_KHR_xcb_surface 扩展可能未被启用,导致 vkCreateWindowSurface 调用失败并返回 VK_ERROR_EXTENSION_NOT_PRESENT。你提到的系统是 Ubuntu 18.04,这通常使用 XCB 来管理窗口系统。

你可以尝试显式地启用 VK_KHR_xcb_surface 扩展。以下是修改后的代码:

  1. 获取所需的扩展列表。
  2. VK_KHR_xcb_surface 添加到启用的扩展列表中。
#include <vulkan/vulkan.h>
#include <GLFW/glfw3.h>

bool CreateRenderContext(RenderContext* contextOut)
{
    glfwInit();
    glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
    glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
    contextOut->window = glfwCreateWindow(contextOut->width, contextOut->height, "Vulkan", NULL, NULL);

    if (!CreateVulkanInstance(contextOut->instance))
    {
        printf("failed creating vulkan instance\n");
    }

    if (!glfwVulkanSupported())
    {
        return false;
    }

    VkResult err = glfwCreateWindowSurface(contextOut->instance, contextOut->window, nullptr, &contextOut->surface);
    if (err != VK_SUCCESS)
    {
        // 窗口表面创建失败
        printf("failed to create surface\n");
        return false;
    }
    return true;
}

bool CreateVulkanInstance(VkInstance instanceOut)
{
    VkApplicationInfo appInfo = {};
    appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
    appInfo.pApplicationName = "Hello Triangle";
    appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
    appInfo.pEngineName = "No Engine";
    appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
    appInfo.apiVersion = VK_API_VERSION_1_0;

    VkInstanceCreateInfo createInfo = {};
    createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
    createInfo.pApplicationInfo = &appInfo;

    uint32_t glfwExtensionCount = 0;
    const char** glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);

    // 添加 VK_KHR_xcb_surface 扩展
    const char* xcbSurfaceExtension = VK_KHR_XCB_SURFACE_EXTENSION_NAME;
    const char* extensions[glfwExtensionCount + 1];
    for (uint32_t i = 0; i < glfwExtensionCount; ++i)
    {
        extensions[i] = glfwExtensions[i];
    }
    extensions[glfwExtensionCount] = xcbSurfaceExtension;

    createInfo.enabledExtensionCount = glfwExtensionCount + 1;
    createInfo.ppEnabledExtensionNames = extensions;
    createInfo.enabledLayerCount = 0;

    if (vkCreateInstance(&createInfo, nullptr, &instanceOut) != VK_SUCCESS)
    {
        return false;
    }

    return true;
}

在这个修改后的代码中,我们首先获取 GLFW 所需的扩展列表,然后将 VK_KHR_xcb_surface 添加到这些扩展中。这样可以确保在创建 Vulkan 实例时启用所有必要的扩展。

请确保你的 NVIDIA GPU 驱动已经正确安装并且支持 Vulkan。你可以通过运行 vulkaninfo 命令来检查 Vulkan 的安装和驱动状态。如果一切正常,你应该能够看到 VK_KHR_xcb_surface 扩展被列出。