Created
January 28, 2019 09:46
-
-
Save pCYSl5EDgo/c8d10196b868a6a792c97a6e577c419b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Diagnostics; | |
using UnityEngine; | |
using Unity.Burst; | |
using Unity.Jobs; | |
using Unity.Collections; | |
using Unity.Collections.LowLevel.Unsafe; | |
using System.Reflection; | |
using System.Reflection.Emit; | |
using static System.Reflection.Emit.OpCodes; | |
public class TestManager : MonoBehaviour | |
{ | |
public unsafe interface IAccessor : IJobParallelFor | |
{ | |
int* GetPtr(); | |
void SetPtr(int* value); | |
JobHandle Schedule(); | |
} | |
private const int V = 50000; | |
IAccessor accessor; | |
void Start() | |
{ | |
const string ModuleName = "Moc"; | |
const string FileName = ModuleName + ".dll"; | |
AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(ModuleName), AssemblyBuilderAccess.RunAndSave); | |
var moduleBulder = assemblyBuilder.DefineDynamicModule(ModuleName, FileName); | |
var typeBuilder = moduleBulder.DefineType("BURSTJOB", | |
TypeAttributes.Public | TypeAttributes.AnsiClass | TypeAttributes.Sealed | TypeAttributes.SequentialLayout, | |
typeof(System.ValueType), | |
new Type[] { typeof(IAccessor), typeof(IJobParallelFor) }); | |
typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(typeof(BurstCompileAttribute).GetConstructor(Type.EmptyTypes), Array.Empty<object>())); | |
var intPtrType = typeof(int).MakePointerType(); | |
var field0 = typeBuilder.DefineField("ptr", | |
intPtrType, | |
FieldAttributes.Public); | |
field0.SetCustomAttribute(new CustomAttributeBuilder(typeof(NativeDisableUnsafePtrRestrictionAttribute).GetConstructor(Type.EmptyTypes), Array.Empty<object>())); | |
const MethodAttributes Attributes = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.NewSlot | MethodAttributes.HideBySig; | |
var schedule = typeBuilder.DefineMethod("Schedule", Attributes, typeof(JobHandle), Type.EmptyTypes); | |
{ | |
var il = schedule.GetILGenerator(); | |
var local = il.DeclareLocal(typeof(JobHandle)); | |
il.Emit(Ldarg_0); | |
il.Emit(Ldobj, typeBuilder); | |
il.Emit(Ldc_I4, V); | |
il.Emit(Ldc_I4, 1024); | |
il.Emit(Ldloca_S, 0); | |
il.Emit(Initobj, typeof(JobHandle)); | |
il.Emit(Ldloc_0); | |
il.EmitCall(Call, typeof(IJobParallelForExtensions).GetMethod("Schedule").MakeGenericMethod(typeBuilder), Type.EmptyTypes); | |
il.Emit(Ret); | |
} | |
var execute = typeBuilder.DefineMethod("Execute", Attributes, CallingConventions.Standard, typeof(void), new Type[] { typeof(int) }); | |
{ | |
var il = execute.GetILGenerator(); | |
il.Emit(Ldarg_0); | |
il.Emit(Ldfld, field0); | |
il.Emit(Ldarg_1); | |
il.Emit(Conv_I); | |
il.Emit(Ldc_I4_4); | |
il.Emit(Mul); | |
il.Emit(Add); | |
il.Emit(Ldarg_1); | |
il.Emit(Stind_I4); | |
il.Emit(Ret); | |
} | |
var setPtr = typeBuilder.DefineMethod("SetPtr", Attributes, CallingConventions.Standard, typeof(void), new[] { intPtrType }); | |
{ | |
var il = setPtr.GetILGenerator(); | |
il.Emit(Ldarg_0); | |
il.Emit(Ldarg_1); | |
il.Emit(Stfld, field0); | |
il.Emit(Ret); | |
} | |
var getPtr = typeBuilder.DefineMethod("GetPtr", Attributes, CallingConventions.Standard, intPtrType, Type.EmptyTypes); | |
{ | |
var il = getPtr.GetILGenerator(); | |
il.Emit(Ldarg_0); | |
il.Emit(Ldfld, field0); | |
il.Emit(Ret); | |
} | |
accessor = (IAccessor)Activator.CreateInstance(typeBuilder.CreateType()); | |
assemblyBuilder.Save(FileName); | |
Verify(assemblyBuilder); | |
} | |
unsafe void Update() | |
{ | |
using (var array = new NativeArray<int>(V, Allocator.TempJob)) | |
{ | |
accessor.SetPtr((int*)array.GetUnsafePtr()); | |
accessor.Schedule().Complete(); | |
} | |
} | |
static void Verify(params AssemblyBuilder[] builders) | |
{ | |
var path = @"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.7.2 Tools\x64\PEVerify.exe"; | |
foreach (var targetDll in builders) | |
{ | |
var psi = new ProcessStartInfo(path, targetDll.GetName().Name + ".dll") | |
{ | |
CreateNoWindow = true, | |
WindowStyle = ProcessWindowStyle.Hidden, | |
RedirectStandardOutput = true, | |
RedirectStandardError = true, | |
UseShellExecute = false | |
}; | |
var p = Process.Start(psi); | |
var data = p.StandardOutput.ReadToEnd(); | |
Console.WriteLine(data); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment