public unsafe GraphicsAdapterFactoryInstance(bool enableValidation) { var applicationInfo = new VkApplicationInfo { sType = VkStructureType.ApplicationInfo, apiVersion = new VkVersion(1, 0, 0), pEngineName = (byte *)Marshal.StringToHGlobalAnsi("Stride"), //engineVersion = new VkVersion() }; var validationLayerNames = new[] { "VK_LAYER_KHRONOS_validation", }; IntPtr[] enabledLayerNames = new IntPtr[0]; if (enableValidation) { var layers = vkEnumerateInstanceLayerProperties(); var availableLayerNames = new HashSet <string>(); for (int index = 0; index < layers.Length; index++) { var properties = layers[index]; var namePointer = properties.layerName; var name = Marshal.PtrToStringAnsi((IntPtr)namePointer); availableLayerNames.Add(name); } enabledLayerNames = validationLayerNames .Where(x => availableLayerNames.Contains(x)) .Select(Marshal.StringToHGlobalAnsi).ToArray(); // Check if validation was really available enableValidation = enabledLayerNames.Length > 0; } var extensionProperties = vkEnumerateInstanceExtensionProperties(); var availableExtensionNames = new List <string>(); var desiredExtensionNames = new List <string>(); for (int index = 0; index < extensionProperties.Length; index++) { var extensionProperty = extensionProperties[index]; var name = Marshal.PtrToStringAnsi((IntPtr)extensionProperty.extensionName); availableExtensionNames.Add(name); } desiredExtensionNames.Add(KHRSurfaceExtensionName); if (!availableExtensionNames.Contains(KHRSurfaceExtensionName)) { throw new InvalidOperationException($"Required extension {KHRSurfaceExtensionName} is not available"); } #if STRIDE_PLATFORM_WINDOWS_DESKTOP desiredExtensionNames.Add(KHRWin32SurfaceExtensionName); if (!availableExtensionNames.Contains(KHRWin32SurfaceExtensionName)) { throw new InvalidOperationException($"Required extension {KHRWin32SurfaceExtensionName} is not available"); } #elif STRIDE_PLATFORM_ANDROID desiredExtensionNames.Add(KHRAndroidSurfaceExtensionName); if (!availableExtensionNames.Contains(KHRAndroidSurfaceExtensionName)) { throw new InvalidOperationException($"Required extension {KHRAndroidSurfaceExtensionName} is not available"); } #elif STRIDE_PLATFORM_LINUX if (availableExtensionNames.Contains("VK_KHR_xlib_surface")) { desiredExtensionNames.Add("VK_KHR_xlib_surface"); HasXlibSurfaceSupport = true; } else if (availableExtensionNames.Contains("VK_KHR_xcb_surface")) { desiredExtensionNames.Add("VK_KHR_xcb_surface"); } else { throw new InvalidOperationException("None of the supported surface extensions VK_KHR_xcb_surface or VK_KHR_xlib_surface is available"); } #endif bool enableDebugReport = enableValidation && availableExtensionNames.Contains(EXTDebugUtilsExtensionName); if (enableDebugReport) { desiredExtensionNames.Add(EXTDebugUtilsExtensionName); } var enabledExtensionNames = desiredExtensionNames.Select(Marshal.StringToHGlobalAnsi).ToArray(); try { fixed(void *enabledExtensionNamesPointer = &enabledExtensionNames[0]) { var instanceCreateInfo = new VkInstanceCreateInfo { sType = VkStructureType.InstanceCreateInfo, pApplicationInfo = &applicationInfo, enabledLayerCount = enabledLayerNames != null ? (uint)enabledLayerNames.Length : 0, ppEnabledLayerNames = enabledLayerNames?.Length > 0 ? (byte **)Core.Interop.Fixed(enabledLayerNames) : null, enabledExtensionCount = (uint)enabledExtensionNames.Length, ppEnabledExtensionNames = (byte **)enabledExtensionNamesPointer, }; vkCreateInstance(&instanceCreateInfo, null, out NativeInstance); vkLoadInstance(NativeInstance); } // Check if validation layer was available (otherwise detected count is 0) if (enableValidation) { debugReport = DebugReport; var createInfo = new VkDebugUtilsMessengerCreateInfoEXT { sType = VkStructureType.DebugUtilsMessengerCreateInfoEXT, messageSeverity = VkDebugUtilsMessageSeverityFlagsEXT.Verbose | VkDebugUtilsMessageSeverityFlagsEXT.Error | VkDebugUtilsMessageSeverityFlagsEXT.Warning, messageType = VkDebugUtilsMessageTypeFlagsEXT.General | VkDebugUtilsMessageTypeFlagsEXT.Validation | VkDebugUtilsMessageTypeFlagsEXT.Performance, pfnUserCallback = Marshal.GetFunctionPointerForDelegate(debugReport) }; vkCreateDebugUtilsMessengerEXT(NativeInstance, &createInfo, null, out debugReportCallback).CheckResult(); } } finally { foreach (var enabledExtensionName in enabledExtensionNames) { Marshal.FreeHGlobal(enabledExtensionName); } foreach (var enabledLayerName in enabledLayerNames) { Marshal.FreeHGlobal(enabledLayerName); } Marshal.FreeHGlobal((IntPtr)applicationInfo.pEngineName); } }
public GraphicsDevice(string applicationName, bool enableValidation, Window window) { VkString name = applicationName; var appInfo = new VkApplicationInfo { sType = VkStructureType.ApplicationInfo, pApplicationName = name, applicationVersion = new VkVersion(1, 0, 0), pEngineName = s_EngineName, engineVersion = new VkVersion(1, 0, 0), apiVersion = vkEnumerateInstanceVersion() }; var instanceExtensions = new List <string> { KHRSurfaceExtensionName }; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { instanceExtensions.Add(KHRWin32SurfaceExtensionName); } var instanceLayers = new List <string>(); if (enableValidation) { FindValidationLayers(instanceLayers); } if (instanceLayers.Count > 0) { instanceExtensions.Add(EXTDebugUtilsExtensionName); } using var vkInstanceExtensions = new VkStringArray(instanceExtensions); var instanceCreateInfo = new VkInstanceCreateInfo { sType = VkStructureType.InstanceCreateInfo, pApplicationInfo = &appInfo, enabledExtensionCount = vkInstanceExtensions.Length, ppEnabledExtensionNames = vkInstanceExtensions }; using var vkLayerNames = new VkStringArray(instanceLayers); if (instanceLayers.Count > 0) { instanceCreateInfo.enabledLayerCount = vkLayerNames.Length; instanceCreateInfo.ppEnabledLayerNames = vkLayerNames; } var debugUtilsCreateInfo = new VkDebugUtilsMessengerCreateInfoEXT { sType = VkStructureType.DebugUtilsMessengerCreateInfoEXT }; if (instanceLayers.Count > 0) { _debugMessengerCallbackFunc = DebugMessengerCallback; debugUtilsCreateInfo.messageSeverity = VkDebugUtilsMessageSeverityFlagsEXT.Error | VkDebugUtilsMessageSeverityFlagsEXT.Warning; debugUtilsCreateInfo.messageType = VkDebugUtilsMessageTypeFlagsEXT.Validation | VkDebugUtilsMessageTypeFlagsEXT.Performance; debugUtilsCreateInfo.pfnUserCallback = Marshal.GetFunctionPointerForDelegate(_debugMessengerCallbackFunc); instanceCreateInfo.pNext = &debugUtilsCreateInfo; } VkResult result = vkCreateInstance(&instanceCreateInfo, null, out VkInstance); if (result != VkResult.Success) { throw new InvalidOperationException($"Failed to create vulkan instance: {result}"); } vkLoadInstance(VkInstance); if (instanceLayers.Count > 0) { vkCreateDebugUtilsMessengerEXT(VkInstance, &debugUtilsCreateInfo, null, out _debugMessenger).CheckResult(); } Log.Info($"Created VkInstance with version: {appInfo.apiVersion.Major}.{appInfo.apiVersion.Minor}.{appInfo.apiVersion.Patch}"); if (instanceLayers.Count > 0) { foreach (var layer in instanceLayers) { Log.Info($"Instance layer '{layer}'"); } } foreach (var extension in instanceExtensions) { Log.Info($"Instance extension '{extension}'"); } _surface = CreateSurface(window); // Find physical device, setup queue's and create device. var physicalDevices = vkEnumeratePhysicalDevices(VkInstance); foreach (var physicalDevice in physicalDevices) { vkGetPhysicalDeviceProperties(physicalDevice, out var properties); var deviceName = properties.GetDeviceName(); } PhysicalDevice = physicalDevices[0]; var queueFamilies = FindQueueFamilies(PhysicalDevice, _surface); var priority = 1.0f; var queueCreateInfo = new VkDeviceQueueCreateInfo { sType = VkStructureType.DeviceQueueCreateInfo, queueFamilyIndex = queueFamilies.graphicsFamily, queueCount = 1, pQueuePriorities = &priority }; List <string> deviceExtensions = new List <string> { KHRSwapchainExtensionName }; var deviceCreateInfo = new VkDeviceCreateInfo { sType = VkStructureType.DeviceCreateInfo, pQueueCreateInfos = &queueCreateInfo, queueCreateInfoCount = 1, pEnabledFeatures = null, }; using var deviceExtensionNames = new VkStringArray(deviceExtensions); deviceCreateInfo.enabledExtensionCount = deviceExtensionNames.Length; deviceCreateInfo.ppEnabledExtensionNames = deviceExtensionNames; result = vkCreateDevice(PhysicalDevice, &deviceCreateInfo, null, out VkDevice); if (result != VkResult.Success) { throw new Exception($"Failed to create Vulkan Logical Device, {result}"); } vkGetDeviceQueue(VkDevice, queueFamilies.graphicsFamily, 0, out GraphicsQueue); vkGetDeviceQueue(VkDevice, queueFamilies.presentFamily, 0, out PresentQueue); // Create swap chain Swapchain = new Swapchain(this, window); _perFrame = new PerFrame[Swapchain.ImageCount]; for (var i = 0; i < _perFrame.Length; i++) { VkFenceCreateInfo fenceCreateInfo = new VkFenceCreateInfo(VkFenceCreateFlags.Signaled); vkCreateFence(VkDevice, &fenceCreateInfo, null, out _perFrame[i].QueueSubmitFence).CheckResult(); VkCommandPoolCreateInfo poolCreateInfo = new VkCommandPoolCreateInfo { sType = VkStructureType.CommandPoolCreateInfo, flags = VkCommandPoolCreateFlags.Transient, queueFamilyIndex = queueFamilies.graphicsFamily, }; vkCreateCommandPool(VkDevice, &poolCreateInfo, null, out _perFrame[i].PrimaryCommandPool).CheckResult(); VkCommandBufferAllocateInfo commandBufferInfo = new VkCommandBufferAllocateInfo { sType = VkStructureType.CommandBufferAllocateInfo, commandPool = _perFrame[i].PrimaryCommandPool, level = VkCommandBufferLevel.Primary, commandBufferCount = 1 }; vkAllocateCommandBuffers(VkDevice, &commandBufferInfo, out _perFrame[i].PrimaryCommandBuffer).CheckResult(); } }
private VkInstance CreateInstance() { List <GCHandle> handles = new List <GCHandle>(); bool debug = false; string[] debugOnlyLayers = new string[] { //"VK_LAYER_GOOGLE_threading", //"VK_LAYER_LUNARG_parameter_validation", //"VK_LAYER_LUNARG_device_limits", Not Present? //"VK_LAYER_LUNARG_object_tracker", //"VK_LAYER_LUNARG_image", Not Present? "VK_LAYER_LUNARG_core_validation", //"VK_LAYER_LUNARG_swapchain", //"VK_LAYER_GOOGLE_unique_objects", }; List <string> layerList = new List <string>(); if (debug) { layerList.AddRange(debugOnlyLayers); } string[] layers = layerList.ToArray(); byte[][] pDebugLayers = new byte[layers.Length][]; byte *[] ppDebugLayerArray = new byte *[pDebugLayers.Length]; if (!debug) { ppDebugLayerArray = new byte *[1];//this is to give a null ptr to use later } for (int i = 0; i < pDebugLayers.Length; i++) { pDebugLayers[i] = Encoding.UTF8.GetBytes(layers[i] + char.MinValue); GCHandle handle = GCHandle.Alloc(pDebugLayers[i]); handles.Add(handle); fixed(byte *p = &(((byte[])handle.Target)[0])) { ppDebugLayerArray[i] = p; } } List <string> requiredExtensions = new List <string>(); requiredExtensions.Add("VK_EXT_debug_report"); requiredExtensions.AddRange(GLFW.Vulkan.GetRequiredInstanceExtensions()); string[] extensionNames = requiredExtensions.ToArray(); byte[][] pExtensionNames = new byte[extensionNames.Length][]; byte *[] ppExtensionNamesArray = new byte *[extensionNames.Length]; for (int i = 0; i < pExtensionNames.Length; i++) { pExtensionNames[i] = Encoding.UTF8.GetBytes(extensionNames[i] + char.MinValue); GCHandle handle = GCHandle.Alloc(pExtensionNames[i]); handles.Add(handle); fixed(byte *p = &(((byte[])handle.Target)[0])) { ppExtensionNamesArray[i] = p; } } VkInstance instance = new VkInstance(); fixed(byte **layersptr = &ppDebugLayerArray[0]) { fixed(byte **extensions = &ppExtensionNamesArray[0]) { VkInstanceCreateInfo pCreateInfo = VkInstanceCreateInfo.New(); pCreateInfo.ppEnabledLayerNames = layersptr; pCreateInfo.ppEnabledExtensionNames = extensions; pCreateInfo.enabledLayerCount = (uint)pDebugLayers.Length; pCreateInfo.enabledExtensionCount = (uint)extensionNames.Length; Assert(vkCreateInstance(&pCreateInfo, null, &instance)); } } foreach (var handle in handles) { handle.Free(); } DebugDelegate debugDelegate = new DebugDelegate(DebugCallback); //PFN_vkDebugReportCallbackEXT _debugCallbackFunc =(PFN_vkDebugReportCallbackEXT) debugDelegate; IntPtr debugFunctionPtr = Marshal.GetFunctionPointerForDelegate(debugDelegate); debugDelegateHandle = GCHandle.Alloc(debugDelegate); VkDebugReportCallbackCreateInfoEXT createInfoEXT = VkDebugReportCallbackCreateInfoEXT.New(); createInfoEXT.pfnCallback = debugFunctionPtr; createInfoEXT.flags = //VkDebugReportFlagsEXT.DebugEXT | VkDebugReportFlagsEXT.ErrorEXT | VkDebugReportFlagsEXT.WarningEXT | (VkDebugReportFlagsEXT)int.MaxValue; byte[] debugExtFnName = Encoding.UTF8.GetBytes("vkCreateDebugReportCallbackEXT" + char.MinValue); IntPtr createFnPtr; fixed(byte *namePtr = &(debugExtFnName[0])) { createFnPtr = vkGetInstanceProcAddr(instance, namePtr); } vkCreateDebugReportCallbackEXT_d createDelegate = Marshal.GetDelegateForFunctionPointer <vkCreateDebugReportCallbackEXT_d>(createFnPtr); VkDebugReportCallbackCreateInfoEXT *createInfoPtr = (&createInfoEXT); fixed(ulong *ptr = &(debugReport.Handle)) { Assert(createDelegate(instance, createInfoPtr, IntPtr.Zero, out debugReport)); } return(instance); }
public unsafe GraphicsAdapterFactoryInstance(bool enableValidation) { var applicationInfo = new VkApplicationInfo { sType = VkStructureType.ApplicationInfo, apiVersion = new VkVersion(1, 0, 0), pEngineName = (byte *)Marshal.StringToHGlobalAnsi("Focus"), }; IntPtr[] enabledLayerNames = new IntPtr[0]; #if DEBUG if (enableValidation) { var desiredLayerNames = new[] { "VK_LAYER_KHRONOS_validation", }; var layers = vkEnumerateInstanceLayerProperties(); var availableLayerNames = new HashSet <string>(); for (int index = 0; index < layers.Length; index++) { var properties = layers[index]; var namePointer = properties.layerName; var name = Marshal.PtrToStringAnsi((IntPtr)namePointer); availableLayerNames.Add(name); } enabledLayerNames = desiredLayerNames .Where(x => availableLayerNames.Contains(x)) .Select(Marshal.StringToHGlobalAnsi).ToArray(); } #endif var extensionProperties = vkEnumerateInstanceExtensionProperties(); var availableExtensionNames = new List <string>(); var desiredExtensionNames = new List <string>(); for (int index = 0; index < extensionProperties.Length; index++) { var extensionProperty = extensionProperties[index]; var name = Marshal.PtrToStringAnsi((IntPtr)extensionProperty.extensionName); availableExtensionNames.Add(name); } desiredExtensionNames.Add("VK_KHR_get_physical_device_properties2"); desiredExtensionNames.Add("VK_KHR_external_semaphore_capabilities"); desiredExtensionNames.Add("VK_KHR_external_semaphore"); desiredExtensionNames.Add("VK_KHR_surface"); desiredExtensionNames.Add("VK_KHR_win32_surface"); // windows desiredExtensionNames.Add("VK_KHR_image_format_list"); // openxr desiredExtensionNames.Add("VK_KHR_android_surface"); // android desiredExtensionNames.Add("VK_KHR_xlib_surface"); // linux desiredExtensionNames.Add("VK_KHR_xcb_surface"); // linux desiredExtensionNames.Add("VK_MVK_macos_surface"); // macos desiredExtensionNames.Add("VK_EXT_metal_surface"); // macos desiredExtensionNames.Add("VK_MVK_moltenvk"); // macos desiredExtensionNames.Add("VK_NV_external_memory_capabilities"); // NVIDIA needs this one for OpenVR desiredExtensionNames.Add("VK_KHR_external_memory_capabilities"); // this one might be used in the future for OpenVR #if DEBUG bool enableDebugReport = enableValidation && availableExtensionNames.Contains("VK_EXT_debug_report"); if (enableDebugReport) { desiredExtensionNames.Add("VK_EXT_debug_report"); } #endif // take out any extensions not supported for (int i = 0; i < desiredExtensionNames.Count; i++) { if (availableExtensionNames.Contains(desiredExtensionNames[i]) == false) { desiredExtensionNames.RemoveAt(i); i--; } } var enabledExtensionNames = desiredExtensionNames.Select(Marshal.StringToHGlobalAnsi).ToArray(); try { fixed(void *enabledExtensionNamesPointer = &enabledExtensionNames[0]) { var instanceCreateInfo = new VkInstanceCreateInfo { sType = VkStructureType.InstanceCreateInfo, pApplicationInfo = &applicationInfo, enabledLayerCount = enabledLayerNames != null ? (uint)enabledLayerNames.Length : 0, ppEnabledLayerNames = enabledLayerNames?.Length > 0 ? (byte **)Core.Interop.Fixed(enabledLayerNames) : null, enabledExtensionCount = (uint)enabledExtensionNames.Length, ppEnabledExtensionNames = (byte **)enabledExtensionNamesPointer, }; vkCreateInstance(&instanceCreateInfo, null, out NativeInstance); vkLoadInstance(NativeInstance); } #if DEBUG if (enableDebugReport) { var createDebugReportCallbackName = Marshal.StringToHGlobalAnsi("vkCreateDebugReportCallbackEXT"); var createDebugReportCallback = (CreateDebugReportCallbackDelegate)Marshal.GetDelegateForFunctionPointer(vkGetInstanceProcAddr(NativeInstance, (byte *)createDebugReportCallbackName), typeof(CreateDebugReportCallbackDelegate)); debugReport = DebugReport; var createInfo = new VkDebugReportCallbackCreateInfoEXT { sType = VkStructureType.DebugReportCallbackCreateInfoEXT, flags = VkDebugReportFlagsEXT.Error | VkDebugReportFlagsEXT.Warning /* | VkDebugReportFlagsEXT.PerformanceWarningEXT | VkDebugReportFlagsEXT.InformationEXT | VkDebugReportFlagsEXT.DebugEXT*/, pfnCallback = Marshal.GetFunctionPointerForDelegate(debugReport) }; createDebugReportCallback(NativeInstance, ref createInfo, null, out debugReportCallback); Marshal.FreeHGlobal(createDebugReportCallbackName); } if (availableExtensionNames.Contains("VK_EXT_debug_marker")) { var beginDebugMarkerName = System.Text.Encoding.ASCII.GetBytes("vkCmdDebugMarkerBeginEXT"); var ptr = vkGetInstanceProcAddr(NativeInstance, (byte *)Core.Interop.Fixed(beginDebugMarkerName)); if (ptr != IntPtr.Zero) { BeginDebugMarker = (BeginDebugMarkerDelegate)Marshal.GetDelegateForFunctionPointer(ptr, typeof(BeginDebugMarkerDelegate)); } var endDebugMarkerName = System.Text.Encoding.ASCII.GetBytes("vkCmdDebugMarkerEndEXT"); ptr = vkGetInstanceProcAddr(NativeInstance, (byte *)Core.Interop.Fixed(endDebugMarkerName)); if (ptr != IntPtr.Zero) { EndDebugMarker = (EndDebugMarkerDelegate)Marshal.GetDelegateForFunctionPointer(ptr, typeof(EndDebugMarkerDelegate)); } } #endif } finally { foreach (var enabledExtensionName in enabledExtensionNames) { Marshal.FreeHGlobal(enabledExtensionName); } foreach (var enabledLayerName in enabledLayerNames) { Marshal.FreeHGlobal(enabledLayerName); } Marshal.FreeHGlobal((IntPtr)applicationInfo.pEngineName); } }
private void CreateInstance() { HashSet <string> availableInstanceLayers = new HashSet <string>(EnumerateInstanceLayers()); HashSet <string> availableInstanceExtensions = new HashSet <string>(EnumerateInstanceExtensions()); VkInstanceCreateInfo instanceCI = VkInstanceCreateInfo.New(); VkApplicationInfo applicationInfo = new VkApplicationInfo(); applicationInfo.apiVersion = new VkVersion(1, 0, 0); applicationInfo.applicationVersion = new VkVersion(1, 0, 0); applicationInfo.engineVersion = new VkVersion(1, 0, 0); applicationInfo.pApplicationName = s_name; applicationInfo.pEngineName = s_name; instanceCI.pApplicationInfo = &applicationInfo; StackList <IntPtr, Size64Bytes> instanceExtensions = new StackList <IntPtr, Size64Bytes>(); StackList <IntPtr, Size64Bytes> instanceLayers = new StackList <IntPtr, Size64Bytes>(); if (!availableInstanceExtensions.Contains(CommonStrings.VK_KHR_SURFACE_EXTENSION_NAME)) { throw new VeldridException($"The required instance extension was not available: {CommonStrings.VK_KHR_SURFACE_EXTENSION_NAME}"); } instanceExtensions.Add(CommonStrings.VK_KHR_SURFACE_EXTENSION_NAME); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { if (!availableInstanceExtensions.Contains(CommonStrings.VK_KHR_WIN32_SURFACE_EXTENSION_NAME)) { throw new VeldridException($"The required instance extension was not available: {CommonStrings.VK_KHR_WIN32_SURFACE_EXTENSION_NAME}"); } instanceExtensions.Add(CommonStrings.VK_KHR_WIN32_SURFACE_EXTENSION_NAME); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { if (!availableInstanceExtensions.Contains(CommonStrings.VK_KHR_XLIB_SURFACE_EXTENSION_NAME)) { throw new VeldridException($"The required instance extension was not available: {CommonStrings.VK_KHR_XLIB_SURFACE_EXTENSION_NAME}"); } instanceExtensions.Add(CommonStrings.VK_KHR_XLIB_SURFACE_EXTENSION_NAME); } else { throw new NotSupportedException("This platform does not support Vulkan."); } bool debug = false; #if DEBUG debug = true; #endif bool debugReportExtensionAvailable = false; if (debug) { if (availableInstanceExtensions.Contains(CommonStrings.VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) { debugReportExtensionAvailable = true; instanceExtensions.Add(CommonStrings.VK_EXT_DEBUG_REPORT_EXTENSION_NAME); } if (availableInstanceLayers.Contains(CommonStrings.StandardValidationLayerName)) { instanceLayers.Add(CommonStrings.StandardValidationLayerName); } } instanceCI.enabledExtensionCount = instanceExtensions.Count; instanceCI.ppEnabledExtensionNames = (byte **)instanceExtensions.Data; instanceCI.enabledLayerCount = instanceLayers.Count; instanceCI.ppEnabledLayerNames = (byte **)instanceLayers.Data; VkResult result = vkCreateInstance(ref instanceCI, null, out _instance); CheckResult(result); if (debug && debugReportExtensionAvailable) { EnableDebugCallback(VkDebugReportFlagsEXT.Warning | VkDebugReportFlagsEXT.Error | VkDebugReportFlagsEXT.PerformanceWarning); } }
public static void Init() { optionalExtn_avail = new bool[optionalDeviceExtns.Length]; Console.BackgroundColor = ConsoleColor.Black; Console.ForegroundColor = ConsoleColor.White; Window = new GameWindow(AppName); fixed(IntPtr *instancePtr = &instanceHndl) fixed(IntPtr * surfacePtr = &surfaceHndl) { VkResult res; var instLayers = new List <string>(); var instExtns = new List <string>(); var devExtns = new List <string>(); uint glfwExtnCnt = 0; var glfwExtns = glfwGetRequiredInstanceExtensions(&glfwExtnCnt); for (int i = 0; i < glfwExtnCnt; i++) { instExtns.Add(Marshal.PtrToStringAnsi(glfwExtns[i])); } instExtns.Add(VkKhrGetPhysicalDeviceProperties2ExtensionName); if (EnableValidation) { instLayers.Add("VK_LAYER_KHRONOS_validation"); instExtns.Add(VkExtDebugUtilsExtensionName); } var layers = stackalloc IntPtr[instLayers.Count]; for (int i = 0; i < instLayers.Count; i++) { layers[i] = Marshal.StringToHGlobalAnsi(instLayers[i]); } var extns = stackalloc IntPtr[instExtns.Count]; for (int i = 0; i < instExtns.Count; i++) { extns[i] = Marshal.StringToHGlobalAnsi(instExtns[i]); } { var appInfo = new VkApplicationInfo() { sType = VkStructureType.StructureTypeApplicationInfo, pApplicationName = AppName, pEngineName = EngineName, apiVersion = VkApiVersion12, applicationVersion = 1, engineVersion = 1, pNext = IntPtr.Zero }; var appInfo_ptr = appInfo.Pointer(); var instCreatInfo = new VkInstanceCreateInfo() { sType = VkStructureType.StructureTypeInstanceCreateInfo, pApplicationInfo = appInfo_ptr, }; instCreatInfo.ppEnabledLayerNames = layers; instCreatInfo.enabledLayerCount = (uint)instLayers.Count; instCreatInfo.ppEnabledExtensionNames = extns; instCreatInfo.enabledExtensionCount = (uint)instExtns.Count; var instCreatInfo_ptr = instCreatInfo.Pointer(); //register instance create debug message handler debugCreatInfo = new VkDebugUtilsMessengerCreateInfoEXT() { sType = VkStructureType.StructureTypeDebugUtilsMessengerCreateInfoExt, messageSeverity = VkDebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityErrorBitExt | VkDebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityWarningBitExt | VkDebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityVerboseBitExt | VkDebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityInfoBitExt, messageType = VkDebugUtilsMessageTypeFlagsEXT.DebugUtilsMessageTypeGeneralBitExt | VkDebugUtilsMessageTypeFlagsEXT.DebugUtilsMessageTypePerformanceBitExt | VkDebugUtilsMessageTypeFlagsEXT.DebugUtilsMessageTypeValidationBitExt, pfnUserCallback = DebugCallback }; var debugCreatInfo_ptr = debugCreatInfo.Pointer(); if (EnableValidation) { instCreatInfo.pNext = debugCreatInfo_ptr; } res = vkCreateInstance(instCreatInfo_ptr, null, instancePtr); if (res != VkResult.Success) { throw new Exception("Failed to create instance."); } } if (EnableValidation) { SetupDebugMessengers(instanceHndl); var debugCreatInfo_ptr = debugCreatInfo.Pointer(); fixed(IntPtr *dbg_ptr = &debugMessenger) res = CreateDebugUtilsMessengerEXT(instanceHndl, debugCreatInfo_ptr, IntPtr.Zero, dbg_ptr); if (res != VkResult.Success) { throw new Exception("Failed to register debug callback."); } } res = Window.CreateSurface(instanceHndl, surfacePtr); if (res != VkResult.Success) { throw new Exception("Failed to create surface."); } uint devCount = 0; vkEnumeratePhysicalDevices(instanceHndl, &devCount, null); if (devCount == 0) { throw new Exception("Failed to find Vulkan compatible devices."); } var devices = new IntPtr[devCount]; fixed(IntPtr *devicesPtr = devices) vkEnumeratePhysicalDevices(instanceHndl, &devCount, devicesPtr); var ratedDevices = new List <(uint, IntPtr)>(); for (int i = 0; i < devices.Length; i++) { //rate each device ratedDevices.Add((RateDevice(devices[i]), devices[i])); } var orderedDevices = ratedDevices.OrderByDescending(a => a.Item1) .Select(a => a.Item2) .ToArray(); DeviceInformation = new DeviceInfo[orderedDevices.Length]; DeviceInformation[0] = new DeviceInfo() { PhysicalDevice = orderedDevices[0] }; //TODO for now just choose the first device { //allocate queues for primary device uint graphicsFamily = ~0u; uint computeFamily = ~0u; uint transferFamily = ~0u; uint presentFamily = ~0u; uint qfam_cnt = 0; vkGetPhysicalDeviceQueueFamilyProperties(orderedDevices[0], &qfam_cnt, null); var qFams_ptr = new ManagedPtrArray <VkQueueFamilyProperties>(qfam_cnt); vkGetPhysicalDeviceQueueFamilyProperties(orderedDevices[0], &qfam_cnt, qFams_ptr); var qFams = qFams_ptr.Value; uint qFamIdx = 0; foreach (var qFam in qFams) { bool presentSupport = false; vkGetPhysicalDeviceSurfaceSupportKHR(orderedDevices[0], qFamIdx, surfaceHndl, &presentSupport); if ((qFam.queueFlags & VkQueueFlags.QueueGraphicsBit) != 0 && graphicsFamily == ~0u) { graphicsFamily = qFamIdx; if (presentSupport) { presentFamily = qFamIdx; } qFamIdx++; continue; } if ((qFam.queueFlags & VkQueueFlags.QueueComputeBit) != 0 && computeFamily == ~0u) { computeFamily = qFamIdx; if ((qFam.queueFlags & VkQueueFlags.QueueTransferBit) != 0) { transferFamily = qFamIdx; } qFamIdx++; continue; } if ((qFam.queueFlags & VkQueueFlags.QueueTransferBit) != 0) { transferFamily = qFamIdx; } if (graphicsFamily != ~0u && computeFamily != ~0u && transferFamily != ~0u && presentFamily != ~0u) { break; } qFamIdx++; } if (presentFamily == ~0u) { throw new Exception("Separate present queue support hasn't been implemented."); } var max_q_priority = stackalloc float[] { 1.0f }; var dual_graph_q_priority = stackalloc float[] { 1.0f }; var triple_graph_q_priority = stackalloc float[] { 1.0f, 1.0f, 1.0f }; VkDeviceQueueCreateInfo graphics_qCreatInfo = new VkDeviceQueueCreateInfo() { sType = VkStructureType.StructureTypeDeviceQueueCreateInfo, queueFamilyIndex = graphicsFamily, queueCount = 1, pQueuePriorities = max_q_priority }; VkDeviceQueueCreateInfo compute_qCreatInfo = new VkDeviceQueueCreateInfo { sType = VkStructureType.StructureTypeDeviceQueueCreateInfo, queueFamilyIndex = computeFamily, queueCount = 1, pQueuePriorities = max_q_priority }; VkDeviceQueueCreateInfo transfer_qCreatInfo = new VkDeviceQueueCreateInfo(); if (transferFamily != graphicsFamily) { transfer_qCreatInfo.sType = VkStructureType.StructureTypeDeviceQueueCreateInfo; transfer_qCreatInfo.queueFamilyIndex = transferFamily; transfer_qCreatInfo.queueCount = 1; transfer_qCreatInfo.pQueuePriorities = max_q_priority; } else { graphics_qCreatInfo.queueCount = 2; graphics_qCreatInfo.pQueuePriorities = dual_graph_q_priority; } var qCreatInfos = new VkDeviceQueueCreateInfo[3]; qCreatInfos[0] = graphics_qCreatInfo; qCreatInfos[1] = compute_qCreatInfo; if (transferFamily != graphicsFamily) { qCreatInfos[2] = transfer_qCreatInfo; } DeviceInformation[0].GraphicsFamily = graphicsFamily; DeviceInformation[0].ComputeFamily = computeFamily; DeviceInformation[0].TransferFamily = transferFamily; DeviceInformation[0].PresentFamily = presentFamily; VkPhysicalDeviceFeatures devFeats = new VkPhysicalDeviceFeatures() { multiDrawIndirect = true, drawIndirectFirstInstance = true, fullDrawIndexUint32 = true, tessellationShader = true, fragmentStoresAndAtomics = true, vertexPipelineStoresAndAtomics = true, robustBufferAccess = EnableValidation, shaderInt16 = true, samplerAnisotropy = true, fillModeNonSolid = true, largePoints = true, }; var devFeats11 = new VkPhysicalDeviceVulkan11Features() { sType = VkStructureType.StructureTypePhysicalDeviceVulkan11Features, shaderDrawParameters = true, //storageBuffer16BitAccess = true, //uniformAndStorageBuffer16BitAccess = true, //storagePushConstant16 = true, }; var devFeats11_ptr = devFeats11.Pointer(); /* * var depthStenc = new VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures() * { * sType = VkStructureType.StructureTypePhysicalDeviceSeparateDepthStencilLayoutsFeatures, * separateDepthStencilLayouts = true, * pNext = devFeats11_ptr * }; * var depthStenc_ptr = depthStenc.Pointer(); * * var timelineSems = new VkPhysicalDeviceTimelineSemaphoreFeatures() * { * sType = VkStructureType.StructureTypePhysicalDeviceTimelineSemaphoreFeatures, * timelineSemaphore = true, * pNext = depthStenc_ptr, * }; * var timelineSems_ptr = timelineSems.Pointer(); * * var indirectCnt = new VkPhysicalDeviceShaderFloat16Int8Features() * { * sType = VkStructureType.StructureTypePhysicalDeviceShaderFloat16Int8Features, * shaderFloat16 = true, * shaderInt8 = true, * pNext = timelineSems_ptr, * }; * var indirectCnt_ptr = indirectCnt.Pointer(); * * var uboLayout = new VkPhysicalDeviceUniformBufferStandardLayoutFeatures() * { * sType = VkStructureType.StructureTypePhysicalDeviceUniformBufferStandardLayoutFeatures, * uniformBufferStandardLayout = true, * pNext = indirectCnt_ptr * }; * var uboLayout_ptr = uboLayout.Pointer(); * * var storageByte = new VkPhysicalDevice8BitStorageFeatures() * { * sType = VkStructureType.StructureTypePhysicalDevice8bitStorageFeatures, * storageBuffer8BitAccess = true, * uniformAndStorageBuffer8BitAccess = true, * pNext = uboLayout_ptr * }; * var storageByte_ptr = storageByte.Pointer(); * var descIndexing = new VkPhysicalDeviceDescriptorIndexingFeatures() * { * sType = VkStructureType.StructureTypePhysicalDeviceDescriptorIndexingFeatures, * descriptorBindingSampledImageUpdateAfterBind = true, * descriptorBindingStorageBufferUpdateAfterBind = true, * descriptorBindingStorageImageUpdateAfterBind = true, * descriptorBindingStorageTexelBufferUpdateAfterBind = true, * descriptorBindingUniformBufferUpdateAfterBind = true, * descriptorBindingUniformTexelBufferUpdateAfterBind = true, * descriptorBindingUpdateUnusedWhilePending = true, * descriptorBindingPartiallyBound = true, * shaderStorageTexelBufferArrayDynamicIndexing = true, * pNext = storageByte_ptr, * }; * var descIndexing_ptr = descIndexing.Pointer();*/ //var drawIndirectCount = new VkDrawIndirecCount var devFeats12 = new VkPhysicalDeviceVulkan12Features() { sType = VkStructureType.StructureTypePhysicalDeviceVulkan12Features, separateDepthStencilLayouts = true, timelineSemaphore = true, drawIndirectCount = true, shaderFloat16 = true, shaderInt8 = true, uniformBufferStandardLayout = true, storageBuffer8BitAccess = true, uniformAndStorageBuffer8BitAccess = true, descriptorIndexing = true, descriptorBindingSampledImageUpdateAfterBind = true, descriptorBindingStorageBufferUpdateAfterBind = true, descriptorBindingStorageImageUpdateAfterBind = true, descriptorBindingStorageTexelBufferUpdateAfterBind = true, descriptorBindingUniformBufferUpdateAfterBind = true, descriptorBindingUniformTexelBufferUpdateAfterBind = true, descriptorBindingUpdateUnusedWhilePending = true, descriptorBindingPartiallyBound = true, shaderStorageTexelBufferArrayDynamicIndexing = true, shaderStorageBufferArrayNonUniformIndexing = true, runtimeDescriptorArray = true, descriptorBindingVariableDescriptorCount = true, pNext = devFeats11_ptr }; var devFeats12_ptr = devFeats12.Pointer(); devExtns.AddRange(requiredDeviceExtns); for (int i = 0; i < optionalExtn_avail.Length; i++) { if (optionalExtn_avail[i]) { devExtns.Add(optionalDeviceExtns[i]); } } var devExtns_ptr = stackalloc IntPtr[devExtns.Count]; for (int i = 0; i < devExtns.Count; i++) { devExtns_ptr[i] = Marshal.StringToHGlobalAnsi(devExtns[i]); } var qCreatInfos_ptr = qCreatInfos.Pointer(); var devFeats_ptr = devFeats.Pointer(); var devCreatInfo = new VkDeviceCreateInfo() { sType = VkStructureType.StructureTypeDeviceCreateInfo, queueCreateInfoCount = (uint)(transferFamily != graphicsFamily ? 3 : 2), enabledExtensionCount = (uint)devExtns.Count, ppEnabledExtensionNames = devExtns_ptr, enabledLayerCount = (uint)instLayers.Count, ppEnabledLayerNames = layers, pEnabledFeatures = devFeats_ptr, pQueueCreateInfos = qCreatInfos_ptr, pNext = devFeats12_ptr }; var devCreatInfo_ptr = devCreatInfo.Pointer(); IntPtr deviceHndl = IntPtr.Zero; res = vkCreateDevice(orderedDevices[0], devCreatInfo_ptr, null, &deviceHndl); if (res != VkResult.Success) { throw new Exception("Failed to create logical device."); } DeviceInformation[0].Device = deviceHndl; //Setup memory allocator var allocCreatInfo = new VmaAllocatorCreateInfo() { physicalDevice = DeviceInformation[0].PhysicalDevice, device = DeviceInformation[0].Device }; var allocCreatInfo_ptr = allocCreatInfo.Pointer(); fixed(IntPtr *vma_alloc_ptr = &DeviceInformation[0].vmaAllocator) res = vmaCreateAllocator(allocCreatInfo_ptr, vma_alloc_ptr); if (res != VkResult.Success) { throw new Exception("Failed to initialize allocator."); } IntPtr graph_q_hndl = IntPtr.Zero; IntPtr trans_q_hndl = IntPtr.Zero; IntPtr comp_q_hndl = IntPtr.Zero; vkGetDeviceQueue(DeviceInformation[0].Device, graphicsFamily, 0, &graph_q_hndl); vkGetDeviceQueue(DeviceInformation[0].Device, computeFamily, 0, &comp_q_hndl); if (transferFamily != graphicsFamily) { vkGetDeviceQueue(DeviceInformation[0].Device, transferFamily, 0, &trans_q_hndl); } else { vkGetDeviceQueue(DeviceInformation[0].Device, graphicsFamily, 1, &trans_q_hndl); } DeviceInformation[0].GraphicsQueue = new GpuQueue(CommandQueueKind.Graphics, graph_q_hndl, graphicsFamily, 0); DeviceInformation[0].TransferQueue = new GpuQueue(CommandQueueKind.Transfer, trans_q_hndl, transferFamily, 0); DeviceInformation[0].ComputeQueue = new GpuQueue(CommandQueueKind.Compute, comp_q_hndl, computeFamily, 0); var queue_indices = new List <uint>(); if (!queue_indices.Contains(DeviceInformation[0].GraphicsFamily)) { queue_indices.Add(DeviceInformation[0].GraphicsFamily); } if (!queue_indices.Contains(DeviceInformation[0].ComputeFamily)) { queue_indices.Add(DeviceInformation[0].ComputeFamily); } if (!queue_indices.Contains(DeviceInformation[0].PresentFamily)) { queue_indices.Add(DeviceInformation[0].PresentFamily); } if (!queue_indices.Contains(DeviceInformation[0].TransferFamily)) { queue_indices.Add(DeviceInformation[0].TransferFamily); } DeviceInformation[0].QueueFamilyIndices = queue_indices.ToArray(); var physDeviceProps = new ManagedPtr <VkPhysicalDeviceProperties>(); vkGetPhysicalDeviceProperties(DeviceInformation[0].PhysicalDevice, physDeviceProps); DeviceInformation[0].Properties = physDeviceProps.Value; var caps_ptr = new ManagedPtr <VkSurfaceCapabilitiesKHR>(); vkGetPhysicalDeviceSurfaceCapabilitiesKHR(DeviceInformation[0].PhysicalDevice, surfaceHndl, caps_ptr); var caps = caps_ptr.Value; VkExtent2D cur_extent = new VkExtent2D(); if (caps.currentExtent.width != uint.MaxValue) { cur_extent = caps.currentExtent; } else { cur_extent.width = System.Math.Clamp((uint)Window.Width, caps.minImageExtent.width, caps.maxImageExtent.width); cur_extent.height = System.Math.Clamp((uint)Window.Height, caps.minImageExtent.height, caps.maxImageExtent.height); } uint img_cnt = caps.minImageCount + 1; VkSwapchainCreateInfoKHR swapCreatInfo = new VkSwapchainCreateInfoKHR() { sType = VkStructureType.StructureTypeSwapchainCreateInfoKhr, surface = surfaceHndl, minImageCount = img_cnt, imageFormat = surface_fmt.format, imageColorSpace = surface_fmt.colorSpace, imageExtent = cur_extent, imageArrayLayers = 1, imageUsage = VkImageUsageFlags.ImageUsageColorAttachmentBit | VkImageUsageFlags.ImageUsageTransferDstBit | VkImageUsageFlags.ImageUsageTransferSrcBit, imageSharingMode = VkSharingMode.SharingModeExclusive, queueFamilyIndexCount = 0, pQueueFamilyIndices = null, preTransform = caps.currentTransform, compositeAlpha = VkCompositeAlphaFlagsKHR.CompositeAlphaOpaqueBitKhr, presentMode = present_mode, clipped = true, oldSwapchain = IntPtr.Zero }; var swapCreatInfo_ptr = swapCreatInfo.Pointer(); fixed(IntPtr *swapchain_ptr = &swapChainHndl) res = vkCreateSwapchainKHR(DeviceInformation[0].Device, swapCreatInfo_ptr, null, swapchain_ptr); if (res != VkResult.Success) throw new Exception("Failed to create swapchain."); fixed(uint *swapchain_img_cnt_ptr = &swapchain_img_cnt) { vkGetSwapchainImagesKHR(DeviceInformation[0].Device, swapChainHndl, swapchain_img_cnt_ptr, null); var swapchainImages_l = new IntPtr[swapchain_img_cnt]; fixed(IntPtr *swapchain_imgs = swapchainImages_l) vkGetSwapchainImagesKHR(DeviceInformation[0].Device, swapChainHndl, swapchain_img_cnt_ptr, swapchain_imgs); MaxFramesInFlight = swapchain_img_cnt; MaxFrameCount = swapchain_img_cnt; swapchainImages = new Image[swapchain_img_cnt]; for (int i = 0; i < swapchainImages.Length; i++) { swapchainImages[i] = new Image($"Swapchain_{i}") { Dimensions = 2, Width = cur_extent.width, Height = cur_extent.height, Depth = 1, Format = (ImageFormat)surface_fmt.format, Layers = 1, Levels = 1, MemoryUsage = MemoryUsage.GpuOnly, Usage = ImageUsage.Sampled, InitialLayout = ImageLayout.Undefined, Cubemappable = false, }; swapchainImages[i].Build(0, swapchainImages_l[i]); } surface_extent = cur_extent; swapchainViews = new ImageView[swapchain_img_cnt]; DefaultFramebuffer = new Framebuffer[swapchain_img_cnt]; for (int i = 0; i < swapchainImages.Length; i++) { swapchainViews[i] = new ImageView($"Swapchain_{i}") { BaseLayer = 0, BaseLevel = 0, Format = (ImageFormat)surface_fmt.format, LayerCount = 1, LevelCount = 1, ViewType = ImageViewType.View2D, }; swapchainViews[i].Build(swapchainImages[i]); DefaultFramebuffer[i] = new Framebuffer(); DefaultFramebuffer[i].Width = surface_extent.width; DefaultFramebuffer[i].Height = surface_extent.height; DefaultFramebuffer[i].Name = $"Swapchain_{i}"; DefaultFramebuffer[i].ColorAttachments = new ImageView[] { swapchainViews[i] }; } } for (int i = 0; i < instLayers.Count; i++) { Marshal.FreeHGlobal(layers[i]); } for (int i = 0; i < instExtns.Count; i++) { Marshal.FreeHGlobal(extns[i]); } for (int i = 0; i < devExtns.Count; i++) { Marshal.FreeHGlobal(devExtns_ptr[i]); } //TODO allocate compute and trasnfer queues for all secondary devices } for (int i = 0; i < 1 /*DeviceInformation.Length*/; i++) { var devInfo = DeviceInformation[i]; IntPtr rrCtxtHndl = IntPtr.Zero; if (rrCreateContextVk(RrApiVersion, devInfo.Device, devInfo.PhysicalDevice, devInfo.ComputeQueue.Handle, devInfo.ComputeFamily, &rrCtxtHndl) != RRError.RrSuccess) { Console.WriteLine($"Failed to initialize RadeonRays for device #{i}."); } DeviceInformation[i].RaysContext = rrCtxtHndl; } FrameFinishedSemaphore = new GpuSemaphore[MaxFramesInFlight]; ImageAvailableSemaphore = new GpuSemaphore[MaxFramesInFlight]; InflightFences = new Fence[MaxFramesInFlight]; for (int i = 0; i < MaxFramesInFlight; i++) { FrameFinishedSemaphore[i] = new GpuSemaphore(); FrameFinishedSemaphore[i].Build(0, false, 0); ImageAvailableSemaphore[i] = new GpuSemaphore(); ImageAvailableSemaphore[i].Build(0, false, 0); InflightFences[i] = new Fence { CreateSignaled = true }; InflightFences[i].Build(0); } Width = (uint)Window.Width; Height = (uint)Window.Height; } }
private VkInstance CreateInstance(bool debug) { VkInstance instance; // Specify standard validation layers. string surfaceExtension; switch (Host.Platform) { case Platform.Android: surfaceExtension = KHRAndroidSurfaceExtensionName; break; case Platform.Win32: surfaceExtension = KHRWin32SurfaceExtensionName; break; default: throw new NotImplementedException(); } VkString name = "TODO Application Name"; var appInfo = new VkApplicationInfo { sType = VkStructureType.ApplicationInfo, pApplicationName = name, applicationVersion = new VkVersion(1, 0, 0), pEngineName = s_EngineName, engineVersion = new VkVersion(1, 0, 0), apiVersion = VkVersion.Version_1_0, }; var instanceExtensions = new List <string> { KHRSurfaceExtensionName, surfaceExtension }; var instanceLayers = new List <string>(); if (EnableValidationLayers) { FindValidationLayers(instanceLayers); } if (instanceLayers.Count > 0) { instanceExtensions.Add(EXTDebugUtilsExtensionName); } using var vkInstanceExtensions = new VkStringArray(instanceExtensions); var instanceCreateInfo = new VkInstanceCreateInfo { sType = VkStructureType.InstanceCreateInfo, pApplicationInfo = &appInfo, enabledExtensionCount = vkInstanceExtensions.Length, ppEnabledExtensionNames = vkInstanceExtensions }; using var vkLayerNames = new VkStringArray(instanceLayers); if (instanceLayers.Count > 0) { instanceCreateInfo.enabledLayerCount = vkLayerNames.Length; instanceCreateInfo.ppEnabledLayerNames = vkLayerNames; } VkResult result = vkCreateInstance(&instanceCreateInfo, null, out instance); vkLoadInstance(instance); if (instanceLayers.Count > 0) { _debugMessengerCallbackFunc = DebugMessengerCallback; var debugCreateInfo = new VkDebugUtilsMessengerCreateInfoEXT { sType = VkStructureType.DebugUtilsMessengerCreateInfoEXT, messageSeverity = VkDebugUtilsMessageSeverityFlagsEXT.Verbose | VkDebugUtilsMessageSeverityFlagsEXT.Error | VkDebugUtilsMessageSeverityFlagsEXT.Warning, messageType = VkDebugUtilsMessageTypeFlagsEXT.General | VkDebugUtilsMessageTypeFlagsEXT.Validation | VkDebugUtilsMessageTypeFlagsEXT.Performance, pfnUserCallback = Marshal.GetFunctionPointerForDelegate(_debugMessengerCallbackFunc) }; vkCreateDebugUtilsMessengerEXT(instance, &debugCreateInfo, null, out debugMessenger).CheckResult(); } return(instance); }