예제 #1
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);
        }
예제 #2
0
 public VkSurfaceCapabilitiesKHR Capabilities(PhysicalDevice dev)
 {
     AssertValid();
     return(dev.Handle.GetPhysicalDeviceSurfaceCapabilitiesKHR(Handle));
 }