aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Vulkan/SpecInfo.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.Vulkan/SpecInfo.cs')
-rw-r--r--Ryujinx.Graphics.Vulkan/SpecInfo.cs103
1 files changed, 103 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.Vulkan/SpecInfo.cs b/Ryujinx.Graphics.Vulkan/SpecInfo.cs
new file mode 100644
index 00000000..83a34cde
--- /dev/null
+++ b/Ryujinx.Graphics.Vulkan/SpecInfo.cs
@@ -0,0 +1,103 @@
+using Silk.NET.Vulkan;
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace Ryujinx.Graphics.Vulkan
+{
+ public enum SpecConstType
+ {
+ Bool32,
+ Int16,
+ Int32,
+ Int64,
+ Float16,
+ Float32,
+ Float64
+ }
+
+ sealed class SpecDescription
+ {
+ public readonly SpecializationInfo Info;
+ public readonly SpecializationMapEntry[] Map;
+
+ // For mapping a simple packed struct or single entry
+ public SpecDescription(params (uint Id, SpecConstType Type)[] description)
+ {
+ int count = description.Length;
+ Map = new SpecializationMapEntry[count];
+
+ uint structSize = 0;
+
+ for (int i = 0; i < count; ++i)
+ {
+ var typeSize = SizeOf(description[i].Type);
+ Map[i] = new SpecializationMapEntry(description[i].Id, structSize, typeSize);
+ structSize += typeSize;
+ }
+
+ Info = new SpecializationInfo()
+ {
+ DataSize = structSize,
+ MapEntryCount = (uint)count
+ };
+ }
+
+ // For advanced mapping with overlapping or staggered fields
+ public SpecDescription(SpecializationMapEntry[] map)
+ {
+ int count = map.Length;
+ Map = map;
+
+ uint structSize = 0;
+ for (int i = 0; i < count; ++i)
+ {
+ structSize = Math.Max(structSize, map[i].Offset + (uint)map[i].Size);
+ }
+
+ Info = new SpecializationInfo()
+ {
+ DataSize = structSize,
+ MapEntryCount = (uint)map.Length
+ };
+ }
+
+ private static uint SizeOf(SpecConstType type) => type switch
+ {
+ SpecConstType.Int16 or SpecConstType.Float16 => 2,
+ SpecConstType.Bool32 or SpecConstType.Int32 or SpecConstType.Float32 => 4,
+ SpecConstType.Int64 or SpecConstType.Float64 => 8,
+ _ => throw new ArgumentOutOfRangeException(nameof(type))
+ };
+
+ private SpecDescription()
+ {
+ Info = new();
+ }
+
+ public static readonly SpecDescription Empty = new();
+ }
+
+ readonly struct SpecData : IRefEquatable<SpecData>
+ {
+ private readonly byte[] _data;
+ private readonly int _hash;
+
+ public int Length => _data.Length;
+ public ReadOnlySpan<byte> Span => _data.AsSpan();
+ public override int GetHashCode() => _hash;
+
+ public SpecData(ReadOnlySpan<byte> data)
+ {
+ _data = new byte[data.Length];
+ data.CopyTo(_data);
+
+ var hc = new HashCode();
+ hc.AddBytes(data);
+ _hash = hc.ToHashCode();
+ }
+
+ public override bool Equals(object obj) => obj is SpecData other && Equals(other);
+ public bool Equals(ref SpecData other) => _data.AsSpan().SequenceEqual(other._data);
+ }
+} \ No newline at end of file