The Great Terminal Rewrite #409
We did a little more research on the OpenGL version results from the survey, and figured out that all of the 2.1 users are macOS users. This is because Minecraft uses the compatibility profile, which on the macOS driver, forces the version to 2.1 or lower.
So, we are basically implementing the VBO renderer for the macOS users (and whoever else comes along with a 2.1 card, though that's very unlikely).
This is a backport of 1.15's terminal rendering code with some further improvements. This duplicates a fair bit of code, and is much more efficient. I expect the work done in #409 will supersede this, but that's unlikely to make its way into the next release so it's worth getting this in for now. - Refactor a lot of common terminal code into `FixedWithFontRenderer`. This shouldn't change any behaviour, but makes a lot of our terminal renderers (printed pages, terminals, monitors) a lot cleaner. - Terminal rendering is done using a single mode/vertex format. Rather than drawing an untextured quad for the background colours, we use an entirely white piece of the terminal font. This allows us to batch draws together more elegantly. - Some minor optimisations: - Skip rendering `"\0"` and `" "` characters. These characters occur pretty often, especially on blank monitors and, as the font is empty here, it is safe to skip them. - Batch together adjacent background cells of the same colour. Again, most terminals will have large runs of the same colour, so this is a worthwhile optimisation. These optimisations do mean that terminal performance is no longer consistent as "noisy" terminals will have worse performance. This is annoying, but still worthwhile. - Switch monitor rendering over to use VBOs. We also add a config option to switch between rendering backends. By default we'll choose the best one compatible with your GPU, but there is a config option to switch between VBOS (reasonable performance) and display lists (bad). When benchmarking 30 full-sized monitors rendering a static image, this improves my FPS[^1] from 7 to 95. This is obviously an extreme case - monitor updates are still slow, and so more frequently updating screens will still be less than stellar. [^1]: My graphics card is an Intel HD Graphics 520. Obviously numbers will vary.
- Write to a PacketBuffer instead of generating an NBT tag. This is then converted to an NBT byte array when we send across the network. - Pack background/foreground colours into a single byte. This derives from some work I did back in 2017, and some of the changes made/planned in #409. However, this patch does not change how terminals are represented, it simply makes the transfer more compact. This makes the patch incredibly small (100 lines!), but also limited in what improvements it can make compared with #409. We send 26626 bytes for a full-sized monitor. While a 2x improvement over the previous 58558 bytes, there's a lot of room for improvement.
This uses the system described in #409 (or at least, how I understand it), to render monitors in a more efficient manner. Each monitor is backed by a texture buffer object (TBO) which contains a relatively compact encoding of the terminal state. This is then rendered using a shader, which consumes the TBO and uses it to index into main font texture. My OpenGL skills are pretty much nonexistent, so the implementation of this is no doubt terrible. However, the performance so far is outstanding compared with the current VBO renderer, as it transmits significantly less data to the GPU.
This uses the system described in #409, to render monitors in a more efficient manner. Each monitor is backed by a texture buffer object (TBO) which contains a relatively compact encoding of the terminal state. This is then rendered using a shader, which consumes the TBO and uses it to index into main font texture. As we're transmitting significantly less data to the GPU (only 3 bytes per character), this effectively reduces any update lag to 0. FPS appears to be up by a small fraction (10-15fps on my machine, to ~110), possibly as we're now only drawing a single quad (though doing much more work in the shader). On my laptop, with its Intel integrated graphics card, I'm able to draw 120 full-sized monitors (with an effective resolution of 3972 x 2330) at a consistent 60fps. Updates still cause a slight spike, but we always remain above 30fps - a significant improvement over VBOs, where updates would go off the chart. Many thanks to @Lignum and @Lemmmy for devising this scheme, and helping test and review it!
Given that most of the rendering changes have been merged, it's probably worth beginning to look into what changes can be made to our network code now.
I guess I'm thinking the following steps:
Having talked with @Lemmmy, I'm going to close this for now.
I really want to add incremental updates in the future, quite possibly using this design. However, we've made several pretty major optimisations to the network code (reducing traffic by at least 50%, often 75-80%), so this is less of a priority.