[FFmpeg-cvslog] lavu/vulkan: add option to switch between shader compilers and cleanup glslang

Lynne git at videolan.org
Fri Nov 19 14:44:59 EET 2021


ffmpeg | branch: master | Lynne <dev at lynne.ee> | Fri Nov 19 12:07:10 2021 +0100| [b2aec70bd6bbf4620d363dfdc7d9e54f2f32f9ee] | committer: Lynne

lavu/vulkan: add option to switch between shader compilers and cleanup glslang

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=b2aec70bd6bbf4620d363dfdc7d9e54f2f32f9ee
---

 libavfilter/Makefile       |  2 --
 libavfilter/glslang.c      | 19 -------------
 libavfilter/vulkan.c       |  3 --
 libavutil/vulkan.c         | 33 ++++++++++++++--------
 libavutil/vulkan.h         | 15 ++++++++++
 libavutil/vulkan_glslang.c | 68 +++++++++++++++++++++++++++++++---------------
 libavutil/vulkan_glslang.h | 41 ----------------------------
 7 files changed, 82 insertions(+), 99 deletions(-)

diff --git a/libavfilter/Makefile b/libavfilter/Makefile
index 07b4a639ec..868ba68b79 100644
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
@@ -578,8 +578,6 @@ SKIPHEADERS-$(CONFIG_OPENCL)                 += opencl.h
 SKIPHEADERS-$(CONFIG_VAAPI)                  += vaapi_vpp.h
 SKIPHEADERS-$(CONFIG_VULKAN)                 += vulkan.h
 
-OBJS-$(CONFIG_LIBGLSLANG)                    += glslang.o
-
 TOOLS     = graph2dot
 TESTPROGS = drawutils filtfmts formats integral
 
diff --git a/libavfilter/glslang.c b/libavfilter/glslang.c
deleted file mode 100644
index 9aa41567a3..0000000000
--- a/libavfilter/glslang.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavutil/vulkan_glslang.c"
diff --git a/libavfilter/vulkan.c b/libavfilter/vulkan.c
index e0fcf87f21..08e0c37cc4 100644
--- a/libavfilter/vulkan.c
+++ b/libavfilter/vulkan.c
@@ -188,8 +188,5 @@ int ff_vk_filter_init(AVFilterContext *avctx)
 
     s->output_format = AV_PIX_FMT_NONE;
 
-    if (ff_vk_glslang_init())
-        return AVERROR_EXTERNAL;
-
     return 0;
 }
diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c
index fba9543cce..22f9bf7eb6 100644
--- a/libavutil/vulkan.c
+++ b/libavutil/vulkan.c
@@ -16,12 +16,15 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include "vulkan.h"
-#include "vulkan_glslang.h"
-
 #include "avassert.h"
+
+#include "vulkan.h"
 #include "vulkan_loader.h"
 
+#if FF_VK_ENABLE_SHADER_COMPILATION && CONFIG_LIBGLSLANG
+#include "vulkan_glslang.c"
+#endif
+
 /* Generic macro for creating contexts which need to keep their addresses
  * if another context is created. */
 #define FN_CREATING(ctx, type, shortname, array, num)                          \
