Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions appendices/VK_EXT_external_semaphore_drm_syncobj.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright 2026 The Khronos Group Inc.
//
// SPDX-License-Identifier: CC-BY-4.0

include::{generated}/meta/{refprefix}VK_EXT_external_semaphore_drm_syncobj.adoc[]

=== Other Extension Metadata

*Last Modified Date*::
2026-03-02
*IP Status*::
No known IP claims.
*Contributors*::
- Julian Orth
- James Jones, NVIDIA
- Simon Ser
- Lisa Wu, Arm Ltd.
- Jon Leech, Khronos

=== Description

This extension adds the ability to import and export timeline semaphores as DRM
synchronization objects (syncobj).

include::{generated}/interfaces/VK_EXT_external_semaphore_drm_syncobj.adoc[]

=== Version History

* Revision 1, 2026-03-02 (Julian Orth)
** Initial revision
9 changes: 9 additions & 0 deletions chapters/capabilities.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1641,6 +1641,12 @@ ifdef::VK_NV_external_sci_sync[]
hardware engines including the CPU and software (intra-process and
inter-process) operating domains and perform signal and wait operations.
endif::VK_NV_external_sci_sync[]
ifdef::VK_EXT_external_semaphore_drm_syncobj[]
* ename:VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_DRM_SYNCOBJ_BIT_EXT specifies a
file descriptor handle to a Linux DRM synchronization object (syncobj).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this extension specifically assumes DRM timeline synchronization objects, but binary syncobjs are a thing too, so the spec should probably be specific here and elsewhere. You may want to consider including that in the name as well, but it might also be considered overly verbose. I could go either way personally.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe the kernel distinguishes between binary and timeline syncobjs. The ioctl to create a syncobj does not have a way to allocate one or the other:

struct drm_syncobj_create {
	__u32 handle;
#define DRM_SYNCOBJ_CREATE_SIGNALED (1 << 0)
	__u32 flags;
};

The kernel warns against using both binary and timeline ioctls on the same syncobj but I believe the following sentence from this PR already covers this:

                                                            Vulkan timeline
    semaphore values correspond to syncobj points.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, I can confirm that the kernel makes no difference between binary and timeline syncobjs. A binary syncobj is a timeline syncobj with only point 0 being used.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do think it's reasonable to have a Vulkan VU or at least a note that says that it should only be imported as the same timeline type it was exported as. That won't cover every case since the client can go call DRM ioctls itself, but if someone is, for instance, using this to share semaphores between two different Vulkan devices, they're going to run into trouble if they mix and match.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This extension only supports import to/export from timeline semaphores.

This type must be used with timeline semaphores and Vulkan timeline
semaphore values corresponding to syncobj points.
endif::VK_EXT_external_semaphore_drm_syncobj[]

[NOTE]
====
Expand Down Expand Up @@ -1674,6 +1680,9 @@ endif::VK_FUCHSIA_external_semaphore[]
ifdef::VK_NV_external_sci_sync[]
| ename:VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SCI_SYNC_OBJ_BIT_NV | No restriction | No restriction
endif::VK_NV_external_sci_sync[]
ifdef::VK_EXT_external_semaphore_drm_syncobj[]
| ename:VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_DRM_SYNCOBJ_BIT_EXT | No restriction | No restriction
endif::VK_EXT_external_semaphore_drm_syncobj[]
|====
--

Expand Down
24 changes: 24 additions & 0 deletions chapters/features.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -9933,6 +9933,30 @@ include::{generated}/validity/structs/VkPhysicalDeviceGpaFeaturesAMD.adoc[]
--
endif::VK_AMD_gpa_interface[]

ifdef::VK_EXT_external_semaphore_drm_syncobj[]
[open,refpage='VkPhysicalDeviceExternalSemaphoreDrmSyncobjFeaturesEXT',desc='Structure describing the external semaphore DRM syncobj features supported by the implementation',type='structs']
--
The sname:VkPhysicalDeviceExternalSemaphoreDrmSyncobjFeaturesEXT structure is defined
as:

include::{generated}/api/structs/VkPhysicalDeviceExternalSemaphoreDrmSyncobjFeaturesEXT.adoc[]

This structure describes the following feature:

* pname:sType is a elink:VkStructureType value identifying this structure.
* pname:pNext is `NULL` or a pointer to a structure extending this
structure.
* [[features-externalSemaphoreDrmSyncobj]] pname:externalSemaphoreDrmSyncobj
indicates whether the implementation has support for the
ename:VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_DRM_SYNCOBJ_BIT_EXT external
semaphore handle type.

:refpage: VkPhysicalDeviceExternalSemaphoreDrmSyncobjFeaturesEXT
include::{chapters}/features.adoc[tag=features]

include::{generated}/validity/structs/VkPhysicalDeviceExternalSemaphoreDrmSyncobjFeaturesEXT.adoc[]
--
endif::VK_EXT_external_semaphore_drm_syncobj[]

