diff options
Diffstat (limited to 'Ryujinx.Graphics.Vulkan/SpecInfo.cs')
-rw-r--r-- | Ryujinx.Graphics.Vulkan/SpecInfo.cs | 103 |
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 |