C语言 使用SDL2创建Vulkan示例失败,我不确定哪里出错了

2admgd59  于 2023-01-12  发布在  其他
关注(0)|答案(1)|浏览(391)

我正在尝试创建一个示例,并验证代码是否可以创建该示例。
但是,由于某种原因,代码编译失败,无法创建示例。我不知道我做错了什么。创建示例之前的所有操作都正常。但当我尝试验证示例创建时失败。我使用SDL2创建窗口。
这是我的cmakelist文件:

cmake_minimum_required(VERSION 3.16)
#COMPIER
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_C_COMPILER "gcc")
set(CMAKE_C_STANDARD 17)   
set(CMAKE_C_STANDARD_REQUIRED ON)

#FLAGS
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -ggdb3") 
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra")

#PROJECT
project(Vulkan_test LANGUAGES C)
enable_language(C)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})

#Find packages installed in your system.
include(FindPkgConfig)
pkg_search_module(SDL2 REQUIRED sdl2)
pkg_search_module(Vulkan REQUIRED vulkan)

#Include global directories 
include_directories( 
    ${SDL2_INCLUDE_DIRS}
    ${Vulkan_INCLUDE_DIRS}
)
#Executable Specific
add_executable(VULKAN_TEST 
    ${CMAKE_CURRENT_SOURCE_DIR}/main.c
)

#Compile options
target_compile_options(VULKAN_TEST PUBLIC -O0 -ggdb3 -std=c2x -Wall -Wextra -Wmissing-prototypes -Wwrite-strings -Wpedantic)

#Libraries to link
target_link_libraries(
    VULKAN_TEST
    ${SDL2_LIBRARIES}
    ${Vulkan_LIBRARIES}
)

这是我的main. h文件:

#pragma once
/*  Required Standard Headers  */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>

/* SDL2 */
#include <SDL2/SDL.h>
#include <SDL2/SDL_vulkan.h>

/* Vulkan */
#include <vulkan/vulkan.h>

#define rt_assert(expr, ...) ((void) sizeof ((expr) ? 1 : 0), __extension__ ({                                                     \
    if (!(expr)) {                                                                                                                 \
        fprintf(stderr,"At function [%s] in file [%s:%d], assert failed: [(%s)].\n", __func__, __FILE__, __LINE__, (#expr));       \
        __VA_ARGS__;                                                                                                               \
        exit(EXIT_FAILURE);                                                                                                        \
    }                                                                                                                              \
}))

typedef struct _App {
    SDL_Window *window;
    int window_height;
    int window_width;
    const char* window_name;
    SDL_Event sdl_event;
    bool quit;
    VkInstance inst;
    uint32_t sdlExtCount;
    const char** extNames;
} App;

/* Function Prototype */
void init_window(App *);
void init_vulkan(App *);
void main_loop(App *);
void cleanup(App *);

/* sub vulkan functions */
void init_vk_instance(App *);

这个文件是我的main. c

#include "main.h"

#define SDL_MAIN_HANDLED
#define App_init(X) App (X) = { \
    .window = NULL, .window_height = 600, .window_width = 800, \
    .window_name = "Vulkan Test", .quit = false, \
    .inst = VK_NULL_HANDLE \
}

VkApplicationInfo appInfo = {0};
VkInstanceCreateInfo instInfo = {0};

void init_vk_instance(App *App) {
    /* Vulkan VkApplicationInfo */
    appInfo.sType =  VK_STRUCTURE_TYPE_APPLICATION_INFO;
    appInfo.pApplicationName = App->window_name;
    appInfo.applicationVersion = VK_MAKE_API_VERSION(0, 1, 0, 0);
    appInfo.pEngineName = App->window_name;
    appInfo.engineVersion = VK_MAKE_API_VERSION(0, 1, 0, 0);
    /* This is version I have installed from my linux package manager */
    appInfo.apiVersion = VK_MAKE_API_VERSION(0,1,3,231); 
    appInfo.pNext = NULL;
    /* Vulkan Instance info - VkInstanceCreateInfo */
    instInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
    instInfo.pApplicationInfo = &appInfo;
    instInfo.enabledLayerCount = 0;
    SDL_Vulkan_GetInstanceExtensions(App->window,&App->sdlExtCount,NULL);
    App->extNames = malloc(App->sdlExtCount * sizeof(const char*));
    SDL_Vulkan_GetInstanceExtensions(App->window,&App->sdlExtCount,App->extNames);
    instInfo.enabledExtensionCount = App->sdlExtCount;
    instInfo.ppEnabledExtensionNames = App->extNames;
    for(uint32_t i = 0; i < App->sdlExtCount; i++) {
        printf("%u : %s\n",i,App->extNames[i]);
    }
    rt_assert( (vkCreateInstance(&instInfo, NULL, &App->inst) == VK_SUCCESS), printf("Instance creation failed\n"), cleanup(App));
}

void init_vulkan(App *App) {
    init_vk_instance(App);
}

