I am trying to run through the basic Vulkan triangle demo. I am getting stuck at
vkGetDeviceQueue which segfaults for me.
I have written the same tutorial to about the same point in C and I am
not getting the segfault.
I have enabled validation layers and they are not picking up anything.

Any suggestions?
module vulkan;

import std.exception : enforce;

import erupted;
import bindbc.sdl : SDL_Window, SDL_Vulkan_GetInstanceExtensions, SDL_Vulkan_CreateSurface;

import memory;
import util: CStringList;

version (validateVulkan) 
{ 
    string [] validationLayers = ["VK_LAYER_KHRONOS_validation"];
    const(char)[] debugExtension = "VK_EXT_debug_utils";
} else {
    string [] validationLayers = [];
}  



CStringList getInstanceExtensions (SDL_Window * window)
{
    uint n;
    SDL_Vulkan_GetInstanceExtensions(window,&n,null);
    version (validateVulkan)
    {
        auto extensions = CStringList(n+1);
        SDL_Vulkan_GetInstanceExtensions(window,&n,extensions.ptr);
        extensions[n] = cast(const(char)*) debugExtension.ptr;
    } else {
        auto extensions = CStringList(n);
        SDL_Vulkan_GetInstanceExtensions(window,&n,extensions.ptr);
    }

    return extensions;
}

void createInstance (CStringList extensions)
{
    auto vlayers = CStringList(validationLayers); 
    VkApplicationInfo appInfo = 
    {
        pApplicationName: "Vulkan Test",
        apiVersion: VK_MAKE_API_VERSION(0,1,3,0),
    };
    VkInstanceCreateInfo createInfo = 
    {
        pApplicationInfo: &appInfo,
        enabledLayerCount: cast(uint) vlayers.length,
        ppEnabledLayerNames: vlayers.ptr,
        enabledExtensionCount: cast(uint) extensions.length,
        ppEnabledExtensionNames: extensions.ptr,
    };
    auto r = vkCreateInstance(&createInfo, null, &instance);
    enforce(r == VK_SUCCESS,"failed to create instance");
    loadInstanceLevelFunctions(instance);
}


void getPhysicalDevices ()
{
    uint n;
    vkEnumeratePhysicalDevices(instance, &n, null);
    physicalDevices = allocator.makeArray!VkPhysicalDevice(n);
    vkEnumeratePhysicalDevices(instance,&n,physicalDevices.ptr);
    enforce(physicalDevices.length > 0,"no physical devices found");
}

void pickPhysicalDevice ()
{
    if (physicalDevices.length == 1) 
    {
        primaryPhysicalDevice = physicalDevices[0];
    } else { 
        ulong maxScore,index=-1;
        foreach(i,device; physicalDevices)
        {
            uint score = 0;
            VkPhysicalDeviceProperties properties;
            device.vkGetPhysicalDeviceProperties(&properties);
            VkPhysicalDeviceFeatures features;
            device.vkGetPhysicalDeviceFeatures(&features);
            switch(properties.deviceType)
            {
                case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: score = 1000; break;
                case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: score = 500; break;
                case VK_PHYSICAL_DEVICE_TYPE_CPU: score = 100; break;
                default: score = 0;
            }
            if (score > maxScore)
            {
                maxScore = score;
                index = i;
            }
            
        }
        primaryPhysicalDevice = physicalDevices[index];
    }
    enforce(primaryPhysicalDevice,"failed to find acceptable physical device");
}

int [2] findQueueFamilies (VkPhysicalDevice dev)
{
    int [2] r = [-1,-1];
    uint n;
    vkGetPhysicalDeviceQueueFamilyProperties(dev,&n,null);
    auto families = memory.allocator.makeArray!VkQueueFamilyProperties(n);
    vkGetPhysicalDeviceQueueFamilyProperties(dev,&n,families.ptr);
    foreach (i,family; families)
    {
        if (family.queueCount > 0 && family.queueFlags & VK_QUEUE_GRAPHICS_BIT) r[0] = cast(uint) i;   
        VkBool32 presentSupport = false;
        vkGetPhysicalDeviceSurfaceSupportKHR(dev,cast(uint)i, surface, &presentSupport);
        if (family.queueCount > 0 && presentSupport) r[1] = cast(uint) i;
    }
    enforce (r[0] >= 0,"failed to find grahpics family");
    enforce (r[1] >= 0,"failed to find present family");
    return r;
}

