Skip to content

Instantly share code, notes, and snippets.

@jeffvella
Last active April 1, 2020 14:39
Show Gist options
  • Save jeffvella/8ac73ba00552998b66140a886646a234 to your computer and use it in GitHub Desktop.
Save jeffvella/8ac73ba00552998b66140a886646a234 to your computer and use it in GitHub Desktop.
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Unity.Burst;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Entities;
using UnityEngine;
using UnityEngine.Profiling;
public unsafe class NativeTypeManager
{
public static readonly SharedStatic<Container> StaticData;
static NativeTypeManager()
{
StaticData = SharedStatic<Container>.GetOrCreate<NativeTypeManager, Container>();
}
[RuntimeInitializeOnLoadMethod]
private static void Allocate()
{
Debug.Log("NativeTypeManager RuntimeInitializeOnLoadMethod");
if (!StaticData.Data.Map.IsCreated)
{
Debug.Log("Allocating NativeTypeManager");
var map = new NativeHashMap<int, int>(TypeManager.MaximumTypesCount, Allocator.Persistent);
StaticData.Data.Map = map;
var types = TypeManager.AllTypes.ToList();
for (var i = 0; i < types.Count; i++)
{
var typeInfo = types[i];
if (typeInfo.Type != null)
{
StaticData.Data.Map[BurstRuntime.GetHashCode32(typeInfo.Type)] = typeInfo.TypeIndex;
}
}
#if ENABLE_UNITY_COLLECTIONS_CHECKS
var sentinelField = map.GetType().GetField("m_DisposeSentinel", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var sentinel = (DisposeSentinel)sentinelField.GetValue(map);
DisposeSentinel.Clear(ref sentinel);
#endif
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetTypeIndex<T>()
{
return (*(SlimNativeHashMap**)StaticData.UnsafeDataPointer)->GetIntValue(BurstRuntime.GetHashCode32<T>());
}
public struct Container
{
public NativeHashMap<int, int> Map;
}
[StructLayout(LayoutKind.Explicit)]
public unsafe struct SlimNativeHashMap
{
[FieldOffset(0)] public byte* values;
[FieldOffset(8)] public byte* keys;
[FieldOffset(16)] public byte* next;
[FieldOffset(24)] public byte* buckets;
[FieldOffset(32)] public int keyCapacity;
[FieldOffset(36)] public int bucketCapacityMask;
[FieldOffset(40)] public int allocatedIndexLength;
public int GetIntValue(int key)
{
int entryIdx = ((int*)buckets)[key & bucketCapacityMask];
if (entryIdx < 0 || entryIdx >= keyCapacity)
return -1;
while (*(int*)(keys + entryIdx * sizeof(int)) != key)
{
entryIdx = ((int*)next)[entryIdx];
if (entryIdx < 0 || entryIdx >= keyCapacity)
return -1;
}
return *(int*)(values + entryIdx * sizeof(int));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment