SpecInfo.cs 2.9 KB

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