It’s been a while that Igalia’s graphics team had been working on the OpenGL extensions that provide the mechanisms for OpenGL and Vulkan interoperability in the Intel iris (gallium3d) driver that is part of mesa.
As there were no conformance tests (CTS) for this extension, and we needed to test it, we have written (and we are still writing) small tests for piglit that allow the exchange and the synchronization of the exchange of resources such as buffers, textures, and depth or stencil buffers.
This was difficult because not only most drivers were untested (and it was tricky to tell if there’s a bug or we don’t use the extension properly) but also, there were no interoperability examples out there to use them as a reference. We had to use debugging hacks like for example writing the tests in OpenGL first, then in Vulkan, and then in both using interoperability to reach a conclusion about how the extension should be used and if the driver is implementing it correctly.
So, after having spent some time trying to understand the interoperability extensions, I thought that it might be useful to start a series of posts on how to use them on Linux for different cases (eg: exchange a texture, a depth buffer, a stencil buffer, a pixel buffer and so on), using the small tests I’ve written for piglit as example. The full code can be found in the piglit repository, although some of the examples might not be there yet as they’re under review at the time of writing.
As this is the first and introductory post, I am only going to explain the ideas behind the interoperability extensions on Linux. I am going to show actual examples in the follow up posts.
The interoperability concept is simple:
Vulkan is a new and low level API that allows controlling the hardware better than OpenGL. But despite that, it has the disadvantage that is complex, and not widely used yet. OpenGL on the other hand is easy to write, it has very good performance in the most common cases, and is already used by many programs out there. The interoperability extensions allow the users to write the critical parts of a program in Vulkan, and the less critical in OpenGL using the same resources, as OpenGL and Vulkan can share the access in external memory objects that have been allocated from Vulkan once. An example of such an application could be a VR compositor: The compositor itself could be written entirely in Vulkan but the clients that might use UI libraries that lack a Vulkan backend or are written in OpenGL already, could re-use the compositor allocated resources and synchronize their access to it.
In order to reuse Vulkan allocated resources we usually need to:
- Use the appropriate flags at allocation to allow “external” (OpenGL) access to them.
- Use the
EXT_external_objects_fdprovided functions to take a file descriptor that points to that memory from Vulkan and give it to OpenGL in order to gain access too.
- Create an OpenGL object that corresponds to that memory.
Use that object like an ordinary OpenGL object (such as texture, buffer, depth or stencil buffer).
- Synchronize the access to that object with a special type of semaphores when necessary (for example when OpenGL must wait for Vulkan to finish an operation before it uses the object or the opposite).
I’ll try to demonstrate examples of Vulkan-GL interoperability in the posts that follow.