diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h
index 5b13ad36a27..6f036991932 100644
--- a/src/gallium/include/pipe/p_defines.h
+++ b/src/gallium/include/pipe/p_defines.h
@@ -1088,6 +1088,7 @@ struct pipe_caps {
unsigned shader_subgroup_supported_stages;
unsigned shader_subgroup_supported_features;
unsigned multiview;
+ uint64_t max_timeline_semaphore_difference;
/** for CL SVM */
uint64_t min_vma;
@@ -1314,6 +1315,7 @@ enum pipe_fd_type
PIPE_FD_TYPE_NATIVE_SYNC,
PIPE_FD_TYPE_SYNCOBJ,
PIPE_FD_TYPE_TIMELINE_SEMAPHORE_D3D12,
+ PIPE_FD_TYPE_TIMELINE_SEMAPHORE_VK,
};
/**
diff --git a/src/mapi/glapi/gen/NV_timeline_semaphore.xml b/src/mapi/glapi/gen/NV_timeline_semaphore.xml
new file mode 100644
index 00000000000..95a5e643ac3
--- /dev/null
+++ b/src/mapi/glapi/gen/NV_timeline_semaphore.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/mapi/glapi/gen/gl_API.xml b/src/mapi/glapi/gen/gl_API.xml
index d75d6399215..48531f74e47 100644
--- a/src/mapi/glapi/gen/gl_API.xml
+++ b/src/mapi/glapi/gen/gl_API.xml
@@ -11122,4 +11122,5 @@
+
diff --git a/src/mapi/glapi/gen/static_data.py b/src/mapi/glapi/gen/static_data.py
index 61ec114ce0a..ab06bddd509 100644
--- a/src/mapi/glapi/gen/static_data.py
+++ b/src/mapi/glapi/gen/static_data.py
@@ -1629,6 +1629,9 @@ all_functions = [
"FramebufferTextureMultiviewOVR",
"NamedFramebufferTextureMultiviewOVR",
"FramebufferTextureMultisampleMultiviewOVR",
+ "CreateSemaphoresNV",
+ "GetSemaphoreParameterivNV",
+ "SemaphoreParameterivNV",
# Keep these last. They are never used by any app.
"ColorTable",
diff --git a/src/mesa/main/consts_exts.h b/src/mesa/main/consts_exts.h
index 63ca724f6e4..06af0af02b1 100644
--- a/src/mesa/main/consts_exts.h
+++ b/src/mesa/main/consts_exts.h
@@ -287,6 +287,7 @@ struct gl_extensions
GLboolean NV_conservative_raster_pre_snap;
GLboolean NV_viewport_array2;
GLboolean NV_viewport_swizzle;
+ GLboolean NV_timeline_semaphore;
GLboolean NVX_gpu_memory_info;
GLboolean TDFX_texture_compression_FXT1;
GLboolean OES_EGL_image;
@@ -1001,6 +1002,9 @@ struct gl_constants
/** Whether pipe_context::draw_vertex_state is supported. */
bool HasDrawVertexState;
+ /* NV_timeline_semaphore */
+ GLuint64 MaxTimelineSemaphoreValueDifference;
+
/** GL_KHR_shader_subgroup */
GLuint ShaderSubgroupSize;
GLuint ShaderSubgroupSupportedStages;
diff --git a/src/mesa/main/extensions_table.h b/src/mesa/main/extensions_table.h
index 6a812aaf97d..74a2cb09b80 100644
--- a/src/mesa/main/extensions_table.h
+++ b/src/mesa/main/extensions_table.h
@@ -440,6 +440,7 @@ EXT(NV_texgen_reflection , dummy_true
EXT(NV_texture_barrier , NV_texture_barrier , GLL, GLC, x , ES2, 2009)
EXT(NV_texture_env_combine4 , NV_texture_env_combine4 , GLL, x , x , x , 1999)
EXT(NV_texture_rectangle , NV_texture_rectangle , GLL, x , x , x , 2000)
+EXT(NV_timeline_semaphore , NV_timeline_semaphore , GLL, GLC, x , 32, 2020)
EXT(NV_vdpau_interop , NV_vdpau_interop , GLL, GLC, x , x , 2010)
EXT(NV_viewport_array2 , NV_viewport_array2 , GLL, GLC, x , 31, 2015)
EXT(NV_viewport_swizzle , NV_viewport_swizzle , GLL, GLC, x , 31, 2015)
diff --git a/src/mesa/main/externalobjects.c b/src/mesa/main/externalobjects.c
index 74cce2e85a5..ceeb4f71d35 100644
--- a/src/mesa/main/externalobjects.c
+++ b/src/mesa/main/externalobjects.c
@@ -778,17 +778,17 @@ _mesa_delete_semaphore_object(struct gl_context *ctx,
}
}
-void GLAPIENTRY
-_mesa_GenSemaphoresEXT(GLsizei n, GLuint *semaphores)
+static void
+create_semaphores(GLsizei n, GLuint *semaphores, bool NV)
{
GET_CURRENT_CONTEXT(ctx);
- const char *func = "glGenSemaphoresEXT";
+ const char *func = NV ? "glCreateSemaphoresNV" : "glGenSemaphoresEXT";
if (MESA_VERBOSE & (VERBOSE_API))
_mesa_debug(ctx, "%s(%d, %p)\n", func, n, semaphores);
- if (!_mesa_has_EXT_semaphore(ctx)) {
+ if (NV ? !_mesa_has_NV_timeline_semaphore(ctx) : !_mesa_has_EXT_semaphore(ctx)) {
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
return;
}
@@ -812,6 +812,18 @@ _mesa_GenSemaphoresEXT(GLsizei n, GLuint *semaphores)
_mesa_HashUnlockMutex(&ctx->Shared->SemaphoreObjects);
}
+void GLAPIENTRY
+_mesa_GenSemaphoresEXT(GLsizei n, GLuint *semaphores)
+{
+ create_semaphores(n, semaphores, false);
+}
+
+void GLAPIENTRY
+_mesa_CreateSemaphoresNV(GLsizei n, GLuint *semaphores)
+{
+ create_semaphores(n, semaphores, true);
+}
+
void GLAPIENTRY
_mesa_DeleteSemaphoresEXT(GLsizei n, const GLuint *semaphores)
{
@@ -890,7 +902,12 @@ _mesa_SemaphoreParameterui64vEXT(GLuint semaphore,
return;
}
- if (pname != GL_D3D12_FENCE_VALUE_EXT) {
+ if (!_mesa_has_NV_timeline_semaphore(ctx) && pname == GL_TIMELINE_SEMAPHORE_VALUE_NV) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(NV_timeline_semaphore unsupported)", func);
+ return;
+ }
+
+ if (pname != GL_D3D12_FENCE_VALUE_EXT && pname != GL_TIMELINE_SEMAPHORE_VALUE_NV) {
_mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
return;
}
@@ -900,8 +917,13 @@ _mesa_SemaphoreParameterui64vEXT(GLuint semaphore,
if (!semObj)
return;
- if (semObj->type != PIPE_FD_TYPE_TIMELINE_SEMAPHORE_D3D12) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "%s(Not a D3D12 fence)", func);
+ if (semObj->type < PIPE_FD_TYPE_TIMELINE_SEMAPHORE_D3D12) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(Not a %s)", func, pname == GL_TIMELINE_SEMAPHORE_VALUE_NV ? "timeline semaphore" : "D3D12 fence");
+ return;
+ }
+ if ((semObj->type == PIPE_FD_TYPE_TIMELINE_SEMAPHORE_D3D12 && pname != GL_D3D12_FENCE_VALUE_EXT) ||
+ (semObj->type == PIPE_FD_TYPE_TIMELINE_SEMAPHORE_VK && pname != GL_TIMELINE_SEMAPHORE_VALUE_NV)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(Not a %s)", func, pname == GL_TIMELINE_SEMAPHORE_VALUE_NV ? "timeline semaphore" : "D3D12 fence");
return;
}
@@ -922,7 +944,42 @@ _mesa_GetSemaphoreParameterui64vEXT(GLuint semaphore,
return;
}
- if (pname != GL_D3D12_FENCE_VALUE_EXT) {
+ if (!_mesa_has_NV_timeline_semaphore(ctx) && pname == GL_TIMELINE_SEMAPHORE_VALUE_NV) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(NV_timeline_semaphore unsupported)", func);
+ return;
+ }
+
+ if (pname != GL_D3D12_FENCE_VALUE_EXT && pname != GL_TIMELINE_SEMAPHORE_VALUE_NV) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
+ return;
+ }
+ struct gl_semaphore_object *semObj = _mesa_lookup_semaphore_object(ctx,
+ semaphore);
+ if (!semObj)
+ return;
+
+ if (semObj->type < PIPE_FD_TYPE_TIMELINE_SEMAPHORE_D3D12) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(Not a %s)", func, pname == GL_TIMELINE_SEMAPHORE_VALUE_NV ? "timeline semaphore" : "D3D12 fence");
+ return;
+ }
+
+ params[0] = semObj->timeline_value;
+}
+
+void GLAPIENTRY
+_mesa_GetSemaphoreParameterivNV(GLuint semaphore,
+ GLenum pname,
+ GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ const char *func = "glGetSemaphoreParameterivNV";
+
+ if (!_mesa_has_NV_timeline_semaphore(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
+ return;
+ }
+
+ if (pname != GL_SEMAPHORE_TYPE_NV) {
_mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
return;
}
@@ -932,12 +989,41 @@ _mesa_GetSemaphoreParameterui64vEXT(GLuint semaphore,
if (!semObj)
return;
- if (semObj->type != PIPE_FD_TYPE_TIMELINE_SEMAPHORE_D3D12) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "%s(Not a D3D12 fence)", func);
+ params[0] = semObj->type == PIPE_FD_TYPE_TIMELINE_SEMAPHORE_VK ?
+ GL_TIMELINE_SEMAPHORE_VALUE_NV :
+ GL_SEMAPHORE_TYPE_BINARY_NV;
+}
+
+void GLAPIENTRY
+_mesa_SemaphoreParameterivNV(GLuint semaphore,
+ GLenum pname,
+ const GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ const char *func = "glSemaphoreParameterivNV";
+
+ if (!_mesa_has_NV_timeline_semaphore(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
return;
}
- params[0] = semObj->timeline_value;
+ if (pname != GL_SEMAPHORE_TYPE_NV) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
+ return;
+ }
+
+ if (params[0] != GL_SEMAPHORE_TYPE_BINARY_NV && params[0] != GL_SEMAPHORE_TYPE_TIMELINE_NV) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
+ return;
+ }
+
+ struct gl_semaphore_object *semObj = _mesa_lookup_semaphore_object(ctx,
+ semaphore);
+ if (!semObj)
+ return;
+
+ enum pipe_fd_type type = params[0] == GL_SEMAPHORE_TYPE_TIMELINE_NV ? PIPE_FD_TYPE_TIMELINE_SEMAPHORE_VK : PIPE_FD_TYPE_SYNCOBJ;
+ create_real_semaphore(ctx, semaphore, semObj, type, func);
}
void GLAPIENTRY
diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c
index 1c7a6301bcd..5b5ae884929 100644
--- a/src/mesa/main/get.c
+++ b/src/mesa/main/get.c
@@ -593,6 +593,7 @@ EXTRA_EXT(NV_viewport_swizzle);
EXTRA_EXT(ARB_sparse_texture);
EXTRA_EXT(KHR_shader_subgroup);
EXTRA_EXT(OVR_multiview);
+EXTRA_EXT(NV_timeline_semaphore);
static const int extra_ARB_gl_spirv_or_es2_compat[] = {
EXT(ARB_gl_spirv),
diff --git a/src/mesa/main/get_hash_params.py b/src/mesa/main/get_hash_params.py
index 43a46f79a4f..cb1cfd74746 100644
--- a/src/mesa/main/get_hash_params.py
+++ b/src/mesa/main/get_hash_params.py
@@ -501,6 +501,9 @@ descriptor=[
# OVR_multiview
[ "MAX_VIEWS_OVR", "CONST(MAX_VIEWS_OVR), extra_OVR_multiview" ],
+
+# NV_timeline_semaphore
+ [ "MAX_TIMELINE_SEMAPHORE_VALUE_DIFFERENCE_NV", "CONTEXT_INT64(Const.MaxTimelineSemaphoreValueDifference), extra_NV_timeline_semaphore" ],
]},
{ "apis": ["GLES", "GLES2"], "params": [
diff --git a/src/mesa/main/glthread_marshal.h b/src/mesa/main/glthread_marshal.h
index e5e53717187..d18466c1e1d 100644
--- a/src/mesa/main/glthread_marshal.h
+++ b/src/mesa/main/glthread_marshal.h
@@ -398,6 +398,8 @@ static inline unsigned
_mesa_semaphore_enum_to_count(GLenum pname)
{
switch (pname) {
+ case GL_TIMELINE_SEMAPHORE_VALUE_NV:
+ return 1;
/* EXT_semaphore and EXT_semaphore_fd define no parameters */
default:
return 0;
diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c
index c11e54cf9c5..3711f9ce33a 100644
--- a/src/mesa/state_tracker/st_extensions.c
+++ b/src/mesa/state_tracker/st_extensions.c
@@ -1313,6 +1313,12 @@ void st_init_extensions(struct pipe_screen *screen,
consts->GLSLZeroInit = screen->caps.glsl_zero_init;
}
+ if (extensions->EXT_semaphore) {
+ consts->MaxTimelineSemaphoreValueDifference = screen->caps.max_timeline_semaphore_difference;
+ extensions->NV_timeline_semaphore = consts->MaxTimelineSemaphoreValueDifference > 0;
+ assert(!extensions->NV_timeline_semaphore || screen->set_fence_timeline_value);
+ }
+
consts->ForceIntegerTexNearest = options->force_integer_tex_nearest;
consts->VendorOverride = options->force_gl_vendor;