Sign in to follow this  

Virtual methods and performance critical code

This topic is 3738 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm currently rethinking the render sub-system of my game engine and I want to move all the API(DirectX)-specific stuff into a separate DLL so I can have different renderers vor different APIs or different API versions. My initial though was to have something like an IRenderDevice interface with a bunch of pure virtual functions that any concrete render device would have to implement. However, now I'm concerned that since these render-methods are going to be called a lot, the dynamic-binding overhead might become an issue. So my question is: should I even worry about this or is the overhead too small to matter?

Share this post


Link to post
Share on other sites
Quote:
the dynamic-binding overhead might become an issue


It might, it might not.

But why would you need virtual functions in the first place? When you load a DLL, you simply bind to the functions it provides. Then you provide a wrapper class no top of those, that is implemented once.

The virtual mechanism here is implicitly provided in the form of DLLs by the OS itself, where implementation is determined by the DLL you just loaded.

Share this post


Link to post
Share on other sites
Thanks for the reply. My plan was to have the DLL return an instance of a device class to the render-subsystem in the engine, so something along the lines of


class D3DDevice : IRenderDevice { ... };

// DLL-Function
IRenderRevice* CreateDevice(int param)
{
return new D3DDevice(param);
}


With your solution, I'd either have to do it all in a procedural fashion or have a lot of DLL functions that effectively invoke methods on a global instance of the device class, right?

Share this post


Link to post
Share on other sites
Thanks again!
I read the article and I'm still a little confused.
I'm familiar with the concept of binding "normal" DLL functions, but my render-device is actually a class with (non-static) member functions and I need to be able to instantiate that class from the DLL host (the engine). So just exporting a set of functions won't do. I know I could just drop the class alltogether and use just use plain old functions, but I'd really rather not.
If I used static binding, I could just DLL-export my render device class, but I would like to swap renderers based on a value in a config file so that won't work.
I probably just misunderstood you, though. If so, please enlighten me ;-

Share this post


Link to post
Share on other sites
Quote:
Original post by Antheus
No virtuals needed, just bind the functions.


That solution is good as long as you just need a wrapper class arroud the DLL static methods. If you need your dll to act like a factory that produces instances of a class that implements an interface, isn't the OP's solution (COM-like) better? (and virtual calls are to be used?)

Regarding the original question, all the methods of a IDirect3dDevice9 are already virtual calls and that doesn't seem to be a performance issue. I wouldn't worry too much if I were you.

Maybe you could implement your own class like:
class OpenGLRenderer : public IDirect3DDevice9

and keep the original Direct3D renderer for Direct3D-based rendering ? (so that you don't have 2 layers of virtual calls)

Share this post


Link to post
Share on other sites
There is also the fact that the solution on that web page uses function pointers which is pretty much how virtual functions are implemented, and they will entail the same overhead: so, bind static functions, and leave virtual functions as they are.

Share this post


Link to post
Share on other sites
Quote:
Original post by ZQJ
There is also the fact that the solution on that web page uses function pointers which is pretty much how virtual functions are implemented, and they will entail the same overhead: so, bind static functions, and leave virtual functions as they are.


Well, yes.

But here's the question. Will you need dynamic binding, or will static do? Better yet, will there be a need to switch renderers during run-time, or will binding it once during start-up do?

Since there are exactly 2 implementations (OpenGL and DX), there is no need for some ultra-elaborate dynamic binding mechanism.

Developing a plug-in system where an arbitrary number of plug-ins exist is different. But here, there will always be a very deterministic number of different implementations.

Find your trade-off: If performance is priority, forget DLLs, use compile-time polymorphism. If flexibility is a priority, use DLLs, and dynamic bindings (virtual functions will be just fine).

Share this post


Link to post
Share on other sites
Using virtual methods in a renderer shouldn't cause a performance problem on the provision you do it at a high enough level.

This is an example of how not to do it:
virtual pushTriangle (Vector3f point1, Vector3f point2, Vector3f point3) = 0;

You want to abstract higher, such as with vertex buffers:
virtual bindVertexBuffer (const VertexBuffer& VB) = 0;

Another consideration to make is whether you can promote tight loops into the virtual method itself to perform processes in batches, in other words from this...

for (SomeIteratorType iter = someContainer.begin(); iter != someContainer.end(); ++iter) {
renderer->someVirtualMethod();
}

into this....

renderer->someVirtualmethod( someContainer.begin(), someContainer.end() );

// elsewhere...

void D3DRenderer::someVirtualMethod(SomeIteratorType first, SomeIteratorType last)
{
for (SomeIteratorType iter = first; iter != last; ++iter) {
// Do Something Thrilling
}
}

Share this post


Link to post
Share on other sites
Antheus method is a TON of extra work. Add a new feature, write up a lot of code instead of adding one virtual function and an empty to each DLL.

Most engines that support more then one API or version of tend to use the OPs original idea. Least all the engines I've seen. Unless you're on a console where virtual functions kill performance, go with that method. The overhead with our engine is near 0 and for the ease of use WELL worth the cost. Plus it makes for a LOT cleaner design and interface. I would have to highly recommend the virtual method way.

You might not need on the fly changing of an API but it sure makes debugging a LOT faster of certain things. Even if you don't support it in the final game. I've on a few occasions make a change to the DLL and just forced a reload without having to reload the whole game/etc. Very nice feature.

Share this post


Link to post
Share on other sites
Quote:
Original post by Antheus
Quote:
Original post by ZQJ
There is also the fact that the solution on that web page uses function pointers which is pretty much how virtual functions are implemented, and they will entail the same overhead: so, bind static functions, and leave virtual functions as they are.


Well, yes.

But here's the question. Will you need dynamic binding, or will static do? Better yet, will there be a need to switch renderers during run-time, or will binding it once during start-up do?

Since there are exactly 2 implementations (OpenGL and DX), there is no need for some ultra-elaborate dynamic binding mechanism.

Developing a plug-in system where an arbitrary number of plug-ins exist is different. But here, there will always be a very deterministic number of different implementations.

Find your trade-off: If performance is priority, forget DLLs, use compile-time polymorphism. If flexibility is a priority, use DLLs, and dynamic bindings (virtual functions will be just fine).


Really? Just 2? Right now we support OpenGL 1.5, 2.0 and looking at 3.0 when drivers get out there. We also support DX9 and 10. That's 5 to me. YMMV of course but you said there cannot be more then 2 so just wanted to let you know there can be ;-)

It's really not complex either, took me 15 minutes or so to get our system setup. Few hours of debugging over time as things got added, it's quicker and easier then your suggested method I think. I think it's also easier to update/maintain as its less typing. Plus its completely encased in a class instead of global functions, which I think is a better solution for a renderer. I do use a lot of global functions (in a namespace) but for things like logging.

Share this post


Link to post
Share on other sites

This topic is 3738 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this