Skip to content

Commit

Permalink
[Backport][2022.3][SRPF] Use FNV-1a 32 for caching and resource hashc…
Browse files Browse the repository at this point in the history
…ode in Render Graph

The main issue goes to the hash method generation that was used for identifying Render Graph resources. We used the most performant way but it was too many collisions. After a bit of research the decision is to use FNV-1a implementation as it's the same performance but much more reliable. There's still a possibility for collision but a probability should be much smaller.
  • Loading branch information
kirill-titov-u authored and Evergreen committed Aug 6, 2024
1 parent 00a903f commit 1f0f19d
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -812,7 +812,7 @@ internal void OnPassAdded(RenderGraphPass pass)
{
if (m_DebugParameters.immediateMode)
{
ExecutePassImmediatly(pass);
ExecutePassImmediately(pass);
}
}

Expand Down Expand Up @@ -1457,7 +1457,7 @@ ref CompiledPassInfo CompilePassImmediatly(RenderGraphPass pass)
return ref passInfo;
}

void ExecutePassImmediatly(RenderGraphPass pass)
void ExecutePassImmediately(RenderGraphPass pass)
{
ExecuteCompiledPass(ref CompilePassImmediatly(pass), m_CurrentImmediatePassIndex - 1);
}
Expand Down Expand Up @@ -1555,7 +1555,7 @@ void PreRenderPassExecute(in CompiledPassInfo passInfo, RenderGraphContext rgCon

// Need to save the command buffer to restore it later as the one in the context can changed if running a pass async.
m_PreviousCommandBuffer = rgContext.cmd;

bool executedWorkDuringResourceCreation = false;
for (int type = 0; type < (int)RenderGraphResourceType.Count; ++type)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Diagnostics;
using UnityEngine.Rendering;

namespace UnityEngine.Experimental.Rendering.RenderGraphModule
{
Expand Down Expand Up @@ -82,13 +83,11 @@ public ComputeBufferDesc(int count, int stride, ComputeBufferType type)
/// <returns>The texture descriptor hash.</returns>
public override int GetHashCode()
{
int hashCode = 17;

hashCode = hashCode * 23 + count;
hashCode = hashCode * 23 + stride;
hashCode = hashCode * 23 + (int)type;

return hashCode;
var hashCode = HashFNV1A32.Create();
hashCode.Append(count);
hashCode.Append(stride);
hashCode.Append((int)type);
return hashCode.value;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,49 +241,43 @@ public TextureDesc(TextureDesc input)
/// <returns>The texture descriptor hash.</returns>
public override int GetHashCode()
{
int hashCode = 17;

unchecked
var hashCode = HashFNV1A32.Create();
switch (sizeMode)
{
switch (sizeMode)
{
case TextureSizeMode.Explicit:
hashCode = hashCode * 23 + width;
hashCode = hashCode * 23 + height;
break;
case TextureSizeMode.Functor:
if (func != null)
hashCode = hashCode * 23 + func.GetHashCode();
break;
case TextureSizeMode.Scale:
hashCode = hashCode * 23 + scale.x.GetHashCode();
hashCode = hashCode * 23 + scale.y.GetHashCode();
break;
}
case TextureSizeMode.Explicit:
hashCode.Append(width);
hashCode.Append(height);
break;
case TextureSizeMode.Functor:
if (func != null)
hashCode.Append(func);
break;
case TextureSizeMode.Scale:
hashCode.Append(scale);
break;
}

hashCode = hashCode * 23 + mipMapBias.GetHashCode();
hashCode = hashCode * 23 + slices;
hashCode = hashCode * 23 + (int)depthBufferBits;
hashCode = hashCode * 23 + (int)colorFormat;
hashCode = hashCode * 23 + (int)filterMode;
hashCode = hashCode * 23 + (int)wrapMode;
hashCode = hashCode * 23 + (int)dimension;
hashCode = hashCode * 23 + (int)memoryless;
hashCode = hashCode * 23 + (int)vrUsage;
hashCode = hashCode * 23 + anisoLevel;
hashCode = hashCode * 23 + (enableRandomWrite ? 1 : 0);
hashCode = hashCode * 23 + (useMipMap ? 1 : 0);
hashCode = hashCode * 23 + (autoGenerateMips ? 1 : 0);
hashCode = hashCode * 23 + (isShadowMap ? 1 : 0);
hashCode = hashCode * 23 + (bindTextureMS ? 1 : 0);
hashCode = hashCode * 23 + (useDynamicScale ? 1 : 0);
hashCode = hashCode * 23 + (int)msaaSamples;
hashCode.Append(mipMapBias);
hashCode.Append(slices);
hashCode.Append((int) depthBufferBits);
hashCode.Append((int) colorFormat);
hashCode.Append((int) filterMode);
hashCode.Append((int) wrapMode);
hashCode.Append((int) dimension);
hashCode.Append((int) memoryless);
hashCode.Append((int) vrUsage);
hashCode.Append(anisoLevel);
hashCode.Append(enableRandomWrite);
hashCode.Append(useMipMap);
hashCode.Append(autoGenerateMips);
hashCode.Append(isShadowMap);
hashCode.Append(bindTextureMS);
hashCode.Append(useDynamicScale);
hashCode.Append((int) msaaSamples);
#if UNITY_2020_2_OR_NEWER
hashCode = hashCode * 23 + (fastMemoryDesc.inFastMemory ? 1 : 0);
hashCode.Append(fastMemoryDesc.inFastMemory);
#endif
}

return hashCode;
return hashCode.value;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
using System;
using System.Runtime.CompilerServices;

namespace UnityEngine.Rendering
{
internal ref struct HashFNV1A32
{
/// <summary>
/// FNV prime.
/// </summary>
const uint k_Prime = 16777619;

/// <summary>
/// FNV offset basis.
/// </summary>
const uint k_OffsetBasis = 2166136261;

uint m_Hash;

public static HashFNV1A32 Create()
{
return new HashFNV1A32 { m_Hash = k_OffsetBasis };
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Append(in int input)
{
unchecked
{
m_Hash = (m_Hash ^ (uint)input) * k_Prime;
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Append(in uint input)
{
unchecked
{
m_Hash = (m_Hash ^ input) * k_Prime;
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Append(in bool input)
{
m_Hash = (m_Hash ^ (input ? 1u : 0u)) * k_Prime;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Append(in float input)
{
unchecked
{
m_Hash = (m_Hash ^ (uint)input.GetHashCode()) * k_Prime;
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Append(in double input)
{
unchecked
{
m_Hash = (m_Hash ^ (uint)input.GetHashCode()) * k_Prime;
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Append(in Vector2 input)
{
unchecked
{
m_Hash = (m_Hash ^ (uint)input.GetHashCode()) * k_Prime;
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Append(in Vector3 input)
{
unchecked
{
m_Hash = (m_Hash ^ (uint)input.GetHashCode()) * k_Prime;
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Append(in Vector4 input)
{
unchecked
{
m_Hash = (m_Hash ^ (uint)input.GetHashCode()) * k_Prime;
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Append<T>(T input) where T : struct
{
unchecked
{
m_Hash = (m_Hash ^ (uint)input.GetHashCode()) * k_Prime;
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Append(Delegate del)
{
unchecked
{
m_Hash = (m_Hash ^ (uint)GetFuncHashCode(del)) * k_Prime;
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static int GetFuncHashCode(Delegate del)
{
return del.Method.GetHashCode() ^ RuntimeHelpers.GetHashCode(del.Target);
}

public int value => (int)m_Hash;

public override int GetHashCode()
{
return value;
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 1f0f19d

Please sign in to comment.