// Derived from https://github.com/keijiro/Akvfx/blob/master/Packages/jp.keijiro.akvfx/Runtime/Internal/Extensions.cs using UnityEngine; using System; using System.Reflection; using UnityEngine.Rendering; namespace SLZ.CustomStaticBatching { public static class CSBBufferExt { // SetData with ReadOnlySpan public unsafe static void SetFromSpan (ComputeBuffer buffer, ReadOnlySpan data) where T : unmanaged { fixed (T* pData = &data.GetPinnableReference()) SetData(buffer, (IntPtr)pData, data.Length, sizeof(T)); } public unsafe static void SetFromSpan (ComputeBuffer buffer, Span data) where T : unmanaged { fixed (T* pData = &data.GetPinnableReference()) SetData(buffer, (IntPtr)pData, data.Length, sizeof(T)); } public unsafe static void SetFromSpan (ComputeBuffer buffer, ReadOnlySpan data, int spanStartIndex, int bufferStartIndex, int count) where T : unmanaged { fixed (T* pData = &data.GetPinnableReference()) SetCBNativeDelegate(buffer, (IntPtr)pData, spanStartIndex, bufferStartIndex, count, sizeof(T)); } public unsafe static void SetFromSpan (ComputeBuffer buffer, Span data, int spanStartIndex, int bufferStartIndex, int count) where T : unmanaged { fixed (T* pData = &data.GetPinnableReference()) SetCBNativeDelegate(buffer, (IntPtr)pData, spanStartIndex, bufferStartIndex, count, sizeof(T)); } public unsafe static void CmdSetFromSpan (CommandBuffer cmd, ComputeBuffer buffer, ReadOnlySpan data) where T : unmanaged { fixed (T* pData = &data.GetPinnableReference()) CmdSetData(cmd, buffer, (IntPtr)pData, data.Length, sizeof(T)); } public unsafe static void CmdSetFromSpan (CommandBuffer cmd, ComputeBuffer buffer, Span data) where T : unmanaged { fixed (T* pData = &data.GetPinnableReference()) CmdSetData(cmd, buffer, (IntPtr)pData, data.Length, sizeof(T)); } public unsafe static void CmdSetFromSpan (CommandBuffer cmd, ComputeBuffer buffer, ReadOnlySpan data, int spanStartIndex, int bufferStartIndex, int count) where T : unmanaged { fixed (T* pData = &data.GetPinnableReference()) SetCmdNativeDelegate(cmd, buffer, (IntPtr)pData, spanStartIndex, bufferStartIndex, count, sizeof(T)); } public unsafe static void CmdSetFromSpan (CommandBuffer cmd, ComputeBuffer buffer, Span data, int spanStartIndex, int bufferStartIndex, int count) where T : unmanaged { fixed (T* pData = &data.GetPinnableReference()) SetCmdNativeDelegate(cmd, buffer, (IntPtr)pData, spanStartIndex, bufferStartIndex, count, sizeof(T)); } // Directly load an unmanaged data array to a compute buffer via an // Intptr. This is not a public interface so will be broken one day. // DO NOT TRY AT HOME. static void SetData (ComputeBuffer buffer, IntPtr pointer, int count, int stride) { /* _args5[0] = pointer; _args5[1] = 0; // source offset _args5[2] = 0; // buffer offset _args5[3] = count; _args5[4] = stride; SetNativeData.Invoke(buffer, _args5); */ SetCBNativeDelegate(buffer, pointer, 0, 0, count, stride); } static void CmdSetData (CommandBuffer cmd, ComputeBuffer buffer, IntPtr pointer, int count, int stride) { /* _args6[0] = buffer; _args6[1] = pointer; _args6[2] = 0; // source offset _args6[3] = 0; // buffer offset _args6[4] = count; _args6[5] = stride; CmdSetNativeData.Invoke(cmd, _args6); */ SetCmdNativeDelegate(cmd, buffer, pointer, 0, 0, count, stride); } static MethodInfo _setNativeData; static MethodInfo _cmdSetNativeData; static MethodInfo SetNativeData => _setNativeData ?? (_setNativeData = GetSetNativeDataMethod()); static MethodInfo CmdSetNativeData => _cmdSetNativeData ?? (_cmdSetNativeData = GetCmdSetNativeDataMethod()); static MethodInfo GetSetNativeDataMethod() => typeof(ComputeBuffer).GetMethod("InternalSetNativeData", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance); static MethodInfo GetCmdSetNativeDataMethod() => typeof(CommandBuffer).GetMethod("InternalSetComputeBufferNativeData", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance); static Action _setCBNativeDelegate; static Action _setCmdNativeDelegate; static Action GetCBNativeDelegate() { MethodInfo method = GetSetNativeDataMethod(); return (Action)Delegate.CreateDelegate(typeof(Action), method); } static Action GetCmdNativeDelegate() { MethodInfo method = GetCmdSetNativeDataMethod(); return (Action)Delegate.CreateDelegate(typeof(Action), method); } static Action SetCBNativeDelegate => _setCBNativeDelegate ?? (_setCBNativeDelegate = GetCBNativeDelegate()); static Action SetCmdNativeDelegate => _setCmdNativeDelegate ?? (_setCmdNativeDelegate = GetCmdNativeDelegate()); //static object[] _args5 = new object[5]; //static object[] _args6 = new object[6]; } }