Unified · Split
| @@ -578,8 +578,6 @@ SKIPHEADERS-$(CONFIG_OPENCL) += opencl.h · 577 unmodified lines | ||
| 578 | 578 | SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_vpp.h |
| 579 | 579 | SKIPHEADERS-$(CONFIG_VULKAN) += vulkan.h |
| 580 | 580 | |
| 581 | −OBJS-$(CONFIG_LIBGLSLANG) += glslang.o | |
| 582 | − | |
| 583 | 581 | TOOLS = graph2dot |
| 584 | 582 | TESTPROGS = drawutils filtfmts formats integral |
| 585 | 583 | |
| @@ -1,19 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * This file is part of FFmpeg. | |
| 3 | − * | |
| 4 | − * FFmpeg is free software; you can redistribute it and/or | |
| 5 | − * modify it under the terms of the GNU Lesser General Public | |
| 6 | − * License as published by the Free Software Foundation; either | |
| 7 | − * version 2.1 of the License, or (at your option) any later version. | |
| 8 | − * | |
| 9 | − * FFmpeg is distributed in the hope that it will be useful, | |
| 10 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 12 | − * Lesser General Public License for more details. | |
| 13 | − * | |
| 14 | − * You should have received a copy of the GNU Lesser General Public | |
| 15 | − * License along with FFmpeg; if not, write to the Free Software | |
| 16 | − * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| 17 | − */ | |
| 18 | − | |
| 19 | −#include "libavutil/vulkan_glslang.c" | |
| @@ -188,8 +188,5 @@ int ff_vk_filter_init(AVFilterContext *avctx) · 187 unmodified lines | ||
| 188 | 188 | |
| 189 | 189 | s->output_format = AV_PIX_FMT_NONE; |
| 190 | 190 | |
| 191 | − if (ff_vk_glslang_init()) | |
| 192 | − return AVERROR_EXTERNAL; | |
| 193 | − | |
| 194 | 191 | return 0; |
| 195 | 192 | } |
| @@ -16,12 +16,15 @@ · 15 unmodified lines | ||
| 16 | 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 17 | 17 | */ |
| 18 | 18 | |
| 19 | −#include "vulkan.h" | |
| 20 | −#include "vulkan_glslang.h" | |
| 21 | − | |
| 22 | 19 | #include "avassert.h" |
| 20 | + | |
| 21 | +#include "vulkan.h" | |
| 23 | 22 | #include "vulkan_loader.h" |
| 24 | 23 | |
| 24 | +#if FF_VK_ENABLE_SHADER_COMPILATION && CONFIG_LIBGLSLANG | |
| 25 | +#include "vulkan_glslang.c" | |
| 26 | +#endif | |
| 27 | + | |
| 25 | 28 | /* Generic macro for creating contexts which need to keep their addresses |
| 26 | 29 | * if another context is created. */ |
| 27 | 30 | #define FN_CREATING(ctx, type, shortname, array, num) \ |
| @@ -843,7 +846,6 @@ void ff_vk_print_shader(void *ctx, FFVkSPIRVShader *shd, int prio) · 815 unmodified lines | ||
| 843 | 846 | int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd, |
| 844 | 847 | const char *entrypoint) |
| 845 | 848 | { |
| 846 | −#if CONFIG_LIBGLSLANG | |
| 847 | 849 | int err; |
| 848 | 850 | VkResult ret; |
| 849 | 851 | FFVulkanFunctions *vk = &s->vkfn; |
| @@ -854,12 +856,21 @@ int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd, · 4 unmodified lines | ||
| 854 | 856 | |
| 855 | 857 | shd->shader.pName = entrypoint; |
| 856 | 858 | |
| 857 | − err = ff_vk_glslang_shader_compile(s, shd, &spirv, &spirv_size, &priv); | |
| 859 | + if (!s->spirv_compiler) { | |
| 860 | +#if FF_VK_ENABLE_SHADER_COMPILATION && CONFIG_LIBGLSLANG | |
| 861 | + s->spirv_compiler = ff_vk_glslang_init(); | |
| 862 | +#else | |
| 863 | + return AVERROR(ENOSYS); | |
| 864 | +#endif | |
| 865 | + if (!s->spirv_compiler) | |
| 866 | + return AVERROR(ENOMEM); | |
| 867 | + } | |
| 868 | + | |
| 869 | + err = s->spirv_compiler->compile_shader(s->spirv_compiler, s, shd, &spirv, | |
| 870 | + &spirv_size, entrypoint, &priv); | |
| 858 | 871 | if (err < 0) |
| 859 | 872 | return err; |
| 860 | 873 | |
| 861 | − ff_vk_print_shader(s, shd, AV_LOG_VERBOSE); | |
| 862 | − | |
| 863 | 874 | av_log(s, AV_LOG_VERBOSE, "Shader %s compiled! Size: %zu bytes\n", |
| 864 | 875 | shd->name, spirv_size); |
| 865 | 876 | |
| @@ -872,7 +883,7 @@ int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd, · 6 unmodified lines | ||
| 872 | 883 | ret = vk->CreateShaderModule(s->hwctx->act_dev, &shader_create, NULL, |
| 873 | 884 | &shd->shader.module); |
| 874 | 885 | |
| 875 | − ff_vk_glslang_shader_free(priv); | |
| 886 | + s->spirv_compiler->free_shader(s->spirv_compiler, &priv); | |
| 876 | 887 | |
| 877 | 888 | if (ret != VK_SUCCESS) { |
| 878 | 889 | 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, · 2 unmodified lines | ||
| 881 | 892 | } |
| 882 | 893 | |
| 883 | 894 | return 0; |
| 884 | −#else | |
| 885 | − return AVERROR(ENOSYS); | |
| 886 | −#endif | |
| 887 | 895 | } |
| 888 | 896 | |
| 889 | 897 | static const struct descriptor_props { |
| @@ -1367,7 +1375,8 @@ void ff_vk_uninit(FFVulkanContext *s) · 477 unmodified lines | ||
| 1367 | 1375 | { |
| 1368 | 1376 | FFVulkanFunctions *vk = &s->vkfn; |
| 1369 | 1377 | |
| 1370 | − ff_vk_glslang_uninit(); | |
| 1378 | + if (s->spirv_compiler) | |
| 1379 | + s->spirv_compiler->uninit(&s->spirv_compiler); | |
| 1371 | 1380 | |
| 1372 | 1381 | for (int i = 0; i < s->exec_ctx_num; i++) |
| 1373 | 1382 | free_exec_ctx(s, s->exec_ctx[i]); |
| @@ -22,6 +22,10 @@ · 21 unmodified lines | ||
| 22 | 22 | #define VK_NO_PROTOTYPES |
| 23 | 23 | #define VK_ENABLE_BETA_EXTENSIONS |
| 24 | 24 | |
| 25 | +#ifndef FF_VK_ENABLE_SHADER_COMPILATION | |
| 26 | +#define FF_VK_ENABLE_SHADER_COMPILATION 1 | |
| 27 | +#endif | |
| 28 | + | |
| 25 | 29 | #include "pixdesc.h" |
| 26 | 30 | #include "bprint.h" |
| 27 | 31 | #include "hwcontext.h" |
| @@ -64,6 +68,15 @@ typedef struct FFVkSPIRVShader { · 36 unmodified lines | ||
| 64 | 68 | VkPipelineShaderStageCreateInfo shader; |
| 65 | 69 | } FFVkSPIRVShader; |
| 66 | 70 | |
| 71 | +typedef struct FFVkSPIRVCompiler { | |
| 72 | + void *priv; | |
| 73 | + int (*compile_shader)(struct FFVkSPIRVCompiler *ctx, void *avctx, | |
| 74 | + struct FFVkSPIRVShader *shd, uint8_t **data, | |
| 75 | + size_t *size, const char *entrypoint, void **opaque); | |
| 76 | + void (*free_shader)(struct FFVkSPIRVCompiler *ctx, void **opaque); | |
| 77 | + void (*uninit)(struct FFVkSPIRVCompiler **ctx); | |
| 78 | +} FFVkSPIRVCompiler; | |
| 79 | + | |
| 67 | 80 | typedef struct FFVkSampler { |
| 68 | 81 | VkSampler sampler[4]; |
| 69 | 82 | } FFVkSampler; |
| @@ -194,6 +207,8 @@ typedef struct FFVulkanContext { · 124 unmodified lines | ||
| 194 | 207 | AVHWFramesContext *frames; |
| 195 | 208 | AVVulkanFramesContext *hwfc; |
| 196 | 209 | |
| 210 | + FFVkSPIRVCompiler *spirv_compiler; | |
| 211 | + | |
| 197 | 212 | /* Properties */ |
| 198 | 213 | int output_width; |
| 199 | 214 | int output_height; |
| @@ -24,10 +24,8 @@ · 23 unmodified lines | ||
| 24 | 24 | #include "mem.h" |
| 25 | 25 | #include "avassert.h" |
| 26 | 26 | |
| 27 | −#include "vulkan_glslang.h" | |
| 28 | − | |
| 29 | −static pthread_mutex_t glslang_mutex = PTHREAD_MUTEX_INITIALIZER; | |
| 30 | −static int glslang_refcount = 0; | |
| 27 | +static pthread_mutex_t glslc_mutex = PTHREAD_MUTEX_INITIALIZER; | |
| 28 | +static int glslc_refcount = 0; | |
| 31 | 29 | |
| 32 | 30 | static const glslang_resource_t glslc_resource_limits = { |
| 33 | 31 | .max_lights = 32, |
| @@ -137,8 +135,10 @@ static const glslang_resource_t glslc_resource_limits = { · 103 unmodified lines | ||
| 137 | 135 | } |
| 138 | 136 | }; |
| 139 | 137 | |
| 140 | −int ff_vk_glslang_shader_compile(void *avctx, FFVkSPIRVShader *shd, | |
| 141 | − uint8_t **data, size_t *size, void **opaque) | |
| 138 | +static int glslc_shader_compile(FFVkSPIRVCompiler *ctx, void *avctx, | |
| 139 | + FFVkSPIRVShader *shd, uint8_t **data, | |
| 140 | + size_t *size, const char *entrypoint, | |
| 141 | + void **opaque) | |
| 142 | 142 | { |
| 143 | 143 | const char *messages; |
| 144 | 144 | glslang_shader_t *glslc_shader; |
| @@ -174,7 +174,7 @@ int ff_vk_glslang_shader_compile(void *avctx, FFVkSPIRVShader *shd, · 29 unmodified lines | ||
| 174 | 174 | .resource = &glslc_resource_limits, |
| 175 | 175 | }; |
| 176 | 176 | |
| 177 | − av_assert0(glslang_refcount); | |
| 177 | + av_assert0(glslc_refcount); | |
| 178 | 178 | |
| 179 | 179 | if (!(glslc_shader = glslang_shader_create(&glslc_input))) |
| 180 | 180 | return AVERROR(ENOMEM); |
| @@ -218,8 +218,12 @@ int ff_vk_glslang_shader_compile(void *avctx, FFVkSPIRVShader *shd, · 37 unmodified lines | ||
| 218 | 218 | glslang_program_SPIRV_generate(glslc_program, glslc_input.stage); |
| 219 | 219 | |
| 220 | 220 | messages = glslang_program_SPIRV_get_messages(glslc_program); |
| 221 | − if (messages) | |
| 221 | + if (messages) { | |
| 222 | + ff_vk_print_shader(s, shd, AV_LOG_WARNING); | |
| 222 | 223 | av_log(avctx, AV_LOG_WARNING, "%s\n", messages); |
| 224 | + } else { | |
| 225 | + ff_vk_print_shader(s, shd, AV_LOG_VERBOSE); | |
| 226 | + } | |
| 223 | 227 | |
| 224 | 228 | glslang_shader_delete(glslc_shader); |
| 225 | 229 | |
| @@ -230,27 +234,47 @@ int ff_vk_glslang_shader_compile(void *avctx, FFVkSPIRVShader *shd, · 4 unmodified lines | ||
| 230 | 234 | return 0; |
| 231 | 235 | } |
| 232 | 236 | |
| 233 | −void ff_vk_glslang_shader_free(void *opaque) | |
| 237 | +static void glslc_shader_free(FFVkSPIRVCompiler *ctx, void **opaque) | |
| 234 | 238 | { |
| 235 | − glslang_program_delete(opaque); | |
| 239 | + if (!opaque || !*opaque) | |
| 240 | + return; | |
| 241 | + | |
| 242 | + av_assert0(glslc_refcount); | |
| 243 | + glslang_program_delete(*opaque); | |
| 244 | + *opaque = NULL; | |
| 236 | 245 | } |
| 237 | 246 | |
| 238 | −int ff_vk_glslang_init(void) | |
| 247 | +static void glslc_uninit(FFVkSPIRVCompiler **ctx) | |
| 239 | 248 | { |
| 240 | − int ret = 0; | |
| 249 | + if (!ctx || !*ctx) | |
| 250 | + return; | |
| 241 | 251 | |
| 242 | − pthread_mutex_lock(&glslang_mutex); | |
| 243 | − if (glslang_refcount++ == 0) | |
| 244 | − ret = !glslang_initialize_process(); | |
| 245 | − pthread_mutex_unlock(&glslang_mutex); | |
| 252 | + pthread_mutex_lock(&glslc_mutex); | |
| 253 | + if (glslc_refcount && (--glslc_refcount == 0)) | |
| 254 | + glslang_finalize_process(); | |
| 255 | + pthread_mutex_unlock(&glslc_mutex); | |
| 246 | 256 | |
| 247 | − return ret; | |
| 257 | + av_freep(ctx); | |
| 248 | 258 | } |
| 249 | 259 | |
| 250 | −void ff_vk_glslang_uninit(void) | |
| 260 | +static FFVkSPIRVCompiler *ff_vk_glslang_init(void) | |
| 251 | 261 | { |
| 252 | − pthread_mutex_lock(&glslang_mutex); | |
| 253 | − if (glslang_refcount && (--glslang_refcount == 0)) | |
| 254 | − glslang_finalize_process(); | |
| 255 | − pthread_mutex_unlock(&glslang_mutex); | |
| 262 | + FFVkSPIRVCompiler *ret = av_mallocz(sizeof(*ret)); | |
| 263 | + if (!ret) | |
| 264 | + return NULL; | |
| 265 | + | |
| 266 | + ret->compile_shader = glslc_shader_compile; | |
| 267 | + ret->free_shader = glslc_shader_free; | |
| 268 | + ret->uninit = glslc_uninit; | |
| 269 | + | |
| 270 | + pthread_mutex_lock(&glslc_mutex); | |
| 271 | + if (!glslc_refcount++) { | |
| 272 | + if (!glslang_initialize_process()) { | |
| 273 | + av_freep(&ret); | |
| 274 | + glslc_refcount--; | |
| 275 | + } | |
| 276 | + } | |
| 277 | + pthread_mutex_unlock(&glslc_mutex); | |
| 278 | + | |
| 279 | + return ret; | |
| 256 | 280 | } |
| @@ -1,41 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * This file is part of FFmpeg. | |
| 3 | − * | |
| 4 | − * FFmpeg is free software; you can redistribute it and/or | |
| 5 | − * modify it under the terms of the GNU Lesser General Public | |
| 6 | − * License as published by the Free Software Foundation; either | |
| 7 | − * version 2.1 of the License, or (at your option) any later version. | |
| 8 | − * | |
| 9 | − * FFmpeg is distributed in the hope that it will be useful, | |
| 10 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 12 | − * Lesser General Public License for more details. | |
| 13 | − * | |
| 14 | − * You should have received a copy of the GNU Lesser General Public | |
| 15 | − * License along with FFmpeg; if not, write to the Free Software | |
| 16 | − * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| 17 | − */ | |
| 18 | − | |
| 19 | −#ifndef AVUTIL_GLSLANG_H | |
| 20 | −#define AVUTIL_GLSLANG_H | |
| 21 | − | |
| 22 | −#include "vulkan.h" | |
| 23 | − | |
| 24 | −/** | |
| 25 | − * Un/initialize glslang's global state. Thread-safe and reference counted. | |
| 26 | − */ | |
| 27 | −int ff_vk_glslang_init(void); | |
| 28 | −void ff_vk_glslang_uninit(void); | |
| 29 | − | |
| 30 | −/** | |
| 31 | − * Compile GLSL into SPIR-V using glslang. | |
| 32 | − */ | |
| 33 | −int ff_vk_glslang_shader_compile(void *avctx, FFVkSPIRVShader *shd, | |
| 34 | − uint8_t **data, size_t *size, void **opaque); | |
| 35 | − | |
| 36 | −/** | |
| 37 | − * Frees the shader-specific context. | |
| 38 | − */ | |
| 39 | −void ff_vk_glslang_shader_free(void *opaque); | |
| 40 | − | |
| 41 | −#endif /* AVUTIL_GLSLANG_H */ | |