
Beginners Guide to Vulkan - deafcalculus
https://www.khronos.org/blog/beginners-guide-to-vulkan
======
Impossible
Oculus Tiny Room is linked, but Valve also has a pretty good minimal Vulkan +
OpenVR example in the OpenVR SDK called hellovr_vulkan
([https://github.com/ValveSoftware/openvr/blob/master/samples/...](https://github.com/ValveSoftware/openvr/blob/master/samples/hellovr_vulkan/hellovr_vulkan_main.cpp)).

On HN this might be attractive because people tend to complain about Windows
only software, and all of Valve's samples use SDL and in theory run on Mac OS
X and Linux. The OpenVR example is a little bit more verbose, but it does have
some extra functionality, like drawing render models (controllers) provided by
the API.

~~~
uep
Thanks for this!

I happen to have a Vive and have been wanting to get my game engine outputting
to it. I am primarily focused on Linux.

~~~
rocky1138
Can we see your engine?

------
Kiro
> It reminds me of a lot of the attitudes surrounding C++ when I was first
> learning it-- yes, it's more lines of code, but that doesn't mean it can't
> be a fine place for a beginner to start learning.

Sure, but Vulkan really feels like another level of complexity. OpenGL is
simple in comparison.

~~~
ATsch
Well, libraries and frameworks have solved problems like that before and
probably will again.

~~~
robotresearcher
Low level graphics programming is tough, specialist work. Imagine a relatively
simple stateful API layer over the top of this stuff, widely adopted and with
an open spec. We could call it the Open Graphics Library, or OpenGL for short.

~~~
kuschku
And a horribly painful codebase that is a horror to work with.

Nowadays people are more comfortable with having objects that represent
something, and executing operations on them, than having to bind an object to
a global variable, execute a global procedure, and unbinding it.

~~~
robotresearcher
You think so? I think people like to call functions with comprehensible
arguments.

I don't agree that people _like_ to bind an object to a global variable,
execute a global procedure, and unbind it. Does that sound like the API of
anyone's dreams? The binding and unbinding sounds like pure overhead to me.

I understand that very high performance and easy API may not be achievable,
but seriously, the modern graphics APIs are hard to love.

~~~
Narishma
> I don't agree that people like to bind an object to a global variable,
> execute a global procedure, and unbind it. Does that sound like the API of
> anyone's dreams? The binding and unbinding sounds like pure overhead to me.

Isn't that how OpenGL works?

~~~
robotresearcher
Not in the old days, no.

glColor3f( 1,0,0 );

glBegin( GL_POLYGON );

glVertex3f( 0,0,0 );

glVertex3f( 1,1,0 );

glVertex3f( 1,2,0 );

glEnd();

~~~
kuschku
That's exactly the global state I am complaining about.

The current polygonal environment is a global state variable.

The current vertex is a globally set variable (as you'll notice once you try
to set textures and colors, becayse glVertex3f just sets a global variable),
etc.

Try throwing two threads at this, you'll get hilarious results, and there's no
way to propeely fix this.

And OpenGL 1.0 to 1.5 and then 2.0 made it even worse.

You allocate a buffer, fine.

But to write to it, you first bind the buffer to a global variable, then use a
call writing to a global variable.

~~~
nhaehnle
_> The current vertex is a globally set variable (as you'll notice once you
try to set textures and colors, becayse glVertex3f just sets a global
variable), etc._

Bad example. glVertex3f is the one function (among the various glColor,
glMultiTexCoord etc.) which _doesn 't_ set global state. It actually triggers
a vertex to be sent (which takes its attributes from the global state you
mentioned).

But all this is pretty moot, because it's not how OpenGL has been meant to be
used in _ages_. Use the core profile, where these functions don't even exist
any more.

 _> You allocate a buffer, fine.

> But to write to it, you first bind the buffer to a global variable, then use
> a call writing to a global variable._

Also outdated, though not by quite as much. Direct state access (DSA) has been
a thing for a pretty long time, now.

~~~
kuschku
> Also outdated, though not by quite as much. Direct state access (DSA) has
> been a thing for a pretty long time, now.

If it just worked for everything...

Even in 4.5 there's many functions that have no direct state version yet, and
many others were only introduced in 4.4 and 4.5 (meaning it won't be really
compatible anywhere).

For me, the #1 advantage of Vulkan is having DSA for everything, just working.

~~~
nhaehnle
_> Even in 4.5 there's many functions that have no direct state version yet_

Which ones are you missing in particular?

------
Nimsical
I clicked cause I thought it was about Star Trek. Always forget there's a
library with that name.

~~~
sleavey
Disappointed it's not on Khan Academy.

------
alistproducer2
Can someone give me a non-graphical use-case for learning Vulkan or just GPU-
based programming in general? I've heard of hardware acceleration. Is it
something like writing your routines in a language like Vulkan and offloading
the computation to the GPU?

~~~
kllrnohj
The use cases for GPU compute are fairly narrow. You need something that is
embarrassingly parallel and deals with almost nothing but floats. You also
need something isolated enough that you're ok with paying the PCI-E bandwidth
overhead to send it to the GPU & receive the results back from the GPU.

~~~
pcwalton
> You need something that…deals with almost nothing but floats.

This hasn't been true for years. GPU integer compute is quite good these days.

~~~
kllrnohj
GPUs will handle ints just fine, but it's not what they are best at. They are
best at fp32, and depending on the GPU the gap is rather substantial. The
performance characteristics of integer ops is also kinda weird.

~~~
nhaehnle
AMD GPUs actually have identical performance for int32 and fp32, except for
full 32-bit integer multiplies and divisions. I think that's a big part of why
cryptocurrency miners like them so much.

------
mncharity
For folks curious about WebGL in a Vulkan world, there's
[https://github.com/KhronosGroup/WebGLNext-
Proposals/tree/mas...](https://github.com/KhronosGroup/WebGLNext-
Proposals/tree/master/Obsidian-Mozilla) .

~~~
kllrnohj
Not to be overly harsh about their work but that just screams "me too!"
instead of solving an actual problem.

Vulkan is a low-level, highly verbose API designed to extract maximum
performance and leverage multiple threads to deal with slower aspects of
rendering. Then you chuck that into a single-threaded, slow (relatively)
runtime where method calls to the actual implementation are particularly
expensive (JavaScript -> native transitions ain't cheap), and that's supposed
to be a good idea? Why? Who is supposed to use this for anything useful?

Instead of just porting native features to the web for the sake of porting
them make it easier to make use of the hardware's capabilities. Let me throw a
GPU shader into a CSS3 transition animation or something like that, for
example. That'd be cool and potentially useful instead of a system where you
can port some game to the web for the sake of porting it to the web where
nobody will ever use it because it sucks compared to the vastly superior
native version of the game.

~~~
pcwalton
> Then you chuck that into a single-threaded, slow (relatively) runtime

Slow relative to C++, sure. But JS is very fast relative to pretty much any
other widely used dynamic language. If we should expose Vulkan bindings to
dynamic languages (and why not?) JS is the obvious first choice for a target,
given its speed and popularity.

> JavaScript -> native transitions ain't cheap

They're actually very cheap nowadays, because so many benchmarks stress the
DOM and C++-implemented builtins. Driver calls, even with Vulkan, far exceed
the cost of JS-to-native transitions. glDrawElements() is probably at least
100x slower than a JS-to-native call, the latter of which has latencies
measured in nanoseconds.

> Let me throw a GPU shader into a CSS3 transition animation or something like
> that, for example.

Please, let's not. This will neither be good for designers (modern GPU
programming has an enormous learning curve compared to CSS) nor browser
developers (shaders would break batching and would expose too many engine-
specific internal details).

~~~
kllrnohj
> If we should expose Vulkan bindings to dynamic languages (and why not?) JS
> is the obvious first choice for a target, given its speed and popularity.

Exposing it to JS and exposing it to web pages in a browser are two completely
different things.

> They're actually very cheap nowadays, because so many benchmarks stress the
> DOM and C++-implemented builtins. Driver calls, even with Vulkan, far exceed
> the cost of JS-to-native transitions. glDrawElements() is probably at least
> 100x slower than a JS-to-native call, the latter of which has latencies
> measured in nanoseconds.

glDrawElements in vulkan is a couple hundred lines of API calls. I don't think
you're fully grokking the orders of magnitude of verbosity that Vulkan brings.

As for the transition cost there's varying levels of cheap, but at the end of
the day it's not great. It's raw per-call overhead on an API designed around
making an obscene amount of calls, and the overhead _is_ significant. Jumping
between these worlds is just not something you want to do very frequently if
your goal is performance.

C++-builtins are a completely different class of problems as intrinsics get to
play by their own compiler rules than regular JS -> native bindings.

> Please, let's not. This will neither be good for designers (modern GPU
> programming has an enormous learning curve compared to CSS) nor browser
> developers (shaders would break batching and would expose too many engine-
> specific internal details).

So simple pixel shaders are too complex, but _vulkan_ is not?

If a pixel/fragment shader is too much, then so is the entirety of WebGL, and
webvulkan would just be pure insanity from that perspective.

Also it doesn't break batching at all, I have no idea what you're talking
about there. A pixel shader is just a function with a set of inputs and a
color output. It's really quite simple, easily emulated for non-GPU fallbacks,
and easily manipulated by the browser.

~~~
pcwalton
> Exposing it to JS and exposing it to web pages in a browser are two
> completely different things.

It would make little sense to expose Vulkan to JS and not to put those
bindings in a Web browser.

> glDrawElements in vulkan is a couple hundred lines of API calls. I don't
> think you're fully grokking the orders of magnitude of verbosity that Vulkan
> brings.

> As for the transition cost there's varying levels of cheap, but at the end
> of the day it's not great. It's raw per-call overhead on an API designed
> around making an obscene amount of calls, and the overhead is significant.
> Jumping between these worlds is just not something you want to do very
> frequently if your goal is performance.

It doesn't matter whether it's a couple hundred calls or not. The overhead,
which again is measured in _nanoseconds_ , really does not matter. Vulkan's
performance demands on API boundary transitions are no worse than that of the
DOM, which has been optimized for decades.

> C++-builtins are a completely different class of problems as intrinsics get
> to play by their own compiler rules than regular JS -> native bindings.

No, they don't. They are one and the same in many JS engines. (I can't speak
for all engines, but I'm familiar with SpiderMonkey, where a JSNative is a
JSNative, whether a builtin or a DOM method.) SpiderMonkey nowadays even knows
about things like purity of various DOM methods and will optimize accordingly.
(bz used this to make Dromaeo really fast.)

