Greetings!
I would like to help with optimizing this SVG renderer, if you're interested. To this end, I've written a rather lengthy outline. I hope you're ready for a lot of reading.
If I use any terms you are unfamiliar with, and you're unable to find what you need with a quick google search, then feel free to contact me, and I can try to help you find the information that you need.
Just to warn you: Because I typed this in Notepad, the formatting might appear kind of wonky on the website.
=========================================================================================
OUTLINE FOR FASTER, MORE POWERFUL RENDERING OF VECTOR GRAPHICS IN GAMEMAKER STUDIO
Typeface used: Lucida Sans Unicode, 8pt. Manual word wrap.
=========================================================================================
GPU Path Rendering:
https://developer.nvidia.com/gpu-accelerated-path-rendering
OpenACC:
https://developer.nvidia.com/openacc
=====================================
SECTION 1: NOTES OF CAUTION AND RELEVANCE
And hopefully, interest and utility.
=====================================
1.1- Because GPU Path Rendering is a non-standard OpenGL extension...
--- It may not work with all device drivers or graphics vendors.
--- --- It also might not work with DirectX.
1.2- Things you might not know about Scalable Vector Graphics:
--- Because it is easily possible to combine XML and HTML, SVGs can easily integrate into HTML applications.
--- SVGs are capable of some rather complex visual effects...
--- SVGs can also be used to make animations, and even self-contained 3D scenes.
--- There have also been experiments in using SVGs as textures for 3D environments.
1.3- OpenACC makes parallelization and GPU Acceleration easy, but there are some caveats:
--- OpenACC will only work when the program is compiled to YYC.
--- OpenACC in GameMaker also requires the ability to insert C++ and/or conventional C directly into your GML.
--- Lastly, OpenACC requires a supported compiler. Oof.
--- OpenACC, right now, is only suggested as a shortcut to replace a lot of the remaining CPU workload.
===============================
SECTION 2: RENDERING OPTIMIZATION
It's time to go Full Throttle.
===============================
2.1- Begin with Front-to-Back Rendering for all layers (Reverse Painter's Algorithm).
--- If a layer isn't completely opaque or has a non-standard blend mode, do not cull the layer below.
--- Once all layers are rendered, switch to Back-to-Front Rendering to calculate properterties from layer blend modes.
--- Also remember to implement Z-Buffering and the Warnock Algorithm.
--- --- This is necessary if you are using *many* layers, and if any shapes happen to overlap.
2.2- Try to make use of Coverage Buffering.
--- IIRC, these are like Stencil Buffers, except with Anti-Aliasing.
2.3- Parallelization and Low-level Optimization
--- If the capability exists, then be sure to mix as much C and C++ as possible into your GML.
--- Always remember to multithread, and try to slip in some OpenACC.
--- Extensions exist on itch.io for Instance Pooling and for using Vectors. Maybe those can help?
2.4- Divide the on-screen rendering into Tiles, and on subsequent frames, only redraw the Tiles which have been updated.
--- Further subdivision into Scanlines adds another layer of optimization:
--- --- On top of only *Tiles* which have changed being redawn, *Entire Scanlines* will behave likewise.
--- --- --- While a Scanline can only cover a small strip of a single Tile, it can still cover multiple Tiles.
--- --- Scanline-based rendering can also be used as a Visibility Determination and Culling mechanism.
--- --- Furthermore, Scanline-based rendering lets you perform some pretty awesome effects, a la the 16-bit era of consoles.
--- --- --- The Scanline effects can be called *before* Rasterization occurs, which would allow not one, but two things:
--- --- --- --- Soon-to-be-hidden pixels can skip being drawn.
--- --- --- --- Soon-to-be-revealed pixels can be drawn even if they weren't originally visible.
--- Tiles which have already been drawn get converted into raster graphics and cached, enabling them to be quickly redrawn if needed.
--- --- Tiles can be built using Indexed Color, enabling the colors to be easily changed.
--- --- Tiles can also be flipped, rotated, and even broken down into even smaller tiles, making for even more reusability.
--- --- --- It's also possible for a single tile to appear in multiple places on screen.
--- --- Tiles which have been cached should be saved and loaded asynchronously for the best performance.
--- --- --- And of course, everything should be done in a separate thread, if possible.
==============================================
SECTION 3: GRAPHICS DATA SIZE AND DECODING OPTIMIZATION
SVGs are already small, but they can be even smaller.
==============================================
3.1- Use Binary XML and the SVG DOM to "bake" the SVGs:
--- Not only does this result in smaller files, but also faster execution; especially when using both C and C++.
--- Can use compression algorithms on the output bytecode to make them even smaller.
--- Don't forget to sneak some OpenACC into the script! Much faster decoding, that way.
3.2- Raster-based Detail Textures can be used to fill in highly noisy details that Vector graphics are ill-suited for:
--- Detail Textures are usually monochrome, but can also be made in indexed color.
--- Because Detail Textures often correspond to materials, they are best used in a tiled format.
--- SVGs can easily function as clipping masks, which prevents detail textures from being drawn where they're not supposed to.
--- Detail Textures do not need to be high resolution to produce fine details, as has been demonstrated by Unreal.
--- --- If you're ever feeling ballsy though, you can go ahead and make a Detail Texture that uses a Signed Distance Field.
=================================
SECTION 4: PATH-RENDERING SHORCUTS
And if all else fails, try cheating.
=================================
4.1- Convert the SVGs into Signed Distance Fields, with Summed Area Tables:
--- Faster on the rendering side than pure path rendering, but uses CPU time to set up.
--- --- Signed Distance Fields are useful for arbitrary scaling, and at angle or aspect ratio.
--- --- Summed Area Tables have a lower memory footprint than Mip Mapping, and greater flexibility in downscaling.
--- Use RGBE (E is for Exponent) format for floating point precision (and a small file size).
--- --- The use of three color channels can preserve sharp corners, which is more difficult to do.
--- Unfortunately, there is no hardware-accelerated implementation to generate them quickly. As such, this must be done through software.
4.2- There are tradeoffs between producing these SDFs/SATs at Run-time, and making them at Compile-time:
--- When done at Run-time, it has the potential to use a lot of CPU time and/or Memory. But here are *some* possible solutions:
--- --- OpenACC and Multithreading are here to help, as always. But GMS makes it difficult to Multithread.
--- --- Could also try writing most of the heavy lifting directly in a mix of C and C++, instead of relying solely on GML.
--- --- When SVGs are processed into SDFs w/ SATs at Runtime, they can be cached locally for later use.
--- --- --- This means transcoding your SVGs asynchronously may not be a bad idea.
--- When done at Compile-time, the problem becomes file size. As Raster graphics, SDFs are inherently much larger than SVGs.
--- --- Fortunately, it is possibe to optimize the output graphics data so that it is much smaller.
--- --- When you have the SVGs pre-processed, it becomes potentially *orders of magnitude* faster.
--- --- --- This is because you are able to skip using Path Rendering outright.
--- --- Lastly, doing it at Compile-time means that you can take as long as you need, and the end user doesn't need to wait.
================
CONCLUSION
================
Thank you for taking the time to read my outline, and feel free to contact me on Discord or Telegram.
Unless I did something wrong, you can easily view the necessary information on my itch.io page.
Good hunting!