• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
Alundra

Virtual still the bad way ?

22 posts in this topic

Hi,
Using virtual on console dev is the bad way to have good perf when used on renderer.
The concept is to have IRenderer and have inherited class by API.
My question is quite simple : Is virtual still bad on both console ?

Thanks
0

Share this post


Link to post
Share on other sites
Even if the user would like to use a different renderer at compile/linkage time, wouldn't the use of a interface class with virtual methods would still be required, to avoid changing client code to use one renderer or another?? Edited by Burnt_Fyr
0

Share this post


Link to post
Share on other sites
Why do you think that requires virtual lookup? Virtual lookup is for runtime decisions.

Which API does this use:
[code]
class CircleRenderer {
public:
Renderer();
~Renderer();

void begin();
void circle(float x, float y, float r);
void end();
private:
// Omitted...
};
[/code]
What client changes are required if the implementation was switched from/to OpenGL/Direct3D/Software? Edited by rip-off
Wrong tags
1

Share this post


Link to post
Share on other sites
Virtual functions are the bedrock of modern, object-oriented C++, and are unlikely to be a significant performance bottleneck on today's relatively fast processors. I recommend you proceed with using them. If at some point in the future, as a result of performance profiling, you do identify a virtual function or two that are slowing your code down (perhaps used very often in a tight loop), then address the problem locally at that time.

Good luck!
Geoff
1

Share this post


Link to post
Share on other sites
Virtual functions are fine... the overhead that they incur negligible in most cases when you consider the benefits. That being said, like anything in C++ it can get out of hand - virtual functions are a tool, and should be used when they're needed and they fit your design pattern.
2

Share this post


Link to post
Share on other sites
[quote name='Hodgman' timestamp='1352955900' post='5001111']
[quote name='gdunbar' timestamp='1352923413' post='5000997']Virtual functions are the bedrock of modern, object-oriented C++, and are unlikely to be a significant performance bottleneck on today's relatively fast processors.[/quote]FWIW, the [font=courier new,courier,monospace]class[/font] is the bedrock of C++ OOP, and [font=courier new,courier,monospace]virtual[/font] is an add-on for the [b]rare[/b] cases where you need runtime polymorphism.
[/quote]
IMO, [font=courier new,courier,monospace]class[/font] is the bedrock of most Object Based languages.
Object Oriented languages imply the availability of [font=courier new,courier,monospace]virtual[/font], as it allows for inheritance in addition to extension and aggregation...

...Perhaps it's more reasonable for us to define what [u][font=courier new,courier,monospace]bedrock[/font][/u] means in programming. :D

I just discovered that my real time script processing module uses virtual for its nodes in its intermediate representaion.
- Might be a good idea to change that... (Thanks Swiftcoder for the example on dealing with many virtual function calls) Edited by SuperVGA
0

Share this post


Link to post
Share on other sites
[quote name='gdunbar' timestamp='1352923413' post='5000997']
today's relatively fast processors
[/quote]

I don't know about you, but I find that processors are never quite fast enough! ;)
0

Share this post


Link to post
Share on other sites
[quote name='SuperVGA' timestamp='1352963167' post='5001125']Object Oriented languages imply the availability of virtual, as it allows for inheritance in addition to extension and aggregation...[/quote]Yeah, I just meant to imply that inheritance and polymorphism aren't the main/most-important/most-common parts of OOP, and are actually quite rare compared to, e.g. the use of composition or encapsulation.
0

Share this post


Link to post
Share on other sites
OK, OK, maybe I went too far with "bedrock". "Indispensable", maybe? C++ certainly wouldn't be much of an object-oriented language without virtual functions!

In any case, my true point stands: Use virtual functions. Don't worry about it. Then, if at some point in the future you have performance issues or otherwise want to optimize performance, you should measure performance. In the event that you find that you are calling a virtual function in a tight loop or something, you should be able to target a fix there; it is _extremely_ unlikely any type of major architectural change will be needed. swiftcoder's method of moving the function call to surround the loop (instead of the other way) is certainly an excellent option.

