-
-
Notifications
You must be signed in to change notification settings - Fork 301
Performance considerations when calling OpenGL Extension Functions
In version 2.4 we changed the way how SharpGL calls OpenGL extension functions. Thanks to @ftlPhysicsGuy for giving the feedback on this topic in issue #41!
The wglGetProcAddress function (MSDN Reference) was used to find a particular OpenGL extension function. The next step was to create a delegate to call the extension function by using Marshal.GetDelegateForFunctionPointer (MSDN Reference). This method converts an unmanaged function pointer to a delegate. The method Delegate.DynamicInvoke (MSDN Reference) was used to call the OpenGL extension function finally.
The problem comes with the Delegate.DynamicInvoke method. This method calls the function dynamically, that means late-bound and involves reflection. This leads to an overhead that decreases performance.
Instead of using the Delegate.DynamicInvoke, we simply create the delegate for the OpenGL extension function and invoke the delegate statically. Here is the code to create the delegate:
private T GetDelegateFor<T>() where T : class
{
// Get the type of the extension function.
Type delegateType = typeof(T);
// Get the name of the extension function.
string name = delegateType.Name;
// ftlPhysicsGuy - Better way
Delegate del = null;
if (extensionFunctions.TryGetValue(name, out del) == false)
{
IntPtr proc = Win32.wglGetProcAddress(name);
if (proc == IntPtr.Zero)
throw new Exception("Extension function " + name + " not supported");
// Get the delegate for the function pointer.
del = Marshal.GetDelegateForFunctionPointer(proc, delegateType);
// Add to the dictionary.
extensionFunctions.Add(name, del);
}
return del as T;
}
And so SharpGL invokes the delegate now:
// NOTE: JUST ONE EXAMPLE. MANY METHODS IN OpenGLExtensions.cs USE THIS PATTERN
public void BlendColor(float red, float green, float blue, float alpha)
{
//InvokeExtensionFunction<glBlendColor>(red, green, blue, alpha);
GetDelegateFor<glBlendColor>()(red, green, blue, alpha);
}
By changing the function invocation process, we were able to increase the performance by 30%.