Raylib-cs-Examples
Raylib-cs-Examples copied to clipboard
[DllImport] pinvoke performance improvement
I see in Utils.cs methods like SetShaderValue<T> do a GCHandle.Alloc().
This is "bad performance" as it is both pinning, and boxing. As all inputs of T value are either unmanaged structs or arrays of unmanaged structs, the following pattern can be used to improve performance
//// Helper functions to pass data into raylib. Pins the data so we can pass in a stable IntPtr to raylib.
////THE ORIGINAL
//public static void SetShaderValue<T>(Shader shader, int uniformLoc, T value, ShaderUniformDataType uniformType)
//{
// GCHandle pinnedData = GCHandle.Alloc(value, GCHandleType.Pinned);
// Raylib.SetShaderValue(shader, uniformLoc, pinnedData.AddrOfPinnedObject(), uniformType);
// pinnedData.Free();
//}
public static unsafe void SetShaderValue<T>(Shader shader, int uniformLoc, ref T value, ShaderUniformDataType uniformType) where T : unmanaged
{
fixed (T* valuePtr = &value)
{
Raylib.SetShaderValue(shader, uniformLoc, (IntPtr)valuePtr, uniformType);
}
}
public static unsafe void SetShaderValue<T>(Shader shader, int uniformLoc, T value, ShaderUniformDataType uniformType) where T : unmanaged
{
Raylib.SetShaderValue(shader, uniformLoc, (IntPtr)(&value), uniformType);
}
public static unsafe void SetShaderValue<T>(Shader shader, int uniformLoc, T[] values, ShaderUniformDataType uniformType) where T : unmanaged
{
SetShaderValue(shader, uniformLoc, (Span<T>)values, uniformType);
}
public static unsafe void SetShaderValue<T>(Shader shader, int uniformLoc, Span<T> values, ShaderUniformDataType uniformType) where T : unmanaged
{
fixed (T* valuePtr = values)
{
Raylib.SetShaderValue(shader, uniformLoc, (IntPtr)valuePtr, uniformType);
}
}
I also suggest moving these "wrappers" into the raylib-cs project itself, as they are required wrappers for normal usage of the api
Additionally, the denizens of the C# Discord #lowlevel channel strongly suggest changing pinvoke signatures from match the underlying raylib.dll signature as closely as possible. For example, changing usage of IntPtr value to the matching void* value signatures, and adding wrappers in addition (such as my above suggestion), to make it more usable for C# devs. IntPtr isn't a good choice because it obscures the inherit unsafe nature of the api.