Mac OS 上 CLion 中的新 Vulkan 项目不会创建 VkInstance

Posted

技术标签:

【中文标题】Mac OS 上 CLion 中的新 Vulkan 项目不会创建 VkInstance【英文标题】:New Vulkan project in CLion on Mac OS will not create VkInstance 【发布时间】:2018-12-04 22:04:20 【问题描述】:

在我第一次成功尝试使用 Java 和 OpenGL (LWJGL3) 的 3D 引擎后,我决定尝试使用 C++ 的 Vulkan。 我几乎没有任何 C/C++ 经验,而且我知道 Vulkan 的陡峭学习曲线。不过这不是问题。

我决定学习这个教程:https://vulkan-tutorial.com/Introduction

它向我展示了如何使用 XCode 使用 Vulkan 创建一个新项目(就像我在 Mac OS Mojave 上一样)。但是,我希望使用 CLion 继续本教程的其余部分,因为我将在多个操作系统之间切换。

我尝试创建一个 CLion 项目并成功创建了我的第一个 CMakeLists 文件,但似乎有些问题。该文件目前包含以下内容:

cmake_minimum_required(VERSION 3.12)
project(VulkanTesting)

set(CMAKE_CXX_STANDARD 14)

add_executable(VulkanTesting main.cpp)

include_directories(/usr/local/include)
include_directories(/Users/[username]/Documents/Vulkan/SDK/vulkansdk-macos-1.1.92.1/macOS/include)

target_link_libraries(VulkanTesting /usr/local/lib/libglfw.3.3.dylib)
target_link_libraries(VulkanTesting /Users/[username]/Documents/Vulkan/SDK/vulkansdk-macos-1.1.92.1/macOS/lib/libvulkan.1.dylib)
target_link_libraries(VulkanTesting /Users/[username]/Documents/Vulkan/SDK/vulkansdk-macos-1.1.92.1/macOS/lib/libvulkan.1.1.92.dylib)

# Don't know if I need the next two lines
link_directories(/usr/local/lib)
link_directories(/Users/[username]/Documents/Vulkan/SDK/vulkansdk-macos-1.1.92.1/macOS/lib)

我展示上述文件的原因将在问题中变得显而易见。

到目前为止的“程序”如下:

#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>

#include <iostream>
#include <stdexcept>
#include <functional>
#include <cstdlib>
#include <vector>

const int WIDTH = 800;
const int HEIGHT = 600;

class HelloTriangleApplication 
public:
    void run() 
        initWindow();
        initVulkan();
        mainLoop();
        cleanup();
    

private:
    GLFWwindow* window;
    VkInstance instance;

    void initWindow()
        glfwInit();
        glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
        glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
        window = glfwCreateWindow(WIDTH, HEIGHT, "My first Vulkan window", nullptr, nullptr);
    

    void initVulkan() 
        createInstance();
    

    void createInstance()
        // Instantiate Application Info
        VkApplicationInfo applicationInfo = ;
        applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
        applicationInfo.pApplicationName = "Hello Triangle";
        applicationInfo.applicationVersion = VK_MAKE_VERSION(1,0,0);
        applicationInfo.pEngineName = "No Engine";
        applicationInfo.engineVersion = VK_MAKE_VERSION(1,0,0);
        applicationInfo.apiVersion = VK_API_VERSION_1_0;

        // Instantiate Instance Creation Info
        VkInstanceCreateInfo createInfo = ;
        createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
        createInfo.pApplicationInfo = &applicationInfo;

        // Get GLFW platform specific extensions
        uint32_t glfwExtensionCount = 0;
        const char** glfwExtensions;
        glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);


        // Fill in required extensions in Instance Creation Info
        createInfo.enabledExtensionCount = glfwExtensionCount;
        createInfo.ppEnabledExtensionNames = glfwExtensions;

        // For validation layers, this is a later step in the tutorial.
        createInfo.enabledLayerCount = 0;

        // Create the Vulkan instance, and check if it was successful.
        VkResult result = vkCreateInstance(&createInfo, nullptr, &instance);
        if(result != VK_SUCCESS)
            std::cout << "glfwExtensionCount: " << glfwExtensionCount << "\n";
            std::cout << "glfwExtensionNames: " << &glfwExtensions << "\n";
            std::cout << "result: " << result << "\n";
            throw std::runtime_error("Failed to create Vulkan Instance");
        

    

    void mainLoop() 
        while(!glfwWindowShouldClose(window))
            glfwPollEvents();
        
    

    void cleanup() 
        glfwDestroyWindow(window);
        glfwTerminate();
    
;

int main() 
    HelloTriangleApplication app;

    try 
        app.run();
     catch (const std::exception& e) 
        std::cerr << e.what() << std::endl;
        return EXIT_FAILURE;
    

    return EXIT_SUCCESS;

我遇到的问题是,当我尝试运行程序时,它不会创建 VkInstance。该函数返回 VK_ERROR_INCOMPATIBLE_DRIVER。现在,我怀疑驱动程序实际上是不兼容的,因为我已经运行了 Vulkan SDK 附带的演示应用程序,而另一个我已经能够在 XCode 中运行完全相同的“程序”。当我进一步调查这个问题时,我注意到当程序像这样在 CLion 中运行时,glfwGetRequiredInstanceExtensions 函数不返回扩展名,但在 XCode 等效项中返回一个。

这一切都让我相信我在链接 Cmake 文件中的库/框架时做错了,因为我知道 Mac OS 不直接支持 Vulkan,而是(不知何故?)通过一个层与Metal通信。

我是否需要为程序指定一种通过 Metal 层传递其 Vulkan 功能的方法,这是在 XCode 中自动完成的,还是我的方法存在其他问题?

任何帮助将不胜感激!

【问题讨论】:

【参考方案1】:

您可能想查看 LunarXchange website 和您的 SDK 中的 MacOS 入门指南。最后有一节介绍了如何使用 CMake 构建 Vulkan 应用程序并在 MacOS 上运行它。您可能还想使用 FindVulkan CMake 模块,而不是手动设置包含目录和目标链接库。

但我对您的具体问题的第一个猜测是您可能没有设置 VK_ICD_FILENAMES 环境变量。您的观察是正确的,没有直接支持 Vulkan。相反,支持由 MoltenVK 库提供,该库被视为 Vulkan 驱动程序。但是这个“驱动程序”并没有被 SDK 安装在任何系统目录中。 SDK 只是在您的主目录结构中解压缩,因此您必须通过此环境变量告诉 Vulkan 加载程序在哪里找到它。

同样,入门指南末尾的 CMake 部分演示了如何使用此环境变量。整个指南详细介绍了各种 Vulkan 和 MoltenVK 组件的工作原理。

【讨论】:

感谢您的快速回复。我没那么快,因为我花了很长时间才开始工作,但是你链接的教程帮助了我!我还没有完全满意,因为我的工作方式是将 MoltenVK 库复制到系统中,而不是以某种方式将其包含在可执行文件中。但我想这是弄清楚事情是如何运作的第一步! 您可以在应用程序包中包含 MoltenVK 库。请参阅入门指南,从“应用程序包结构”部分开始。

以上是关于Mac OS 上 CLion 中的新 Vulkan 项目不会创建 VkInstance的主要内容,如果未能解决你的问题,请参考以下文章

如何评价 JetBrains 的新 C/C++ IDE CLion?

如何评价 JetBrains 的新 C/C++ IDE CLion?

Mac上使用clion基于cmake 开发gtk

Mac OS配置C/C++环境

无法在 Mac OS Big Sur 上运行 git

在最新版本的 Mac OS X 上安装旧版本的 MySQL 5.5