VulkanInstance.cs
1 using Ryujinx.Common.Utilities; 2 using Silk.NET.Core; 3 using Silk.NET.Vulkan; 4 using System; 5 using System.Collections.Generic; 6 using System.Collections.Immutable; 7 using System.Linq; 8 using System.Runtime.InteropServices; 9 10 namespace Ryujinx.Graphics.Vulkan 11 { 12 class VulkanInstance : IDisposable 13 { 14 private readonly Vk _api; 15 public readonly Instance Instance; 16 public readonly Version32 InstanceVersion; 17 18 private bool _disposed; 19 20 private VulkanInstance(Vk api, Instance instance) 21 { 22 _api = api; 23 Instance = instance; 24 25 if (api.GetInstanceProcAddr(instance, "vkEnumerateInstanceVersion") == IntPtr.Zero) 26 { 27 InstanceVersion = Vk.Version10; 28 } 29 else 30 { 31 uint rawInstanceVersion = 0; 32 33 if (api.EnumerateInstanceVersion(ref rawInstanceVersion) != Result.Success) 34 { 35 rawInstanceVersion = Vk.Version11.Value; 36 } 37 38 InstanceVersion = (Version32)rawInstanceVersion; 39 } 40 } 41 42 public static Result Create(Vk api, ref InstanceCreateInfo createInfo, out VulkanInstance instance) 43 { 44 instance = null; 45 46 Instance rawInstance = default; 47 48 Result result = api.CreateInstance(SpanHelpers.AsReadOnlySpan(ref createInfo), ReadOnlySpan<AllocationCallbacks>.Empty, SpanHelpers.AsSpan(ref rawInstance)); 49 50 if (result == Result.Success) 51 { 52 instance = new VulkanInstance(api, rawInstance); 53 } 54 55 return result; 56 } 57 58 public Result EnumeratePhysicalDevices(out VulkanPhysicalDevice[] physicalDevices) 59 { 60 physicalDevices = null; 61 62 uint physicalDeviceCount = 0; 63 64 Result result = _api.EnumeratePhysicalDevices(Instance, SpanHelpers.AsSpan(ref physicalDeviceCount), Span<PhysicalDevice>.Empty); 65 66 if (result != Result.Success) 67 { 68 return result; 69 } 70 71 PhysicalDevice[] rawPhysicalDevices = new PhysicalDevice[physicalDeviceCount]; 72 73 result = _api.EnumeratePhysicalDevices(Instance, SpanHelpers.AsSpan(ref physicalDeviceCount), rawPhysicalDevices); 74 75 if (result != Result.Success) 76 { 77 return result; 78 } 79 80 physicalDevices = rawPhysicalDevices.Select(x => new VulkanPhysicalDevice(_api, x)).ToArray(); 81 82 return Result.Success; 83 } 84 85 public static IReadOnlySet<string> GetInstanceExtensions(Vk api) 86 { 87 uint propertiesCount = 0; 88 89 api.EnumerateInstanceExtensionProperties(ReadOnlySpan<byte>.Empty, SpanHelpers.AsSpan(ref propertiesCount), Span<ExtensionProperties>.Empty).ThrowOnError(); 90 91 ExtensionProperties[] extensionProperties = new ExtensionProperties[propertiesCount]; 92 93 api.EnumerateInstanceExtensionProperties(ReadOnlySpan<byte>.Empty, SpanHelpers.AsSpan(ref propertiesCount), extensionProperties).ThrowOnError(); 94 95 unsafe 96 { 97 return extensionProperties.Select(x => Marshal.PtrToStringAnsi((IntPtr)x.ExtensionName)).ToImmutableHashSet(); 98 } 99 } 100 101 public static IReadOnlySet<string> GetInstanceLayers(Vk api) 102 { 103 uint propertiesCount = 0; 104 105 api.EnumerateInstanceLayerProperties(SpanHelpers.AsSpan(ref propertiesCount), Span<LayerProperties>.Empty).ThrowOnError(); 106 107 LayerProperties[] layerProperties = new LayerProperties[propertiesCount]; 108 109 api.EnumerateInstanceLayerProperties(SpanHelpers.AsSpan(ref propertiesCount), layerProperties).ThrowOnError(); 110 111 unsafe 112 { 113 return layerProperties.Select(x => Marshal.PtrToStringAnsi((IntPtr)x.LayerName)).ToImmutableHashSet(); 114 } 115 } 116 117 public void Dispose() 118 { 119 if (!_disposed) 120 { 121 _api.DestroyInstance(Instance, ReadOnlySpan<AllocationCallbacks>.Empty); 122 123 _disposed = true; 124 } 125 } 126 } 127 }