Here is Herb Sutter talking about dynamic memory management in a talk entitled Leak-Freedom in C++… By Default, going into examples of when and where to use the standard library’s smart pointers. He actually brings up a multithreading-ready version of the weak_ptr/shared_ptr-based resource bank class I showed off in a recent post.
Want fast C++? Know your hardware! is about, well, knowing your hardware. This is one of those annoying harsh realities. You want to not have to think about the metal. The whole point of high-level programming languages like C++ is to get away from worrying about the hardware. Worrying about the hardware is the hardware developer’s job, right? Well, no. At least until languages catch up with the fact that the performance bottleneck in computing is no longer CPU speed but memory speed1, data-oriented code is going to be the way forward for high-performance applications2.
I enjoyed this talk on “Colonies, performance and why you should care”. Basically, a ‘colony’ is a container written for fast insertion, erasure and iteration; the kind of thing you want to put your GameObjects in. This is one of the many nice things coming out of SG14, the ISO-C++ study group focusing on low-latency, real-time applications like games.
That’s all I have time for, but I recommend having a browse around the selection of videos. There are significantly more than there were for Steam Dev Days, and some of them are very focused, so there was no way I could have watched and judged them all. Hopefully the ones I’ve linked here are a good starting point for your own meandering through the archives.
If you know of any languages or features of any language which abstractify data-oriented programming practices, please tell me about them. ↩
Fun fact: Data on CDs/DVDs for games which use streaming for most or all of their assets (so basically any seamless open-world game since GTA 3) have optimized data layouts on disk, with data commonly accessed at around the same time placed physically near each other to minimize the amount of movement needed to move from one asset to the next. ↩
The second ever Steam Dev Days was held in October and, by all accounts, was a pretty rad event. Fortunately for us shmucks who didn’t go Valve have kindly put recordings of all the talks and panels on YouTube. The full playlist is here, but I’ve watched most of all of them and can guide you towards what I think are the best ones.
Each heading should be a link to its corresponding YouTube video. Please let me know if I missed one or messed one up!
This is basically just a mission statement for what Steam Dev Days is aiming to be: not an expo, more of a conference, but more intimate than Game Developers Conference.
It’s really cool to look back and reflect on how Steam has evolved over the years. I’ve been there for almost all of that time, installing it because of Dark Messiah of Might and Magic (the best game ever) in 2006 and gradually becoming more of a regular user until The Orange Box exploded my brain with SHEER GAMING VALUE FOR MONEY and transformed me into a lifelong Valve fan and enormous1 Steam library-haver. I can remember Steam’s first crappy iteration and all the ways it’s changed on the path to becoming the terrifying juggernaut it is today. It’s interesting to get the perspective of someone at Valve on that history, and learn about where they think they’re taking the platform next.
Input programming is usually pretty horrible, for all the reasons Lars Doucet (developer on Defenders Quest) talks about. His enthusiasm for the Steam Controller and its API is infectious – I wasn’t interested in owning one before this talk, but now I want to get one just so that I can play with it as a programmer.
I haven’t played ARK. I don’t think I ever will - it’s not really my thing - but I find it fascinating to watch its history unfold. I remember being quite excited to watch DayZ develop from a shonky, obscure ArmA II mod to PC gaming household name. Of the many games following in its footsteps, ARK definitely seems to be taking the most confident strides, overtaking its inspiration in almost every way.
Worthy discussion of the pros and cons of Early Access from developers working on the frontline. Each panellist has a different perspective and approach, but no one positions themselves as the developer who got it ‘right’. Having said that, there’s a bit of ego-grooming, but it’s not bad.
I don’t cheat in games. Consequently, I know nothing about how cheating is done, and therefore less than nothing about how to prevent it. I like the presenter’s examples of simple game design changes that can discourage cheating. It’s also useful to have an overview of Steam’s anti-cheat and game moderation features.
Put together, these panellists probably have enough industry experience to make me look like a newborn. They have a lot of really well-articulated advice to share on when and when not to get a publisher, and how to do it properly.
A panel of graphics programmers talk about Vulkan, the new open-source low-level graphics API on the block. They seem pretty pleased and I’m now even more eager to learn it.
I don’t have one of these newfangled ‘VRs’, but even my neo-skeptic mind can tell there’s a lot of interesting stuff to talk about with regards to making VR games. In this panel the developers of Fantastic Contraption, Hover Junkers, Space Pirate Trainer and Audioshield share the insights they’ve gained from working on the frontline. The YouTube video’s thumbnail image is rather good, too.
That’s all of them, assuming I haven’t missed one somewhere. Even if you only watch a couple of them, I think you’ll have an edifying old time.
Is there one you think I missed? Or one talk in particular that really grabbed your attention? Let me know what you think!
I’m too ashamed to count how many unplayed games there are in it, my friends. Too ashamed. ↩
No, I don’t know how the capitalisation should work in that title, either.
In my last post I talked about how I’m starting to use the C++ standard library’s smart pointers in my own code and finding it quite pleasant. But all I did was name and give brief descriptions of the three templates – unique_ptr, shared_ptr and weak_ptr. I didn’t give any examples of them in use.
One RenderComponent, One sf::Texture
In my game engine Entities are made up of Components (a common design pattern). The PhysicsComponent connects it to the physical world. The RenderComponent describes how to draw it. RenderComponents can have textures. For now all my rendering code makes use of SFML’s graphics library, so RenderComponents make use of textures through sf::Texture objects.
Initially, I’m willing to take the simplest course of action: RenderComponent has a sf::Texture member.
classRenderComponent{sf::TexturemTexture;};
When I want to use the texture, I call mTexture.loadFromFile("example.png") and continue on my way.
Advantages include:
When the RenderComponent is deallocated, so is the sf::Texture, along with the actual texture data that might have been loaded onto the GPU’s memory with loadFromFile.
Disadvantages include:
It’s wasteful of main memory. sf::Texture has many members. I’m probably never going to use most of them.
It’s wasteful of GPU memory. If two RenderComponents use example.png, two copies of it will be sitting in the graphics card’s memory. Why load an asset twice? This would also be wasteful of main memory because the sf::Textures would be identical too.
I can solve the first disadvantage by having RenderComponent own a pointer to an sf::Texture instead.
Nice. When I want the RenderComponent to be textured, I allocate a new sf::Texture and call loadFromFile with it. Unfortunately I now have to remember to call delete at some point, and I might screw up by exposing the pointer to outside bits of code, who might deallocate the memory or modify the pointer. Hence:
Those insecurities are now nicely stitched up. Unfortunately, I’m still worried about being wasteful of space when multiple RenderComponents are using the same texture.
Multiple RenderComponents, One sf::Texture
You could accomplish this in a bunch of ways. Here’s one that takes advantage of smart pointers to minimize book-keeping and waste. First, I give RenderComponent a shared_ptr so that it can participate in shared ownership of an sf::Texture with other objects.
When I want to set the texture to example.png, I need a way of knowing if there is already a dynamically-allocated sf::Texture somewhere out there that’s been loaded with example.png.
Enter the TextureLibrary class. It keeps track of all that for me. Setting the RenderComponent’s texture is a matter of writing mTexture = sTextureLibrary.LoadTexture("example.png"), and I’m guaranteed not to be creating a duplicate. When no RenderComponents are using example.png, it will be automatically cleaned up.
TextureLibrary needs to know about the reference count of each sf::Texture it oversees without actually modifying it. A perfect fit for std::weak_ptr.
classTextureLibrary{private:// Map of {filename, texture} key-value pairs.std::unordered_map<std::string,std::weak_ptr<sf::Texture>>mLoadedTextures;public:std::shared_ptr<sf::Texture>LoadTexture(std::stringfilename){// Cast filename to all-lower case.std::transform(filename.begin(),filename.end(),filename.begin(),::tolower);// Check if the filename has already been loaded.if(mLoadedTextures.find(filename)!=mLoadedTextures.end()){// Make sure the weak_ptr is not dangling before we create a new reference.if(!mLoadedTextures[filename].expired()){returnmLoadedTextures[filename].lock();}}// There is no sf::Texture using this file. Create a new one.std::unique_ptr<sf::Texture>temp(newsf::Texture);if(temp->loadFromFile(filename)){std::shared_ptr<sf::Texture>shared(temp.release());mLoadedTextures[filename]=shared;returnshared;}returnnullptr;// If loadFromFile failed, temp will go out of scope here and delete itself.}};
Concise and safe. There are definitely drawbacks – a little reference-counting overhead here and there – but for now I’m willing to believe the benefits outweigh the costs.
The concept of the smart pointer is not particularly new. It’s probably existed for as long as malloc and free have been inspiring programmers to invent increasingly elaborate garbage collection systems instead of manually managing the heap memory they use. In fact it’s quite easy to create some form of smart pointer without realizing you’re replicating the pattern. All you do is write a class which wraps up a pointer to a dynamically-allocated block of memory. Maybe it prevents other parts of the codebase coming in and pointing that pointer at something else without freeing the memory. Maybe it calls delete on the pointer in the destructor. Voila. You’ve written a ‘smart’ pointer: an abstraction which automates or simplifies resource management.
If this is all a bit alien to you, you might be fairly new to C++ and still getting used to how pointers and manual memory management work in general. You also might not be up to speed on how the language standard has evolved in recent years. One nice evolution I’ve recently started taking advantage of is the addition of smart pointer class templates to the standard library.
std::unique_ptr helps with exclusive-ownership resource management. std::unique_ptr<int> p(new int) makes wrapper around a pointer to a dynamically-allocated int. Nobody else can point to that int, and certainly nobody else can delete it out from underneath p1. When p goes out of scope and its destructor is called it deallocates the int so you don’t have to remember to call delete yourself to avoid a resource leak. The overhead of using a unique_ptr instead of a raw int*? Negligible. The maintainability overhead of using a raw pointer? Definitely not negligible. This kind of smart pointer receives a big thumbs-up from me, and having a nice implementation right there in the standard library makes it hard to defend not making use of it2.
std::shared_ptr, on the other hand, is for shared-ownership resource management. Multiple shared_ptr instances can point to the same block of data without the programmer needing to worry about someone deleting it before everyone else has finished with it. In order to do this it introduces reference-counting into the mix, so this time, yes, there is some overhead. That overhead, however, is book-keeping you’d probably be doing anyway. When a shared_ptr’s destructor is called, the reference count variable it shares with the other shared_ptrs that point to the same resource is decremented. If the reference count hits zero, it deallocates the resource.
There’s one more. std::unique_ptr and std::shared_ptr have a scrawny sibling: std::weak_ptr. It acts like a shared_ptr, but doesn’t participate in shared ownership. When pointed at a resource, the weak pointer shares a reference count variable with any shared_ptrs that also point to that resource. Unlike the shared_ptr it doesn’t modify the reference count; it just looks at it. This means it can tell when it’s dangling - when it points at memory that’s been freed - because the reference count is 0. Useful!
The main takeaway here is that I like these things, and I think should too. Once you’re used to them they’re very useful tools. If you’re still not convinced, my next post will demonstrate a use-case I found for weak_ptr in a spare-time project that might tip the scales.
I had two new experiences last week that were fresh, eye-opening and actually quite inspiring: a journey to an island, and a journey underground…
The Inchcolm Project
Sunday 16th October
I was one of seventy-ish lucky people to take a ferry from South Queensferry out to the small isle of Inchcolm in order to take part in an experience best described simply as ‘Dear Esther in real life’.
With our smartphones in our hands, we roamed the island’s pathways, navigating our way towards the specific geo-tagged areas in which we’d receive a little audio narration from a sad man. Not the same sad man as the one from Dear Esther – this one was bereaved by the loss of a Rachel, and had a Scottish accent rather than an English one. Hearing this guy open his speeches with my name over and over again, I couldn’t help but feel it leant a little something to my experience that made it a bit different to that of non-Rachels on the island. It was hard to take in and digest all the narrative that was there in the time we had, but there was definitely an appreciable level of terror of the sea, which I can relate to. There were symbolic, story-related art installations scattered around the island (some in quite hard to find places), and members of the Mantra Collective playing musical accompaniments to some spaces. You could walk through the pitch-black tunnel that runs through one of the island’s two hills to the sound of a violin, its notes echoing eerily through the darkness, and emerge blinking into the sunlight at the other end, feeling very spectacular indeed.
Inchcolm is a beautiful place. Its ruined abbey is kept company by the bunkers and turrets of the World Wars – almost all the islands in the Firth are encrusted with these concrete barnacles. There are seals in the surrounding waters who swim into the little bay where the boat docks and a thin strip of grassy green land connects the two halves of the island. I think they know people love to spot them and come close just to bask in attention. There is a rock out a bit into the water which has been covered in garden gnomes and christened, yes, ‘Inch-gnome’.
While we were there the weather cleared up a little bit, and warm rays of sunshine poked through to us from the West, lighting up the Forth bridges in the distance. To the South there was a clear view to Edinburgh, looking windswept and small in the shadow of Arthur’s Seat, but proud nonetheless.
At the end of our time on the island we went into a darkened room in the abbey to watch Dear Esther being played, projected onto the rough stone wall. Then we were led into another room and played several songs from the game by the whole Mantra Collective. It’s beautiful music, some of my favourite music in all the world, and I’m intensely grateful to have been able to experience it in such a stunning setting.
There’s an article about the project on the Abertay University website, written before the fact, if you’re interested.
Games Are For Everyone, Volume IV
Thursday 20th October
Through a mixture of bad luck and incompetence on my part, this was the first Games Are For Everyone I’ve managed to attend, and oh boy do I feel sad about missing out on all the previous events.
It took place at The Caves, a massive converted whisky cellar in the bowels of the Edinburgh old town (it’s just off Cowgate, beneath South Bridge, to be exact), which was a weird, cool, kinda surreal space to be in.
There were a lot of games there. Some were running on television screens or monitors, while others were set up in these cool faux-arcade cabinets that We Throw Switches have. Among the lineup were:
Lieve Oma, by Florian Veltman. I played this when it was released, it’s one of my favourites of the year, and I heartily recommend checking it out.
Manifold Garden: There’s a lot of hype around this extremely gif-able game, and I can’t say it isn’t justified. It looks completely unlike anything else, and every time I see it I can’t help but try to work out how it does its infinitely-repeating-world thing. Unfortunately I didn’t play it while I had the chance.
Pathfinder: You don’t play this game. Instead, you watch a drummer play it. Using a drumkit. It’s kind of amazing, even if half the time you can’t work out what the hell is going on, and very, very loud. This is the best link I could find for it.
Gravity Pong, by Amy Parent. This is a neat little twist on Pong, delivered with a lot of polish. There seemed to be people playing it against their friends on more or less non-stop for the whole evening.
And there were a tonne of others, all really cool. To my pleasant surprise Devil Daggers was there and I got to show off my skills. I can only make it up to about 150 seconds, which isn’t as good as I aim to get someday, but still quite impressive to someone who’s only just played the game for the first time. It had a cellar all to itself in which ominous red candles had been lit. The game was being projected onto the bare stones of the cellar wall, just like Dear Esther had been. All very sinister and altar-like, quite suitable for the most Faustian game ever made.
I got to meet lots of new people as well as chat with existing games friends, which is something I seem to thrive on more and more, and I also got to help out a little with running the event, which was rewarding despite the fact I didn’t really get to sit down for the whole evening.
All in all a good time, but I don’t think dragging myself home at 1 in the morning on a workday is something I should repeat often.
Photo credit goes to We Throw Switches and Ellie Morag. Thanks, folks!