ifdef::VK_KHR_device_address_commands[]
[open,refpage='VkPhysicalDeviceDeviceAddressCommandsFeaturesKHR',desc='Structure describing support for device address commands',type='structs']
Expand Down
25 changes: 25 additions & 0 deletions chapters/synchronization.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -3746,6 +3746,17 @@ ifdef::VK_NV_external_sci_sync[]
slink:VkPhysicalDeviceExternalSciSyncFeaturesNV::pname:sciSyncExport>>
features must: be enabled
endif::VK_NV_external_sci_sync[]
ifdef::VK_EXT_external_semaphore_drm_syncobj[]
* If pname:handleTypes includes
ename:VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_DRM_SYNCOBJ_BIT_EXT, the
<<features-externalSemaphoreDrmSyncobj,
slink:VkPhysicalDeviceExternalSemaphoreDrmSyncobjFeaturesEXT::pname:externalSemaphoreDrmSyncobj>>
feature must: be enabled
* If pname:handleTypes includes
ename:VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_DRM_SYNCOBJ_BIT_EXT, the
slink:VkSemaphoreTypeCreateInfo::pname:semaphoreType field must: be
ename:VK_SEMAPHORE_TYPE_TIMELINE
endif::VK_EXT_external_semaphore_drm_syncobj[]
****

include::{generated}/validity/structs/VkExportSemaphoreCreateInfo.adoc[]
Expand Down Expand Up @@ -5180,6 +5191,9 @@ The handle types supported by pname:handleType are:
| Handle Type | Transference | Permanence Supported
| ename:VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT | Reference | Temporary,Permanent
| ename:VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT | Copy | Temporary
ifdef::VK_EXT_external_semaphore_drm_syncobj[]
| ename:VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_DRM_SYNCOBJ_BIT_EXT | Reference | Permanent
endif::VK_EXT_external_semaphore_drm_syncobj[]
|====

.Valid Usage
Expand Down Expand Up @@ -5213,6 +5227,17 @@ ifdef::VK_BASE_VERSION_1_2,VK_KHR_timeline_semaphore[]
semaphore from which pname:fd was exported must: not be
ename:VK_SEMAPHORE_TYPE_TIMELINE
endif::VK_BASE_VERSION_1_2,VK_KHR_timeline_semaphore[]
ifdef::VK_EXT_external_semaphore_drm_syncobj[]
* If pname:handleType is
ename:VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_DRM_SYNCOBJ_BIT_EXT, the
<<features-externalSemaphoreDrmSyncobj,
slink:VkPhysicalDeviceExternalSemaphoreDrmSyncobjFeaturesEXT::pname:externalSemaphoreDrmSyncobj>>
feature must: be enabled
* If pname:handleType is
ename:VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_DRM_SYNCOBJ_BIT_EXT, the
slink:VkSemaphoreTypeCreateInfo::pname:semaphoreType field must: be
ename:VK_SEMAPHORE_TYPE_TIMELINE
endif::VK_EXT_external_semaphore_drm_syncobj[]
****

If pname:handleType is ename:VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
Expand Down
58 changes: 58 additions & 0 deletions proposals/VK_EXT_external_semaphore_drm_syncobj.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright 2021-2026 The Khronos Group Inc.
//
// SPDX-License-Identifier: CC-BY-4.0

= VK_EXT_external_semaphore_drm_syncobj
:toc: left
:docs: https://docs.vulkan.org/spec/latest/
:refpages: https://docs.vulkan.org/refpages/latest/refpages/source/
:sectnums:

This extension aims to add interoperability between timeline semaphores and
syncobjs.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpicking:
maybe use the full name 'Linux DRM synchronization objects (syncobjs) " instead of the short form?


== Problem Statement

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpicking:IMHO, the information in this session seems to fit better as a proposal instead of a problem statement. :) Particaluarly, the information about the syncobjs provides the justification why it is the chosen solution, while the information about 'OPAQUE_FD' seems like an alternative proposal, and the limitation comes along with it.

For the problem statement, it may be sufficient to explain what is the problem the extension is intended to solve. For example:
Vulkan does not define an external sync handle type that is suited for sharing timeline semaphore outside of Vulkan.
The existing external semaphore handle types for cross-API sharing are limited to binary semaphore usage. This limits Vulkan's ability to use timeline semaphore as sync primitive for cross API and process sharing.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vulkan does not define an external sync handle type that is suited for sharing timeline semaphore outside of Vulkan.

I don't think that is true. Vulkan does have such types on windows. And I think opaque FDs can be shared with cuda on the nvidia driver.

I wrote this section to show specifically why there is value in supporting syncobj interop. If it is already assumed that all interop with any external synchronization primitive is valuable, then I'd rather just cut this section down to the following without changing the proposal section.

Vulkan currently does not provide semaphore interoperability with syncobjs which are a synchronization primitive used on linux.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough.
I like the trim down version much better :)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can do that if it is the consensus. If I were to read the proposal document, I would prefer to know more about why the extension was added and what things I could do with it.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason I suggested an alternative problem statement is that the original problem statement reads like “Vulkan lacks a sync handle type for syncobj” and I slightly disagree with it.

