开发者

Is C still being widely used in game engines? [closed]

开发者 https://www.devze.com 2023-01-14 08:36 出处:网络
Closed. This question is opinion-based. It is not currently accepting answers. 开发者_如何转开发
Closed. This question is opinion-based. It is not currently accepting answers.
开发者_如何转开发

Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.

Closed 2 years ago.

Improve this question

The title is a bit of a misnomer, what I mean really is "C with classes".

Let me explain, recently I bought the book ShaderX7 which came with a lite (and old) copy of the Unigine engine for one of the articles about shadow mapping techniques.

I was dabbling through the code when I realized that, while the author was using C++ and inheritance and all the C++ goodness, most if not all the method content was essentially C-style code; for example:

int Shader::get_param(const char *name,char *src,String &dest) const {
    char *s = src;
    int size = (int)strlen(name);
    while(*s) {
        if(!strncmp(s,name,size)) {
            if((s == src || strchr("\n\r",*(s - 1))) && strchr(" \t",*(s + size))) {
                src = s;
                s += size;
                dest.clear();
                while(*s && strchr(" \t",*s)) s++;
                while(*s && strchr(" \t\n\r",*s) == NULL) dest += *s++;
                if(dest.isEmpty()) {
                    Log::error("Shader::get_param(): can't get \"%s\" \n",name);
                    return 0;
                }
                memmove(src,s,strlen(s) + 1);
                return 1;
            }
        }
        s++;
    }
    return 0;
}

I am not saying this is bad, it does the job and that's what matters but I'm more used to C++ style constructs, with std::string, vectors etc... and I make big use of the Boost libraries; so this kind of style come as a bit of a surprise to me.

Is it really better/faster to use this kind of code than to go the generic, OO way ?

Did I fall into the "too much abstraction" trap ?

Edit: corrected method name to make it clear what it is doing.


First and foremost I must admit that I'm not a games developer, even though I have developed a fully functional 3D game engine in the past.

That aside, I do have a few words about optimizations, "spoiling" languages and so on.

When developing an application — any application — the golden rule of optimizations is "don't optimize before you make it work." You need to fully support all the functionality you want in your application, and only then you should optimize it. The reasons vary; the most important one is that while you may believe something is "slow," it may not be your bottleneck. You may be spending a lot of time optimizing something that doesn't require optimization. Furthermore, optimizations often blur your code simplicity and maintainability, which may lead to bugs in the near or far future. If this piece of code didn't require optimizations, you've complicated the code for nothing.

While that is the golden rule of optimizations, there is one big exception. When you know in advance that your application will be stressed out to the max, you need to make some different choices in the beginning (in the architecture or in the design phases) and also along the way. Also, the general rule that the platforms are getting better and faster doesn't apply for games, where the competition between the developers is on the very edge of technology. Here are several points to consider:

  1. Some lingual features may be costly. Exceptions in C++ are a good example.
  2. Some lingual features may actually save you code and will cost little or nothing during runtime. C++ templates are a good example, though you still may wind up creating lots of code during compilation, leading to a bigger binary, and therefore lower performance, potentially.
  3. Infrastructures (STL for example) are generic. By making a solution specific to your domain, you MAY be improving your performance. A simple example — if you have a vector that will always be 3 items long, you will definitely be better than the stl::vector implementation. However, this is not always the case. For further reading, see chapter 11 of "Efficient C++" by Dov Bulka. This is an excellent book in general for your question.

In general, using C with classes is a good start for writing fast code while retaining a structured and well-designed project, but one should not neglect the whole of C++ excellent features. More often than not, trying to roll out your own solution to a problem covered by C++ (e.g., polymorphism) will be slower than the out-of-the-box solution, unless you can make the solution VERY specific to the problem at hand.


C++ without STL

As I have seen it in my professional history, what is mostly used in game development is not C with classes, but rather C++ without STL. Some parts of STL are considered too slow for a reasonable game engine performance, most notably the streams. Other parts provide reasonable general performance, but the way memory allocation is handled is mostly unacceptable for games - this applies to string and vector libraries in most scenarios. Excellent extensive discussion of this can be found in EASTL white paper. Game developers frequently use boost or even implement their own alternative to part of whole of STL (see Game STL or EASTL).

No exceptions

There is one particular language feature which is never used in any performance critical engine parts - the exception handling. This is because on the most important game development platform (Visual Studio x86/x64) the exceptions are quite costly, and you pay some cost even when no exceptions are hit. The exceptions are avoided into the extent some development console platforms even do not provide them, or the support is known to be incomplete, unreliable and basically "broken".

Used to C

Other than that, it often happens that game programmers use C instead of C++ simply because they are used to it.


If you really want to be drawing graphics as fast as possible, and you start off by saying

int size = (int)strlen(name);

that looks like barking up the wrong tree.

What does get_something get? It doesn't appear to be graphical.

Optimization doesn't consist of doing the wrong thing very quickly. It's about cutting the fat and spending all the time on the important stuff. If your graphics engine wastes a significant number of cycles on string processing, it has an issue that changing languages probably won't solve.

So… write auxiliary functions as expediently, maintainably, and clearly as possible. When you need to micro-optimize the critical path, C++ still covers the low-level style.


If it:

  1. Works and you're happy with it, don't touch it.
  2. Doesn't work, change it the way you like, as long as it's fixed afterwards.
  3. Works and it's not fast enough, make it faster (NOT without profiling first).

I'll guess that you're falling into case 1, so I'd advise to leave it alone. If you need to change things, and don't have serious performance concerns, by all means dish out some C++isms on it. In the general case I find it difficult to read C-style C++ programmers, they either:

  1. Haven't had time or don't care to learn the C++ way to do things (which really isn't acceptable from a safety perspective),
  2. are cherry-picking the parts of C++ they actually need (very wise),
  3. or they honestly need the performance characteristics of C (very rare).

Looking at the code it could be any of these cases. Either way it doesn't matter now, the code is in your hands.

0

精彩评论

暂无评论...
验证码 换一张
取 消