Dav1dde / glad

Multi-Language Vulkan/GL/GLES/EGL/GLX/WGL Loader-Generator based on the official specs.
https://glad.dav1d.de/
Other
3.79k stars 447 forks source link

Surface related vk calls fail with an SDL-created Vulkan Surface (Vulkan 1.3) #451

Open TheMagehawk opened 9 months ago

TheMagehawk commented 9 months ago

API: Vulkan 1.3 Windowing Library: SDL2 Build System Generator: CMake

During the Vulkan Setup Process, I encounter an issue with Surface related vk functions.

This particular function causes a Segmentation Fault:

VkBool32 supportsPresentation = 0;
vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, familyIndex, surface, &supportsPresentation);

I generate the glad library with CMake:

glad_add_library(glad STATIC EXCLUDE_FROM_ALL REPRODUCIBLE API vulkan=1.3)
target_link_libraries(${PROJECT_NAME} PUBLIC glad)

It works, if I use the system-wide Vulkan package instead without applying the glad load functions, so it's probably related to missing symbols:

find_package(Vulkan)
target_link_libraries(${PROJECT_NAME} PUBLIC Vulkan::Vulkan)

Here is a summarized overview of the Vulkan Setup Process:

window = SDL_CreateWindow(name, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_VULKAN);

...

gladLoadVulkanUserPtr(nullptr, (GLADuserptrloadfunc) SDL_Vulkan_GetVkGetInstanceProcAddr(), nullptr);

...

uint32_t sdlExtensionCount = 0;
SDL_bool result = SDL_Vulkan_GetInstanceExtensions(window, &sdlExtensionCount, nullptr);
CC_ENGINE_ASSERT_ARGS(result == SDL_TRUE, "Failed to retrieve SDL required Vulkan Extensions! SDL_Error: {}", SDL_GetError());
std::vector<const char*> requiredExtensions(sdlExtensionCount);
result = SDL_Vulkan_GetInstanceExtensions(window, &sdlExtensionCount, requiredExtensions.data());

...

VkApplicationInfo appInfo{};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pNext = nullptr;
appInfo.pApplicationName = name;
appInfo.applicationVersion = VK_MAKE_VERSION(0, 1, 0);
appInfo.pEngineName = "";
appInfo.engineVersion = VK_MAKE_VERSION(0, 1, 0);
appInfo.apiVersion = VK_API_VERSION_1_3;

VkInstanceCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pNext = nullptr;
createInfo.flags = 0;
createInfo.pApplicationInfo = &appInfo;
createInfo.enabledLayerCount = static_cast<uint32_t>(enabledLayers.size());  // This mainly contains VK_LAYER_KHRONOS_validation
createInfo.ppEnabledLayerNames = enabledLayers.data();
createInfo.enabledExtensionCount = static_cast<uint32_t>(extensionNames.size());  // This contains the SDL required extensions
createInfo.ppEnabledExtensionNames = extensionNames.data();

VkResult createResult = vkCreateInstance(&createInfo, nullptr, &instance);
gladLoadVulkanUserPtr(nullptr, (GLADuserptrloadfunc) SDL_Vulkan_GetVkGetInstanceProcAddr(), instance);

...

// Find the first physical device GPU
...
physicalDevice = physicalDevices.at(0);

gladLoadVulkanUserPtr(physicalDevice, (GLADuserptrloadfunc) SDL_Vulkan_GetVkGetInstanceProcAddr(), instance);

...

// Find first Graphics Queue Family and create a VkDevice and receive the first Graphics Queue
...

SDL_Vulkan_CreateSurface(window, instance, &surface);

I also notice that, if I create a VkInstance with the Application API Version set to Vulkan 1.2 or lower (even if I generate for Vulkan 1.3 on glad), the problem suddenly disappears.

Following code change fixes the issue, but restricts usage to Vulkan <=1.2:

appInfo.apiVersion = VK_API_VERSION_1_2;

I couldn't figure out what specifically made it work on Vulkan 1.2, but I applied no other changes.

EDIT: On Android (Android 14) it fails on exactly the same function call on any selected VK_API_VERSION1*

vs49688 commented 3 weeks ago

Bit of a necropost, but I hit this same issue using Vulkan 1.3/SDL on RADV.

Special-casing vkEnumerateInstanceVersion and vkEnumerateInstanceExtensionProperties fixes it, similar to https://github.com/Dav1dde/glad/issues/329#issuecomment-854694410

e.g.

    if(strcmp("vkEnumerateInstanceVersion", name) == 0 || strcmp("vkEnumerateInstanceExtensionProperties", name) == 0)
        return self->getInstanceProcAddr(NULL, name);

    return self->getInstanceProcAddr(self->vulkan, name);