FR: JUCE Vulkan

juce_vulkan : Classes for rendering Vulkan in a JUCE window.

According to the JUCE 2019 survey. GUI Rendering performance is the most wanted improvement.

Apple deprecated OpenGL and on Windows the OpenGL performance causes constant irritation.

Vulkan SDK
https://www.lunarg.com/about/
https://www.lunarg.com/vulkan-sdk/

Vulkan SDK - Getting Started (Windows)
https://vulkan.lunarg.com/doc/sdk/latest/windows/getting_started.html

Vulkan SDK - Getting Started (MacOS)
https://vulkan.lunarg.com/doc/sdk/latest/mac/getting_started.html

Vulkan Tutorial
https://vulkan.lunarg.com/doc/sdk/1.2.141.2/windows/tutorial/html/index.html

Please smash that vote button! :grinning:

Yes. Another very interesting alternative is WebGPU: https://dawn.googlesource.com/dawn

Would like to see that too and I think the JUCE team is already working of it, however if I got the information shared here in January right, then we won’t see a Vulkan-only solution with MoltenVK used for macOS as the link @parawave shared suggests.

I believe there is a lot work involved in getting this done right, but maybe we could get an update from @t0m on the current plans regarding this whole topic on a regular basis? This could help us having the direction the framework will be going in mind when we would e.g. start to design a new product with heavy GPU rendering today. Would it be more like an abstraction layer that redirects the most common rendering API calls to whatever suits the platform we are on, where we would only have to write individual shaders for each platform? Or would it be something like a base class for all GPU rendering solutions all renderers (e.g. legacy OpenGL for backwards compatibility, Vulkan and Metal) derive from? Or something completely different? Would be really great to know which direction you are going :slight_smile:

1 Like

Smashed, I wasn’t there for the survey but my vote is clearly for the graphical perf improvments too.

The new APIs also allow multi-threaded draw calls, which I presume means they work with the host software much better.
Juce’s internal rendering will have to be more of a surface renderer, using shaders for pixel work, for it to take advantage of the power of hardware rendering. The whole development GPU push is based around polygons - you can blame gaming for that!
Having said that, to start with I would be happy with just a hook into the GPU, rather than make it all work with it. I can do animations myself outside of the Juce functions. And perhaps they could integrate it later, which would be a lot of work, and may take some time.

3 Likes