@@ -843,7 +846,6 @@ void ff_vk_print_shader(void *ctx, FFVkSPIRVShader *shd, int prio)
 int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd,
                          const char *entrypoint)
 {
-#if CONFIG_LIBGLSLANG
     int err;
     VkResult ret;
     FFVulkanFunctions *vk = &s->vkfn;
@@ -854,12 +856,21 @@ int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd,
 
     shd->shader.pName = entrypoint;
 
-    err = ff_vk_glslang_shader_compile(s, shd, &spirv, &spirv_size, &priv);
+    if (!s->spirv_compiler) {
+#if FF_VK_ENABLE_SHADER_COMPILATION && CONFIG_LIBGLSLANG
+        s->spirv_compiler = ff_vk_glslang_init();
+#else
+        return AVERROR(ENOSYS);
+#endif
+        if (!s->spirv_compiler)
+            return AVERROR(ENOMEM);
+    }
+
+    err = s->spirv_compiler->compile_shader(s->spirv_compiler, s, shd, &spirv,
+                                            &spirv_size, entrypoint, &priv);
     if (err < 0)
         return err;
 
-    ff_vk_print_shader(s, shd, AV_LOG_VERBOSE);
-
     av_log(s, AV_LOG_VERBOSE, "Shader %s compiled! Size: %zu bytes\n",
            shd->name, spirv_size);
 
@@ -872,7 +883,7 @@ int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd,
     ret = vk->CreateShaderModule(s->hwctx->act_dev, &shader_create, NULL,
                                  &shd->shader.module);
 
-    ff_vk_glslang_shader_free(priv);
+    s->spirv_compiler->free_shader(s->spirv_compiler, &priv);
 
     if (ret != VK_SUCCESS) {
         av_log(s, AV_LOG_ERROR, "Unable to create shader module: %s\n",
@@ -881,9 +892,6 @@ int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd,
     }
 
     return 0;
-#else
-    return AVERROR(ENOSYS);
-#endif
 }
 
 static const struct descriptor_props {
@@ -1367,7 +1375,8 @@ void ff_vk_uninit(FFVulkanContext *s)
 {
     FFVulkanFunctions *vk = &s->vkfn;
 
-    ff_vk_glslang_uninit();
+    if (s->spirv_compiler)
+        s->spirv_compiler->uninit(&s->spirv_compiler);
 
     for (int i = 0; i < s->exec_ctx_num; i++)
         free_exec_ctx(s, s->exec_ctx[i]);
diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h
index 14c69ce015..3d89f02732 100644
--- a/libavutil/vulkan.h
+++ b/libavutil/vulkan.h
@@ -22,6 +22,10 @@
 #define VK_NO_PROTOTYPES
 #define VK_ENABLE_BETA_EXTENSIONS
 
+#ifndef FF_VK_ENABLE_SHADER_COMPILATION
+#define FF_VK_ENABLE_SHADER_COMPILATION 1
+#endif
+
 #include "pixdesc.h"
 #include "bprint.h"
 #include "hwcontext.h"
@@ -64,6 +68,15 @@ typedef struct FFVkSPIRVShader {
     VkPipelineShaderStageCreateInfo shader;
 } FFVkSPIRVShader;
 
+typedef struct FFVkSPIRVCompiler {
+    void *priv;
+    int (*compile_shader)(struct FFVkSPIRVCompiler *ctx, void *avctx,
+                          struct FFVkSPIRVShader *shd, uint8_t **data,
+                          size_t *size, const char *entrypoint, void **opaque);
+    void (*free_shader)(struct FFVkSPIRVCompiler *ctx, void **opaque);
+    void (*uninit)(struct FFVkSPIRVCompiler **ctx);
+} FFVkSPIRVCompiler;
+
 typedef struct FFVkSampler {
     VkSampler sampler[4];
 } FFVkSampler;
@@ -194,6 +207,8 @@ typedef struct FFVulkanContext {
     AVHWFramesContext     *frames;
     AVVulkanFramesContext *hwfc;
 
+    FFVkSPIRVCompiler     *spirv_compiler;
+
     /* Properties */
     int                 output_width;
     int                output_height;
diff --git a/libavutil/vulkan_glslang.c b/libavutil/vulkan_glslang.c
index 51f76c9418..ac5efe2365 100644
--- a/libavutil/vulkan_glslang.c
+++ b/libavutil/vulkan_glslang.c
@@ -24,10 +24,8 @@
 #include "mem.h"
 #include "avassert.h"
 
-#include "vulkan_glslang.h"
-
-static pthread_mutex_t glslang_mutex = PTHREAD_MUTEX_INITIALIZER;
-static int glslang_refcount = 0;
+static pthread_mutex_t glslc_mutex = PTHREAD_MUTEX_INITIALIZER;
+static int glslc_refcount = 0;
 
 static const glslang_resource_t glslc_resource_limits = {
     .max_lights = 32,
@@ -137,8 +135,10 @@ static const glslang_resource_t glslc_resource_limits = {
     }
 };
 
-int ff_vk_glslang_shader_compile(void *avctx, FFVkSPIRVShader *shd,
-                                 uint8_t **data, size_t *size, void **opaque)
+static int glslc_shader_compile(FFVkSPIRVCompiler *ctx, void *avctx,
+                                FFVkSPIRVShader *shd, uint8_t **data,
+                                size_t *size, const char *entrypoint,
+                                void **opaque)
 {
     const char *messages;
     glslang_shader_t *glslc_shader;
@@ -174,7 +174,7 @@ int ff_vk_glslang_shader_compile(void *avctx, FFVkSPIRVShader *shd,
         .resource                          = &glslc_resource_limits,
     };
 
-    av_assert0(glslang_refcount);
+    av_assert0(glslc_refcount);
 
     if (!(glslc_shader = glslang_shader_create(&glslc_input)))
         return AVERROR(ENOMEM);
@@ -218,8 +218,12 @@ int ff_vk_glslang_shader_compile(void *avctx, FFVkSPIRVShader *shd,
     glslang_program_SPIRV_generate(glslc_program, glslc_input.stage);
 
     messages = glslang_program_SPIRV_get_messages(glslc_program);
-    if (messages)
+    if (messages) {
+        ff_vk_print_shader(s, shd, AV_LOG_WARNING);
         av_log(avctx, AV_LOG_WARNING, "%s\n", messages);
+    } else {
+        ff_vk_print_shader(s, shd, AV_LOG_VERBOSE);
+    }
 
     glslang_shader_delete(glslc_shader);
 
@@ -230,27 +234,47 @@ int ff_vk_glslang_shader_compile(void *avctx, FFVkSPIRVShader *shd,
     return 0;
 }
 
-void ff_vk_glslang_shader_free(void *opaque)
+static void glslc_shader_free(FFVkSPIRVCompiler *ctx, void **opaque)
 {
-    glslang_program_delete(opaque);
+    if (!opaque || !*opaque)
+        return;
+
+    av_assert0(glslc_refcount);
+    glslang_program_delete(*opaque);
+    *opaque = NULL;
 }
 
-int ff_vk_glslang_init(void)
+static void glslc_uninit(FFVkSPIRVCompiler **ctx)
 {
-    int ret = 0;
+    if (!ctx || !*ctx)
+        return;
 
-    pthread_mutex_lock(&glslang_mutex);
-    if (glslang_refcount++ == 0)
-        ret = !glslang_initialize_process();
-    pthread_mutex_unlock(&glslang_mutex);
+    pthread_mutex_lock(&glslc_mutex);
+    if (glslc_refcount && (--glslc_refcount == 0))
+        glslang_finalize_process();
+    pthread_mutex_unlock(&glslc_mutex);
 
-    return ret;
+    av_freep(ctx);
 }
 
-void ff_vk_glslang_uninit(void)
+static FFVkSPIRVCompiler *ff_vk_glslang_init(void)
 {
-    pthread_mutex_lock(&glslang_mutex);
-    if (glslang_refcount && (--glslang_refcount == 0))
-        glslang_finalize_process();
-    pthread_mutex_unlock(&glslang_mutex);
+    FFVkSPIRVCompiler *ret = av_mallocz(sizeof(*ret));
+    if (!ret)
+        return NULL;
+
+    ret->compile_shader = glslc_shader_compile;
+    ret->free_shader    = glslc_shader_free;
+    ret->uninit         = glslc_uninit;
+
+    pthread_mutex_lock(&glslc_mutex);
+    if (!glslc_refcount++) {
+        if (!glslang_initialize_process()) {
+            av_freep(&ret);
+            glslc_refcount--;
+        }
+    }
+    pthread_mutex_unlock(&glslc_mutex);
+
+    return ret;
 }
diff --git a/libavutil/vulkan_glslang.h b/libavutil/vulkan_glslang.h
deleted file mode 100644
index b09d1251bf..0000000000
--- a/libavutil/vulkan_glslang.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef AVUTIL_GLSLANG_H
-#define AVUTIL_GLSLANG_H
-
-#include "vulkan.h"
-
-/**
- * Un/initialize glslang's global state. Thread-safe and reference counted.
- */
-int ff_vk_glslang_init(void);
-void ff_vk_glslang_uninit(void);
-
-/**
- * Compile GLSL into SPIR-V using glslang.
- */
-int ff_vk_glslang_shader_compile(void *avctx, FFVkSPIRVShader *shd,
-                                 uint8_t **data, size_t *size, void **opaque);
-
-/**
- * Frees the shader-specific context.
- */
-void ff_vk_glslang_shader_free(void *opaque);
-
-#endif /* AVUTIL_GLSLANG_H */



More information about the ffmpeg-cvslog mailing list