internal PhysicalDevice(Instance instance, VkPhysicalDevice handle) { Instance = instance; Handle = handle; unsafe { var props = Handle.GetPhysicalDeviceProperties(); _properties = props; DeviceName = Marshal.PtrToStringAnsi(new IntPtr(props.DeviceName)); { var memProps = Handle.GetPhysicalDeviceMemoryProperties(); var heapList = new List <MemoryHeap>((int)memProps.MemoryHeapCount); for (uint i = 0; i < memProps.MemoryHeapCount; i++) { heapList.Add(new MemoryHeap(i, memProps.MemoryHeaps[(int)i])); } MemoryHeaps = heapList; var typeList = new List <MemoryType>((int)memProps.MemoryTypeCount); for (uint i = 0; i < memProps.MemoryTypeCount; i++) { typeList.Add(new MemoryType(i, heapList[(int)memProps.MemoryTypes[(int)i].HeapIndex], (VkMemoryPropertyFlag)memProps.MemoryTypes[(int)i].PropertyFlags)); } MemoryTypes = typeList; } } { ExtensionProperties = new List <VkExtensionProperties>(Handle.EnumerateExtensionProperties(null)); LayerProperties = new List <VkLayerProperties>(Handle.EnumerateLayerProperties()); var availableExt = new HashSet <ExtensionDescriptionAttribute>(); foreach (var ext in ExtensionProperties) { var desc = VkExtensionDatabase.Extension(ext.ExtensionNameString); if (desc != null) { availableExt.Add(desc); } } AvailableExtensions = availableExt; } }
public Instance(ICollection <VkExtension> preferredExtensions, ICollection <VkExtension> requiredExtensions, ICollection <string> preferredLayers, ICollection <string> requiredLayers) { var supportedLayers = Vulkan.EnumerateLayerProperties().Select(x => x.LayerNameString).ToHashSet(); Log.Info($"Supported instance 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 = Vulkan.EnumerateExtensionProperties(null).Union( layersToUse.SelectMany(Vulkan.EnumerateExtensionProperties)).Select(x => x.ExtensionNameString) .ToHashSet(); Log.Info($"Supported instance 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 instance layers: {string.Join(", ", layersToUse)}"); Log.Info($"Using instance extensions: {string.Join(", ", extensionsToUse)}"); 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]); } var pinnedLayersToUse = GCHandle.Alloc(layersToUseAnsi, GCHandleType.Pinned); var pinnedExtensionsToUse = GCHandle.Alloc(extensionsToUseAnsi, GCHandleType.Pinned); try { AllocationCallbacks = (VkAllocationCallbacks *)0; var appInfo = new VkApplicationInfo() { SType = VkStructureType.ApplicationInfo, ApiVersion = new VkVersion(1, 0, 0), PApplicationName = (byte *)0, PEngineName = (byte *)0, PNext = IntPtr.Zero }; var instanceInfo = new VkInstanceCreateInfo() { SType = VkStructureType.InstanceCreateInfo, 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, Flags = 0, PApplicationInfo = &appInfo, PNext = IntPtr.Zero }; Handle = Vulkan.CreateInstance(&instanceInfo, AllocationCallbacks); } finally { pinnedLayersToUse.Free(); pinnedExtensionsToUse.Free(); foreach (var ptr in layersToUseAnsi) { Marshal.FreeHGlobal(ptr); } foreach (var ptr in extensionsToUseAnsi) { Marshal.FreeHGlobal(ptr); } } } var devs = new List <PhysicalDevice>(); foreach (var dev in Handle.EnumeratePhysicalDevices()) { devs.Add(new PhysicalDevice(this, dev)); } PhysicalDevices = devs; }
/// <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); }