Good luck,
Geoff Edited by gdunbar
0

Share this post


Link to post
Share on other sites
[quote name='gdunbar' timestamp='1353091710' post='5001602']
OK, OK, maybe I went too far with "bedrock". "Indispensable", maybe? C++ certainly wouldn't be much of an object-oriented language without virtual functions!

In any case, my true point stands: Use virtual functions. Don't worry about it. Then, if at some point in the future you have performance issues or otherwise want to optimize performance, you should measure performance. In the event that you find that you are calling a virtual function in a tight loop or something, you should be able to target a fix there; it is _extremely_ unlikely any type of major architectural change will be needed. swiftcoder's method of moving the function call to surround the loop (instead of the other way) is certainly an excellent option.

Good luck,
Geoff
[/quote]
Use virtual functions if you need polymorphism. If you don't need, don't default to using virtual functions. Using of virtual functions is a design decision about where you want your abstractions to be. They should be used wisely or they will complicate whole code base. It is much easier to introduce virtual functions later on, than it is to get rid of them.

My answer to the OP is, the console is not going to change rendering API on runtime. Thus, it shouldn't be runtime polymorphic. Edited by Codarki
0

Share this post


Link to post
Share on other sites
In most cases, IMHO, virtual methods are better replaced with a plug-in system providing dependency inversion rather than concretet dependency, since its more amenable to automated unit testing and mocking. Dependency inversion allows the assembly of the class functions at runtime without implying any specific hierarchy.

As an example; a pseudo logging class using inheritence -

Class SystemLog : FileWriter
{
public WriteLog(string comment) : base(comment);
}

Using dependency injection

Class SystemLog
{
public IWriteDestination WriterStream {get;set;}
public WriteLog(string comment)
{
this.WriterStream.Write(comment);
}

}

The first example requires a class called FileWriter whose functionality is expressly built into the class hierarchy, but the second does not need this dependency; its entirely ignorant of how the functionality on which it depends is provided. The first example has the class "knowing" at design time about which class it will use to implement its features, but the second example has the class being ignorant of what other class will provide this function (allowing for a test framework to provide a replacement implementation without affecting the calling class).

Although polymorphism is a solid OO concept, anything but the simplist inheritence hierarchy requires a lot of design level decisions which could reasonably be left until runtime.

So - in short; Virtual generally is better replaced by a

public MyProvider : IProviderClass
{
get;set;
}

Phillip
1

Share this post


Link to post
Share on other sites
[quote name='PhillipHamlyn' timestamp='1353103516' post='5001649']
...
[/quote]
You introduce an indirection which adds an extra method call in means of performance.
Furthermore not using Polymorphism where it is appropriate will increase code size dramatically.

For testing this should imo not be a runtime decision, but a decision at build time.
In C++ you can easily swap in mockup classes in a type hierarchy with #ifdefs or by including different directories for unit/integration tests.
Not sure about C# though.
0

Share this post


Link to post
Share on other sites
[quote name='myro' timestamp='1353192309' post='5001865']
[quote name='PhillipHamlyn' timestamp='1353103516' post='5001649']
...
[/quote]
You introduce an indirection which adds an extra method call in means of performance.
Furthermore not using Polymorphism where it is appropriate will increase code size dramatically.

For testing this should imo not be a runtime decision, but a decision at build time.
In C++ you can easily swap in mockup classes in a type hierarchy with #ifdefs or by including different directories for unit/integration tests.
Not sure about C# though.
[/quote]

But inheritence uses a virtual method lookup anyway, so no net loss ?
Dont agree with the code size argument - I dont see a difference in code size either way. Same logic; same compiler.
Agreed you can use Mocking, but inheritence concepts indicate that the inheritor "is interested in" or "knows" about the implementation details of the inherited class and extends that [i]implementation[/i], Mocking replaces the implementation with a different one and therefore invalidates the assumptions on which the inheritence contract was originally made. With a dependency inversion approach, no assumptions are made about the implementation because these are interfaced away leaving only the calling contract.
2

