the Fiddler's picture

Add runtime support for OpenGL debugging

Project:The Open Toolkit library
Version:1.x-dev
Component:Code
Category:feature request
Priority:normal
Assigned:Unassigned
Status:open
Description

Right now, OpenTK ships release and debug versions of OpenTK.dll. The debug version contains additional debugging code that calls GL.GetError() after every GL call and throws an exception if an error is detected.

This is a very useful feature during development. Unfortunately, it requires the use of a different OpenTK.dll, which is not ideal from a deployment and usability standpoint. Ideally, we would be able to enable/disable debugging at runtime, for example:

GL.EnableDebugging();
GL.DisableDebugging();

How would this work? Right now, a typical GL wrapper looks like this:

        /// <summary>
        /// Enable or disable server-side GL capabilities
        /// </summary>
        /// <param name="cap">
        /// <para>
        /// Specifies a symbolic constant indicating a GL capability.
        /// </para>
        /// </param>
        [AutoGenerated(Category = "Version10", Version = "1.0", EntryPoint = "glEnable")]
        public static 
        void Enable(OpenTK.Graphics.OpenGL.EnableCap cap)
        {
            #if DEBUG
            using (new ErrorHelper(GraphicsContext.CurrentContext))
            {
            #endif
            Delegates.glEnable((OpenTK.Graphics.OpenGL.EnableCap)cap);
            #if DEBUG
            }
            #endif
        }

Delegates.glEnable holds a pointer to the function implementation, retrieved by [wgl/glX/egl]GetProcAddress or the equivalent NSAddressOfSymbol on Mac OS X. The debugging code (new ErrorHelper) is part of the wrapper and compiled conditionally into the debug version of OpenTK.dll (which is why we need two distinct dlls).

The idea is to find a way to fold the using (new ErrorHelper()) { } region into the delegate call:

        [AutoGenerated(Category = "Version10", Version = "1.0", EntryPoint = "glEnable")]
        public static 
        void Enable(OpenTK.Graphics.OpenGL.EnableCap cap)
        {
            Delegates.glEnable((OpenTK.Graphics.OpenGL.EnableCap)cap);
        }
  • when debugging is disabled, the delegate calls the function pointer directly (no performance penalty)
  • when debugging is enabled, the delegate is modified to contain a using-region in addition to the function pointer (performance equivalent to using the debug OpenTK.dll)

What we need is someone familiar with System.Reflection.Emit (or maybe expression trees?) to help implement this feature. The attached zip contains an accurate but very simple implementation of a GL-like binding for testing purposes (native dll included).

AttachmentSize
Tracing.zip12.81 KB

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
martinsm's picture

#1

In my old GL wrapper I was using LCG to generate debug cheching. Here's small part of my wrapper that does LCG:

http://pastebin.com/49yeJryS

I used LCG with Opcodes.Calli because that gave me best performance on Mono instead of using Marshal.GetDelegateForFunctionPointer().

Lines 91-97 contains #ifdef if OpenGL error checking must be called after real OpenGL error call. This ifdef can be simply changed to runtime check if this is needed and regeneration of delegates can be rerun with GL.EnableDebugging()/DisableDebugging() calls.

Probably same mechanism can be simply used in feature to generate OpenGL trace (another topic). You would just need to collect all arguments in object[] array and call trace method that will print its arguments - I guess string.format will take care of argument types itself.

the Fiddler's picture

#2

Thanks, this is almost exactly what I was looking for.