void init_window(App *App) {
    App->window =  SDL_CreateWindow( App->window_name,
        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 
        App->window_width, App->window_height, SDL_WINDOW_SHOWN | SDL_WINDOW_VULKAN |
        SDL_WINDOW_RESIZABLE);
}
void cleanup(App *App) {
    free(App->extNames);
    SDL_DestroyWindow(App->window);
    SDL_Quit();
}
void main_loop(App *App) {
    while(!App->quit) {
        while (SDL_PollEvent(&App->sdl_event)) {
            if( App->sdl_event.type == SDL_QUIT ) App->quit = true;
        }
    }
}
int main ( void ) {
    printf("Vulkan-Engine\n");
    SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
    App_init(test);
    init_window(&test);
    init_vulkan(&test);
    main_loop(&test);
    vkDestroyInstance(test.inst, NULL);
    cleanup(&test);
    return EXIT_SUCCESS;
}

这是我运行程序后得到的输出:

Vulkan-Engine
0 : VK_KHR_surface
1 : VK_KHR_xlib_surface
At function [init_vk_instance] in file [/home/Codes/C/Vulkan/main.c:35], assert failed: [((vkCreateInstance(&instInfo, NULL, &App->inst) == VK_SUCCESS))].
Instance creation failed

CMake编译期间的输出:

-- The C compiler identification is GNU 12.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/gcc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.29.2") 
-- Checking for one of the modules 'sdl2'
-- Checking for one of the modules 'vulkan'
-- Configuring done
-- Generating done
-- Build files have been written to: /home/Codes/C/Vulkan/build
[ 50%] Building C object CMakeFiles/VULKAN_TEST.dir/main.c.o
[100%] Linking C executable /home/Codes/C/Vulkan/VULKAN_TEST
[100%] Built target VULKAN_TEST

这些是我通过包管理器安装在系统上的Vulkan相关包:

如图所示,vulkan API版本为1.3.231.1。我是否正确使用了VK_MAKE_API_VERSION(0,1,3,231)

j5fpnvbx

j5fpnvbx1#

我认为您缺少KHR
例如,我使用了windows 10MSYS2这就是我所做的

#define VK_USE_PLATFORM_WIN32_KHR
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define SDL_MAIN_HANDLED
#include <SDL2/SDL.h>
#include <SDL2/SDL_vulkan.h>
#include <vulkan/vulkan.h>
#include <vulkan/vulkan_core.h>

int main(int argc, char** argv)
{
    if (0 != SDL_Init(SDL_INIT_EVERYTHING))
    {
        printf("failed to initialize SDL2 with everything\n");
    }

    SDL_Window* window = SDL_CreateWindow("test", 10, 10, 640, 480, SDL_WINDOW_SHOWN | SDL_WINDOW_VULKAN);
    if (NULL == window)
    {
        printf("failed to create window\n");
    }

    VkApplicationInfo app_info = { 0 };
    app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
    app_info.apiVersion = VK_API_VERSION_1_3;
    app_info.pApplicationName = "test-app";
    app_info.applicationVersion = VK_MAKE_API_VERSION(1, 0, 0, 0);
    app_info.pEngineName = "test-engine";
    app_info.engineVersion = VK_MAKE_API_VERSION(1, 0, 0, 0);

    VkInstanceCreateInfo instance_info = { 0 };
    instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
    instance_info.pApplicationInfo = &app_info;
    instance_info.enabledLayerCount = 0;
    instance_info.ppEnabledLayerNames = NULL;

    unsigned int count = 0;
    SDL_Vulkan_GetInstanceExtensions(window, &count, NULL);
    const char** extensions = malloc(sizeof(char*) * count);
    SDL_Vulkan_GetInstanceExtensions(window, &count, extensions);

    for (unsigned int i = 0; i < count; i ++)
    {
        printf("%u: %s\n", i, extensions[i]);
    }

    instance_info.enabledExtensionCount = count;
    instance_info.ppEnabledExtensionNames = extensions;

    VkInstance instance = VK_NULL_HANDLE;
    if (0 > vkCreateInstance(&instance_info, NULL, &instance))
    {
        printf("failed to create instance\n");
    }

    VkSurfaceKHR surface = VK_NULL_HANDLE;
    if (SDL_FALSE == SDL_Vulkan_CreateSurface(window, instance, &surface))
    {
        printf("failed to create surface, SDL Error: %s", SDL_GetError());
    }

    return 0;
}

对我来说,它工作得很好,所以我的观察是,您需要找到一种方法来定义类似的宏,如#define VK_USE_PLATFORM_WIN32_KHR
以下是vulkan.h中假定的列表扩展名

VK_USE_PLATFORM_ANDROID_KHR
VK_USE_PLATFORM_FUCHSIA
VK_USE_PLATFORM_IOS_MVK
VK_USE_PLATFORM_MACOS_MVK
VK_USE_PLATFORM_METAL_EXT
VK_USE_PLATFORM_VI_NN
VK_USE_PLATFORM_WAYLAND_KHR
VK_USE_PLATFORM_WIN32_KHR
VK_USE_PLATFORM_XCB_KHR
VK_USE_PLATFORM_XLIB_KHR
VK_USE_PLATFORM_DIRECTFB_EXT
VK_USE_PLATFORM_XLIB_XRANDR_EXT
VK_USE_PLATFORM_GGP
VK_USE_PLATFORM_SCREEN_QNX
VK_ENABLE_BETA_EXTENSIONS

这就是我在MSYS2中编译的方式

gcc -O0 -g3 -Wall -c -fmessage-length=0 -o "src\\ansi-c.o" "..\\src\\ansi-c.c" 
gcc -o ansi-c.exe "src\\ansi-c.o" -lmingw32 -lSDL2main -lSDL2 -lvulkan-1.dll

相关问题