Nova Update: April 2018

Oops, this one was a little late. We're all going to have to find a way to deal with that.

What happened in April? Fun things! The render graph, which I've been working on for a couple months, is coming together. Get hype!


As the render graph became more complete, it became obvious that Nova needed a material system of some sort. It needed a way to specify which resources (textures and other data) were bound to each shader.

I ended up going with a simple dictionary-like thing. You use the uniform names from your shader and assign the name of a resource to each uniform. I wrote up a wiki page that gives you an overview of this system.

Putting it all together

With the render graph in place, and the material system in place, Nova should finally run!

Except there were a number of bugs and errors, which is to be expected when one writes a large block of code without running it. A few days of bug-fixing, and we finally have some images, including one very nice image of the GUI!

That tweet was also retweeted by the offical Vulkan Twitter acount, which isn't a huge achievement but it did give us some nice publicity.


The GUI is pink! Oh no! I hadn't made the code to get textures working yet - so that's what I worked on next. It was kinda painful; since the way that Vulkan handles textures is very different from how OpenGL handles them, but after a couple days I got them sorted. Behold!

That's cool. The render graph is now mostly working!

You'll notice that there's no text on the GUI. Nova is issuing the draw call for the text, but nothing renders because the font is using the GUI texture atlas, not the font texture atlas. This issue will be solved when I get virtual textures in, but for now I have to make a new material for GUI text. I was hoping I wouldn't have to do that, but here we are.

Swapchain Management

In OpenGL, everything relating to the swapchain is handled by the driver. You write to framebuffer 0 from a shader, tell the windowing system to swap the backbuffer with the frontbuffer, and there you go. In Vulkan, however...

If you want to write directly to the swapchain, you have to create a framebuffer for each swapchain image. A framebuffer needs to be created with a reference to the renderpass that uses it, so I would have had to create (and manage) one framebuffer per swapchain image per renderpass that outputs to the swapchain directly.

That doesn't appeal to me. Instead, I'm adding a step after rendering is completed to copy the data from the texture named "Backbuffer (which is created by the render graph) into the current swapchain image. No more need to deal with a ton of framebuffers! Yay!

Unfortunately, I had originally set up the code to assume that there was only one swapchain image...which is in no way correct. Changing to the way I want to do this has proved less than trivial, as a quick glance at Nova's commit log will tell you. Still, it's happening.

The Future

Where does Nova go from here?

The render graph still needs more testing. I've only seen the GUI rendered with it - will it handle chunks? It better! There's definitely more work to be done with the render graph to ensure that it's robust enough for usage by shader devs at large. I know a few Minecraft shader devs - they will take whatever system I give them and push it far past any reasonable limits. It's my job to make sure pushing it that far doesn't break it.

As part of that, I need to get the scripting system set up. The scripting will tie in with the render graph - you'll be able to write Lua scripts that are executed before, during, and after each render pass. This will let shader devs perform work on the CPU, such as calculating custom uniform values or only running certain passes every few ticks. The scripting system will be what really pushes Nova past other Minecraft shader implementations.

I'm not going to stop there, however. After scripting comes virtual textures, which is essentially a way to load a texture in at runtime in a memory-efficient way. This technology was originally developed by id Software for Rage, then improved for Wolfenstein: The New Order and DOOM 2016. It's also shown up in Far Cry 4, Battlefield 3, and associated sequels. This will vastly change how textures work in Minecraft. Rather than loading all textures into a single atlas texture, they'll be loaded as needed. If you only have one type of block on screen, only one block texture will be loaded. This will vastly decrease memory usage, allowing for larger resource packs than are currently feasible. Combined with texture compression, this may make 2k resource packs usable by consumer graphics cards

This is all great, but Nova will still be running on a single core. Sometime around virtual textures, I'll be implementing a task-based threading system. This will allow Nova to scale with the available CPU - buying a processor with more cores will make Nova faster. It should also vastly reduce frame time, further improving what will already be a very solid renderer.

I haven't forgotten about Forge either. The plan is still that, once Forge for Minecraft: Java Edition 1.13 becomes available, Nova will move from modifying the Minecraft client directly to injecting through Forge. I fully expect that to be absolute hell, given how many changes Forge makes to Minecraft. There's a possibility it won't be worth the effort - although, considering the immense value the Forge provides to Minecraft modding, that's pretty unlikely.

And that's just what's on my plate! In the last couple of weeks Nova has had a couple people start working on setting Nova up for CI/CD (Continuous Integration/Continuous Delivery). There's a number of benefits to CI/CD, including that Nova could be compiled on a server somewhere and not on an end-user's computer like it is now. Licensing with the Minecraft client prevents us from distributing more than the C++ part of Nova in a per-compiled format, but once Nova moves to Forge we should be able to distribute the whole thing as a compiled Forge mod, which Forge will then inject into the Minecraft client. That's where the fun begins.

In closing...

That's where Nova is now, and that's the next few major tasks for Nova. As always everything is subject to how much time I have and how many other developers are working on Nova at any given point in time - you'll notice that I haven't given any estimates for when things might be done - but all those big tasks are probably a few months of work each for a single developer. If you're willing to help, we could deliver features much faster!