Example #1
0
        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;
            }
        }
Example #2
0
        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;
        }
Example #3
0
        /// <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);
        }