I think the actual problem is that we lack a mechanism to share timeline semaphore payloads between Vulkan and other APIs on Linux. Opaque_FD could be used in a fairly limited set of use cases, while syncobj fits better to that problem, because it is a Linux kernel primitive with the same semantics as a Vulkan timeline semaphore, and is widely supported by the Linux ecosys. Therefore exporting/importing timeline semaphore payloads through drm syncobj handle becomes the choice on Linux.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks very much for writing the proposal document, by the way.
If we don’t receive others input on this, I’m fine with using the original problem statement.

@mahkoh mahkoh Jun 12, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason I suggested an alternative problem statement is that the original problem statement reads like “Vulkan lacks a sync handle type for syncobj” and I slightly disagree with it.

That was how I intended it to be read. The two usecases from the problem statement are the usecases I wanted to solve with this extension.

It being the first well-defined handle type for timeline semaphores on linux is only a side effect and having any other such type would not solve the usecases I had in mind, since they specifically use syncobjs.


Linux DRM synchronization objects (syncobjs) are a kernel primitive that can be
used to implement timeline semaphores. Syncobjs can be represented as file
descriptors and some implementations use them as the file type of
`VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT`.

Syncobjs are also used for inter-process synchronization. In some situations it
might be useful to use the same syncobj both as a timeline semaphore and for
inter-process synchronization.

Syncobjs furthermore allow applications to asynchronously wait for individual
timeline points by integrating with `poll(2)`. In some applications it might be
preferable to use this mechanism to wait for signal operations.

Currently, there is no official mechanism for applications to export syncobjs
from timeline semaphores or to import syncobjs into timeline semaphores.
Applications can detect whether the file descriptor used for
`VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT` refers to a syncobj but this
does not solve the issue on implementations that do not use syncobjs.

== Proposal

The `VK_EXT_external_semaphore_drm_syncobj` extension adds a new handle type
`VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_DRM_SYNCOBJ_BIT_EXT`.

This type can be used to import syncobjs into/export syncobjs from timeline
semaphores with _reference_ transference and _permanent_ permanence.

Existing VUs disallow _temporary_ permanence for timeline semaphores.

The mapping between syncobj points and timeline semaphore points is unambiguous
since both support `2^64 - 1` points for timeline operations.

== Issues

=== Should binary semaphores also be supported?

Some implementations use syncobjs to implement binary semaphores. This was not
explored as part of this proposal. If the need arises, the author believes that
support could be added with a new revision of the extension.

For now, binary semaphores already support interop via
`VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT`, albeit without
wait-before-signal support.
15 changes: 12 additions & 3 deletions xml/vk.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12093,6 +12093,11 @@ typedef void* <name>MTLSharedEvent_id</name>;
<member optional="true"><type>VkDataGraphOpticalFlowExecuteFlagsARM</type> <name>flags</name></member>
<member optional="true"><type>uint32_t</type> <name>meanFlowL1NormHint</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceExternalSemaphoreDrmSyncobjFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_DRM_SYNCOBJ_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>externalSemaphoreDrmSyncobj</name></member>
</type>
</types>


Expand Down Expand Up @@ -32118,10 +32123,14 @@ endif::VK_KHR_internally_synchronized_queues[]
<feature name="dataGraphNeuralAcceleratorStatistics" struct="VkPhysicalDeviceDataGraphNeuralAcceleratorStatisticsFeaturesARM" />
</require>
</extension>
<extension name="VK_EXT_extension_678" number="678" author="EXT" contact="Julian Orth @mahkoh" supported="disabled">
<extension name="VK_EXT_external_semaphore_drm_syncobj" number="678" type="device" depends="(VK_VERSION_1_2,VK_KHR_timeline_semaphore)" author="EXT" contact="Julian Orth @mahkoh" supported="vulkan">
<require>
<enum value="0" name="VK_EXT_EXTENSION_678_SPEC_VERSION" />
<enum value="&quot;VK_EXT_extension_678&quot;" name="VK_EXT_EXTENSION_678_EXTENSION_NAME" />
<enum value="1" name="VK_EXT_EXTERNAL_SEMAPHORE_DRM_SYNCOBJ_SPEC_VERSION" />
<enum value="&quot;VK_EXT_external_semaphore_drm_syncobj&quot;" name="VK_EXT_EXTERNAL_SEMAPHORE_DRM_SYNCOBJ_EXTENSION_NAME" />
<enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_DRM_SYNCOBJ_FEATURES_EXT" />
<enum bitpos="8" extends="VkExternalSemaphoreHandleTypeFlagBits" name="VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_DRM_SYNCOBJ_BIT_EXT" />
<type name="VkPhysicalDeviceExternalSemaphoreDrmSyncobjFeaturesEXT" />
<feature name="externalSemaphoreDrmSyncobj" struct="VkPhysicalDeviceExternalSemaphoreDrmSyncobjFeaturesEXT" />
</require>
</extension>
<extension name="VK_EXT_primitive_restart_index" number="679" type="device" depends="VK_KHR_get_physical_device_properties2,VK_VERSION_1_1" author="EXT" contact="Mike Blumenkrantz @zmike" supported="vulkan" ratified="vulkan" specialuse="glemulation">
Expand Down
Loading