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");
}