> So simple pixel shaders are too complex, but vulkan is not?

Fragment shaders are too complex _for CSS_. They aren't too complex for
programmatic manipulation in JS. The reason is simple: CSS is a high-level
declarative language intended to be accessible to designers, while JS is an
imperative language mainly used by programmers.

> Also it doesn't break batching at all, I have no idea what you're talking
> about there.

As you know, switching shader programs can only be done in between draw calls.

> A pixel shader is just a function with a set of inputs and a color output.

With hundreds of pages of specification describing how all the different
operations that that function can perform must behave.

------
atemerev
800 lines of code to render a triangle. OK.

I understand the need of being explicit, but why not include some reasonable
defaults? When you need that last drop of performance, you could opt out of
those defaults, but specifying everything by hand...

OK, OK, I understand. Perhaps Vulkan is a compiler target. It was never
intended for someone to write Vulkan code by hand. Just code in some higher-
level API or language and get everything compiled into low-level Vulkan calls.
I surely hope so, for the sake of my sanity. Right? Right?

~~~
corysama
It's not intended for someone to use Vulkan to render a triangle. If you want
to render a triangle (or merely a million triangles), just throw together some
simple OpenGL code and you'll have no problems assuming basic optimizations
(large batches).

If you really need Vulkan's advantages, you are committing yourself to a whole
lot more than 800 lines of code, Vulkan or no. The setup code will be done
once, then you'll move on to many thousands of lines of pipeline code that
will take the vast majority of dev time. The GL vs Vulkan question is more
about what you get in the end. GL takes care of a lot for you, but that makes
writing a highly specialized pipeline more complicated. Vulkan makes
everything complicated because specialization is presumed to be the goal.

~~~
atemerev
Firstly, I am worried that OpenGL development seems to be stalled and it looks
like its going into maintenance mode, where Vulkan is where all action
happens. It is increasingly pushed as a replacement to OpenGL, implicitly or
explicitly, and if it will be the only mainstream alternative, I am somewhat
worried.

Secondly, I am worried that there are no mid-level 3D graphic toolkits. We
have low-level (very very low-level) like Vulkan, or high-level stuff like
Three.js and game engines (which are not what I need, as I write realtime
scientific visualization code). What I want is something like imgui
([https://github.com/ocornut/imgui](https://github.com/ocornut/imgui)), but
for 3D. Simple, powerful, and bloat-free. However, I can't find anything like
this.

~~~
corysama
Maybe [https://github.com/bkaradzic/bgfx](https://github.com/bkaradzic/bgfx)
or maybe [http://www.ogre3d.org](http://www.ogre3d.org) depending on the
abstraction level you are looking for.

~~~
atemerev
Looks interesting, thank you.

