aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Vulkan/VulkanInstance.cs
blob: 843d341250d01cdc93b4d6b98eacbf6f08e9de75 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
using Ryujinx.Common.Utilities;
using Silk.NET.Core;
using Silk.NET.Vulkan;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Runtime.InteropServices;

namespace Ryujinx.Graphics.Vulkan
{
    class VulkanInstance : IDisposable
    {
        private readonly Vk _api;
        public readonly Instance Instance;
        public readonly Version32 InstanceVersion;

        private bool _disposed;

        private VulkanInstance(Vk api, Instance instance)
        {
            _api = api;
            Instance = instance;

            if (api.GetInstanceProcAddr(instance, "vkEnumerateInstanceVersion") == IntPtr.Zero)
            {
                InstanceVersion = Vk.Version10;
            }
            else
            {
                uint rawInstanceVersion = 0;

                if (api.EnumerateInstanceVersion(ref rawInstanceVersion) != Result.Success)
                {
                    rawInstanceVersion = Vk.Version11.Value;
                }

                InstanceVersion = (Version32)rawInstanceVersion;
            }
        }

        public static Result Create(Vk api, ref InstanceCreateInfo createInfo, out VulkanInstance instance)
        {
            instance = null;

            Instance rawInstance = default;

            Result result = api.CreateInstance(SpanHelpers.AsReadOnlySpan(ref createInfo), ReadOnlySpan<AllocationCallbacks>.Empty, SpanHelpers.AsSpan(ref rawInstance));

            if (result == Result.Success)
            {
                instance = new VulkanInstance(api, rawInstance);
            }

            return result;
        }

        public Result EnumeratePhysicalDevices(out VulkanPhysicalDevice[] physicalDevices)
        {
            physicalDevices = null;

            uint physicalDeviceCount = 0;

            Result result = _api.EnumeratePhysicalDevices(Instance, SpanHelpers.AsSpan(ref physicalDeviceCount), Span<PhysicalDevice>.Empty);

            if (result != Result.Success)
            {
                return result;
            }

            PhysicalDevice[] rawPhysicalDevices = new PhysicalDevice[physicalDeviceCount];

            result = _api.EnumeratePhysicalDevices(Instance, SpanHelpers.AsSpan(ref physicalDeviceCount), rawPhysicalDevices);

            if (result != Result.Success)
            {
                return result;
            }

            physicalDevices = rawPhysicalDevices.Select(x => new VulkanPhysicalDevice(_api, x)).ToArray();

            return Result.Success;
        }

        public static IReadOnlySet<string> GetInstanceExtensions(Vk api)
        {
            uint propertiesCount = 0;

            api.EnumerateInstanceExtensionProperties(ReadOnlySpan<byte>.Empty, SpanHelpers.AsSpan(ref propertiesCount), Span<ExtensionProperties>.Empty).ThrowOnError();

            ExtensionProperties[] extensionProperties = new ExtensionProperties[propertiesCount];

            api.EnumerateInstanceExtensionProperties(ReadOnlySpan<byte>.Empty, SpanHelpers.AsSpan(ref propertiesCount), extensionProperties).ThrowOnError();

            unsafe
            {
                return extensionProperties.Select(x => Marshal.PtrToStringAnsi((IntPtr)x.ExtensionName)).ToImmutableHashSet();
            }
        }

        public static IReadOnlySet<string> GetInstanceLayers(Vk api)
        {
            uint propertiesCount = 0;

            api.EnumerateInstanceLayerProperties(SpanHelpers.AsSpan(ref propertiesCount), Span<LayerProperties>.Empty).ThrowOnError();

            LayerProperties[] layerProperties = new LayerProperties[propertiesCount];

            api.EnumerateInstanceLayerProperties(SpanHelpers.AsSpan(ref propertiesCount), layerProperties).ThrowOnError();

            unsafe
            {
                return layerProperties.Select(x => Marshal.PtrToStringAnsi((IntPtr)x.LayerName)).ToImmutableHashSet();
            }
        }

        public void Dispose()
        {
            if (!_disposed)
            {
                _api.DestroyInstance(Instance, ReadOnlySpan<AllocationCallbacks>.Empty);

                _disposed = true;
            }
        }
    }
}