<p>Fundamentally what you're asking is equivalent to asking how to do multi-threaded asynchronous Vulkan rendering.  You just need one of those threads to be doing the Vulkan and OpenGL work with the shared semaphores.</p>
<p>I would recommend having a set of 3 or more shared surfaces for GL to render to, and as each one completes, you can push it into a queue for consumption by another thread which is pure Vulkan and running your screen targeted rendering.  If the prior image hasn't yet been consumed you can swap it out (although this is likely wasteful since you're rendering and then discarding those results) or you can block the VK/GL thread on waiting for the prior image to be consumed.</p>
<p>I'd suggest looking for a pure Vulkan asynchronous rendering example and then adapting it to add the GL interop to one of the threads in that example.</p>
<p>Hope the GL interop sample was clear and useful. I wrote it.</p>

CC BY-SA 4.0
2024-07-20T07:17:53.887Z
Thanks for both the answer and the sample. It helped tremendously. I'll see if this answer fits my archtictural constraints, but it sounds reasonable.
Tare
CC BY-SA 4.0
2024-08-27T07:25:22.593Z
I ended up discarding a semaphore and adding a mutex instead. Now the wait and signal semaphore are the very same, double wait without signal cannot happen anymore. Double access is prevented by the (CPU side) mutex.
Tare
CC BY-SA 4.0
2024-07-19T17:00:42.607Z
2024-07-19T17:13:22.487Z
2024-07-19T17:13:22.487Z
Jherico
<p>I have an interop system where Vulkan renders a shared image to a rendertarget which then gets presented to a surface (i.e. visible in a window).
OpenGL renders to the shared image, but does so in a different thread.</p>
<p>The OpenGL thread may render a lot faster or slower than the Vulkan thread, so the access of the shared image is unpredictable.</p>
<p>In the <a href="https://github.com/KhronosGroup/Vulkan-Samples/blob/main/samples/extensions/open_gl_interop/open_gl_interop.cpp" rel="nofollow noreferrer">official Vulkan interop sample</a>, they render synchronously and thus the shared semaphores make sense. OpenGL waits for a ready signal, then renders, then signals done and waits again. Vulkan sets ready, waits for done, then does it's thing and signals ready. But this system works only for synchronous rendering.</p>
<p>In my asynchronous system, right now OpenGL renders a lot faster and more often, but according to the <a href="https://registry.khronos.org/OpenGL/extensions/EXT/EXT_external_objects.txt" rel="nofollow noreferrer">OpenGL specs</a>:</p>
<blockquote>
<p>After completion of the semaphore wait operation, the semaphore
will be returned to the unsignaled state.  Calling WaitSemaphore on
a semaphore that has not previously had a signal operation flushed
to the GL server or submitted by an external semaphore signaler
since the semaphore was created or last waited on results in
undefined behavior.</p>
</blockquote>
<p>I understand this as &quot;don't call Wait twice without signaling&quot;, so asynchronous rendering doesn't really work this way.</p>
<p>It is important that Vulkan does not block the OpenGL rendering, as it is more of a progressive display of intermediate results, the final image may take a long time to be done. So any blocking behaviour may significantly slow down the overall rendering.</p>
<p>This leads me to the question: How can I do asynchronous Vulkan / OpenGL interop rendering?</p>
<p>My initial thought was that using only one semaphore instead of two would effectively turn this into a mutex, but this still throws a &quot;GL_INVALID_OPERATION error generated. Wait for sync object failed.&quot; occasionally.</p>

<opengl><vulkan><interop>
How to do asynchronous Vulkan / OpenGL interop rendering?
Tare
# How to do asynchronous Vulkan / OpenGL interop rendering?

(Asked by: username_0 on 2024-07-19)

I have an interop system where Vulkan renders a shared image to a rendertarget which then gets presented to a surface (i.e. visible in a window).
OpenGL renders to the shared image, but does so in a different thread.

The OpenGL thread may render a lot faster or slower than the Vulkan thread, so the access of the shared image is unpredictable.

In the [official Vulkan interop sample](https://github.com/KhronosGroup/Vulkan-Samples/blob/main/samples/extensions/open_gl_interop/open_gl_interop.cpp), they render synchronously and thus the shared semaphores make sense. OpenGL waits for a ready signal, then renders, then signals done and waits again. Vulkan sets ready, waits for done, then does it's thing and signals ready. But this system works only for synchronous rendering.

In my asynchronous system, right now OpenGL renders a lot faster and more often, but according to the [OpenGL specs](https://registry.khronos.org/OpenGL/extensions/EXT/EXT_external_objects.txt):

> After completion of the semaphore wait operation, the semaphore
> will be returned to the unsignaled state. Calling WaitSemaphore on
> a semaphore that has not previously had a signal operation flushed
> to the GL server or submitted by an external semaphore signaler
> since the semaphore was created or last waited on results in
> undefined behavior.

I understand this as "don't call Wait twice without signaling", so asynchronous rendering doesn't really work this way.

It is important that Vulkan does not block the OpenGL rendering, as it is more of a progressive display of intermediate results, the final image may take a long time to be done. So any blocking behaviour may significantly slow down the overall rendering.

This leads me to the question: How can I do asynchronous Vulkan / OpenGL interop rendering?

My initial thought was that using only one semaphore instead of two would effectively turn this into a mutex, but this still throws a "GL\_INVALID\_OPERATION error generated. Wait for sync object failed." occasionally.

**Tags:** opengl, vulkan, interop


---

## 1 answers

### Answer by username_1 on 2024-07-19. Score: 1 | Accepted answer

Fundamentally what you're asking is equivalent to asking how to do multi-threaded asynchronous Vulkan rendering. You just need one of those threads to be doing the Vulkan and OpenGL work with the shared semaphores.

I would recommend having a set of 3 or more shared surfaces for GL to render to, and as each one completes, you can push it into a queue for consumption by another thread which is pure Vulkan and running your screen targeted rendering. If the prior image hasn't yet been consumed you can swap it out (although this is likely wasteful since you're rendering and then discarding those results) or you can block the VK/GL thread on waiting for the prior image to be consumed.

I'd suggest looking for a pure Vulkan asynchronous rendering example and then adapting it to add the GL interop to one of the threads in that example.

Hope the GL interop sample was clear and useful. I wrote it.

> **Comments:**
> **username_0**: Thanks for both the answer and the sample. It helped tremendously. I'll see if this answer fits my archtictural constraints, but it sounds reasonable.  
> **username_0**: I ended up discarding a semaphore and adding a mutex instead. Now the wait and signal semaphore are the very same, double wait without signal cannot happen anymore. Double access is prevented by the (CPU side) mutex.  

---

