So it’s already a couple of days ago since Vulkan launched. We were one of the first non-test programs in the world to launch on Day One with a quite mature Vulkan implementation. So far it seems only ARM Mali, nVidia and Intel Broadwell Mesa drivers can handle all the features inside RetroArch’s Vulkan backend.

This is a followup to the earlier article which can be found here.

WSI XCB support

Back when RetroArch added Vulkan support on Launch Day, there was only a working Wayland implementation.

We support Vulkan over XCB now too. This means you can get Vulkan to run now on Linux with an nVidia GPU since their binary blob driver doesn’t support Wayland.

I have tested the XCB context successfully on an Intel Ivy Bridge GPU as well. You need DRI3 support in order for this to work.

In case the Vulkan driver does not work for you on Intel, try creating the file ‘/etc/X11/xorg.conf.d/20-intel.conf. The file can be found here.

We recommend that if you have the option to choose between the two (and on some GPUs you simply might not have this option, like nVidia), that you pick Wayland over XCB and an X11 server. It’s a lot smoother.

Some Intel Ivy Bridge/Haswell snags and how we overcame some of them so far

Mesa Ivy Bridge/Haswell drivers (you can find them here) are currently very incomplete for Vulkan, so we had to workaround some things in order to make RetroArch run with Vulkan on them.

Ivy Bridge/Haswell drivers currently don’t support push constants, so this commit was necessary in order to get past it.

This made RetroArch go ingame on Ivy Bridge, however, there were still a couple of issues. RGUI doesn’t work and just shows a black screen (it works on Broadwell though), XMB crashes on an assertion (works on Broadwell), and GLUI/MaterialUI showed messed up font glyphs.

The messed up font glyphs required another workaround since it seems Ivy Bridge/Haswell drivers don’t support swizzling yet for vkImageView. So this commit made most of the graphics issues with GLUI/MaterialUI go away.

In case you want to test RetroArch with Vulkan and you don’t know how to set it manually to GLUI/MaterialUI, open up a text editor, find your retroarch config file (usually it’s ~/.config/retroarch/retroarch.cfg”), find the line that says “menu_driver = ” and replace it with:

menu_driver = “glui”

In order to start RetroArch with the Vulkan driver, you can either try to set it to the Vulkan driver through the builtin GUI, or if this is not an option, open retroarch’s config file with a text editor (usually ~/.config/retroarch/retroarch.cfg”), find the line that says ‘video_driver =’ and replace it with:

video_driver = “vulkan”

There are still some remaining issues that are the fault of the driver. For instance, if we go to the ‘Video’ subsection of the Settings menu, you will see some debug lines in the terminal complaining about:

anv_device.c:1016: execbuf2 failed: Invalid argument (VK_ERROR_OUT_OF_DEVICE_MEMORY)

For some reason the few on/off icon labels it needs to draw apparently triggers this. On Broadwell this works fine so we just assume it’s another driver bug to do with experimental Ivy Bridge/Haswell support.

We also get spammed a lot with this warning message inside the menu:

genX_cmd_buffer.c:195 ASSERT: srcStageMask == 0

Other things that are currently broken on Ivy Bridge/Haswell – GPU Recording/Screenshot seems to cause a crash –

anv_cmd_buffer.c: 805: anv_cmd_buffer_emit_binding_table: Assertion ‘surface_state.alloc_size’ failed.

According to Themaister this works fine on Broadwell.

Fortunately, the Vulkan shaders that maister already made do seem to work already on Ivy Bridge/Haswell. Right now there is just a few tiny shaders, two variations on a CRT shader, and they both worked on Ivy Bridge and at fullspeed.

The repo can be found here.

To use these, you’d launch a game with RetroArch, go to the Quick Menu, go to Shader Options, select ‘Load Preset’ and then browse to the directory containing the shader files and select one of them.

Discrete card progress

Themaister today addressed some performance issues on discrete GPUs like Nvidia which don’t really like you doing linear texture uploads, which is actually preferred for integrated GPUs like Intel HD.

