The best GPU vector rendering library I have seen is https://sluglibrary.com/. The principal use case is fonts, but it appears that the underlying mechanism can be used for any vector graphics.
I think the issue with slug is that it requires a fair amount of pre-computation. So it's great for its use case: rendering glyphs, especially on surfaces in games.
Random fact - the artwork was by Tom Ashton - previously the guitarist for The March Violets, also performed with The Sisters of Mercy, and went on to Clan of Xymox.
Also, this was the project I worked on before BRender - covered in another thread here.
I really need to thank you for that game for me it was ... amazing. I still have the original box and I clearly remember been fascinating about how on earth it was possible to pack such a game in a couple of floppy disks. Thanks man.
Something I missed above is that either prior, or concurrently, there will be performance experiments to check that things are staying sane, but these do not contribute to the later software development (except as a reference) and are likely not consistent with each other. The deliverable at this point is only documentation - getting it good as possible without any concern for impact on existing implementation. The goal is to get as far up the slippery pole as possible - inevitably things will slide back over future version iterations.
The starting point for BRender was a sequence of software rendering experiments that grew from 'never doing it like our hand coded asm real mode x86 renderers ever again'. There were various diversions, eg: an achingly beautiful plane sweep that only rendered the visible parts of each output scanline, whilst murdering the cache so comprehensively that there are likely still lines waiting to be filled even now. Fortunately, to get the FX Fighter team going with something stable whilst debugging continued, I knocked up a Z buffer implementation, and was given a sharp lesson on caching when it blew all the previous attempts away (notably with consistency of performance).
Arriving at this point we figured there might be a product in it and looking at our own interaction with other libraries, it was clear that a manual was key to this. If I remember correctly, the API was a negotiation between myself proposing designs, and Crosbie Fitch documenting it - pushing back with ways to make things easier to explain.
It worked out very well, and we took it into later Argonaut hardware projects. The hardware guys had enough tools to do frame capture and replay from various games/apps at a low level, so were not desperate for a full software stack. The clients had very particular views about how APIs should look, depending on planned uses, in house style, compatibility etc. We would negotiate the API documentation back and forth - including lots of sample code.
This sample code was important, (and BRender would have benefited from more of this). I took lots of real use cases, then wrote proper code to implement them against the proposed APIs and included them in the docs as tutorial and example code. Importantly - they were a representative sampling of the anticipated uses (not just the easy ones), they were not 'handwavy' and included all appropriate resource management and error handling, and they had to read well on the page. As the API negotiation continued, so the examples and tutorials got updated.
This process also had the benefit that we only started investing in client specific software development once the project had got enough momentum (typically committing hardware NRE).
This is what I love about HN. Somebody quotes an almost 30 year old readme file, and the person mentioned in the readme chips in to tell the full story. Thank you Sam!
It is! Although what I missed out from above is that whilst the API and it's documentation is the deliverable - we would, to the best of ability, try and minimise risk whist developing it. Eg: by doing small performance experiments, drawing on prior experience, thinking about the evolution of resources within the API whilst writing samples, and looking at how other APIs handle similar things (but be careful - they may have had to perform heroics to achieve their behaviour).
Whilst the official progress is top down, the duck's feet are working hard feeling along the bottom to check for obstacles.
I feel like sprints should be more relaxed: "Oh you might bleed over into the next week? Don't stress, that's fine. Can we help you get unblocked and how?"
Just because you say you want it in 2 weeks does not make it so. Don't over promise, you will be severely disappointed. Software breaks, it does not care for deadlines.
This how my team functions. It's such a refreshing work experience. Estimating work is hard, we shouldn't be punished or feel bad when we're off a bit.
That's kind of the way I write APIs, albeit at a smaller scale. First write the code of how I want to use the API, then write the the actual API. I remember a talk from the developers of the Python requests library mentioning this same process.
Yes, I do this too...its a different thing when you are talking about your own insular project or something at a smaller scale.
The thing I was talking about was larger scale projects like the ones mentioned by the author (of the sort I work on at my day job) where you have teams of stakeholders and outside influence combined with a desire to release rapidly in an iterative form.
Software these days is just done differently in those contexts...we can't slow down enough to do what was detailed above...I just wish the world was sorted in a way or slowed down enough to do REAL engineering.
I kinda work this way on my personal projects: first I come up with a rough idea of the UX, and only then do I start implementing it. The desired UX ends up driving the decisions about the implementation details and technicalities — not the other way around as it often happens in much of modern software. And I, of course, disregard the time component.
I seem to remember BRender being one of the highest-performance software renderers of the day. I used to talk to Jez on Usenet and he offered me an interview at Argonaut (I was 16 I think) after I showed him my hand-coded x86 renderer. I don't think I was doing any real mode by that time, though. I can't even remember what effect running in real mode would have outside of the memory limitations? You can still access the full 32bit registers, right? (been 25 years since I coded x86).
There were three similarish software renderers around at that time, BRender, Canon Renderware (Adam Billyard), and Rendermorphics RealityLab (Servan Keondjian). There were also some renderers out of the demo scene that were definitely faster (but often with perf. related limitations).
The code was mostly C, with some protected mode x86 for inner loops. Prior to that point, all our PC games had been real mode x86- and BRender was a result of moving away from that.
Yeah, I was coming from the demo scene side, although my code ended up in an Eidos game.
I dug into the released BRender source until I found the inner loops, then I "Nope!"'d all the way out and remembered why I never went back to assembler.
Thanks for the memories. I'm glad the code survived all these years until it could be released.
Anyway, from my recollection, it was a case of me wanting to produce a C++ API/wrapper around the C API, and realising that the extant documentation wasn't quite sufficient for me to do so (to fully grok what went on underneath the C API enough to produce a C++ wrapper). Therefore, producing a more thorough technical reference manual seemed to me to kill 2 birds: I'd obtain a sufficient understanding, and so would the customers. Thus although Jez was right that the manual came first, the process of producing a more thorough TRM gave rise to Sam's observations.
It should fit, as you said, but the last time I tried it the VHDL front-end for Yosys was not up to it. That might have changed as it was a few years ago.
It is (I think) much better now - it is ghdl as a plugin synthesising to yosys IR. The nightlies from https://github.com/YosysHQ/fpga-toolchain have it all ready to go.
Fun fact - I wrote some customised firmware for the Tigon2 AceNIC ancestor I n this tale - (video stream offload). The original MIPS firmware solved the lack of mul/div ... by carefully writing code that never emitted those instructions. That caused a few head scratching moments!
Also, an interesting feature of this architecture was that it had no interrupt mechanism. There was a hardware ‘event’ bit register, and a special instruction to convert that it a ‘most important event’ offset into dispatch table. This made all race/concurrency issues go away - and the code was easy to reason about.
I was working on 3D rendering and games around this time - pretty much all the PC cards were burdened with terrible CPU->GPU interfaces. The handshaking, setup calculations and register wrangling was such that below a certain triangle size, it would have been quicker for the CPU to just draw the pixels itself. Some cards (Um, Oak?) required per-scanline setup.
I got one of these cards - confirmed it was indeed hella fast (even for large meshes of small triangles), and then dropped into SoftICE a few times, winding up at this code:
My thoughts were - "Wow, somebody gets it!" - Very tight triangle setup, and a simple PCI register layout that means that the setup code just writes the gradients out to a block - the last write pushes the triangle into the huge on-card FIFO.
That performance, along with the simplicity of glide, made it a a no-brainer to drop all other card support and focus on that exclusively.