Unified · Split
| @@ -578,8 +578,6 @@ SKIPHEADERS-$(CONFIG_OPENCL) += opencl.h · 577 unmodified lines | |||
| 578 | SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_vpp.h | 578 | SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_vpp.h |
| 579 | SKIPHEADERS-$(CONFIG_VULKAN) += vulkan.h | 579 | SKIPHEADERS-$(CONFIG_VULKAN) += vulkan.h |
| 580 | 580 | ||
| 581 | OBJS-$(CONFIG_LIBGLSLANG) += glslang.o | ||
| 582 | |||
| 583 | TOOLS = graph2dot | 581 | TOOLS = graph2dot |
| 584 | TESTPROGS = drawutils filtfmts formats integral | 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 | s->output_format = AV_PIX_FMT_NONE; | 189 | s->output_format = AV_PIX_FMT_NONE; |
| 190 | 190 | ||
| 191 | if (ff_vk_glslang_init()) | ||
| 192 | return AVERROR_EXTERNAL; | ||
| 193 | |||
| 194 | return 0; | 191 | return 0; |
| 195 | } | 192 | } |
| @@ -16,12 +16,15 @@ · 15 unmodified lines | |||
| 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 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 | #include "avassert.h" | 19 | #include "avassert.h" |
| 20 | |||
| 21 | #include "vulkan.h" | ||
| 23 | #include "vulkan_loader.h" | 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 | /* Generic macro for creating contexts which need to keep their addresses | 28 | /* Generic macro for creating contexts which need to keep their addresses |
| 26 | * if another context is created. */ | 29 | * if another context is created. */ |
| 27 | #define FN_CREATING(ctx, type, shortname, array, num) \ | 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 | int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd, | 846 | int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd, |
| 844 | const char *entrypoint) | 847 | const char *entrypoint) |
| 845 | { | 848 | { |
| 846 | #if CONFIG_LIBGLSLANG | ||
| 847 | int err; | 849 | int err; |
| 848 | VkResult ret; | 850 | VkResult ret; |
| 849 | FFVulkanFunctions *vk = &s->vkfn; | 851 | FFVulkanFunctions *vk = &s->vkfn; |
| @@ -854,12 +856,21 @@ int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd, · 4 unmodified lines | |||
| 854 | 856 | ||
| 855 | shd->shader.pName = entrypoint; | 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 | if (err < 0) | 871 | if (err < 0) |
| 859 | return err; | 872 | return err; |
| 860 | 873 | ||
| 861 | ff_vk_print_shader(s, shd, AV_LOG_VERBOSE); | ||
| 862 | |||
| 863 | av_log(s, AV_LOG_VERBOSE, "Shader %s compiled! Size: %zu bytes\n", | 874 | av_log(s, AV_LOG_VERBOSE, "Shader %s compiled! Size: %zu bytes\n", |
| 864 | shd->name, spirv_size); | 875 | shd->name, spirv_size); |
| 865 | 876 | ||
| @@ -872,7 +883,7 @@ int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd, · 6 unmodified lines | |||
| 872 | ret = vk->CreateShaderModule(s->hwctx->act_dev, &shader_create, NULL, | 883 | ret = vk->CreateShaderModule(s->hwctx->act_dev, &shader_create, NULL, |
| 873 | &shd->shader.module); | 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 | if (ret != VK_SUCCESS) { | 888 | if (ret != VK_SUCCESS) { |
| 878 | av_log(s, AV_LOG_ERROR, "Unable to create shader module: %s\n", | 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 | return 0; | 894 | return 0; |
| 884 | #else | ||
| 885 | return AVERROR(ENOSYS); | ||
| 886 | #endif | ||
| 887 | } | 895 | } |
| 888 | 896 | ||
| 889 | static const struct descriptor_props { | 897 | static const struct descriptor_props { |
| @@ -1367,7 +1375,8 @@ void ff_vk_uninit(FFVulkanContext *s) · 477 unmodified lines | |||
| 1367 | { | 1375 | { |
| 1368 | FFVulkanFunctions *vk = &s->vkfn; | 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 | for (int i = 0; i < s->exec_ctx_num; i++) | 1381 | for (int i = 0; i < s->exec_ctx_num; i++) |
| 1373 | free_exec_ctx(s, s->exec_ctx[i]); | 1382 | free_exec_ctx(s, s->exec_ctx[i]); |
| @@ -22,6 +22,10 @@ · 21 unmodified lines | |||
| 22 | #define VK_NO_PROTOTYPES | 22 | #define VK_NO_PROTOTYPES |
| 23 | #define VK_ENABLE_BETA_EXTENSIONS | 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 | #include "pixdesc.h" | 29 | #include "pixdesc.h" |
| 26 | #include "bprint.h" | 30 | #include "bprint.h" |
| 27 | #include "hwcontext.h" | 31 | #include "hwcontext.h" |
| @@ -64,6 +68,15 @@ typedef struct FFVkSPIRVShader { · 36 unmodified lines | |||
| 64 | VkPipelineShaderStageCreateInfo shader; | 68 | VkPipelineShaderStageCreateInfo shader; |
| 65 | } FFVkSPIRVShader; | 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 | typedef struct FFVkSampler { | 80 | typedef struct FFVkSampler { |
| 68 | VkSampler sampler[4]; | 81 | VkSampler sampler[4]; |
| 69 | } FFVkSampler; | 82 | } FFVkSampler; |
| @@ -194,6 +207,8 @@ typedef struct FFVulkanContext { · 124 unmodified lines | |||
| 194 | AVHWFramesContext *frames; | 207 | AVHWFramesContext *frames; |
| 195 | AVVulkanFramesContext *hwfc; | 208 | AVVulkanFramesContext *hwfc; |
| 196 | 209 | ||
| 210 | FFVkSPIRVCompiler *spirv_compiler; | ||
| 211 | |||
| 197 | /* Properties */ | 212 | /* Properties */ |
| 198 | int output_width; | 213 | int output_width; |
| 199 | int output_height; | 214 | int output_height; |
| @@ -24,10 +24,8 @@ · 23 unmodified lines | |||
| 24 | #include "mem.h" | 24 | #include "mem.h" |
| 25 | #include "avassert.h" | 25 | #include "avassert.h" |
| 26 | 26 | ||
| 27 | #include "vulkan_glslang.h" | 27 | static pthread_mutex_t glslc_mutex = PTHREAD_MUTEX_INITIALIZER; |
| 28 | 28 | static int glslc_refcount = 0; | |
| 29 | static pthread_mutex_t glslang_mutex = PTHREAD_MUTEX_INITIALIZER; | ||
| 30 | static int glslang_refcount = 0; | ||
| 31 | 29 | ||
| 32 | static const glslang_resource_t glslc_resource_limits = { | 30 | static const glslang_resource_t glslc_resource_limits = { |
| 33 | .max_lights = 32, | 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, | 138 | static int glslc_shader_compile(FFVkSPIRVCompiler *ctx, void *avctx, |
| 141 | uint8_t **data, size_t *size, void **opaque) | 139 | FFVkSPIRVShader *shd, uint8_t **data, |
| 140 | size_t *size, const char *entrypoint, | ||
| 141 | void **opaque) | ||
| 142 | { | 142 | { |
| 143 | const char *messages; | 143 | const char *messages; |
| 144 | glslang_shader_t *glslc_shader; | 144 | glslang_shader_t *glslc_shader; |
| @@ -174,7 +174,7 @@ int ff_vk_glslang_shader_compile(void *avctx, FFVkSPIRVShader *shd, · 29 unmodified lines | |||
| 174 | .resource = &glslc_resource_limits, | 174 | .resource = &glslc_resource_limits, |
| 175 | }; | 175 | }; |
| 176 | 176 | ||
| 177 | av_assert0(glslang_refcount); | 177 | av_assert0(glslc_refcount); |
| 178 | 178 | ||
| 179 | if (!(glslc_shader = glslang_shader_create(&glslc_input))) | 179 | if (!(glslc_shader = glslang_shader_create(&glslc_input))) |
| 180 | return AVERROR(ENOMEM); | 180 | return AVERROR(ENOMEM); |
| @@ -218,8 +218,12 @@ int ff_vk_glslang_shader_compile(void *avctx, FFVkSPIRVShader *shd, · 37 unmodified lines | |||
| 218 | glslang_program_SPIRV_generate(glslc_program, glslc_input.stage); | 218 | glslang_program_SPIRV_generate(glslc_program, glslc_input.stage); |
| 219 | 219 | ||
| 220 | messages = glslang_program_SPIRV_get_messages(glslc_program); | 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 | av_log(avctx, AV_LOG_WARNING, "%s\n", messages); | 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 | glslang_shader_delete(glslc_shader); | 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 | return 0; | 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); | 252 | pthread_mutex_lock(&glslc_mutex); |
| 243 | if (glslang_refcount++ == 0) | 253 | if (glslc_refcount && (--glslc_refcount == 0)) |
| 244 | ret = !glslang_initialize_process(); | 254 | glslang_finalize_process(); |
| 245 | pthread_mutex_unlock(&glslang_mutex); | 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); | 262 | FFVkSPIRVCompiler *ret = av_mallocz(sizeof(*ret)); |
| 253 | if (glslang_refcount && (--glslang_refcount == 0)) | 263 | if (!ret) |
| 254 | glslang_finalize_process(); | 264 | return NULL; |
| 255 | pthread_mutex_unlock(&glslang_mutex); | 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 */ | ||