Happy New Year – Progress Report!

Been over due a blog post as usual but lots of work has been going on in the background, mainly on my 2d sprite renderer that I’m using to render the editor and all the particles. Made a huge amount of progress with it and learnt a lot more about Vulkan and graphics coding in general. I think this will pay off as my ultimate goal is to have all the particles get updated in a compute shader.

So last year was the last year that I was going to work on web sites (my main source of income). So happy that I’ve now moved on from web dev and will be persuing TimelineFX and other projects full time so expect a lot more updates coming this year.

So as mentioned the last 6 months when I had time I worked mostly on my renderer. I realised that I reached a point in the editor and particle library that I needed the renderer to be more flexible and able to help me experiment with different shaders and such. Here’s some of the things I worked on to help with that (a little bit technical):

Rendering Set Ups

It’s much easier now to set up a rendering pipeline where you can specify which render targets to draw to and in what order. I guess it’s basically a scene graph of some sort where you can set up dependencies between the different render passes. It’s also much more optimised now, I was doing things before that just weren’t necessary like compute shaders in there own command buffers and having to syncronise with the renderpass in another command buffer. Compute shaders can just be in the same command buffer with a pipeline barrier to make things a lot more straight forward.

Additionally everything used to render to a render target before being rendered to the swap chain but now you have the option to just render straight to the swap chain if you want for more flexibility in simpler applications/games. Setting up a scene for rendering (I call them command queues as they’re all recorded in a Vulkan command buffer) looks something like this:

Memory Management

My original memory management was very straight forward in that I would create a new buffer for every single allocation. This isn’t a great way of doing it especially because GPUs have a limit on how many allocations you can assign at one time. I’ve now implemented much better memory management where large allocations are created and then ranges are set up within those larger allocations. If a range runs out of memory then it will automatically be resized. You should of course make your ranges big enough in the first place but while you’re working on a program you don’t really know much much memory you need so it’s useful to have this feature.

It also outputs a debug memory report when the program ends which lets you know a lot of details about memory usage including how many times allocations were resized so you can size your allocations ahead of time to avoid that.

Instanced Rendering

My first approach to drawing lots of sprites was to use a compute shader to build the vertex buffer which would then be sent to the vertex/fragment shader for rendering. This was ok but I kept hearing about instanced rendering so thought I’d give it a go. I heard mixed things about it for rendering small instances like quads but actually they work extrememly well. It’s faster then using the compute shader which is great, always nice to get a speed boost plus it also uses less memory as you don’t need a vertex or index buffer at all, all you need as a buffer containing the position, size etc of each sprite.

You upload this buffer each frame and then you can just build the quad inside the vertex shader based on the gl_VertexIndex. Rather then call VkCmdDrawIndexed you simply call VkCmdDraw and send 6 vertices along with the number of instances that you want to draw.

At some point I’ll release the render as open source on github.

 

There’s still a few more things that I’d like to tidy up this month but overall I’m very happy with the render, then it will be back to the next Alpha vertsion of the TimelineFX editor where I’ll be working on stability!