VulkanInstance.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  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. namespace Ryujinx.Graphics.Vulkan
  10. {
  11. class VulkanInstance : IDisposable
  12. {
  13. private readonly Vk _api;
  14. public readonly Instance Instance;
  15. public readonly Version32 InstanceVersion;
  16. private bool _disposed;
  17. private VulkanInstance(Vk api, Instance instance)
  18. {
  19. _api = api;
  20. Instance = instance;
  21. if (api.GetInstanceProcAddr(instance, "vkEnumerateInstanceVersion") == IntPtr.Zero)
  22. {
  23. InstanceVersion = Vk.Version10;
  24. }
  25. else
  26. {
  27. uint rawInstanceVersion = 0;
  28. if (api.EnumerateInstanceVersion(ref rawInstanceVersion) != Result.Success)
  29. {
  30. rawInstanceVersion = Vk.Version11.Value;
  31. }
  32. InstanceVersion = (Version32)rawInstanceVersion;
  33. }
  34. }
  35. public static Result Create(Vk api, ref InstanceCreateInfo createInfo, out VulkanInstance instance)
  36. {
  37. instance = null;
  38. Instance rawInstance = default;
  39. Result result = api.CreateInstance(SpanHelpers.AsReadOnlySpan(ref createInfo), ReadOnlySpan<AllocationCallbacks>.Empty, SpanHelpers.AsSpan(ref rawInstance));
  40. if (result == Result.Success)
  41. {
  42. instance = new VulkanInstance(api, rawInstance);
  43. }
  44. return result;
  45. }
  46. public Result EnumeratePhysicalDevices(out VulkanPhysicalDevice[] physicalDevices)
  47. {
  48. physicalDevices = null;
  49. uint physicalDeviceCount = 0;
  50. Result result = _api.EnumeratePhysicalDevices(Instance, SpanHelpers.AsSpan(ref physicalDeviceCount), Span<PhysicalDevice>.Empty);
  51. if (result != Result.Success)
  52. {
  53. return result;
  54. }
  55. PhysicalDevice[] rawPhysicalDevices = new PhysicalDevice[physicalDeviceCount];
  56. result = _api.EnumeratePhysicalDevices(Instance, SpanHelpers.AsSpan(ref physicalDeviceCount), rawPhysicalDevices);
  57. if (result != Result.Success)
  58. {
  59. return result;
  60. }
  61. physicalDevices = rawPhysicalDevices.Select(x => new VulkanPhysicalDevice(_api, x)).ToArray();
  62. return Result.Success;
  63. }
  64. public static IReadOnlySet<string> GetInstanceExtensions(Vk api)
  65. {
  66. uint propertiesCount = 0;
  67. api.EnumerateInstanceExtensionProperties(ReadOnlySpan<byte>.Empty, SpanHelpers.AsSpan(ref propertiesCount), Span<ExtensionProperties>.Empty).ThrowOnError();
  68. ExtensionProperties[] extensionProperties = new ExtensionProperties[propertiesCount];
  69. api.EnumerateInstanceExtensionProperties(ReadOnlySpan<byte>.Empty, SpanHelpers.AsSpan(ref propertiesCount), extensionProperties).ThrowOnError();
  70. unsafe
  71. {
  72. return extensionProperties.Select(x => Marshal.PtrToStringAnsi((IntPtr)x.ExtensionName)).ToImmutableHashSet();
  73. }
  74. }
  75. public static IReadOnlySet<string> GetInstanceLayers(Vk api)
  76. {
  77. uint propertiesCount = 0;
  78. api.EnumerateInstanceLayerProperties(SpanHelpers.AsSpan(ref propertiesCount), Span<LayerProperties>.Empty).ThrowOnError();
  79. LayerProperties[] layerProperties = new LayerProperties[propertiesCount];
  80. api.EnumerateInstanceLayerProperties(SpanHelpers.AsSpan(ref propertiesCount), layerProperties).ThrowOnError();
  81. unsafe
  82. {
  83. return layerProperties.Select(x => Marshal.PtrToStringAnsi((IntPtr)x.LayerName)).ToImmutableHashSet();
  84. }
  85. }
  86. public void Dispose()
  87. {
  88. if (!_disposed)
  89. {
  90. _api.DestroyInstance(Instance, ReadOnlySpan<AllocationCallbacks>.Empty);
  91. _disposed = true;
  92. }
  93. }
  94. }
  95. }