diff options
author | Lynne <dev@lynne.ee> | 2021-11-08 11:31:05 +0300 |
---|---|---|
committer | Lynne <dev@lynne.ee> | 2021-11-12 07:23:41 +0300 |
commit | 246f841b53e16f2cccf3101cb61c264014f54e5c (patch) | |
tree | 6850f70277522b919b3b14d7b312e8bf960a4cac /libavfilter | |
parent | fef85c376adabc15715ed8d9c53cc8e889c9c7dc (diff) |
lavfi/glslang: migrate to the C API and robustify library detection
Finally, this is as close to usable as it gets for glslang.
Much faster to compile as well, and eliminates the need for a C++
compiler, which is great.
Also, changes to the resource limits won't break users, as we
can use designated initializers in C90.
Diffstat (limited to 'libavfilter')
-rw-r--r-- | libavfilter/glslang.c | 256 | ||||
-rw-r--r-- | libavfilter/glslang.cpp | 241 | ||||
-rw-r--r-- | libavfilter/glslang.h | 41 | ||||
-rw-r--r-- | libavfilter/vf_avgblur_vulkan.c | 2 | ||||
-rw-r--r-- | libavfilter/vf_chromaber_vulkan.c | 4 | ||||
-rw-r--r-- | libavfilter/vf_overlay_vulkan.c | 4 | ||||
-rw-r--r-- | libavfilter/vf_scale_vulkan.c | 4 | ||||
-rw-r--r-- | libavfilter/vulkan.c | 63 | ||||
-rw-r--r-- | libavfilter/vulkan.h | 21 |
9 files changed, 315 insertions, 321 deletions
diff --git a/libavfilter/glslang.c b/libavfilter/glslang.c new file mode 100644 index 0000000000..e5a8d4dc2a --- /dev/null +++ b/libavfilter/glslang.c @@ -0,0 +1,256 @@ +/* + * 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 <pthread.h> + +#include <glslang/build_info.h> +#include <glslang/Include/glslang_c_interface.h> + +#include "libavutil/mem.h" +#include "libavutil/avassert.h" + +#include "glslang.h" + +static pthread_mutex_t glslang_mutex = PTHREAD_MUTEX_INITIALIZER; +static int glslang_refcount = 0; + +static const glslang_resource_t glslc_resource_limits = { + .max_lights = 32, + .max_clip_planes = 6, + .max_texture_units = 32, + .max_texture_coords = 32, + .max_vertex_attribs = 64, + .max_vertex_uniform_components = 4096, + .max_varying_floats = 64, + .max_vertex_texture_image_units = 32, + .max_combined_texture_image_units = 80, + .max_texture_image_units = 32, + .max_fragment_uniform_components = 4096, + .max_draw_buffers = 32, + .max_vertex_uniform_vectors = 128, + .max_varying_vectors = 8, + .max_fragment_uniform_vectors = 16, + .max_vertex_output_vectors = 16, + .max_fragment_input_vectors = 15, + .min_program_texel_offset = -8, + .max_program_texel_offset = 7, + .max_clip_distances = 8, + .max_compute_work_group_count_x = 65535, + .max_compute_work_group_count_y = 65535, + .max_compute_work_group_count_z = 65535, + .max_compute_work_group_size_x = 1024, + .max_compute_work_group_size_y = 1024, + .max_compute_work_group_size_z = 64, + .max_compute_uniform_components = 1024, + .max_compute_texture_image_units = 16, + .max_compute_image_uniforms = 8, + .max_compute_atomic_counters = 8, + .max_compute_atomic_counter_buffers = 1, + .max_varying_components = 60, + .max_vertex_output_components = 64, + .max_geometry_input_components = 64, + .max_geometry_output_components = 128, + .max_fragment_input_components = 128, + .max_image_units = 8, + .max_combined_image_units_and_fragment_outputs = 8, + .max_combined_shader_output_resources = 8, + .max_image_samples = 0, + .max_vertex_image_uniforms = 0, + .max_tess_control_image_uniforms = 0, + .max_tess_evaluation_image_uniforms = 0, + .max_geometry_image_uniforms = 0, + .max_fragment_image_uniforms = 8, + .max_combined_image_uniforms = 8, + .max_geometry_texture_image_units = 16, + .max_geometry_output_vertices = 256, + .max_geometry_total_output_components = 1024, + .max_geometry_uniform_components = 1024, + .max_geometry_varying_components = 64, + .max_tess_control_input_components = 128, + .max_tess_control_output_components = 128, + .max_tess_control_texture_image_units = 16, + .max_tess_control_uniform_components = 1024, + .max_tess_control_total_output_components = 4096, + .max_tess_evaluation_input_components = 128, + .max_tess_evaluation_output_components = 128, + .max_tess_evaluation_texture_image_units = 16, + .max_tess_evaluation_uniform_components = 1024, + .max_tess_patch_components = 120, + .max_patch_vertices = 32, + .max_tess_gen_level = 64, + .max_viewports = 16, + .max_vertex_atomic_counters = 0, + .max_tess_control_atomic_counters = 0, + .max_tess_evaluation_atomic_counters = 0, + .max_geometry_atomic_counters = 0, + .max_fragment_atomic_counters = 8, + .max_combined_atomic_counters = 8, + .max_atomic_counter_bindings = 1, + .max_vertex_atomic_counter_buffers = 0, + .max_tess_control_atomic_counter_buffers = 0, + .max_tess_evaluation_atomic_counter_buffers = 0, + .max_geometry_atomic_counter_buffers = 0, + .max_fragment_atomic_counter_buffers = 1, + .max_combined_atomic_counter_buffers = 1, + .max_atomic_counter_buffer_size = 16384, + .max_transform_feedback_buffers = 4, + .max_transform_feedback_interleaved_components = 64, + .max_cull_distances = 8, + .max_combined_clip_and_cull_distances = 8, + .max_samples = 4, + .max_mesh_output_vertices_nv = 256, + .max_mesh_output_primitives_nv = 512, + .max_mesh_work_group_size_x_nv = 32, + .max_mesh_work_group_size_y_nv = 1, + .max_mesh_work_group_size_z_nv = 1, + .max_task_work_group_size_x_nv = 32, + .max_task_work_group_size_y_nv = 1, + .max_task_work_group_size_z_nv = 1, + .max_mesh_view_count_nv = 4, + .maxDualSourceDrawBuffersEXT = 1, + + .limits = { + .non_inductive_for_loops = 1, + .while_loops = 1, + .do_while_loops = 1, + .general_uniform_indexing = 1, + .general_attribute_matrix_vector_indexing = 1, + .general_varying_indexing = 1, + .general_sampler_indexing = 1, + .general_variable_indexing = 1, + .general_constant_matrix_vector_indexing = 1, + } +}; + +int ff_vk_glslang_shader_compile(AVFilterContext *avctx, FFSPIRVShader *shd, + uint8_t **data, size_t *size, void **opaque) +{ + const char *messages; + glslang_shader_t *glslc_shader; + glslang_program_t *glslc_program; + + static const glslang_stage_t glslc_stage[] = { + [VK_SHADER_STAGE_VERTEX_BIT] = GLSLANG_STAGE_VERTEX, + [VK_SHADER_STAGE_FRAGMENT_BIT] = GLSLANG_STAGE_FRAGMENT, + [VK_SHADER_STAGE_COMPUTE_BIT] = GLSLANG_STAGE_COMPUTE, + }; + + const glslang_input_t glslc_input = { + .language = GLSLANG_SOURCE_GLSL, + .stage = glslc_stage[shd->shader.stage], + .client = GLSLANG_CLIENT_VULKAN, + /* GLSLANG_TARGET_VULKAN_1_2 before 11.6 resulted in targeting 1.0 */ +#if (((GLSLANG_VERSION_MAJOR) > 11) || ((GLSLANG_VERSION_MAJOR) == 11 && \ + (((GLSLANG_VERSION_MINOR) > 6) || ((GLSLANG_VERSION_MINOR) == 6 && \ + ((GLSLANG_VERSION_PATCH) > 0))))) + .client_version = GLSLANG_TARGET_VULKAN_1_2, + .target_language_version = GLSLANG_TARGET_SPV_1_5, +#else + .client_version = GLSLANG_TARGET_VULKAN_1_1, + .target_language_version = GLSLANG_TARGET_SPV_1_3, +#endif + .target_language = GLSLANG_TARGET_SPV, + .code = shd->src.str, + .default_version = 460, + .default_profile = GLSLANG_NO_PROFILE, + .force_default_version_and_profile = false, + .forward_compatible = false, + .messages = GLSLANG_MSG_DEFAULT_BIT, + .resource = &glslc_resource_limits, + }; + + av_assert0(glslang_refcount); + + if (!(glslc_shader = glslang_shader_create(&glslc_input))) + return AVERROR(ENOMEM); + + if (!glslang_shader_preprocess(glslc_shader, &glslc_input)) { + ff_vk_print_shader(avctx, shd, AV_LOG_WARNING); + av_log(avctx, AV_LOG_ERROR, "Unable to preprocess shader: %s (%s)!\n", + glslang_shader_get_info_log(glslc_shader), + glslang_shader_get_info_debug_log(glslc_shader)); + glslang_shader_delete(glslc_shader); + return AVERROR(EINVAL); + } + + if (!glslang_shader_parse(glslc_shader, &glslc_input)) { + ff_vk_print_shader(avctx, shd, AV_LOG_WARNING); + av_log(avctx, AV_LOG_ERROR, "Unable to parse shader: %s (%s)!\n", + glslang_shader_get_info_log(glslc_shader), + glslang_shader_get_info_debug_log(glslc_shader)); + glslang_shader_delete(glslc_shader); + return AVERROR(EINVAL); + } + + if (!(glslc_program = glslang_program_create())) { + glslang_shader_delete(glslc_shader); + return AVERROR(EINVAL); + } + + glslang_program_add_shader(glslc_program, glslc_shader); + + if (!glslang_program_link(glslc_program, GLSLANG_MSG_SPV_RULES_BIT | + GLSLANG_MSG_VULKAN_RULES_BIT)) { + ff_vk_print_shader(avctx, shd, AV_LOG_WARNING); + av_log(avctx, AV_LOG_ERROR, "Unable to link shader: %s (%s)!\n", + glslang_program_get_info_log(glslc_program), + glslang_program_get_info_debug_log(glslc_program)); + glslang_program_delete(glslc_program); + glslang_shader_delete(glslc_shader); + return AVERROR(EINVAL); + } + + glslang_program_SPIRV_generate(glslc_program, glslc_input.stage); + + messages = glslang_program_SPIRV_get_messages(glslc_program); + if (messages) + av_log(avctx, AV_LOG_WARNING, "%s\n", messages); + + glslang_shader_delete(glslc_shader); + + *size = glslang_program_SPIRV_get_size(glslc_program) * sizeof(unsigned int); + *data = (void *)glslang_program_SPIRV_get_ptr(glslc_program); + *opaque = glslc_program; + + return 0; +} + +void ff_vk_glslang_shader_free(void *opaque) +{ + glslang_program_delete(opaque); +} + +int ff_vk_glslang_init(void) +{ + int ret = 0; + + pthread_mutex_lock(&glslang_mutex); + if (glslang_refcount++ == 0) + ret = !glslang_initialize_process(); + pthread_mutex_unlock(&glslang_mutex); + + return ret; +} + +void ff_vk_glslang_uninit(void) +{ + pthread_mutex_lock(&glslang_mutex); + if (glslang_refcount && (--glslang_refcount == 0)) + glslang_finalize_process(); + pthread_mutex_unlock(&glslang_mutex); +} diff --git a/libavfilter/glslang.cpp b/libavfilter/glslang.cpp deleted file mode 100644 index 986bddd789..0000000000 --- a/libavfilter/glslang.cpp +++ /dev/null @@ -1,241 +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 <pthread.h> - -extern "C" { -#include "libavutil/mem.h" -#include "libavutil/avassert.h" -} - -#include <glslang/Include/ResourceLimits.h> -#include <glslang/Public/ShaderLang.h> -#include <glslang/SPIRV/GlslangToSpv.h> - -#include "glslang.h" - -using namespace glslang; - -static pthread_mutex_t glslang_mutex = PTHREAD_MUTEX_INITIALIZER; -static int glslang_refcount = 0; - -/* We require Vulkan 1.1 */ -#define GLSL_VERSION EShTargetVulkan_1_1 - -/* Vulkan 1.1 implementations require SPIR-V 1.3 to be implemented */ -#define SPIRV_VERSION EShTargetSpv_1_3 - -// Taken from glslang's examples, which apparently generally bases the choices -// on OpenGL specification limits -static const TBuiltInResource DefaultTBuiltInResource = { - /* .MaxLights = */ 32, - /* .MaxClipPlanes = */ 6, - /* .MaxTextureUnits = */ 32, - /* .MaxTextureCoords = */ 32, - /* .MaxVertexAttribs = */ 64, - /* .MaxVertexUniformComponents = */ 4096, - /* .MaxVaryingFloats = */ 64, - /* .MaxVertexTextureImageUnits = */ 32, - /* .MaxCombinedTextureImageUnits = */ 80, - /* .MaxTextureImageUnits = */ 32, - /* .MaxFragmentUniformComponents = */ 4096, - /* .MaxDrawBuffers = */ 32, - /* .MaxVertexUniformVectors = */ 128, - /* .MaxVaryingVectors = */ 8, - /* .MaxFragmentUniformVectors = */ 16, - /* .MaxVertexOutputVectors = */ 16, - /* .MaxFragmentInputVectors = */ 15, - /* .MinProgramTexelOffset = */ -8, - /* .MaxProgramTexelOffset = */ 7, - /* .MaxClipDistances = */ 8, - /* .MaxComputeWorkGroupCountX = */ 65535, - /* .MaxComputeWorkGroupCountY = */ 65535, - /* .MaxComputeWorkGroupCountZ = */ 65535, - /* .MaxComputeWorkGroupSizeX = */ 1024, - /* .MaxComputeWorkGroupSizeY = */ 1024, - /* .MaxComputeWorkGroupSizeZ = */ 64, - /* .MaxComputeUniformComponents = */ 1024, - /* .MaxComputeTextureImageUnits = */ 16, - /* .MaxComputeImageUniforms = */ 8, - /* .MaxComputeAtomicCounters = */ 8, - /* .MaxComputeAtomicCounterBuffers = */ 1, - /* .MaxVaryingComponents = */ 60, - /* .MaxVertexOutputComponents = */ 64, - /* .MaxGeometryInputComponents = */ 64, - /* .MaxGeometryOutputComponents = */ 128, - /* .MaxFragmentInputComponents = */ 128, - /* .MaxImageUnits = */ 8, - /* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8, - /* .MaxCombinedShaderOutputResources = */ 8, - /* .MaxImageSamples = */ 0, - /* .MaxVertexImageUniforms = */ 0, - /* .MaxTessControlImageUniforms = */ 0, - /* .MaxTessEvaluationImageUniforms = */ 0, - /* .MaxGeometryImageUniforms = */ 0, - /* .MaxFragmentImageUniforms = */ 8, - /* .MaxCombinedImageUniforms = */ 8, - /* .MaxGeometryTextureImageUnits = */ 16, - /* .MaxGeometryOutputVertices = */ 256, - /* .MaxGeometryTotalOutputComponents = */ 1024, - /* .MaxGeometryUniformComponents = */ 1024, - /* .MaxGeometryVaryingComponents = */ 64, - /* .MaxTessControlInputComponents = */ 128, - /* .MaxTessControlOutputComponents = */ 128, - /* .MaxTessControlTextureImageUnits = */ 16, - /* .MaxTessControlUniformComponents = */ 1024, - /* .MaxTessControlTotalOutputComponents = */ 4096, - /* .MaxTessEvaluationInputComponents = */ 128, - /* .MaxTessEvaluationOutputComponents = */ 128, - /* .MaxTessEvaluationTextureImageUnits = */ 16, - /* .MaxTessEvaluationUniformComponents = */ 1024, - /* .MaxTessPatchComponents = */ 120, - /* .MaxPatchVertices = */ 32, - /* .MaxTessGenLevel = */ 64, - /* .MaxViewports = */ 16, - /* .MaxVertexAtomicCounters = */ 0, - /* .MaxTessControlAtomicCounters = */ 0, - /* .MaxTessEvaluationAtomicCounters = */ 0, - /* .MaxGeometryAtomicCounters = */ 0, - /* .MaxFragmentAtomicCounters = */ 8, - /* .MaxCombinedAtomicCounters = */ 8, - /* .MaxAtomicCounterBindings = */ 1, - /* .MaxVertexAtomicCounterBuffers = */ 0, - /* .MaxTessControlAtomicCounterBuffers = */ 0, - /* .MaxTessEvaluationAtomicCounterBuffers = */ 0, - /* .MaxGeometryAtomicCounterBuffers = */ 0, - /* .MaxFragmentAtomicCounterBuffers = */ 1, - /* .MaxCombinedAtomicCounterBuffers = */ 1, - /* .MaxAtomicCounterBufferSize = */ 16384, - /* .MaxTransformFeedbackBuffers = */ 4, - /* .MaxTransformFeedbackInterleavedComponents = */ 64, - /* .MaxCullDistances = */ 8, - /* .MaxCombinedClipAndCullDistances = */ 8, - /* .MaxSamples = */ 4, - /* .maxMeshOutputVerticesNV = */ 256, - /* .maxMeshOutputPrimitivesNV = */ 512, - /* .maxMeshWorkGroupSizeX_NV = */ 32, - /* .maxMeshWorkGroupSizeY_NV = */ 1, - /* .maxMeshWorkGroupSizeZ_NV = */ 1, - /* .maxTaskWorkGroupSizeX_NV = */ 32, - /* .maxTaskWorkGroupSizeY_NV = */ 1, - /* .maxTaskWorkGroupSizeZ_NV = */ 1, - /* .maxMeshViewCountNV = */ 4, - - .limits = { - /* .nonInductiveForLoops = */ 1, - /* .whileLoops = */ 1, - /* .doWhileLoops = */ 1, - /* .generalUniformIndexing = */ 1, - /* .generalAttributeMatrixVectorIndexing = */ 1, - /* .generalVaryingIndexing = */ 1, - /* .generalSamplerIndexing = */ 1, - /* .generalVariableIndexing = */ 1, - /* .generalConstantMatrixVectorIndexing = */ 1, - } -}; - -GLSlangResult *glslang_compile(const char *glsl, enum GLSlangStage stage) -{ - GLSlangResult *res = (GLSlangResult *)av_mallocz(sizeof(*res)); - if (!res) - return NULL; - - static const EShLanguage lang[] = { - [GLSLANG_VERTEX] = EShLangVertex, - [GLSLANG_FRAGMENT] = EShLangFragment, - [GLSLANG_COMPUTE] = EShLangCompute, - }; - - assert(glslang_refcount); - TShader *shader = new TShader(lang[stage]); - if (!shader) { - res->rval = AVERROR(ENOMEM); - return res; - } - - shader->setEnvClient(EShClientVulkan, GLSL_VERSION); - shader->setEnvTarget(EShTargetSpv, SPIRV_VERSION); - shader->setStrings(&glsl, 1); - if (!shader->parse(&DefaultTBuiltInResource, GLSL_VERSION, true, EShMsgDefault)) { - res->error_msg = av_strdup(shader->getInfoLog()); - res->rval = AVERROR_EXTERNAL; - delete shader; - return res; - } - - TProgram *prog = new TProgram(); - if (!prog) { - res->rval = AVERROR(ENOMEM); - delete shader; - return res; - } - - prog->addShader(shader); - if (!prog->link(EShMsgDefault)) { - res->error_msg = av_strdup(prog->getInfoLog()); - res->rval = AVERROR_EXTERNAL; - delete shader; - delete prog; - return res; - } - - std::vector<unsigned int> spirv; /* Result */ - - SpvOptions options; /* Options - by default all optimizations are off */ - options.generateDebugInfo = false; /* Makes sense for files but not here */ - options.disassemble = false; /* Will print disassembly on compilation */ - options.validate = false; /* Validates the generated SPIRV, unneeded */ - options.disableOptimizer = false; /* For debugging */ - options.optimizeSize = true; /* Its faster */ - - GlslangToSpv(*prog->getIntermediate(lang[stage]), spirv, NULL, &options); - - res->size = spirv.size()*sizeof(unsigned int); - res->data = av_memdup(spirv.data(), res->size); - if (!res->data) { - res->rval = AVERROR(ENOMEM); - delete shader; - delete prog; - return res; - } - - delete shader; - delete prog; - - return res; -} - -int glslang_init(void) -{ - int ret = 0; - - pthread_mutex_lock(&glslang_mutex); - if (glslang_refcount++ == 0) - ret = !InitializeProcess(); - pthread_mutex_unlock(&glslang_mutex); - - return ret; -} - -void glslang_uninit(void) -{ - pthread_mutex_lock(&glslang_mutex); - if (glslang_refcount && (--glslang_refcount == 0)) - FinalizeProcess(); - pthread_mutex_unlock(&glslang_mutex); -} diff --git a/libavfilter/glslang.h b/libavfilter/glslang.h index d33808b945..93a077dbfc 100644 --- a/libavfilter/glslang.h +++ b/libavfilter/glslang.h @@ -19,34 +19,23 @@ #ifndef AVFILTER_GLSLANG_H #define AVFILTER_GLSLANG_H -#include <stdlib.h> +#include "vulkan.h" -#ifdef __cplusplus -extern "C" { -#endif - -int glslang_init(void); -void glslang_uninit(void); - -typedef struct GLSlangResult { - int rval; - char *error_msg; - - void *data; /* Shader data or NULL */ - size_t size; -} GLSlangResult; - -enum GLSlangStage { - GLSLANG_VERTEX, - GLSLANG_FRAGMENT, - GLSLANG_COMPUTE, -}; +/** + * 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 a SPIRV stream, if possible */ -GLSlangResult *glslang_compile(const char *glsl, enum GLSlangStage stage); +/** + * Compile GLSL into SPIR-V using glslang. + */ +int ff_vk_glslang_shader_compile(AVFilterContext *avctx, FFSPIRVShader *shd, + uint8_t **data, size_t *size, void **opaque); -#ifdef __cplusplus -} -#endif +/** + * Frees the shader-specific context. + */ +void ff_vk_glslang_shader_free(void *opaque); #endif /* AVFILTER_GLSLANG_H */ diff --git a/libavfilter/vf_avgblur_vulkan.c b/libavfilter/vf_avgblur_vulkan.c index 158ccf02df..bf02dab1db 100644 --- a/libavfilter/vf_avgblur_vulkan.c +++ b/libavfilter/vf_avgblur_vulkan.c @@ -70,7 +70,7 @@ static const char blur_kernel[] = { static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) { int err; - SPIRVShader *shd; + FFSPIRVShader *shd; AvgBlurVulkanContext *s = ctx->priv; const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); VkSampler *sampler = ff_vk_init_sampler(ctx, 1, VK_FILTER_LINEAR); diff --git a/libavfilter/vf_chromaber_vulkan.c b/libavfilter/vf_chromaber_vulkan.c index 2503972c2a..25ef20fe73 100644 --- a/libavfilter/vf_chromaber_vulkan.c +++ b/libavfilter/vf_chromaber_vulkan.c @@ -109,8 +109,8 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) }, }; - SPIRVShader *shd = ff_vk_init_shader(ctx, s->pl, "chromaber_compute", - VK_SHADER_STAGE_COMPUTE_BIT); + FFSPIRVShader *shd = ff_vk_init_shader(ctx, s->pl, "chromaber_compute", + VK_SHADER_STAGE_COMPUTE_BIT); if (!shd) return AVERROR(ENOMEM); diff --git a/libavfilter/vf_overlay_vulkan.c b/libavfilter/vf_overlay_vulkan.c index 77b3668819..f08800af2c 100644 --- a/libavfilter/vf_overlay_vulkan.c +++ b/libavfilter/vf_overlay_vulkan.c @@ -136,8 +136,8 @@ static av_cold int init_filter(AVFilterContext *ctx) .buf_content = "ivec2 o_offset[3], o_size[3];", }; - SPIRVShader *shd = ff_vk_init_shader(ctx, s->pl, "overlay_compute", - VK_SHADER_STAGE_COMPUTE_BIT); + FFSPIRVShader *shd = ff_vk_init_shader(ctx, s->pl, "overlay_compute", + VK_SHADER_STAGE_COMPUTE_BIT); if (!shd) return AVERROR(ENOMEM); diff --git a/libavfilter/vf_scale_vulkan.c b/libavfilter/vf_scale_vulkan.c index 83e101954b..680e9c2f4f 100644 --- a/libavfilter/vf_scale_vulkan.c +++ b/libavfilter/vf_scale_vulkan.c @@ -170,8 +170,8 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) .buf_content = "mat4 yuv_matrix;", }; - SPIRVShader *shd = ff_vk_init_shader(ctx, s->pl, "scale_compute", - VK_SHADER_STAGE_COMPUTE_BIT); + FFSPIRVShader *shd = ff_vk_init_shader(ctx, s->pl, "scale_compute", + VK_SHADER_STAGE_COMPUTE_BIT); if (!shd) return AVERROR(ENOMEM); diff --git a/libavfilter/vulkan.c b/libavfilter/vulkan.c index 4ac8e5e90a..c9a2ae4593 100644 --- a/libavfilter/vulkan.c +++ b/libavfilter/vulkan.c @@ -794,7 +794,7 @@ int ff_vk_filter_init(AVFilterContext *avctx) s->output_format = AV_PIX_FMT_NONE; - if (glslang_init()) + if (ff_vk_glslang_init()) return AVERROR_EXTERNAL; return 0; @@ -924,11 +924,11 @@ int ff_vk_create_imageview(AVFilterContext *avctx, FFVkExecContext *e, return 0; } -FN_CREATING(VulkanPipeline, SPIRVShader, shader, shaders, shaders_num) -SPIRVShader *ff_vk_init_shader(AVFilterContext *avctx, VulkanPipeline *pl, - const char *name, VkShaderStageFlags stage) +FN_CREATING(VulkanPipeline, FFSPIRVShader, shader, shaders, shaders_num) +FFSPIRVShader *ff_vk_init_shader(AVFilterContext *avctx, VulkanPipeline *pl, + const char *name, VkShaderStageFlags stage) { - SPIRVShader *shd = create_shader(pl); + FFSPIRVShader *shd = create_shader(pl); if (!shd) return NULL; @@ -946,7 +946,7 @@ SPIRVShader *ff_vk_init_shader(AVFilterContext *avctx, VulkanPipeline *pl, return shd; } -void ff_vk_set_compute_shader_sizes(AVFilterContext *avctx, SPIRVShader *shd, +void ff_vk_set_compute_shader_sizes(AVFilterContext *avctx, FFSPIRVShader *shd, int local_size[3]) { shd->local_size[0] = local_size[0]; @@ -958,7 +958,7 @@ void ff_vk_set_compute_shader_sizes(AVFilterContext *avctx, SPIRVShader *shd, shd->local_size[0], shd->local_size[1], shd->local_size[2]); } -static void print_shader(AVFilterContext *avctx, SPIRVShader *shd, int prio) +void ff_vk_print_shader(AVFilterContext *avctx, FFSPIRVShader *shd, int prio) { int line = 0; const char *p = shd->src.str; @@ -979,51 +979,39 @@ static void print_shader(AVFilterContext *avctx, SPIRVShader *shd, int prio) av_bprint_finalize(&buf, NULL); } -int ff_vk_compile_shader(AVFilterContext *avctx, SPIRVShader *shd, +int ff_vk_compile_shader(AVFilterContext *avctx, FFSPIRVShader *shd, const char *entrypoint) { + int err; VkResult ret; VulkanFilterContext *s = avctx->priv; FFVulkanFunctions *vk = &s->vkfn; VkShaderModuleCreateInfo shader_create; - GLSlangResult *res; - - static const enum GLSlangStage emap[] = { - [VK_SHADER_STAGE_VERTEX_BIT] = GLSLANG_VERTEX, - [VK_SHADER_STAGE_FRAGMENT_BIT] = GLSLANG_FRAGMENT, - [VK_SHADER_STAGE_COMPUTE_BIT] = GLSLANG_COMPUTE, - }; + uint8_t *spirv; + size_t spirv_size; + void *priv; shd->shader.pName = entrypoint; - res = glslang_compile(shd->src.str, emap[shd->shader.stage]); - if (!res) - return AVERROR(ENOMEM); + err = ff_vk_glslang_shader_compile(avctx, shd, &spirv, &spirv_size, &priv); + if (err < 0) + return err; - if (res->rval) { - av_log(avctx, AV_LOG_ERROR, "Error compiling shader %s: %s!\n", - shd->name, av_err2str(res->rval)); - print_shader(avctx, shd, AV_LOG_ERROR); - if (res->error_msg) - av_log(avctx, AV_LOG_ERROR, "%s", res->error_msg); - av_free(res->error_msg); - return res->rval; - } + ff_vk_print_shader(avctx, shd, AV_LOG_VERBOSE); - print_shader(avctx, shd, AV_LOG_VERBOSE); + av_log(avctx, AV_LOG_VERBOSE, "Shader %s compiled! Size: %zu bytes\n", + shd->name, spirv_size); shader_create.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; shader_create.pNext = NULL; - shader_create.codeSize = res->size; + shader_create.codeSize = spirv_size; shader_create.flags = 0; - shader_create.pCode = res->data; + shader_create.pCode = (void *)spirv; ret = vk->CreateShaderModule(s->hwctx->act_dev, &shader_create, NULL, &shd->shader.module); - /* Free the GLSlangResult struct */ - av_free(res->data); - av_free(res); + ff_vk_glslang_shader_free(priv); if (ret != VK_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Unable to create shader module: %s\n", @@ -1031,9 +1019,6 @@ int ff_vk_compile_shader(AVFilterContext *avctx, SPIRVShader *shd, return AVERROR_EXTERNAL; } - av_log(avctx, AV_LOG_VERBOSE, "Shader %s linked! Size: %zu bytes\n", - shd->name, shader_create.codeSize); - return 0; } @@ -1059,7 +1044,7 @@ static const struct descriptor_props { }; int ff_vk_add_descriptor_set(AVFilterContext *avctx, VulkanPipeline *pl, - SPIRVShader *shd, VulkanDescriptorSetBinding *desc, + FFSPIRVShader *shd, VulkanDescriptorSetBinding *desc, int num, int only_print_to_shader) { VkResult ret; @@ -1423,7 +1408,7 @@ static void free_pipeline(VulkanFilterContext *s, VulkanPipeline *pl) FFVulkanFunctions *vk = &s->vkfn; for (int i = 0; i < pl->shaders_num; i++) { - SPIRVShader *shd = pl->shaders[i]; + FFSPIRVShader *shd = pl->shaders[i]; av_bprint_finalize(&shd->src, NULL); vk->DestroyShaderModule(s->hwctx->act_dev, shd->shader.module, s->hwctx->alloc); @@ -1471,7 +1456,7 @@ void ff_vk_filter_uninit(AVFilterContext *avctx) VulkanFilterContext *s = avctx->priv; FFVulkanFunctions *vk = &s->vkfn; - glslang_uninit(); + ff_vk_glslang_uninit(); for (int i = 0; i < s->exec_ctx_num; i++) free_exec_ctx(s, s->exec_ctx[i]); diff --git a/libavfilter/vulkan.h b/libavfilter/vulkan.h index da5936dd43..89b76ba355 100644 --- a/libavfilter/vulkan.h +++ b/libavfilter/vulkan.h @@ -55,12 +55,12 @@ /* Useful for attaching immutable samplers to arrays */ #define DUP_SAMPLER_ARRAY4(x) (VkSampler []){ x, x, x, x, } -typedef struct SPIRVShader { +typedef struct FFSPIRVShader { const char *name; /* Name for id/debugging purposes */ AVBPrint src; int local_size[3]; /* Compute shader workgroup sizes */ VkPipelineShaderStageCreateInfo shader; -} SPIRVShader; +} FFSPIRVShader; typedef struct VulkanDescriptorSetBinding { const char *name; @@ -89,7 +89,7 @@ typedef struct VulkanPipeline { VkPipeline pipeline; /* Shaders */ - SPIRVShader **shaders; + FFSPIRVShader **shaders; int shaders_num; /* Push consts */ @@ -249,29 +249,34 @@ VulkanPipeline *ff_vk_create_pipeline(AVFilterContext *avctx); /** * Inits a shader for a specific pipeline. Will be auto-freed on uninit. */ -SPIRVShader *ff_vk_init_shader(AVFilterContext *avctx, VulkanPipeline *pl, - const char *name, VkShaderStageFlags stage); +FFSPIRVShader *ff_vk_init_shader(AVFilterContext *avctx, VulkanPipeline *pl, + const char *name, VkShaderStageFlags stage); /** * Writes the workgroup size for a shader. */ -void ff_vk_set_compute_shader_sizes(AVFilterContext *avctx, SPIRVShader *shd, +void ff_vk_set_compute_shader_sizes(AVFilterContext *avctx, FFSPIRVShader *shd, int local_size[3]); /** * Adds a descriptor set to the shader and registers them in the pipeline. */ int ff_vk_add_descriptor_set(AVFilterContext *avctx, VulkanPipeline *pl, - SPIRVShader *shd, VulkanDescriptorSetBinding *desc, + FFSPIRVShader *shd, VulkanDescriptorSetBinding *desc, int num, int only_print_to_shader); /** * Compiles the shader, entrypoint must be set to "main". */ -int ff_vk_compile_shader(AVFilterContext *avctx, SPIRVShader *shd, +int ff_vk_compile_shader(AVFilterContext *avctx, FFSPIRVShader *shd, const char *entrypoint); /** + * Pretty print shader, mainly used by shader compilers. + */ +void ff_vk_print_shader(AVFilterContext *avctx, FFSPIRVShader *shd, int prio); + +/** * Initializes the pipeline layout after all shaders and descriptor sets have * been finished. */ |