Programmer Ramblings – Continued Screwing with std::thread

This is a followup to yesterday’s ramblings about initial work screwing with std::thread.

In talking with Quintosh on Twitter, he asked why I didn’t go with some sort of thread pool. Frankly, it’s because I’m lazy. However, it did give me an idea. The data that I’m working on is fairly parallelizable without memory collisions. Rather than creating a thread pool where I hand work to threads, it would be a lot lower amount of work for a simple program if I let the threads directly request work themselves. This gave me a few things:

  • A unit of work could be much smaller, so cores that are running slower because of other system processes don’t present blocks.
  • Once I implement other things that scale the program non-linearly (ex: reflection/refraction), I don’t have to worry about intelligently breaking up the work into equal sizes.
  • The only member that is accessed across many threads is the piece of data controlling the work request. This keeps my actual locks to a minimum.

Much to my surprise, I also managed to get Intel VTune working completely. This helped confirm some of my assumptions from yesterday’s article, so I’ll cover that in some detail later on.

Programmer Ramblings – Screwing Around With std::thread

Being a primarily Unreal-focused developer, I don’t really spend that much time in standard C++. Ya, technically I work a lot in C++, but C++ using STL and related things is very different from the custom containers and macro-heavy nature of working in Unreal. Part of the fallout of that is that I generally miss new features of the language for quite a while. I didn’t get into working in C++11 and newer until I was off of working in UE3, and even moving into UE4 I don’t get exposed to things like STL or the the standard implementation of threads. It’s one of those things where, ya I’ve used threads and I get the concepts behind it, but creating a worker thread to offload a specific task is much different than architecting code to properly and efficiently support a threadable workload. That’s where my screwing around here comes into play.

For this screwing around, I decided to thread an implementation of a raytracer. It’s a workload that is inherently parallelizable. You’ve got a bunch of rays going out that can independently resolve themselves. Ya, you may need to have a ray spawn further rays, but that can live within the worker thread as it chews through the work. From a naive implementation standpoint, each pixel could be its own thread and run in parallel, and that’s basically where I started.

Some notes:

  • For the purposes of this, I started with a sample implementation from Ray Tracing in One Weekend by Peter Shirley. This series of books is a supremely fantastic quick look at basic concepts behind ray tracing, and gave me a quick place to get to a point where I could investigate threading.
  • For my CPU, I’m running this on an AMD 3950x (16 core, 32 thread) at stock speeds. I’m not doing anything to minimize background processes, but it shouldn’t be a huge issue for where I’m at.
  • I’m currently using Visual Studio 2019’s built-in performance profiler. I don’t particularly like it compared to other tools, but my profiler of choice on my current hardware (AMD uProf) currently has a bug on some installs of the May 2020 version of Windows 10 that prevents profile captures. The VS profiler is basic, but gets me enough information for the basics that I’m starting at.
  • This is running in release with default optimizations purely out of laziness.
  • I’ll post some code samples around. These won’t generally compile because I’m stripping out unnecessary stuff from the samples (ex: you don’t need to care about me setting image dimensions and writing it to disk).

For the purposes of my current testing, this is the output image. It’s two spheres where each pixel color represents the surface normal hit by a ray. The image is 800×400 resolution and each pixel does 100 slightly randomized rays to give an anti-aliased result. In the basic current pass, I’m not doing any bounced rays on collisions. The final image is therefore the result of 32 million ray casts. In some future tests, I’ll be adapting the rest of the book to the multithreaded version and support reflection/refraction and increasing the workload through that process.

Game Ramblings #116 – Ovivo

More Info from IzHard

  • Genre: Platformer
  • Platform: PS4
  • Also Available On: iOS, Android, Steam, Xbox One, Switch

Ovivo is the perfect kind of indie experience for me. It takes a single mechanic, polishes it to a brilliant shine, and lasts as long as it needs to. It doesn’t start adding a bunch of cruft. It doesn’t add 20 hours of extra shit purely meant to extend gameplay. It doesn’t try to be something it isn’t. In focusing on what makes it special, it ends up being better than games that push higher and fall hard.

This is an early level that I was playing, but I figure it’s a good place to start. The only mechanic available to you is the ability to switch between the white and black gameplay spaces. As you go further in the game, there’s some amount of nuance there, but it really is that simple. You can move left and right, and you can press the one button to switch between color planes. However, it’s the nuance that ends up giving the game a lot of depth.

Early on they give you those curved platforms and elevation changes. In swapping planes, you start to see a bit of momentum from the swap. It intuitively pushes you to preload your swap, which then teaches you about really using that momentum change to get to new spots. Meanwhile, this is all being taught in complete safety. Later levels start adding little pits that you have to use momentum to get around, giving you a spot to experiment with. It then proceeds to moving platforms and moving traps, giving another layer of depth to the interaction.

It’s that little step at a time push forward in complexity that works really well. You hit a new wall, have to experiment a bit, learn a little bit more, and move on. You see it in games like Super Mario Bros – can’t run left, always move right; jump before the first Goomba and hit your head on a question mark block – where new mechanics are introduced in a spot where you intuitively learn something, rather than being hand fed something. In the case of Ovivo, they do it extremely well. The complexity they get out of the one simple mechanic is astounding.

This is all helped by the fact that the game is visually stunning AND the visuals are core to that single gameplay mechanic. The entire game is presented in black and white, and everything you see is part of the gameplay space. The transition in colors literally acts as the collision boundary. Things that rare visually spiky and dangerous looking are literally dangerous and will kill you. Nothing is wasted in the layout of the levels, and it’s all important to the experience.

The fact that it is visually interesting leads to the one other sort of mechanic, which ends up being the light collection aspect. There’s two types of collectible items to find in the levels, and they’re a mix of on the core path and off of it in unique side areas. They end up playing a nice role in forcing you to pay attention to what’s going on around you to find those little side spots. In general, the ones off the path are also the ones that have the most interesting puzzle and momentum tricks, so it ends up being fun to find them anyway.

Each level is followed by a zoom out, showing both the entirety of the level you went into, and the art theme around it. It’s always impressive.

These kinds of short indie experiences are the type of game that I really like playing, and also the type of game that I’m glad to see coming to physical releases. In this case, I got this one from Red Art Games. These types of indie releases usually have a pretty small audience, so seeing them on disc is always a nice treat. Despite the small release number, it’s still getting it out to an expanded audience, and in a way that it will continue to be preserved. This definitely fell on the positive side for me. They really took their core mechanic to a polished state that isn’t common in many games, and it results in a game that feels truly unique in execution.