From cee712105850ac3385cd0091a923438167433f9f Mon Sep 17 00:00:00 2001 From: TSR Berry <20988865+TSRBerry@users.noreply.github.com> Date: Sat, 8 Apr 2023 01:22:00 +0200 Subject: Move solution and projects to src --- .../Shader/HashTable/HashState.cs | 113 +++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 src/Ryujinx.Graphics.Gpu/Shader/HashTable/HashState.cs (limited to 'src/Ryujinx.Graphics.Gpu/Shader/HashTable/HashState.cs') diff --git a/src/Ryujinx.Graphics.Gpu/Shader/HashTable/HashState.cs b/src/Ryujinx.Graphics.Gpu/Shader/HashTable/HashState.cs new file mode 100644 index 00000000..584eefdc --- /dev/null +++ b/src/Ryujinx.Graphics.Gpu/Shader/HashTable/HashState.cs @@ -0,0 +1,113 @@ +using System; +using System.Runtime.InteropServices; + +namespace Ryujinx.Graphics.Gpu.Shader.HashTable +{ + /// + /// State of a hash calculation. + /// + struct HashState + { + // This is using a slightly modified implementation of FastHash64. + // Reference: https://github.com/ztanml/fast-hash/blob/master/fasthash.c + private const ulong M = 0x880355f21e6d1965UL; + private ulong _hash; + private int _start; + + /// + /// One shot hash calculation for a given data. + /// + /// Data to be hashed + /// Hash of the given data + public static uint CalcHash(ReadOnlySpan data) + { + HashState state = new HashState(); + + state.Initialize(); + state.Continue(data); + return state.Finalize(data); + } + + /// + /// Initializes the hash state. + /// + public void Initialize() + { + _hash = 23; + } + + /// + /// Calculates the hash of the given data. + /// + /// + /// The full data must be passed on . + /// If this is not the first time the method is called, then must start with the data passed on the last call. + /// If a smaller slice of the data was already hashed before, only the additional data will be hashed. + /// This can be used for additive hashing of data in chuncks. + /// + /// Data to be hashed + public void Continue(ReadOnlySpan data) + { + ulong h = _hash; + + ReadOnlySpan dataAsUlong = MemoryMarshal.Cast(data.Slice(_start)); + + for (int i = 0; i < dataAsUlong.Length; i++) + { + ulong value = dataAsUlong[i]; + + h ^= Mix(value); + h *= M; + } + + _hash = h; + _start = data.Length & ~7; + } + + /// + /// Performs the hash finalization step, and returns the calculated hash. + /// + /// + /// The full data must be passed on . + /// must start with the data passed on the last call to . + /// No internal state is changed, so one can still continue hashing data with + /// after calling this method. + /// + /// Data to be hashed + /// Hash of all the data hashed with this + public uint Finalize(ReadOnlySpan data) + { + ulong h = _hash; + + int remainder = data.Length & 7; + if (remainder != 0) + { + ulong v = 0; + + for (int i = data.Length - remainder; i < data.Length; i++) + { + v |= (ulong)data[i] << ((i - remainder) * 8); + } + + h ^= Mix(v); + h *= M; + } + + h = Mix(h); + return (uint)(h - (h >> 32)); + } + + /// + /// Hash mix function. + /// + /// Hash to mix + /// Mixed hash + private static ulong Mix(ulong h) + { + h ^= h >> 23; + h *= 0x2127599bf4325c37UL; + h ^= h >> 47; + return h; + } + } +} -- cgit v1.2.3