> after twenty years OpenGL was starting to looking like a bad abstraction: it didn’t provide the capabilities application authors needed [...] The Vulkan project was a long-running effort to define a better, more modern, abstraction
For someone who knows nothing but triangles=good, why OpenGL is a bad abstraction and how Vulkan avoids the same problems?
I'm by no means an expert, but my understanding is that OpenGL's API is designed to abstract away details of the underlying hardware, while Vulkan's API is designed to expose the details of the hardware.
When OpenGL was designed, the thinking was that graphics programming is hard, and so the API should do the heavy lifting and make the application's job easy. It turns out, though, that graphics programming is so hard that the majority of folk tend to use even higher level graphics libraries to write their applications.
The folk writing those graphics libraries want to make their libraries as optimally performant as possible, and the abstract nature of the OpenGL API stands in the way of doing that. They would rather just directly access the hardware. Vulkan is an API that gives that direct access, within the limitations of running in an unprivileged userspace process.
I still wish there was some kind of middle ground between OpenGL and Vulkan though, as an aspiring indie dev who’s making a 3D game without using Unity/Unreal (The reason for this is that for my game I need at least tens of thousands of simulated AI agents, and conventional gameobject systems aren’t designed to do this performantly.)
The Metal API from Apple seems to be just the right abstraction for general graphics programming, though it sucks that you can only use it on Apple devices. Maybe SDL_gpu can take this role once it’s finished, but till then I’m toiling away with Vulkan… yeah it’s still better than OpenGL, but its usability can definitely be improved. Maybe I should have just gone to DirectX 11… since the drivers there are ridiculously optimized.
I don’t want to use Rust though, I want to use C++. (And before all the Rust afficionados immediately jump at me, I just feel much more productive in C++ than Rust when doing graphics programming.) I’ve heard that Google has a C++ webgpu library in the works, but I wasn’t sure if it was stable enough to actually ship games in.
I've had a decent experience with bgfx (https://github.com/bkaradzic/bgfx). It is solely a rendering library (no input, physics, sound, etc). It operates a layer just above a native rendering library, such as DirectX, OpenGL, Vulkan, Metal, etc - those are the "backend renderers" that bgfx uses.
Though I have my complaints about it, I think bgfx gives a good powerful-but-not-too-complicated abstraction over graphics programming; for some design info, see: https://bkaradzic.github.io/bgfx/internals.html
I am also writing a game engine, also because of the gameobject issues, also doing tens of thousands of simulated AI agents. In my case they are GPU-accelerated and I'd guess you are doing something basically similar even if it's CPU-based.
Would be interested to discuss architecture as there aren't many of us out there and not much of a shared knowledge base. I looked for contact info in your profile but didn't immediately turn it up.
Have you looked at either Raylib or SFML? Both are somewhat high-level graphics abstraction libraries, but neither are anywhere near the weight or functionality of a proper game engine.
No, I’m making a 3D game that’s going to lean into heavy shader usage (probably going to implement either deferred or forward clustered rendering), and also might have to potentially use compute shaders for some expensive geometry-querying tasks.
> at least tens of thousands of simulated AI agents
Are you planning on displaying all/most of them every frame, or just to control that many of them, then draw those nearby/visible?
If it's the former (but how exactly?) then perhaps Vk is the way to go, if the latter, then it's hard to see how Vulkan vs OpenGL is all that relevant here.
Many of the enemy entities (which I’m expecting to be around the ten-thousands in the late portions of the game) are going to be visible on-screen, since most of them are going to be flying above the ground and only the terrain is going to hide them (no big architectural structures on the map obstructing them). And I would like to create lighting effects when they explode, which would require huge lighting counts.
The AI for the flying enemies isn’t going to be too complex, it will probably going to be some variation of boid simulation. However I still expect this to be computationally intensive, particularly when it comes to querying nearby entities and terrain. I am expecting some of the expensive geometric querying can be moved to the GPU via compute shaders.
The reason for using Vulkan instead of OpenGL was more of a pragmatic one: I’ve heard that OpenGL drivers can be hilariously bad on Windows, when it comes to both conformance and performance. Vulkan seems to be better in that respect, since both Nvidia and Amd has incentive to develop decent enough Vulkan drivers since some high-profile AAA games use it. Also, it is a pain in the ass to debug issues in OpenGL, and Vulkan is at least better than that.
Right, there's no reason to discard a game engine just because its most common usage patterns are inappropriate to your needs. Even if you do need to draw a zillion objects on screen, any engine will let you create your own mesh and feed that to the renderer.
IIRC the game From the Depths does this, being a game where you create ships using thousands of voxels. Using gameobjects for everything just would not have worked
There can still be and there already is plenty of middle grounds between OpenGL and Vulkan. Like Skia, OpenGL etc... They can just be implemented on top of Vulkan. Vulkan is just an API provided by GPU vendors like Nvidia, AMD etc.. to expose the capabilities of their hardware and not worry about accommodating all the edge cases of various graphics use cases in their bloated mess of "drivers".
If you’re making a 3d game with a customed designed renderer, then what should I use instead of Vulkan though? (The real answer for this is DX11, but assume I care a bit for cross-platform and relatively less vendor lock-in.) Skia is only for 2D graphics, OpenGL has shit drivers on Windows, and WebGPU is still work-in-progress and isn’t something you should depend on just yet. Between DX and Vulkan, there isn’t really that much choice.
You can still use OpenGL. Just not the vendor provided drivers. They are indeed horrible. There are libraries like:
* ANGLE ( https://github.com/google/angle ) - An OpenGL ES implementation with Direct3D 9, Direct3D 11, Desktop GL, GL ES, Vulkan and Metal backends. This is what we used to use for shipping our Qt 3D application, that used a bunch of OpenGL Shaders. We used to get bug reports about various shaders not working properly on various hardware. After switching to this, all those bug reports vanished.
* Zinc ( https://www.supergoodcode.com/do-not/ ) - A more recent, OpenGL implementation on top of Vulkan. I haven't used this one yet. But they are making a lot of progress and it is almost as performant as vendor provided OpenGL Drivers these days. So if I ever have to ship a desktop app, needing opengl, I'd strongly consider using this.
I think Ogre3D and Metal are two really different things though…
By the way do you know how is the current status of the next version of Ogre3D? I’ve heard they were doing a complete overhaul (with a new much performant render system), but I’m not sure if it was actually finished.
Vulkans ease of use is an explicity non-goal I think - it's benefit comes from exposing the maximally flexible set of APIs to control the underlying GPU hardware, which is in direct opposition of a simple "hello world".
The idea is that you use high-level APIs built on top of Vulkan (usually engines like Unity, Unreal or Godot) that then leverage the underlying hardware.
I still think that there should be some room for rogue developers who want to make “weirder” games that need specific technical decisions that you can’t make inside an existing game engine. Unity and Unreal all assume that the world you are making is generally made up of static environmental objects, and are hyper-optimized for that use-case both in terms of workflow and performance optimizations. But for types of games that emphasize simulation, procedural generation, or user creation, these assumptions might not hold and custom engines might serve them better. (Games that come to mind are No Man’a Land, Dreams, Factorio, They Are Billions, etc…)
It's still work-in-progress though, and people who are developing games right now shouldn't gamble on it. I would rather want to stick with something that has been for at least 5 years and has successfully shipped multiple games, so that's why I'm using Vulkan even with all its problems. (Maybe I should have used DX11 though, if I was seeking for even more stability.)
People were teasing the idea of a good-enough Metal-like API on top of Vulkan that takes care of the pain points since the early days (most notably this article: https://aras-p.info/blog/2015/03/13/thoughts-on-explicit-gra...), but so far, nothing has materialized.
> do you think vulkan will progress into being easier and easier to use?
I don't think that is the goal for Vulkan, nor should it be. Vulkan is a low-level, high-performance API that can be used as the backend for high-level, high-performance libraries and frameworks.
> is it mature enough?
Mature enough for what? It's mature and stable enough that you can develop high-level libraries on top of it. wgpu [1], for example, has a Vulkan backend.
Vulkan may be easy to use one day, but it will probably be because you are "writing vulkan" but actually using an impressive set of libraries, languages and other tooling that do stuff for you that you don't want to do.
guess it depends on how specialized to vulkan you mean. Like, Aras in this article even mentioned BGFX as a potential abstracted library, and I'm 99.9% certain that it supports vulkan now. But you can certainly argue that with BGFX you're not "writing vulkan".
But if you wanted something that was "vulkan but without 1000 lines to make a triangle", that's what Open GL was trying to be 25 years ago. So Vulkan naturally diverged from that model after seeing the weaknesses. I'm unsure if there's any maintained package trying to wrap this stuff; that's something a graphics engineer would end up doing anyways.
There's a point to make which is that most people don't probably have problems writing Vulkan code, but shaders instead (that's unless you already know OpenGL). For Vulkan you have many good bindings already in different languages, but then you get into actually writing shaders which requires completely different programming mindset -- everything runs in parallel by default. All your algorithms have to be divide and conquer, so say bye bye to imperative style accumulators. The concepts might be hard to grasp unless you know your way around functional and array programming languages.
imo, it’s unlikely that it will get much easier directly. if you’re interested in getting into GPU programming, i’d still recommend it. i know it can be daunting at first - the API spec is huge, and there are lots of things to get your head around. ultimately though, the concepts are not exotic or hard to understand. it’s certainly no more difficult than learning to program a regular computer :)
Damn, though the hardware of the GPU is a lot much weirder than what you’re used to with the CPU, and don’t let me even get started about CPU-GPU memory transfers…
I kind of think of OpenGL vs Vulkan like Java vs C. OpenGL tries to help you like Java tries to help you. Vulkan, on the other hand, is like C--get it right or you will blow your foot off.
OpenGL holds a lot of implicit state in the driver. This makes writing your code a lot easier as you don't have to track all that state yourself. If you want to learn 3D graphics, I'd either start with OpenGL or some "engine" that makes an abstraction that looks a lot like OpenGL.
The problem is that OpenGL state is implicit. Every driver does it differently and there is no way to get at the state via OpenGL. This becomes an issue when you want to optimize--either for maximum performance or for maximum battery life.
Vulkan, on the other hand, makes EVERYTHING explicit. This means that every single transition, barrier, matrix change, byte transfer, etc. is all in your hands. You know exactly what is going on because you have to specify it exactly. But don't get it wrong or your pixels will get eaten by a grue. This is precisely what you want when you absolutely need to optimize your graphics, but, man, is it painful to get right.
One side benefit of the explicit nature of Vulkan carries over to concurrency. Vulkan can actually do multithreading--OpenGL has no hope because of all its implicit state.
Just to make this clear for people who don't already know OpenGL:
The public API state of OpenGL can be queried programmatically and with tooling such as Renderdoc, and it is of course standardized. The hidden state in drivers that you are talking about should only ("only") matter for performance, not correctness. Sometimes it matters for correctness when drivers are buggy, which many are. Driver quality varies widely, with mobile platform OpenGL drivers generally being the worst.
Except that OpenGL limitation isn't as bad as it seems, as most of the work not pixel related can be done by background threads anyway, with the GL thread puting the scene graph into pixels.
Also if one is feelig adventurous they can make use of switching the OpenGL context on the active thread, although I wouldn't advise that given it isn't portable anyway.
About OpenGL, here’s a long post outlining some of the problems: https://softwareengineering.stackexchange.com/a/88055/25371
While not directly applicable to the Pi where there’s no Direct3D, the GL issues are pretty much cross-platform.
Vulkan fixes that by stripping these problematic higher-level abstraction layers from the GL. Instead, Vulkan provides low-level access to the GPU hardware.
The triangles are still there usually, but the Vulkan has no GL-like high-level APIs to render them. Instead, in Vulkan we create and update GPU buffers and textures with the source data, create pipeline states (an object containing shaders, input layout, alpha blending, and quite a few other relevant parameters), and finally submit draw calls rendering triangles from buffers, using some pipeline state.
Thank you so much for that link. I have been wondering for a long time why OpenGL was relegated to the graveyard, and that post has painted the picture for me.
To be fair, in modern GL versions they fixed some of these things. In GLES 3.1 which I used a lot on Pi4 https://github.com/Const-me/Vrmac/ GPU vertex buffers and shaders worked fine, GLSL compiler in the drivers worked fine too.
However, others issues are still present. There’s no shaders bytecode, they have an extension to grab compiled shaders from GPU driver to cache on disk, but it doesn’t work. The only way to create shaders is separate compile and link API calls. Texture loading and binding API is still less than ideal.
Vulkan tries to avoid some performance pitfalls of OpenGL by requiring the application to be more explicit about what it's doing, and have the application take over responsibility for some aspects of resource management and synchronisation. This means that, if the application developers know what they're doing, they can use Vulkan to make better choices than the OpenGL driver would have made for them. Also, Vulkan skips all input validation at runtime, which reduces CPU overhead.
It's not actually “closer” to the hardware than OpenGL was though, it's just an attempt to define a more predictable abstraction. The underlying architecture of two Vulkan GPUs can be wildly different.
Absolutely, Vulkan is still nevertheless an abstraction that currently happens to fit well on today’s commodity GPUs. Maybe 20 years later we might have some changes in the hardware design space such that Vulkan might not be fit for efficient real-time rendering anymore, who knows? (I think recent advances in things like CUDA, mesh shaders, and RTX already show this and point towards a departure from “conventional” graphics pipelines…)
(If I remember rightly) the culling capabilities of mesh shaders are absolutely staggering - and the performance gains are in no way vendor restricted.
>> The underlying architecture of two Vulkan GPUs can be wildly different.
Cool. When I read that bit about exposing hardware I was afraid that meant having to query for various capabilities and adapt ones code to it, which is not an abstraction at all. I'm guessing you can ask which Vulkan capabilities are present, but not actual hardware details?
There is a large list of things you can query, like for example the number of available queues and then the types of commands supported by each queue. I think this can be considered as a hardware detail. It's like querying the execution ports of your CPU.
OpenGL done us good for a long time. Khronos (the standards maintainer) refused to advance the standard in any meaningful way since the API was based around a stateful glBegin/glEnd model.
modern graphics hardware does not work well in this model. they’re really much closer to whole other systems. you want to push the triangle data into the card in a single (or few) API calls, then submit as few draw calls as you can manage.
fun fact, OpenGL 3, originally code named “longs peak”, was supposed to upend the stateful model, and advance the API ahead of its proprietary counter part(s) - DirectX. for what ever reason this completely fell apart, and OpenGL just sort of.. stopped improving :/
we have Vulkan now basically thanks to AMD opening their more modern GPU oriented Mantle API, and valve for running with it.
Vertex arrays have been part of OpenGL since 1.1, released in 1995. VBOs since 2.1 (with extensions available earlier). glBegin/glEnd aka "immediate mode" has been "legacy" for a LONG time and were even removed in the core profiles with OpenGL 3.2.
The biggest problem with OpenGL for is/was the context model that made multi-threading almost impossible. And yes, it being stateful is a big part of it. Plenty advances and low level functionality was available in OpenGL before vulkan was released.
Vulkan also reduces overhead since its abstractions better match today's hardware and it allows excplicitly moving more calculations up front that had to be done just in time with OpenGL.
Also, it's not like Khronos (a standards body made up of industry participants) "refused to advance" but rather that different interests had different ideas - e.g. some care more about backwards compat - so that they can tell their clients that their legacy software runs on the latest OpenGL - than getting the last edge on performance so having a separate 100% performance-oriented API was probably an eventuality anyway.
Also, remember that Microsoft and Apple are/were part of Khronos too and giving these two comanies' incentives and past behaviors it would not be entirely surprising if they did their part to hold back the standard.
OpenGL direct state access (DSA) is actually part of OpenGL 4.5! You still need to set up a lot of state for draw calls, but changing little pieces of state has changed from (pseudocode, and I'm showing a worst case for pre-DSA here):
const int oldTexture = currentTexture();
switchToTexture(myTexture)
setTextureData(myRgbImage);
switchToTexture(oldTexture);
eh honestly i don't think extensions are really all that bad. it's a standard and extensible way for third parties to advance the API, and - presuming the extension is rationalized into the API appropriately - allows for clean evolution & progression.
on the other hand, i'm not so sure that i agree with the approach of advertising even basic functionality (e.g. swapchain) through extensions. i understand vulkan has uses outside of graphics. i think that could have been better exposed with hard profile boundaries or something..
Most people that talk about how portable Khronos APIs are, versus the proprietary alternatives, never really used them in anger across multiple systems and graphics cards.
You end up with several code paths, where you have an architecture similar to multiple APIs middleware, but actually it is only using OpenGL, or Vulkan, and jungling among all possible cases.
At least now they got why proprietary APIs use profiles.
Not a graphics expert but as I understand it, it doesn't match how hardware works anymore and also has a huge amount of global state that you constantly have to save and restore. Also it basically assumed a single thread.
I’m an ex-graphics expert and this is a sufficiently good summary.
GL is based on a very outdated model of the GPU as a register-based state machine that grew bigger and bigger for decades. Meanwhile, the hardware moved towards being able to switch rapidly between pre-configured structs representing chunks of state. GL drivers have had to reconcile an interface where you make changes incrementally grinding against an implementation where dynamic state is super expensive and lots of pre-configured state is super cheap. Vulkan presents an interface much closer to the current hardware implementations —with all of their problems and opportunities brought to the surface.
Offtopic question : broadcom doesn't want to open source the driver because of the red tape and ton of legal work required Or is there another reason ?
Broadcom seems to generally have issues with open-source.
It’s one of the reasons OpenWRT has poor support for Broadcom SoCs and Broadcom WiFi-controllers, and in general Broadcom-based devices are shunned in the OpenWRT community.
Broadcom is one of the reasons why the rpi foundation is able to ship so many devices. But I also believe they should, perhaps, find another partner, who's willing to go full in the open source thing.
The original prototypes for an RPi like thing by Upton were ATMega based [1] but I imagine with Upton's connections to Broadcom it made some sense both technically and financially.
Thing is nearly all the ARM-chip manufactures are similar or the same.
One of the weird things about the Apple M chips (well at least on Laptops) is you can make the more open source than most ARM chips.
This is one of the reasons why I sort of dread the upcoming move to arm on desktops and laptops, despite the potential massive performance improvements. At least it seems like the industry will need to head that way if they want performance per watt on par with the Apple M chips.
The story as I heard it is:
There original WRT54g that was the start of openWRT was BCM chip. BCM wrote a lot of the software, especially low level, as Cisco was their major customer at the time. Then Cisco got sued for GPL violations that were BCM's fault. Both companies were large and not too worried by lawsuits, but eventually it dawned on them that unlike the usual between businesses, they weren't just going to be able to settle by paying some money, because their antagonists were not in it for the money. They had to release the source, which both companies regarded as significantly part of their own IP. Cisco was pissed at BCM, BCM were upset that an external factor could piss off their major customer like this, and some high ranked individuals at BCM were butthurt about open source licenses having a say in their operations. So a policy was put in place that where significant R&D effort was made on software, in product lines those individuals controlled, it would be legally firewalled from open source licenses, even to the extent of designing future chip architectures so that there were extra processors, not running Linux, that would run features BCM wanted to keep proprietary.
So that's why it's difficult to run open WRT on BCM chips.
Linux in general has issues with Broadcom wifi. If you're shopping for a laptop to run linux. One of the biggest red flags for driver support is Broadcom wifi.
Yeah, I've been trying to replace my Raspberry Pi units with other hardware to avoid this hassle, its getting increasingly annoying trying to get ahold of a decent RPi.
What's your price point and spec desire/use case? ARM or x86-64?
There are good ARM SBC alternatives with good community by ODroid and a few other brands for $30-$100. ODroid probably has the biggest and best community outside RPi.
Used thin and zero clients can be had for very cheap and used for low power, low resource needs.
Alternatively, the new ultra low power Jasper Lake CPUs are pretty insane for the price/power and you can get complete mini PCs with "real" nvme or sata storage, dual 4k@60Hz video output, 1 or 2.5Gbit Ethernet for $150-250. Search for n5095 (15W TDP), n5100 (6W), n5105 (10W), n6000 (6W), or n6105 (10 W) mini PC on Amazon. The iGPUs on these are killer and can handle 2-3 4k transcodes too. They make great media/storage servers (that's what I'm using one I just bought for)
I love SBCs, homelabbing, and squeezing as much out of hardware per watt and dollar. Liliputing and ServetheHome have been great resources.
If you just want a little Linux box and don't need GPIO, I'd recommend buying a used "thin client" from eBay. These are usually low-end x86(-64) machines with decent connectivity but not much storage, as they're meant to just display the UI for apps running on a server somewhere. You can generally hack more storage into them pretty easily.
A 4-thread machine with case, heat sink, power supply, 8gb ram, and an SSD can be had for less than the MSRP of a bare 8GB RPi 4.
One downside is power: the thin clients generally idle around 5-10W and use 20W or more at peak; compared to the Pi which will idle at 2 watts and use 10W peak.
I've had some success using this page and subscribing to the twitter feed from the same person: https://rpilocator.com
Adafruit appears to be the best resource for ordering Pis in the US as they require you log in with MFA and limit purchases. That is, if you're just in the market for a single unit.
So with this what games actually support Vulkan 1.2 and ARM processors? Maybe there's a version of Quake that could run but I'm wondering what would really work outside of just tech demos and benchmarks.
Well, it's a bit of a chicken-and-egg problem, so maybe this is the egg. I can definitely see various emulators taking advantage of this for RetroPie and the like.
Also, as the article mentions, there's a fork of Android that runs on a Raspberry Pi, and there are already Android games that will take advantage of Vulkan 1.2 support.
You don't need the game itself to actually support ARM. Box86 (runs x86 on ARM) already works with plenty of games, and it will even work with Wine and DXVK to run Windows games: https://youtu.be/JuRZGf7Jqxg
Jan 31st, 2020 First Triangle - https://www.raspberrypi.com/news/vulkan-raspberry-pi-first-t...
Jun 9th, 2020 Vulkan Youtube Demos From Mike Hooper - https://www.youtube.com/watch?v=ygBB3D5vryw
Jun 9th, 2020 Progress Report 2 - https://www.raspberrypi.com/news/vulkan-update-now-with-adde...
Nov 24th, 2020 Vulkan 1 Conformance - https://www.raspberrypi.com/news/vulkan-update-were-conforma...
August 10, 2021 Nearing Vulkan 1.1 conformance - https://blogs.igalia.com/itoral/2021/08/10/an-update-on-feat...
Oct 26th, 2021 Vulkan 1.1 conformance - https://www.raspberrypi.com/news/vulkan-update-version-1-1-c... Vulkan 1.2 conformance
Aug 1st 2022 Vulkan 1.2 conformance - https://www.raspberrypi.com/news/vulkan-update-version-1-2-c...
Lets see if we can hit Vulkan 1.3 conformance next!