/// <summary> /// Creates a new device and queues /// </summary> /// <param name="physDevice">Physical device</param> /// <param name="requiredLayers"></param> /// <param name="preferredExtensions"></param> /// <param name="requiredExtensions"></param> /// <param name="preferredLayers"></param> /// <param name="queueOptions">Queue options</param> /// <param name="desiredFeatures">Desired physical device features</param> public Device(PhysicalDevice physDevice, ICollection <VkExtension> preferredExtensions, ICollection <VkExtension> requiredExtensions, ICollection <string> preferredLayers, ICollection <string> requiredLayers, QueueCreateInfo[] queueOptions, VkPhysicalDeviceFeatures desiredFeatures) { PhysicalDevice = physDevice; foreach (var ext in preferredExtensions.Union(requiredExtensions).Select(VkExtensionDatabase.Extension)) { Debug.Assert(ext.Type == ExtensionType.Device || ext.Type == ExtensionType.Unknown, $"Ext {ext.Extension} type {ext.Type} doesn't conform"); } var supportedLayers = physDevice.Handle.EnumerateLayerProperties().Select(x => x.LayerNameString).ToHashSet(); Log.Info($"Supported device layers: {string.Join(", ", supportedLayers)}"); foreach (var requiredLayer in requiredLayers) { if (!supportedLayers.Contains(requiredLayer)) { throw new NotSupportedException($"Layer {requiredLayer} isn't supported"); } } var layersToUse = requiredLayers.Union(preferredLayers.Where(supportedLayers.Contains)).ToList(); var supportedExtensions = physDevice.Handle.EnumerateExtensionProperties(null).Union( layersToUse.SelectMany(physDevice.Handle.EnumerateExtensionProperties)) .Select(x => x.ExtensionNameString).ToHashSet(); Log.Info($"Supported device extensions: {string.Join(", ", supportedExtensions)}"); foreach (var requiredExtension in requiredExtensions) { if (!supportedExtensions.Contains(VkExtensionDatabase.Extension(requiredExtension).Extension)) { throw new NotSupportedException($"Extension {requiredExtension} isn't supported"); } } var extensionsToUse = requiredExtensions.Select(VkExtensionDatabase.Extension).Select(x => x.Extension) .Union( preferredExtensions.Select(VkExtensionDatabase.Extension).Select(x => x.Extension) .Where(supportedExtensions.Contains)).ToList(); _enabledExtensions = extensionsToUse.Select(VkExtensionDatabase.Extension).Where(y => y != null).Select(x => x.ExtensionId) .ToHashSet(); _enableExtensionsByName = extensionsToUse.ToHashSet(); Log.Info($"Using device layers: {string.Join(", ", layersToUse)}"); Log.Info($"Using device extensions: {string.Join(", ", extensionsToUse)}"); var pins = new List <GCHandle>(); var queueOptionsRedirect = new int[queueOptions.Length]; try { VkDeviceQueueCreateInfo[] queueCreateInfo; { var queueOptionsRewrite = new Dictionary <uint, List <float> >(); for (var queueId = 0; queueId < queueOptions.Length; queueId++) { var opti = queueOptions[queueId]; if (opti.Priorities.Count == 0) { continue; } if (!queueOptionsRewrite.TryGetValue(opti.Family, out var list)) { list = queueOptionsRewrite[opti.Family] = new List <float>(); } queueOptionsRedirect[queueId] = list.Count; list.AddRange(opti.Priorities); } queueCreateInfo = new VkDeviceQueueCreateInfo[queueOptionsRewrite.Count]; var family = 0; foreach (var kv in queueOptionsRewrite) { unsafe { var block = kv.Value.ToArray(); pins.Add(GCHandle.Alloc(block, GCHandleType.Pinned)); queueCreateInfo[family++] = new VkDeviceQueueCreateInfo() { SType = VkStructureType.DeviceQueueCreateInfo, Flags = 0, PNext = IntPtr.Zero, QueueFamilyIndex = kv.Key, QueueCount = (uint)block.Length, PQueuePriorities = (float *)Marshal.UnsafeAddrOfPinnedArrayElement(block, 0).ToPointer() }; } } } unsafe { var layersToUseAnsi = new IntPtr[layersToUse.Count]; for (var i = 0; i < layersToUse.Count; i++) { layersToUseAnsi[i] = Marshal.StringToHGlobalAnsi(layersToUse[i]); } var extensionsToUseAnsi = new IntPtr[extensionsToUse.Count]; for (var i = 0; i < extensionsToUse.Count; i++) { extensionsToUseAnsi[i] = Marshal.StringToHGlobalAnsi(extensionsToUse[i]); } try { fixed(VkDeviceQueueCreateInfo *queueOptionsPtr = queueCreateInfo) { Features = desiredFeatures; var deviceCreateInfo = new VkDeviceCreateInfo() { SType = VkStructureType.DeviceCreateInfo, QueueCreateInfoCount = (uint)queueOptions.Length, PQueueCreateInfos = queueOptionsPtr, PEnabledFeatures = &desiredFeatures, EnabledExtensionCount = (uint)extensionsToUse.Count, PpEnabledExtensionNames = extensionsToUse.Count > 0 ? (byte **)Marshal.UnsafeAddrOfPinnedArrayElement(extensionsToUseAnsi, 0) .ToPointer() : (byte **)0, EnabledLayerCount = (uint)layersToUse.Count, PpEnabledLayerNames = layersToUse.Count > 0 ? (byte **)Marshal.UnsafeAddrOfPinnedArrayElement(layersToUseAnsi, 0).ToPointer() : (byte **)0, }; Handle = PhysicalDevice.Handle.CreateDevice(&deviceCreateInfo, Instance.AllocationCallbacks); } } finally { foreach (var ptr in layersToUseAnsi) { Marshal.FreeHGlobal(ptr); } foreach (var ptr in extensionsToUseAnsi) { Marshal.FreeHGlobal(ptr); } } } } finally { foreach (var pin in pins) { pin.Free(); } pins.Clear(); } _queues = new Queue[queueOptions.Length][]; var queuesAll = new List <Queue>(); for (var i = 0; i < queueOptions.Length; i++) { _queues[i] = new Queue[queueOptions[i].Priorities.Count]; for (var j = 0; j < _queues[i].Length; j++) { queuesAll.Add(_queues[i][j] = new Queue(this, queueOptions[i].Family, (uint)(queueOptionsRedirect[i] + j))); } } Queues = queuesAll; MemoryPool = new DeviceMemoryPools(this); BufferPools = new BufferPools(this); }
public VkSurfaceCapabilitiesKHR Capabilities(PhysicalDevice dev) { AssertValid(); return(dev.Handle.GetPhysicalDeviceSurfaceCapabilitiesKHR(Handle)); }