/ src / Ryujinx.Graphics.Vulkan / SpecInfo.cs
SpecInfo.cs
  1  using Silk.NET.Vulkan;
  2  using System;
  3  
  4  namespace Ryujinx.Graphics.Vulkan
  5  {
  6      public enum SpecConstType
  7      {
  8          Bool32,
  9          Int16,
 10          Int32,
 11          Int64,
 12          Float16,
 13          Float32,
 14          Float64,
 15      }
 16  
 17      sealed class SpecDescription
 18      {
 19          public readonly SpecializationInfo Info;
 20          public readonly SpecializationMapEntry[] Map;
 21  
 22          // For mapping a simple packed struct or single entry
 23          public SpecDescription(params (uint Id, SpecConstType Type)[] description)
 24          {
 25              int count = description.Length;
 26              Map = new SpecializationMapEntry[count];
 27  
 28              uint structSize = 0;
 29  
 30              for (int i = 0; i < Map.Length; ++i)
 31              {
 32                  var typeSize = SizeOf(description[i].Type);
 33                  Map[i] = new SpecializationMapEntry(description[i].Id, structSize, typeSize);
 34                  structSize += typeSize;
 35              }
 36  
 37              Info = new SpecializationInfo
 38              {
 39                  DataSize = structSize,
 40                  MapEntryCount = (uint)count,
 41              };
 42          }
 43  
 44          // For advanced mapping with overlapping or staggered fields
 45          public SpecDescription(SpecializationMapEntry[] map)
 46          {
 47              Map = map;
 48  
 49              uint structSize = 0;
 50              for (int i = 0; i < map.Length; ++i)
 51              {
 52                  structSize = Math.Max(structSize, map[i].Offset + (uint)map[i].Size);
 53              }
 54  
 55              Info = new SpecializationInfo
 56              {
 57                  DataSize = structSize,
 58                  MapEntryCount = (uint)map.Length,
 59              };
 60          }
 61  
 62          private static uint SizeOf(SpecConstType type) => type switch
 63          {
 64              SpecConstType.Int16 or SpecConstType.Float16 => 2,
 65              SpecConstType.Bool32 or SpecConstType.Int32 or SpecConstType.Float32 => 4,
 66              SpecConstType.Int64 or SpecConstType.Float64 => 8,
 67              _ => throw new ArgumentOutOfRangeException(nameof(type)),
 68          };
 69  
 70          private SpecDescription()
 71          {
 72              Info = new();
 73          }
 74  
 75          public static readonly SpecDescription Empty = new();
 76      }
 77  
 78      readonly struct SpecData : IRefEquatable<SpecData>
 79      {
 80          private readonly byte[] _data;
 81          private readonly int _hash;
 82  
 83          public int Length => _data.Length;
 84          public ReadOnlySpan<byte> Span => _data.AsSpan();
 85          public override int GetHashCode() => _hash;
 86  
 87          public SpecData(ReadOnlySpan<byte> data)
 88          {
 89              _data = new byte[data.Length];
 90              data.CopyTo(_data);
 91  
 92              var hc = new HashCode();
 93              hc.AddBytes(data);
 94              _hash = hc.ToHashCode();
 95          }
 96  
 97          public override bool Equals(object obj) => obj is SpecData other && Equals(other);
 98          public bool Equals(ref SpecData other) => _data.AsSpan().SequenceEqual(other._data);
 99      }
100  }