See my link above (WebGPU: https://dawn.googlesource.com/dawn) - I think WebGPU seems like a very promising solution for cross platform graphics rendering. It presents one graphics API and supports different platform specific backends:

  • D3D12 on Windows 10
  • Metal on macOS and iOS
  • Vulkan on Windows, Linux, ChromeOS, Android and Fuchsia
  • OpenGL as best effort where available
2 Likes

Yes, it’s definitely worth looking into. I’ve been looking for one myself, but they always turn out to be monsters with gaming addons. This one looks nice and compact, I ignored it at first because its name implied a WebGL connection.

Vulkan won’t help JUCE any when this framework treats a high-performance rendering engine as an image to draw on; the current approach is totally missing the point.

I would much prefer seeing things like SVGs and text converting into Paths that a shader parses and draws (tesselation would be needed), and where gradients and colours are managed wholly by shaders. With that, an image pool containing all of the Image data, except on the GPU (ie: as it should be).

7 Likes

Exactly this.

We’ve got to start somewhere, and perhaps just the ability to render anything with our own polygon lists, would be great start.

Sure. Although I say don’t just “start somewhere” because that probably means “starting similarly to what is done for OpenGL right now because it was the easiest thing to do.” I’d rather see a proper rendering pipeline in place where the concept of components, text, paths, images, anything that you want to show on the screen, you only get a quick handle to them after passing the data to the GPU, and use shaders to apply effects - pixel, or otherwise… and also, I’d rather not be constrained by 2D for any of these graphical implements.

Right now, JUCE is only “using” OpenGL to satisfy a minimum bar, one that most people don’t seem to understand: it’s treating it like a rasteriser, which is defeating the purpose of having a GPU driven renderer in the first place. One has to wonder why bother connecting to a GPU at all, only to do all of the work on the CPU anyways?

I’m not suggesting to compete with Unreal Engine or Unity. Instead, I’m saying the fundamental building blocks should be flexible enough to go wild with all of the graphics features (and not be capped by having the underlying system drawing to an image and using all sorts of craziness with EdgeTables…). For example - imagine being able to call up all of the rectangle drawing with Graphics in your Component, apply a shader in between each rectangle draw, and get everything you need right there on the GPU?

7 Likes

So in the end it’s something like the JUCE Graphics API on top of the WebGPU API on top of the Vulkan API? :grinning:

Almost sounds too good to be true. There is definitely a catch. The problem with these projects is the sheer mass of dependencies and the associated setup procedure.

Looking at Building Dawn;

Dawn uses the Chromium build system and dependency management so you need to install depot_tools and add it to the PATH.

Unfortunately this sentence alone makes it kind of unusable for JUCE.

JUCE was always lightweight without any additional dependencies. And if there are ones, they’re managed easily by the Projucer. VST SDK? Add the path to the Projucer, done. Intel IPP? Install it, turn it on in the Projucer, done.

JUCE users want to install Visual Studio / XCode, open the Projucer, create a Project, hit save and compile the project. They don’t want to use a package manager. They don’t want to use a custom build system. And no they don’t want to install Python for some builder/test/config scripts.

Looking at the current state of JUCE I think anything that requires more than just dropping in some .h and .cpp files will not find its way into a module.

To be manageable and future proof it must be a project that is free of complicated installations or additional compilation steps. I think this is the main struggle the JUCE team is facing when making these decisions.

In that regard it’s probably easier to JUCE the natively provided Metal/Vulkan/OpenGL functions.

4 Likes

I don’t mind installing tools to work with, as long as the end user doesn’t need to install stuff, or has to be asked to install things.
The D3D12 Windows 10 bit concerned me a little, but I see we can use Vulkan with Windows as well.

I love that Juce is self-contained and doesn’t have a ton of dependencies that I need to keep track of with fragile links between open source bits and bobs here and there. We have enough to worry about on the DAW end, bringing in sub-projects that might or might not work at various version numbers of Juce, third party project dependencies and the hosts is really not what we need to solve the OpenGL deprecation issue. Frying pan / fire.

9 Likes

Imo, the end results should always be the prime driver. If making JUCE a little more complicated with an extra dependency and a learning curve means we can create better products, I say do it. Settling for something sub par because its easy or convenient isn’t what anyone should be doing. My 2c, im sure there’s a bucket load of valid reasons to disagree with me.

3 Likes

In case that we will have to wait years for it to come, has anyone considered implementing the Vulkan SDK? Anyone experienced in the field, what’s the estimated time to get it to the same point as the OpenGL module? Any resources and links in that regard are welcome here.

Vulkan Tutorial - Seems like a good starting point too.

Vulkan-Hpp: C++ Bindings for Vulkan

Additionally to experience with render/rasterizer pipelines, it’s also necessary to grasp the new concepts introduced by Vulkan and what they offer. Is there even a developer on the JUCE Team that could dedicate his work to the implementation? I would imagine it also takes a deep knowledge of how JUCE set up its windowing and graphic contexts.

2 Likes

Yeah, improved GUI Rendering performance would be great to have!
Let’s hope Vulkan can help with that.

1 Like

Looked into it. First experience so far:

Wow, Vulkan is insanely specific. Before you can do anything you have to specify everything! It’s a lot of setup code, most of the stuff was previously hidden by drivers. But there is a good thing about that. There are no secrets. Everything you do ultimately makes sense and there are no surprises or deprecated and outdated burdens.

The SDK size of ~250MB is surprisingly small. Install it, test if the basic cube demo runs on your system. Link some libs, set the header path and you’re ready to go.

Trying to understand every step in the tutorial takes a while, but there are some good references and examples. Although the majority of demos use the C API, I highly recommend to look into the C++ API too. It’s a bit different and confusing at first, but it nicely abstracts some of the steps.

Initialization code like…

 const VkApplicationInfo app = {
    .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
    .pNext = NULL,
    .pApplicationName = APP_SHORT_NAME,
    .applicationVersion = 0,
    .pEngineName = APP_SHORT_NAME,
    .engineVersion = 0,
    .apiVersion = VK_API_VERSION_1_0,
};

… which is mainly done with structs. will become a bit cleaner in C++.
There are also methods for automatic memory managment. And since a lot of functionality is done by extensions, the dynamic loader for functions seems very helpful in C++.

auto const app = vk::ApplicationInfo()
                     .setPApplicationName(APP_SHORT_NAME)
                     .setApplicationVersion(0)
                     .setPEngineName(APP_SHORT_NAME)
                     .setEngineVersion(0)
                     .setApiVersion(VK_API_VERSION_1_0);

Now for the C interface the best example resource is probably by Sascha Willems at:
Vulkan (C API) examples and demos

Luckily someone ported these to the C++ API here:
Vulkan (C++ API) examples and demos

Another more concrete and realistic scenario is this project
Animate - Interesting minimalist animations.

As initial reference for how to setup the instance and devices.
Vulkan Context Example


Unfortunately most of the demos drag in GLFW as dependency. Since we probably don’t want that in JUCE, it’s necessary to setup the surfaces manually together with the native JUCE handles.

Looking at the overall picture, it seems a lot of the heavy context stuff in juce_opengl can be avoided in Vulkan, which will probably give a big performance boost in plugins. Moreover the idea of offscreen rendering and compute shaders that work multithreaded are ideally suited for heavy processing stuff audio visualisation. Vulkan is the future!

3 Likes

Like juce::ShaderPrograms::RadialGradientProgram and its kin in juce_OpenGLGraphicsContext.cpp?

2 Likes

Damn it, you’ve made me want to look into it now! :grinning:

I presume all the helper files are like Glut was to OpenGL, where beginners tend to use it, as a shield from being overwhelmed to start with?

1 Like