/ src / Ryujinx.Graphics.Vulkan / VulkanInstance.cs
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  }