Raylib-cs-Examples icon indicating copy to clipboard operation
Raylib-cs-Examples copied to clipboard

[DllImport] pinvoke performance improvement

Open jasonswearingen opened this issue 4 years ago • 0 comments

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.

jasonswearingen avatar Oct 23 '21 17:10 jasonswearingen