haymo's picture

performance suggestion

Hello Fiddler, and / or other OpenTK people,

I am currently writing a scene graph application for CAD visualizations. Somehow similar to Java3D. I dont have much knowledge about game development but would expect similar requirements coming up there. Wouldn't it be advantageously to track the current state of OpenGL for the current thread in the managed part? That way one could prevent for multiple state-setting-function calls which only increase the context change overhead - but actually do nothing. I realized, I have to set some properties for each node of the graph ever and ever again, just to make sure, the state hasn't been changed from other nodes. I guess, if such tracking is the way to go here, it should be implemented in the OpenTK layer and not on the level of application logic? Any other suggestions?
Thanks, Haymo

PS. I repeat myself: OpenTK is a great project! Hope you keep going, regardless of any obstacles :)


Comments

Comment viewing options

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

[OpenTK call overhead]
I simply timed a few million calls with System.Diagnostics.Stopwatch, then verified the results on the #mono-dev channel. There is some code in the Examples directory if you are qurious.

[State tracking]
While this would be *very* useful for debugging purposes (in fact, this is how OpenGL debuggers work), I don't think it would help performance. Remember that modern OpenGL drivers take *years* to develop (e.g. ati started work on their new driver at least 2 years before the first release). Even if it were possible to outperform their state trackers, it just wouldn't be effective from an effort standpoint when sorting by shader/material/texture can achieve good enough results already. The other problem is that extensions interact with OpenGL state in non-obvious ways: simply the existence of an extension can change the behavior of the state machine (it's a MxN problem that may be simply too complex to solve on its entirety).

That said, it would simply be awesome to have *some* state tracked for debugging. For example, there has been an idea to place an implicit call to GL.Error after each function when running in debug mode. According to the docs, you cannot call GL.Error inside a GL.Begin-GL.End block, so even this simingly simple task needs some thought.

Have you given any thought regarding possible implementations? My suggestion would be to keep state information in the GraphicsContext class and take advantage of C# 3 partial methods to update this state (untested code):

// GL.cs
partial static class GL
{
    // glEnable
    public void Enable(...)
    {
         EnableCalled(...);  // EnableCalled is a partial method.
         Delegates.Enable(...);
    }
 
    // Partial declarations
    partial void EnableCalled(...);
}
// GLState.cs
partial static class GL
{
#if DEBUG
     // partial implementations
     partial void EnableCalled(...)
     {
         Debug.Assert(GraphicsContext.CurrentContext != null, "No current context on the calling thread");
         // Update state for GraphicsContext.CurrentContext
     }
#endif
}

To do this you'd need to:

  1. Update the binding generator to emit partial methods for each GL function.
  2. Add GLState.cs and implement whichever of these partial methods you wish. The compiler will remove all unused methods, so there's no performance penalty.

This should be an interesting experiment :)

haymo's picture

I am not fmiliar with partial methods yet. But I suppose, they are handled like macros by the compiler and inlined for compilation? So your suggestion is for performance reasons?
Originally I somehow have been more into the idea of using a GL.State object, carrying all trackable properties. This would be only the most needed subset of all available properties (blend, dephtest, texture, ...). But I somehow like your idea. Will have to keep thinking about it.

the Fiddler's picture

In the end you need to things: the state object and a way to update it.

Partial methods are a possible implementation of the update part - they provide a way to hook into generated code (i.e. the bindings) without hurting performance (they are simple function calls that are removed by the compiler if you don't provide the implementation).

Regarding the GL.State object itself, it would fit nicely inside the GraphicsContext class since OpenGL commands affect it directly. Not saying that keeping it elsewhere wouldn't worm, just that GraphicsContext feels like a natural fit.

In any case, this is just a possible (and completely untested) implemetation suggestion. There are many other ways to go ahead, experimentation is key.