通过CMake FetchContent提供VulkanSDK

问题描述 投票:0回答:1

我想通过 CMake 的 FetchContent 模块提供 Vulkan SDK。

# Vulkan SDK
set(VULKAN_SDK_VERSION 1.3.290.0)

# FetchContent_Declare() calls
FetchContent_Declare(VulkanHeaders
                     GIT_REPOSITORY https://github.com/KhronosGroup/Vulkan-Headers.git
                     GIT_TAG "vulkan-sdk-${VULKAN_SDK_VERSION}"
                     OVERRIDE_FIND_PACKAGE)

FetchContent_Declare(VulkanLoader
                     GIT_REPOSITORY https://github.com/KhronosGroup/Vulkan-Loader.git
                     GIT_TAG "vulkan-sdk-${VULKAN_SDK_VERSION}"
                     OVERRIDE_FIND_PACKAGE)

FetchContent_Declare(VulkanUtilityLibraries
                     GIT_REPOSITORY https://github.com/KhronosGroup/Vulkan-Utility-Libraries.git
                     GIT_TAG "vulkan-sdk-${VULKAN_SDK_VERSION}"
                     OVERRIDE_FIND_PACKAGE)

FetchContent_Declare(SPIRV-Headers
                     GIT_REPOSITORY https://github.com/KhronosGroup/SPIRV-Headers.git
                     GIT_TAG "vulkan-sdk-${VULKAN_SDK_VERSION}"
                     OVERRIDE_FIND_PACKAGE)

FetchContent_Declare(SPIRV-Tools
                     GIT_REPOSITORY https://github.com/KhronosGroup/SPIRV-Tools.git
                     GIT_TAG "vulkan-sdk-${VULKAN_SDK_VERSION}"
                     OVERRIDE_FIND_PACKAGE)

FetchContent_Declare(VulkanValidationLayers
                     GIT_REPOSITORY https://github.com/KhronosGroup/Vulkan-ValidationLayers.git
                     GIT_TAG "vulkan-sdk-${VULKAN_SDK_VERSION}"
                     OVERRIDE_FIND_PACKAGE)

# Build Settings
set(SPIRV_SKIP_TESTS ON CACHE BOOL "" FORCE)
set(USE_MIMALLOC OFF CACHE BOOL "" FORCE)
set(USE_ROBIN_HOOD_HASHING OFF CACHE BOOL "" FORCE)

# FetchContent_MakeAvailable() calls
FetchContent_MakeAvailable(VulkanHeaders) 
FetchContent_MakeAvailable(VulkanLoader) 
FetchContent_MakeAvailable(VulkanUtilityLibraries)
FetchContent_MakeAvailable(SPIRV-Headers) 
FetchContent_MakeAvailable(SPIRV-Tools) 
FetchContent_MakeAvailable(VulkanValidationLayers) 

add_library(Vulkan::Vulkan INTERFACE IMPORTED GLOBAL)

target_link_libraries(Vulkan::Vulkan INTERFACE 
                      Vulkan::Headers 
                      Vulkan::Loader
                      Vulkan::LayerSettings
                      Vulkan::UtilityHeaders
                      Vulkan::SafeStruct
                      SPIRV-Headers
                      SPIRV-Tools
                      VkLayer_utils)

我链接到我的项目。

add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} PRIVATE 
                      glm::glm 
                      glfw
                      Vulkan::Vulkan)

我有简单的 Vulkan Hello World 来检查验证层是否可用。

#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
#include <iostream>
#include <stdexcept>
#include <vector>

const std::vector<const char*> validationLayers = {
    "VK_LAYER_KHRONOS_validation"
};

#ifdef NDEBUG
const bool enableValidationLayers = false;
#else
const bool enableValidationLayers = true;
#endif

void checkValidationLayerSupport() {
    uint32_t layerCount;
    vkEnumerateInstanceLayerProperties(&layerCount, nullptr);

    std::vector<VkLayerProperties> availableLayers(layerCount);
    vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());

    for (const char* layerName : validationLayers) {
        bool layerFound = false;

        for (const auto& layerProperties : availableLayers) {
            if (strcmp(layerName, layerProperties.layerName) == 0) {
                layerFound = true;
                break;
            }
        }

        if (!layerFound) {
            throw std::runtime_error("Required validation layer not found!");
        }
    }
}

VkInstance createInstance() {
    if (enableValidationLayers) {
        checkValidationLayerSupport();
    }

    VkInstance instance;
    VkInstanceCreateInfo createInfo{};
    createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;

    if (enableValidationLayers) {
        createInfo.ppEnabledLayerNames = validationLayers.data();
        createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
    } else {
        createInfo.enabledLayerCount = 0;
    }

    if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) {
        throw std::runtime_error("Failed to create Vulkan instance!");
    }

    return instance;
}

int main() {
    try {
        // GLFW initialisieren
        glfwInit();
        glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);

        // Vulkan Instanz erstellen
        VkInstance instance = createInstance();

        // Hier könnte dein Vulkan-Code fortgesetzt werden

        vkDestroyInstance(instance, nullptr);
    } catch (const std::runtime_error& e) {
        std::cerr << e.what() << std::endl;
        return EXIT_FAILURE;
    }

    glfwTerminate();
    return EXIT_SUCCESS;
}

我在配置或构建阶段没有收到任何错误。当我运行该程序时,它指出没有可用的验证层。这不是正确的行为,因为当我使用安装的普通 VulkanSDK 并使用 find_package() 时,它会正确列出所有可用的验证层。

cmake vulkan
1个回答
0
投票

问题是您的 CMake 文件在构建树中的某个位置构建了验证层,而 Vulkan 加载程序无法找到它,因为您的构建树不是它查找层的标准位置之一。 解决此问题的一种方法是在启动应用程序之前设置

VK_LAYER_PATH
环境变量以包含验证层二进制文件和 JSON 文件最终位于构建树中的目录。 Loader GitHub 存储库应包含描述此行为的文档。

© www.soinside.com 2019 - 2024. All rights reserved.