예제 #1
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;
        }