/ src / Ryujinx.Graphics.Vulkan / PipelineUid.cs
PipelineUid.cs
  1  using Ryujinx.Common.Memory;
  2  using Silk.NET.Vulkan;
  3  using System;
  4  using System.Runtime.CompilerServices;
  5  using System.Runtime.InteropServices;
  6  using System.Runtime.Intrinsics;
  7  
  8  namespace Ryujinx.Graphics.Vulkan
  9  {
 10      struct PipelineUid : IRefEquatable<PipelineUid>
 11      {
 12          public ulong Id0;
 13          public ulong Id1;
 14          public ulong Id2;
 15          public ulong Id3;
 16  
 17          public ulong Id4;
 18          public ulong Id5;
 19          public ulong Id6;
 20  
 21          public ulong Id7;
 22          public ulong Id8;
 23  
 24          private readonly uint VertexAttributeDescriptionsCount => (byte)((Id5 >> 38) & 0xFF);
 25          private readonly uint VertexBindingDescriptionsCount => (byte)((Id5 >> 46) & 0xFF);
 26          private readonly uint ColorBlendAttachmentStateCount => (byte)((Id6 >> 8) & 0xFF);
 27          private readonly bool HasDepthStencil => ((Id6 >> 63) & 0x1) != 0UL;
 28  
 29          public Array32<VertexInputAttributeDescription> VertexAttributeDescriptions;
 30          public Array33<VertexInputBindingDescription> VertexBindingDescriptions;
 31          public Array8<PipelineColorBlendAttachmentState> ColorBlendAttachmentState;
 32          public Array9<Format> AttachmentFormats;
 33          public uint AttachmentIntegerFormatMask;
 34          public bool LogicOpsAllowed;
 35  
 36          public readonly override bool Equals(object obj)
 37          {
 38              return obj is PipelineUid other && Equals(other);
 39          }
 40  
 41          public bool Equals(ref PipelineUid other)
 42          {
 43              if (!Unsafe.As<ulong, Vector256<byte>>(ref Id0).Equals(Unsafe.As<ulong, Vector256<byte>>(ref other.Id0)) ||
 44                  !Unsafe.As<ulong, Vector256<byte>>(ref Id4).Equals(Unsafe.As<ulong, Vector256<byte>>(ref other.Id4)) ||
 45                  !Unsafe.As<ulong, Vector128<byte>>(ref Id7).Equals(Unsafe.As<ulong, Vector128<byte>>(ref other.Id7)))
 46              {
 47                  return false;
 48              }
 49  
 50              if (!SequenceEqual<VertexInputAttributeDescription>(VertexAttributeDescriptions.AsSpan(), other.VertexAttributeDescriptions.AsSpan(), VertexAttributeDescriptionsCount))
 51              {
 52                  return false;
 53              }
 54  
 55              if (!SequenceEqual<VertexInputBindingDescription>(VertexBindingDescriptions.AsSpan(), other.VertexBindingDescriptions.AsSpan(), VertexBindingDescriptionsCount))
 56              {
 57                  return false;
 58              }
 59  
 60              if (!SequenceEqual<PipelineColorBlendAttachmentState>(ColorBlendAttachmentState.AsSpan(), other.ColorBlendAttachmentState.AsSpan(), ColorBlendAttachmentStateCount))
 61              {
 62                  return false;
 63              }
 64  
 65              if (!SequenceEqual<Format>(AttachmentFormats.AsSpan(), other.AttachmentFormats.AsSpan(), ColorBlendAttachmentStateCount + (HasDepthStencil ? 1u : 0u)))
 66              {
 67                  return false;
 68              }
 69  
 70              return true;
 71          }
 72  
 73          private static bool SequenceEqual<T>(ReadOnlySpan<T> x, ReadOnlySpan<T> y, uint count) where T : unmanaged
 74          {
 75              return MemoryMarshal.Cast<T, byte>(x[..(int)count]).SequenceEqual(MemoryMarshal.Cast<T, byte>(y[..(int)count]));
 76          }
 77  
 78          public override int GetHashCode()
 79          {
 80              ulong hash64 = Id0 * 23 ^
 81                             Id1 * 23 ^
 82                             Id2 * 23 ^
 83                             Id3 * 23 ^
 84                             Id4 * 23 ^
 85                             Id5 * 23 ^
 86                             Id6 * 23 ^
 87                             Id7 * 23 ^
 88                             Id8 * 23;
 89  
 90              for (int i = 0; i < (int)VertexAttributeDescriptionsCount; i++)
 91              {
 92                  hash64 ^= VertexAttributeDescriptions[i].Binding * 23;
 93                  hash64 ^= (uint)VertexAttributeDescriptions[i].Format * 23;
 94                  hash64 ^= VertexAttributeDescriptions[i].Location * 23;
 95                  hash64 ^= VertexAttributeDescriptions[i].Offset * 23;
 96              }
 97  
 98              for (int i = 0; i < (int)VertexBindingDescriptionsCount; i++)
 99              {
100                  hash64 ^= VertexBindingDescriptions[i].Binding * 23;
101                  hash64 ^= (uint)VertexBindingDescriptions[i].InputRate * 23;
102                  hash64 ^= VertexBindingDescriptions[i].Stride * 23;
103              }
104  
105              for (int i = 0; i < (int)ColorBlendAttachmentStateCount; i++)
106              {
107                  hash64 ^= ColorBlendAttachmentState[i].BlendEnable * 23;
108                  hash64 ^= (uint)ColorBlendAttachmentState[i].SrcColorBlendFactor * 23;
109                  hash64 ^= (uint)ColorBlendAttachmentState[i].DstColorBlendFactor * 23;
110                  hash64 ^= (uint)ColorBlendAttachmentState[i].ColorBlendOp * 23;
111                  hash64 ^= (uint)ColorBlendAttachmentState[i].SrcAlphaBlendFactor * 23;
112                  hash64 ^= (uint)ColorBlendAttachmentState[i].DstAlphaBlendFactor * 23;
113                  hash64 ^= (uint)ColorBlendAttachmentState[i].AlphaBlendOp * 23;
114                  hash64 ^= (uint)ColorBlendAttachmentState[i].ColorWriteMask * 23;
115              }
116  
117              for (int i = 0; i < (int)ColorBlendAttachmentStateCount; i++)
118              {
119                  hash64 ^= (uint)AttachmentFormats[i] * 23;
120              }
121  
122              return (int)hash64 ^ ((int)(hash64 >> 32) * 17);
123          }
124      }
125  }