void createLogicalDevice (int[2] q)
{
    const(float[]) priority = [1.0f];
    VkDeviceQueueCreateInfo queueCreateInfo =
    {
        sType: VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
        queueFamilyIndex: cast(uint) q[0],
        queueCount: 1,
        pQueuePriorities: priority.ptr,
    };
    VkPhysicalDeviceFeatures deviceFeatures;
    VkDeviceCreateInfo createInfo =
    {
        sType: VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
        pQueueCreateInfos: &queueCreateInfo,
        queueCreateInfoCount: 1,
        pEnabledFeatures: &deviceFeatures,
    };
    auto r = vkCreateDevice(primaryPhysicalDevice,&createInfo,null,&device);
    enforce(r == VK_SUCCESS,"failed to create logical device");

}

void getGraphicsQueue (uint i)
{
    vkGetDeviceQueue(device, 0, 0, &graphicsQueue);
    enforce(graphicsQueue,"failed to get graphics queue");
}

void init (SDL_Window * window)
{
    createInstance(getInstanceExtensions(window));

    version(validateVulkan) setupDebugMessenger();
    
    getPhysicalDevices();
    pickPhysicalDevice();
    SDL_Vulkan_CreateSurface(window,instance,&surface);
    enforce(surface,"failed to create surface"); 
    auto indicies = findQueueFamilies(primaryPhysicalDevice);
    createLogicalDevice(indicies);
    getGraphicsQueue(cast(uint)indicies[0]);  
}

void shutdown()
{
    
    vkDestroySurfaceKHR(instance,surface,null);
    memory.allocator.dispose(physicalDevices);
    version(validateVulkan) destroyDebugUtilsMessengerEXT(instance, debugMessenger, null);
    vkDestroyInstance(instance,null);
}




VkDebugUtilsMessengerEXT debugMessenger;
VkSurfaceKHR surface = VK_NULL_HANDLE;
VkInstance instance = null;
VkPhysicalDevice [] physicalDevices;
VkPhysicalDevice primaryPhysicalDevice;
VkDevice device;
VkQueue graphicsQueue, presentQueue;


// Debug functions
extern (C) uint debugCallback ( VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, uint messageType, 
                                const(VkDebugUtilsMessengerCallbackDataEXT)* pCallbackData, void * pUserData) nothrow @nogc
{
    import std.stdio;
    printf("message type: %i\n",messageType);
    printf("%s\n", pCallbackData.pMessage);
   return VK_FALSE;  
}

VkResult createDebugUtilsMessengerEXT(  VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, 
                                        const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pDebugMessenger) 
{
    auto func = cast(PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
    if (func != null) {
        return func(instance, pCreateInfo, pAllocator, pDebugMessenger);
    } else {
        return VK_ERROR_EXTENSION_NOT_PRESENT;
    }
}

void destroyDebugUtilsMessengerEXT( VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, 
                                    const VkAllocationCallbacks* pAllocator) 
{
    auto func = cast(PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT");
    if (func != null) {
        func(instance, debugMessenger, pAllocator);
    }
}

void setupDebugMessenger ()
{
    if (validationLayers.length == 0) return;

    VkDebugUtilsMessengerCreateInfoEXT createInfo = 
    {
        sType: VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
        messageSeverity: VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | 
                         VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | 
                         VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
        messageType: VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | 
                     VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | 
                     VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
        pfnUserCallback: &debugCallback,
    };
    enforce( createDebugUtilsMessengerEXT(instance, &createInfo, null, &debugMessenger) == VK_SUCCESS,"failed to create debug messenger");
}

Reply via email to