News for hackers. Stuff that matters.
Re:CryEngine out on GitHub by stuxnet79 on Tuesday May 24, 2016 @09:01AM (#11761174)
The fact that you are using university requirements as an exemplar is very telling. The moment I graduated and started hacking away in the real world is when I discovered that there was a lawless wild-wild-west of coding conventions out there.
Re:CryEngine out on GitHub by Jeema101 on Tuesday May 24, 2016 @10:24AM (#11761743)
A mish-mash of coding conventions is understandable, given the fact that coding standards may not exist in the first place, or can change over time, etc.

Long functions which have grown over time are also understandable, given the realities of changing requirements and such.

Thousands of lines of uncommented code, however, are not understandable... in the sympathetic sense, or literally.

Re:CryEngine out on GitHub by Derpdiherp on Tuesday May 24, 2016 @09:09AM (#11761218)
Seems as you've picked up on the same thing -

"I've worked in the Games industry with age old engines, I currently work in embedded development with a code base over 10 years old - I'm fully aware of what "real life" code is like. There is no excuse for not writing well commented code - or even code with well named variables and functions that reduce the need for as much commenting. If you suffer from code like this in your workplace, perhaps actively comment it as you reach an understanding of what it does."

Relatively experienced 6 year C++ dev - I mainly mentioned university because things where much stricter - but having an environment with decent code reviews and maintaining a little self discipline goes a long way with the sanity of your co-workers.

Re:CryEngine out on GitHub by sillysaurus3 on Tuesday May 24, 2016 @09:30AM (#11761338)
You're a C++ dev, not a gamedev. They use different coding conventions. You'll find a lack of refcounted pointers, for example, whereas university teaches you to use them.

6 years is significant, but it's not a long time. There's much to learn, particularly about the cultural aspects of various segments of the industry.

This is excellent code that was produced on a tight timeline.

Re:CryEngine out on GitHub by Derpdiherp on Tuesday May 24, 2016 @09:33AM (#11761353)
I was a game dev for 3 of my 6 years. I just got sick of the layoffs after project ends - and my university tuition was in fact games development specific.

*Edit - Yes though - by no means do I think I'm some big shot know it all. But I do have strong feelings about readability after having had to deal with code which is awful to grok.

Re:CryEngine out on GitHub by sillysaurus3 on Tuesday May 24, 2016 @09:37AM (#11761372)
Fair enough. It's a valid point of view. Sorry you had to deal with layoffs. It's one of the darker aspects of the industry.

To clarify, my objection was that we're criticizing this code for superfluous reasons when it's currently a delicate political climate in most game companies to even release code like this in the first place. It's probably best not to imply their reputation should be harmed by their lack of comments, since this can discourage other game companies from releasing their code in a similar manner. I've seen the argument "it might harm our reputation" be used to block endeavors like this.

Re:CryEngine out on GitHub by Derpdiherp on Tuesday May 24, 2016 @10:10AM (#11761613)
I'd argue that a company should be able to take a little criticism - style based ones like mine will likely be ignored, as you mentioned before it's down to the culture of the company - for every function like the one outlined in the OP I'm sure there's countless examples of good style in the code base, engines are huge.

I really hope that companies don't view criticism as a negative thing, it's cause for discussion and change which are most certainly positive - I hope some bugs are found and they start to feel the benefit of the community a little.

Re:CryEngine out on GitHub by shmerl on Tuesday May 24, 2016 @05:01PM (#11765451)
What's wrong with managed pointers? Rust uses them just fine. C++11 has them natively.

Using raw pointers in C++ is rarely really needed.

Re:CryEngine out on GitHub by sillysaurus3 on Wednesday May 25, 2016 @01:18AM (#11767799)
In gamedev, using raw pointers is necessary. As a rule, game engines do not use refcounted pointers. This is because whenever you decrement a refcount, you're accessing the cache line in which the refcount resides. This results in thrashing the L1 cache, which translates into at least a 10% drop in performance. This is an unacceptable margin for game engines that fight to stay ahead of the competition.

More info on performance loss due to cache thrashing:

https://lmax-exchange.github.io/disruptor/

https://lmax-exchange.github.io/disruptor/files/Disruptor-1....

http://martinfowler.com/articles/lmax.html

http://mechanical-sympathy.blogspot.com/2011/08/disruptor-20...

And http://mechanical-sympathy.blogspot.com/ is great in general.

The reason that raw pointer management works in gamedev is because gamedev is closer to crafting than traditional programming. No one will die if a game crashes, and the iteration loop is a tight feedback cycle of code-compile-run code-compile-run.

Due to the nature of the entertainment industry, the codebase also loses much of its value within a year of releasing the game, as opposed to traditional software that typically gains value with time, meaning it's more important to get code out the door than to get it right. History is littered with the skeletons of game companies that disregarded this unfortunate truth.

Re:CryEngine out on GitHub by shermanyo on Thursday May 26, 2016 @10:35PM (#11783491)
> The reason that raw pointer management works in gamedev is because gamedev is closer to crafting than traditional programming. > No one will die if a game crashes, and the iteration loop is a tight feedback cycle of code-compile-run code-compile-run.

The more time I've spent understanding and building game engines, the more I see it as an organised network of state-machines managing and working with collections of data.

More often than not, shared state has clear ownership and lifecycle management built into the relevant state-machines. By isolating creation and destruction of resources in the transitional states (load and start a level, open a menu, change to Game Over screen), most of the code can safely reference data from other subsystems without reference counting, under the assumption that references are only valid until a global, shared transition in state.

Imagine a player entity that stores a reference to a model, texture, sound effect, input state, etc... If that data is loaded at the start of the level, and destroyed when the level ends, is there really a need to inc/dec a reference count if an enemy entity shares a sound effect reference?

Re:CryEngine out on GitHub by shmerl on Wednesday May 25, 2016 @11:17AM (#11770367)
Well, shared_ptr has its costs. What about unique_ptr though? It's not a raw pointer, but it's for transferring ownership, so it shouldn't have problems of the reference counting.
Re:CryEngine out on GitHub by sillysaurus3 on Wednesday May 25, 2016 @03:22PM (#11772375)
Ownership typically isn't transferred in a game engine, but sure.
Re:CryEngine out on GitHub by shmerl on Wednesday May 25, 2016 @04:06PM (#11772675)
Cases when different threads work on some objects passing them around aren't common?
Re:CryEngine out on GitHub by sillysaurus3 on Wednesday May 25, 2016 @04:39PM (#11772888)
They are, but in that case you'd use raw pointers.

The reason this works is because of discipline. Generally, there is a FooManager class which owns Foos. The FooManager is responsible for both allocating and deallocating Foos, regardless of where they're used. And in a game, "When should something be deallocated?" usually has a clear answer: When the level loads, for example, or when you move from one part of the continuous world to another part.

Then there are Subsystems (singletons) for each division of the engine: GraphicsSubsystem, InputSubsystem, etc.

Between those two patterns, there aren't a lot of ways to lose track of a pointer.

Re:CryEngine out on GitHub by shermanyo on Thursday May 26, 2016 @10:47PM (#11783545)
Great post, related to my thoughts above: https://news.ycombinator.com/item?id=11783491

I think another important factor is the pseudo-realtime update loop that synchronization is tied to.

Unless there is some garbage collection between game state changes (unloading unused resources during a level, etc...), its rare that references are invalidated unexpectedly, or accessed in parallel to the cleanup step between game state changes.

eg. a global state change from RUN to CLEANUP tells the subsystems to stop using a resource, so during the CLEANUP state the subsystems can safely delete any resources they have ownership of.

Re:CryEngine out on GitHub by shmerl on Wednesday May 25, 2016 @07:13PM (#11773925)
Idea of levels or areas isn't always applicable, and in vast open space games like Star Citizen or Witcher 3 with tons of random events you might need to load / free something pretty regularly I suppose, and it should happen seamlessly (i.e. if some event is triggered or passed).

So limiting lifetime of the object by some scope should work pretty well for it, and if you can pass raw pointers to transfer ownership, you can as well pass managed ones. At least it's safer.

Anyway, by using something like Rust a lot of such problems are solved by the language itself.

Re:CryEngine out on GitHub by sillysaurus3 on Wednesday May 25, 2016 @08:49PM (#11774383)
The idea of levels or areas is always applicable. A vast open game like Star Citizen is partitioned into area spaces, usually in a cubic array. When you move out of range of one of the cubes, past the point where you can see it, then all resources in that cube can be safely freed.

I don't know where Rust came from, since the discussion was about C++. But feel free to write an engine in Rust. It seems like a promising approach.

Re:CryEngine out on GitHub by shmerl on Wednesday May 25, 2016 @09:18PM (#11774520)
I hope it will happen eventually, especially with projects like this: https://github.com/tomaka/vulkano
Re:CryEngine out on GitHub by steveklabnik on Tuesday May 24, 2016 @05:37PM (#11765715)
To be clear, Rust does support refcounted pointers, but they're used very sparingly, and also have the advantage of allowing regular old pointers to their interior while remaining safe, which reduces refcount twiddling.
Re:CryEngine out on GitHub by shmerl on Tuesday May 24, 2016 @05:53PM (#11765839)
I didn't just mean refcounting, but simply managed ones (i.e. "smart" pointers), in contrast to raw pointers which require manual management.

Shared pointers (as in ref counting) is just an example of that, so I understood the above comment as implying that game development somehow encourages manual pointers management. May be I just understood the intention wrong, and it didn't mean to exclude other types.