mirror of
https://github.com/ryujinx-mirror/ryujinx.git
synced 2025-12-21 10:05:08 -06:00
Move solution and projects to src
This commit is contained in:
113
src/Ryujinx.Graphics.Gpu/Shader/HashTable/HashState.cs
Normal file
113
src/Ryujinx.Graphics.Gpu/Shader/HashTable/HashState.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Graphics.Gpu.Shader.HashTable
|
||||
{
|
||||
/// <summary>
|
||||
/// State of a hash calculation.
|
||||
/// </summary>
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// One shot hash calculation for a given data.
|
||||
/// </summary>
|
||||
/// <param name="data">Data to be hashed</param>
|
||||
/// <returns>Hash of the given data</returns>
|
||||
public static uint CalcHash(ReadOnlySpan<byte> data)
|
||||
{
|
||||
HashState state = new HashState();
|
||||
|
||||
state.Initialize();
|
||||
state.Continue(data);
|
||||
return state.Finalize(data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the hash state.
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
_hash = 23;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the hash of the given data.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The full data must be passed on <paramref name="data"/>.
|
||||
/// If this is not the first time the method is called, then <paramref name="data"/> 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.
|
||||
/// </remarks>
|
||||
/// <param name="data">Data to be hashed</param>
|
||||
public void Continue(ReadOnlySpan<byte> data)
|
||||
{
|
||||
ulong h = _hash;
|
||||
|
||||
ReadOnlySpan<ulong> dataAsUlong = MemoryMarshal.Cast<byte, ulong>(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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs the hash finalization step, and returns the calculated hash.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The full data must be passed on <paramref name="data"/>.
|
||||
/// <paramref name="data"/> must start with the data passed on the last call to <see cref="Continue"/>.
|
||||
/// No internal state is changed, so one can still continue hashing data with <see cref="Continue"/>
|
||||
/// after calling this method.
|
||||
/// </remarks>
|
||||
/// <param name="data">Data to be hashed</param>
|
||||
/// <returns>Hash of all the data hashed with this <see cref="HashState"/></returns>
|
||||
public uint Finalize(ReadOnlySpan<byte> 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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hash mix function.
|
||||
/// </summary>
|
||||
/// <param name="h">Hash to mix</param>
|
||||
/// <returns>Mixed hash</returns>
|
||||
private static ulong Mix(ulong h)
|
||||
{
|
||||
h ^= h >> 23;
|
||||
h *= 0x2127599bf4325c37UL;
|
||||
h ^= h >> 47;
|
||||
return h;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user