Share this post


Link to post
Share on other sites
If you have legitimate reason to be worried about the performance costs of run time polymorphism, Agner Fog has a section in his free guide to [url="http://www.agner.org/optimize/optimizing_cpp.pdf"]Optimizing C++[/url] that describes how to do compile time polymorphism. You sacrifice a bit of readability for that possible benefit in performance though. Section 7.28 - "Templates" describes this. That pdf is an interesting thing to read if you ever have bits of free time scattered through your day that you need to make use of.
1

Share this post


Link to post
Share on other sites
I just want to say, each and every person so far has posted "true" statements ... but most of the posters have made a simple scientific / engineering question into a religious idea when it has no reason to be.

1. A language without "virtual" would not be very good for OO. I agree with this, on the grounds that dynamic dispatch / run-time polymorphism is one of the key ideas for the standard type of OO programming practiced today, from Smalltalk based roots. There are however other types of "OO", including the template / compile time version used in Advanced Template Metaprogramming and Modern C++ Design.

More people need to realize that programming languages exist to make life easier for the programmer to express a desire at programming time ... not to make any certain set of things happen at run-time unless they are needed to accomplish the desired result. Hence the rise of declarative concepts in recent years, which make the compiler and run-time work harder for the programmer.

2. Use virtual when you want run-time polymorphism or dispatch. Absolutely agree. This very useful keyword exist almost exclusively for this very purpose. When this is what you want, only very specialized alternatives can give any increased performance over the very simple virtual table. Examples of slightly "specialized" optimizations were already mentioned earlier in this thread ... such as polymorphic / virtual factories, which then do NOT use virtual method invocations internally ... so you pay the cost only during initialization (where it doesn't matter and isn't repeated), instead of during every method call of every object in your game loops.

3. The cost of virtual is "just" an extra indirection - function lookup. True. But "just" can be misleading. It is no more, nor less than this.

4. The cost of virtual is insignificant. Not always true. If you are trying to write a modern game engine, you simply cannot afford the cost of virtual function call on every function. It would be impossible to write a highly oo, completely dynamic game engine which tens-of-thousands of object running every frame with uncessary indirections at every level. When used "correctly" or at least either "when necessary", "when appropriate" or "sparingly" ... then virtual is great. When used for "no reason", "by default", "without consideration" or "excessively" ... virtual function call costs can actually account for a large percentage of your total performance cost - especially if also mixed with deep abstract object trees.

4. Inheritance implies virtual functions. Not at all true. virtual functions imply inheritance but NOT the other way around. Many many programming problems use inheiritance, but not run-time polymorphism.

I don't advocate avoiding virtual. In fact I use it quite heavily. And when prototyping I actual apply it "by default" on my prototype classes. But as your design solidifies, you realize a large set of methods has no reason to be virtual - UNLESS you are releasing BINARY class libraries to be consumed in unexpected ways by THIRD PARTIES who do NOT have access to your source code. That is the ONLY case where unknown use-cases dictate extra virtuals where not "needed" by existing client code.

Even more than virtuals I do most my programming in C# / .NET with all of its costs ... but when I have to tune the performance of an audio mixing library, or reduce the footprint / performance profile of some asynchronous networking code - I go to C++, and I use a "proper" design for the problem ... not just throw abstractions and features at it and hope performance just happens to be "good enough".
0

Share this post


Link to post
Share on other sites
You just have to understand what you are doing.
For a render you will not be passing the data directly to the functions, you will be passing pointers if-not handles to the methods.
So structured-coding overhead is guaranteed.
If you start creating function-pointers to code something up, you may-as-well have just used virtual functions.
0

Share this post


Link to post
Share on other sites

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  
Followers 0