
*TLDR, another very technical and dry post about performance ahead! I'm playing with different techniques that could potentially double draw distances. Still not sure when it will be done*
I'm still busy on these huge performance changes and, well its been a ride to say the least!
Since my last post, Cubic Worlds released so I gave their demo a try and I have to say, their draw distance is impressive. It made me realise I must be doing something fundamentally wrong and so I went back and checked over techniques I had tried in the past to see if I was missing something.
Turns out, I did do something wrong when I was testing an early technique around instancing.
What I explained in my last post around graphics cards being better around processing large chunks of information, where a bigger chunk is quicker to render than 4 smaller chunks, can be leveraged in a unique way. Say you want to render, 100,000 cubes. Your graphics card will struggle with this because for each cube, it needs to do things like make sure its mesh, texture, materials etc are ready to be used.
Hence why combining chunks saves time because it will reduce the time spent preparing for each draw.
However if you utilise something called instancing (a common technique already used extensively in Aiyana and most games) then you effectively tell the graphics card, "I am about to render a lot of the same thing, skip all your usual checks".
So what I'm now doing is instead of expressing the world as complex meshes, it is expressed entirely as cubes and rendered using instancing.
I had tried this in the past but it was so long ago I'm not sure what I would have missed to dismiss the technique. For example I have a technique called Greedy Meshing which lets me scan a chunk and combine the same blocks into the same face, which I was able to rewrite to combine into the same cubes instead of faces. Perhaps my first tests of instancing didn't have greedy meshing yet. Anyway, doing this cuts down on how many cubes are needed to render very drastically and combining this with the Occlusion Culling technique mentioned in the last post, worlds can be expressed in a sensible number of cubes.
However it now means that Occlusion Culling was a bit primitive since it was running on sections of 16x16x16 blocks, but since I'm not trying to combine into a mesh and instead can link specific cubes to an Occlusion group, it means I could rewrite OC to be more dynamic and thus more efficient. So instead of arbitarily trying to join 16 block sections together, it can now scan to the exact height of each cave and so entire cave sections can be disabled instead of partial sections.
So now I can express worlds as a sensible number of cubes and it has exposed some interesting other problems to solve! For example, this means I'm now processing and trying to prepare 100,000+ cubes for rendering every frame. Which is just a Lot of data to be moving around and since I'm working in Unity+Burst it means I can't use traditional techniques for storing/accessing large arrays of data and had to get creative with pointers to get Occlusion Culling to even work.
Once all this data was prepared in an effecient way, I then need to send the changes to the graphics card and that would take a bit of time so I looked into how to improve this and found that Unity has a new-ish technique for writing directly to memory on the graphics card, but to utilise it I had to rewrite how everything in the game that uses instancing (a ton of things) processes their memory.
Now that I have done that, it turns out that by writing to GPU memory directly requires really careful control of when/how you write that data, otherwise your CPU sits and waits on the GPU and vice versa. Which is what I'm trying to solve today.
So its been a bit of a trip! I've rewrote a lot of things and hopefully now the end is closer in sight. Its hard to predict how long this will take since each time I turn a corner, I've had to learn something new in order to solve a problem I didn't expect. I've also not had as much time to work on Aiyana this past couple of weeks but surely now its not That much more work to get this working... right? (On a serious note, it does feel like I'm getting close with all this).