Some initial impressions

So it’s early days but what are some of the things that stand out so far?

1 – GPU Recording is supposed to be much faster now vs. the PBO readback approach that we had to use with the OpenGL driver. I haven’t been able to test it though since the Ivy Bridge/Haswell driver currently crashes when selecting it. On Broadwell and nVidia I am told it works though.

2 – When you have ‘logging enabled’ in RetroArch, it will always report frame time deviations at application exit inside the terminal. They are much lower with Vulkan than they ever were in GL. Frame time deviations as low as 0.005% and 0.035% are pretty much expected, with GL you could only dream of such low figures.

Because of these much lower deviations and because of much better control over buffer swap management (see point 3), audio/video sync is just so much nicer. You especially notice it with cores like Beetle/Mednafen PSX when you are running a game that is interlaced, the deinterlacing seems to render a lot smoother and has less ugly ghosting side effects as before.

3 – Vulkan gives you much more control over the swap chain. Because of this, fastforwarding will no longer screen tear like it did with OpenGL. This is actually a very cool improvement. RetroArch allows you to set the maximum fast forwarding runspeed. If you set it to 2x and then run a game that runs internally at a 30fps framerate, you can actually make it run at double the framerate by just fastforwarding it, and unlike with OpenGL, you won’t experience any video tearing. Of course your audio will also be sped up by 2x but hey :).

4 – I can notice on average so far a 3 to 4fps increase when running Vulkan over XCB compared to the OpenGL driver running in X11. To preface this: this is using a software rendered core like Mednafen PSX, as in, the 3 to 4fps speed increase appears to be mainly faster blitting and reduced overhead.

With Vulkan, it is possible to increase performance of our libretro cores even further with software rendered cores. A new environment callback added to the libretro API called RETRO_ENVIRONMENT_GET_CURRENT_SOFTWARE_FRAMEBUFFER allows us to grab a pointer to GPU memory which we can use as a framebuffer for the core. With OpenGL, how video rendering would work with a software rendered core is as follows: the core maintains its own internal framebuffer, it updates this as it pleases, then at the end of a frame it sends the frame to the frontend through the video_refresh_t callback. The libretro frontend would then take this frame, copy it to the GPU through glTexImage2D or glTexSubImage2D, and then render it.

With this new environ callback (and video driver backends that support it like Vulkan), this additional copy can be entirely skipped, leading to a performance increase. I have already implemented this for a few cores like TyrQuake and FCEUmm.

5 – Shader passes are already a thing, and we can already stack shaders like we could with the OpenGL and Direct3D 9 drivers. Shader parameters aren’t implemented yet but something will be worked out.

Obviously this will have some consequences for the common-shaders repository as it currently exists. Obviously we will not at any point just remove the currently existing Cg/GLSL shaders that currently exist, but we might have to make an entirely different repository for Vulkan.

6 – Comparing actual Vulkan cores like the libretro-test-vulkan core to the GL test core serves no purpose so far since the test cores don’t even render the same thing, so I’m not going to be making any comparisons there. In short, there will be advantages for both hardware-accelerated cores and software rendered cores with Vulkan.

What remains to be done?

1 – Waiting on better drivers, obviously. There is only so much stuff that can currently be worked around with the Ivy Bridge/Haswell drivers. Hopefully a lot of these workarounds will in the future no longer be needed.

2 – There are currently some rendering issues with the ‘Zarch ‘menu driver (not that we intend that to be used right now for endusers but still, we need it rendering correctly with Vulkan too anyway for feature parity).

3 – More WSI context support. Win32 still has to be done (don’t have the hardware or the OS on my side, hopefully others can hop in here and help out), Android (I will be able to look at this myself and at least nVidia should have Vulkan drivers ready for use on Shield devices, I suppose), and Mir (we don’t actually support Mir yet on a context driver level, but it might be time to look into that). Native DRM/KMS context driver support is something I personally am really hopeful for.