4 ms·
> 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 widel
by pcwalton 9y ago
> 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).
- pandaman 9y agoI don't think glDrawElements() goes into the driver though (at least there is no sane reason for it I can imagine, you only need to go into the driver to kick a command buffer at the end of frame). Nevertheless, even if some implementations actually do call driver, the GP's point is that the whole point of Vulkan is getting rid of global state to allow parallel command buffer creation. JS is single threaded so, no matter how cheap or expensive the calls are, you won't be able to take advantage of Vulkan since you are running just one thread.
- nhaehnle 9y agoOf course glDrawElements() has to go into the driver, because it needs to do hardware-specific work. This is obviously true in OpenGL(ES), but even if you were to implement it via a translation layer to Vulkan, you still have to call the various Vulkan-equivalent commands, at the very least vkCmdDrawIndexed. Here's an implementation to make it painfully obvious why that has to involve the driver: https://github.com/mesa3d/mesa/blob/d819b1fcec02be5e0cfc87b6246833a2a2d5f034/src/amd/vulkan/radv_cmd_buffer.c#L2758 https://github.com/mesa3d/mesa/blob/d819b1fcec02be5e0cfc87b6...
- pandaman 9y agoNo, you only need to go into the driver when you need to do work that cannot be done in the userland. What are you talking about is just a shared library in the address space of your app, and the code you are showing is literally just writing bytes into a buffer. Nobody forbids you from calling it "driver", of course but then the whole point of "going into the driver" does not make sense, since there is no syscall and it's just a regular function.
- nhaehnle 9y agoYou're thinking of kernel-mode drivers. What I've linked to is a driver. Everybody calls it that. When you go download a driver for graphics cards, whether on Linux or Windows, that driver actually consists of multiple components, some of them running in kernel-mode and some of them running in user-mode. It's basically the exo-kernel principle, but without feeling the need of giving it a fancy name :) There's a broader history of user-mode drivers not just for graphics, and not just in the obvious case of micro-kernels. User-mode USB drivers used to be a thing, for example (and I guess they still are for some more obscure hardware).
- pandaman 9y agoAs I said, you can call it whatever you want, "driver", "kernel" or "linux" even. The point of "going into the driver" being expensive only makes sense if it's a syscall, which it is not as we both seem to agree.
- crzwdjk 9y agoNot really. OpenGL in particular has to do a surprising amount of work on every call, to make sure the state hasn't changed and to update all sorts of things if it has, to manage the various buffers and make sure they're mapped in the right place, and then to go down through all the abstraction layers until you end up in the code that actually writes stuff into the command buffer. It's not going to be a syscall level of overhead, though it may end up being that if stuff needs to get mapped into the GPU address space, but it's definitely going to be more than the dozen instruction overhead of going from JITed to native C++ code.
- Impossible 9y agoYou just stumbled into and argument the game industry has been dealing with for years, whether or not programmers or artists should own shader code. This boils down to whether or not you implement a visual node based shader editor in your game engine. While I agree that expecting designers to know "modern gpu programming" is extreme, exposing fragment shader style functionality isn't a bad idea, if properly implemented. I also don't think it'd be super difficult for designers to grok.
- pcwalton 9y ago> exposing fragment shader style functionality isn't a bad idea, if properly implemented. I agree that functionality like fragment shaders is useful, as long as it's declarative and fits in with the rest of CSS. In fact, we already have it: the CSS filter property.
- kllrnohj 9y ago> 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 9y ago> 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.