lavu/vulkan: move common Vulkan code from libavfilter to libavutil

This commit is contained in:
Lynne 2021-11-19 07:46:15 +01:00
parent 8c150d3d97
commit d1133e8c44
No known key found for this signature in database
GPG Key ID: A2FEA5F03F034464
15 changed files with 2258 additions and 2197 deletions

2
configure vendored
View File

@ -3620,7 +3620,7 @@ interlace_filter_deps="gpl"
kerndeint_filter_deps="gpl"
ladspa_filter_deps="ladspa libdl"
lensfun_filter_deps="liblensfun version3"
libplacebo_filter_deps="libplacebo vulkan libglslang"
libplacebo_filter_deps="libplacebo vulkan"
lv2_filter_deps="lv2"
mcdeint_filter_deps="avcodec gpl"
metadata_filter_deps="avformat"

View File

@ -16,241 +16,4 @@
* 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);
}
#include "libavutil/vulkan_glslang.c"

View File

@ -71,8 +71,9 @@ static const char blur_kernel[] = {
static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
{
int err;
FFSPIRVShader *shd;
FFVkSPIRVShader *shd;
AvgBlurVulkanContext *s = ctx->priv;
FFVulkanContext *vkctx = &s->vkctx;
const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
FFVulkanDescriptorSetBinding desc_i[2] = {
@ -94,9 +95,9 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
},
};
ff_vk_qf_init(ctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0);
ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0);
desc_i[0].sampler = ff_vk_init_sampler(ctx, 1, VK_FILTER_LINEAR);
desc_i[0].sampler = ff_vk_init_sampler(vkctx, 1, VK_FILTER_LINEAR);
if (!desc_i[0].sampler)
return AVERROR_EXTERNAL;
@ -104,16 +105,16 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
desc_i[0].updater = s->input_images;
desc_i[1].updater = s->tmp_images;
s->pl_hor = ff_vk_create_pipeline(ctx, &s->qf);
s->pl_hor = ff_vk_create_pipeline(vkctx, &s->qf);
if (!s->pl_hor)
return AVERROR(ENOMEM);
shd = ff_vk_init_shader(ctx, s->pl_hor, "avgblur_compute_hor",
shd = ff_vk_init_shader(s->pl_hor, "avgblur_compute_hor",
VK_SHADER_STAGE_COMPUTE_BIT);
ff_vk_set_compute_shader_sizes(ctx, shd, (int [3]){ CGS, 1, 1 });
ff_vk_set_compute_shader_sizes(shd, (int [3]){ CGS, 1, 1 });
RET(ff_vk_add_descriptor_set(ctx, s->pl_hor, shd, desc_i, 2, 0));
RET(ff_vk_add_descriptor_set(vkctx, s->pl_hor, shd, desc_i, 2, 0));
GLSLF(0, #define FILTER_RADIUS (%i) ,s->size_x - 1);
GLSLC(0, #define INC(x) (ivec2(x, 0)) );
@ -137,26 +138,26 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
}
GLSLC(0, } );
RET(ff_vk_compile_shader(ctx, shd, "main"));
RET(ff_vk_compile_shader(vkctx, shd, "main"));
RET(ff_vk_init_pipeline_layout(ctx, s->pl_hor));
RET(ff_vk_init_compute_pipeline(ctx, s->pl_hor));
RET(ff_vk_init_pipeline_layout(vkctx, s->pl_hor));
RET(ff_vk_init_compute_pipeline(vkctx, s->pl_hor));
}
{ /* Create shader for the vertical pass */
desc_i[0].updater = s->tmp_images;
desc_i[1].updater = s->output_images;
s->pl_ver = ff_vk_create_pipeline(ctx, &s->qf);
s->pl_ver = ff_vk_create_pipeline(vkctx, &s->qf);
if (!s->pl_ver)
return AVERROR(ENOMEM);
shd = ff_vk_init_shader(ctx, s->pl_ver, "avgblur_compute_ver",
shd = ff_vk_init_shader(s->pl_ver, "avgblur_compute_ver",
VK_SHADER_STAGE_COMPUTE_BIT);
ff_vk_set_compute_shader_sizes(ctx, shd, (int [3]){ 1, CGS, 1 });
ff_vk_set_compute_shader_sizes(shd, (int [3]){ 1, CGS, 1 });
RET(ff_vk_add_descriptor_set(ctx, s->pl_ver, shd, desc_i, 2, 0));
RET(ff_vk_add_descriptor_set(vkctx, s->pl_ver, shd, desc_i, 2, 0));
GLSLF(0, #define FILTER_RADIUS (%i) ,s->size_y - 1);
GLSLC(0, #define INC(x) (ivec2(0, x)) );
@ -180,14 +181,14 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
}
GLSLC(0, } );
RET(ff_vk_compile_shader(ctx, shd, "main"));
RET(ff_vk_compile_shader(vkctx, shd, "main"));
RET(ff_vk_init_pipeline_layout(ctx, s->pl_ver));
RET(ff_vk_init_compute_pipeline(ctx, s->pl_ver));
RET(ff_vk_init_pipeline_layout(vkctx, s->pl_ver));
RET(ff_vk_init_compute_pipeline(vkctx, s->pl_ver));
}
/* Execution context */
RET(ff_vk_create_exec_ctx(ctx, &s->exec, &s->qf));
RET(ff_vk_create_exec_ctx(vkctx, &s->exec, &s->qf));
s->initialized = 1;
@ -202,29 +203,30 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *tmp_f
int err;
VkCommandBuffer cmd_buf;
AvgBlurVulkanContext *s = avctx->priv;
FFVulkanFunctions *vk = &s->vkctx.vkfn;
FFVulkanContext *vkctx = &s->vkctx;
FFVulkanFunctions *vk = &vkctx->vkfn;
AVVkFrame *in = (AVVkFrame *)in_f->data[0];
AVVkFrame *tmp = (AVVkFrame *)tmp_f->data[0];
AVVkFrame *out = (AVVkFrame *)out_f->data[0];
int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
/* Update descriptors and init the exec context */
ff_vk_start_exec_recording(avctx, s->exec);
cmd_buf = ff_vk_get_exec_buf(avctx, s->exec);
ff_vk_start_exec_recording(vkctx, s->exec);
cmd_buf = ff_vk_get_exec_buf(s->exec);
for (int i = 0; i < planes; i++) {
RET(ff_vk_create_imageview(avctx, s->exec, &s->input_images[i].imageView,
in->img[i],
RET(ff_vk_create_imageview(vkctx, s->exec,
&s->input_images[i].imageView, in->img[i],
av_vkfmt_from_pixfmt(s->vkctx.input_format)[i],
ff_comp_identity_map));
RET(ff_vk_create_imageview(avctx, s->exec, &s->tmp_images[i].imageView,
tmp->img[i],
RET(ff_vk_create_imageview(vkctx, s->exec,
&s->tmp_images[i].imageView, tmp->img[i],
av_vkfmt_from_pixfmt(s->vkctx.output_format)[i],
ff_comp_identity_map));
RET(ff_vk_create_imageview(avctx, s->exec, &s->output_images[i].imageView,
out->img[i],
RET(ff_vk_create_imageview(vkctx, s->exec,
&s->output_images[i].imageView, out->img[i],
av_vkfmt_from_pixfmt(s->vkctx.output_format)[i],
ff_comp_identity_map));
@ -233,8 +235,8 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *tmp_f
s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
}
ff_vk_update_descriptor_set(avctx, s->pl_hor, 0);
ff_vk_update_descriptor_set(avctx, s->pl_ver, 0);
ff_vk_update_descriptor_set(vkctx, s->pl_hor, 0);
ff_vk_update_descriptor_set(vkctx, s->pl_ver, 0);
for (int i = 0; i < planes; i++) {
VkImageMemoryBarrier bar[] = {
@ -293,20 +295,20 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *tmp_f
out->access[i] = bar[2].dstAccessMask;
}
ff_vk_bind_pipeline_exec(avctx, s->exec, s->pl_hor);
ff_vk_bind_pipeline_exec(vkctx, s->exec, s->pl_hor);
vk->CmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGS)/CGS,
s->vkctx.output_height, 1);
ff_vk_bind_pipeline_exec(avctx, s->exec, s->pl_ver);
ff_vk_bind_pipeline_exec(vkctx, s->exec, s->pl_ver);
vk->CmdDispatch(cmd_buf, s->vkctx.output_width,
FFALIGN(s->vkctx.output_height, CGS)/CGS, 1);
ff_vk_add_exec_dep(avctx, s->exec, in_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
ff_vk_add_exec_dep(avctx, s->exec, out_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
ff_vk_add_exec_dep(vkctx, s->exec, in_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
ff_vk_add_exec_dep(vkctx, s->exec, out_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
err = ff_vk_submit_exec_queue(avctx, s->exec);
err = ff_vk_submit_exec_queue(vkctx,s->exec);
if (err)
return err;
@ -315,7 +317,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *tmp_f
return err;
fail:
ff_vk_discard_exec_deps(avctx, s->exec);
ff_vk_discard_exec_deps(s->exec);
return err;
}
@ -364,7 +366,7 @@ static void avgblur_vulkan_uninit(AVFilterContext *avctx)
{
AvgBlurVulkanContext *s = avctx->priv;
ff_vk_filter_uninit(avctx);
ff_vk_uninit(&s->vkctx);
s->initialized = 0;
}

View File

@ -70,16 +70,17 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
int err;
FFVkSampler *sampler;
ChromaticAberrationVulkanContext *s = ctx->priv;
FFVulkanContext *vkctx = &s->vkctx;
const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
ff_vk_qf_init(ctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0);
ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0);
/* Create a sampler */
sampler = ff_vk_init_sampler(ctx, 0, VK_FILTER_LINEAR);
sampler = ff_vk_init_sampler(vkctx, 0, VK_FILTER_LINEAR);
if (!sampler)
return AVERROR_EXTERNAL;
s->pl = ff_vk_create_pipeline(ctx, &s->qf);
s->pl = ff_vk_create_pipeline(vkctx, &s->qf);
if (!s->pl)
return AVERROR(ENOMEM);
@ -110,22 +111,22 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
},
};
FFSPIRVShader *shd = ff_vk_init_shader(ctx, s->pl, "chromaber_compute",
VK_SHADER_STAGE_COMPUTE_BIT);
FFVkSPIRVShader *shd = ff_vk_init_shader(s->pl, "chromaber_compute",
VK_SHADER_STAGE_COMPUTE_BIT);
if (!shd)
return AVERROR(ENOMEM);
ff_vk_set_compute_shader_sizes(ctx, shd, CGROUPS);
ff_vk_set_compute_shader_sizes(shd, CGROUPS);
GLSLC(0, layout(push_constant, std430) uniform pushConstants { );
GLSLC(1, vec2 dist; );
GLSLC(0, }; );
GLSLC(0, );
ff_vk_add_push_constant(ctx, s->pl, 0, sizeof(s->opts),
ff_vk_add_push_constant(s->pl, 0, sizeof(s->opts),
VK_SHADER_STAGE_COMPUTE_BIT);
RET(ff_vk_add_descriptor_set(ctx, s->pl, shd, desc_i, 2, 0)); /* set 0 */
RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, desc_i, 2, 0)); /* set 0 */
GLSLD( distort_chroma_kernel );
GLSLC(0, void main() );
@ -152,14 +153,14 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
}
GLSLC(0, } );
RET(ff_vk_compile_shader(ctx, shd, "main"));
RET(ff_vk_compile_shader(vkctx, shd, "main"));
}
RET(ff_vk_init_pipeline_layout(ctx, s->pl));
RET(ff_vk_init_compute_pipeline(ctx, s->pl));
RET(ff_vk_init_pipeline_layout(vkctx, s->pl));
RET(ff_vk_init_compute_pipeline(vkctx, s->pl));
/* Execution context */
RET(ff_vk_create_exec_ctx(ctx, &s->exec, &s->qf));
RET(ff_vk_create_exec_ctx(vkctx, &s->exec, &s->qf));
s->initialized = 1;
@ -174,23 +175,24 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f)
int err = 0;
VkCommandBuffer cmd_buf;
ChromaticAberrationVulkanContext *s = avctx->priv;
FFVulkanFunctions *vk = &s->vkctx.vkfn;
FFVulkanContext *vkctx = &s->vkctx;
FFVulkanFunctions *vk = &vkctx->vkfn;
AVVkFrame *in = (AVVkFrame *)in_f->data[0];
AVVkFrame *out = (AVVkFrame *)out_f->data[0];
int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
/* Update descriptors and init the exec context */
ff_vk_start_exec_recording(avctx, s->exec);
cmd_buf = ff_vk_get_exec_buf(avctx, s->exec);
ff_vk_start_exec_recording(vkctx, s->exec);
cmd_buf = ff_vk_get_exec_buf(s->exec);
for (int i = 0; i < planes; i++) {
RET(ff_vk_create_imageview(avctx, s->exec, &s->input_images[i].imageView,
in->img[i],
RET(ff_vk_create_imageview(vkctx, s->exec,
&s->input_images[i].imageView, in->img[i],
av_vkfmt_from_pixfmt(s->vkctx.input_format)[i],
ff_comp_identity_map));
RET(ff_vk_create_imageview(avctx, s->exec, &s->output_images[i].imageView,
out->img[i],
RET(ff_vk_create_imageview(vkctx, s->exec,
&s->output_images[i].imageView, out->img[i],
av_vkfmt_from_pixfmt(s->vkctx.output_format)[i],
ff_comp_identity_map));
@ -198,7 +200,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f)
s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
}
ff_vk_update_descriptor_set(avctx, s->pl, 0);
ff_vk_update_descriptor_set(vkctx, s->pl, 0);
for (int i = 0; i < planes; i++) {
VkImageMemoryBarrier bar[2] = {
@ -241,19 +243,19 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f)
out->access[i] = bar[1].dstAccessMask;
}
ff_vk_bind_pipeline_exec(avctx, s->exec, s->pl);
ff_vk_bind_pipeline_exec(vkctx, s->exec, s->pl);
ff_vk_update_push_exec(avctx, s->exec, VK_SHADER_STAGE_COMPUTE_BIT,
ff_vk_update_push_exec(vkctx, s->exec, VK_SHADER_STAGE_COMPUTE_BIT,
0, sizeof(s->opts), &s->opts);
vk->CmdDispatch(cmd_buf,
FFALIGN(s->vkctx.output_width, CGROUPS[0])/CGROUPS[0],
FFALIGN(s->vkctx.output_height, CGROUPS[1])/CGROUPS[1], 1);
ff_vk_add_exec_dep(avctx, s->exec, in_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
ff_vk_add_exec_dep(avctx, s->exec, out_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
ff_vk_add_exec_dep(vkctx, s->exec, in_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
ff_vk_add_exec_dep(vkctx, s->exec, out_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
err = ff_vk_submit_exec_queue(avctx, s->exec);
err = ff_vk_submit_exec_queue(vkctx, s->exec);
if (err)
return err;
@ -262,7 +264,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f)
return err;
fail:
ff_vk_discard_exec_deps(avctx, s->exec);
ff_vk_discard_exec_deps(s->exec);
return err;
}
@ -302,7 +304,7 @@ static void chromaber_vulkan_uninit(AVFilterContext *avctx)
{
ChromaticAberrationVulkanContext *s = avctx->priv;
ff_vk_filter_uninit(avctx);
ff_vk_uninit(&s->vkctx);
s->initialized = 0;
}

View File

@ -127,7 +127,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
int err = 0;
char *kernel_def;
uint8_t *kernel_mapped;
FFSPIRVShader *shd;
FFVkSPIRVShader *shd;
GBlurVulkanContext *s = ctx->priv;
const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
@ -160,7 +160,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
.buf_content = NULL,
};
image_descs[0].sampler = ff_vk_init_sampler(ctx, 1, VK_FILTER_LINEAR);
image_descs[0].sampler = ff_vk_init_sampler(&s->vkctx, 1, VK_FILTER_LINEAR);
if (!image_descs[0].sampler)
return AVERROR_EXTERNAL;
@ -172,28 +172,28 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
buf_desc.buf_content = kernel_def;
ff_vk_qf_init(ctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0);
ff_vk_qf_init(&s->vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0);
{ /* Create shader for the horizontal pass */
image_descs[0].updater = s->input_images;
image_descs[1].updater = s->tmp_images;
buf_desc.updater = &s->params_desc_hor;
s->pl_hor = ff_vk_create_pipeline(ctx, &s->qf);
s->pl_hor = ff_vk_create_pipeline(&s->vkctx, &s->qf);
if (!s->pl_hor) {
err = AVERROR(ENOMEM);
goto fail;
}
shd = ff_vk_init_shader(ctx, s->pl_hor, "gblur_compute_hor", image_descs[0].stages);
shd = ff_vk_init_shader(s->pl_hor, "gblur_compute_hor", image_descs[0].stages);
if (!shd) {
err = AVERROR(ENOMEM);
goto fail;
}
ff_vk_set_compute_shader_sizes(ctx, shd, (int [3]){ CGS, CGS, 1 });
RET(ff_vk_add_descriptor_set(ctx, s->pl_hor, shd, image_descs, FF_ARRAY_ELEMS(image_descs), 0));
RET(ff_vk_add_descriptor_set(ctx, s->pl_hor, shd, &buf_desc, 1, 0));
ff_vk_set_compute_shader_sizes(shd, (int [3]){ CGS, CGS, 1 });
RET(ff_vk_add_descriptor_set(&s->vkctx, s->pl_hor, shd, image_descs, FF_ARRAY_ELEMS(image_descs), 0));
RET(ff_vk_add_descriptor_set(&s->vkctx, s->pl_hor, shd, &buf_desc, 1, 0));
GLSLD( gblur_horizontal );
GLSLC(0, void main() );
@ -214,23 +214,23 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
}
GLSLC(0, } );
RET(ff_vk_compile_shader(ctx, shd, "main"));
RET(ff_vk_compile_shader(&s->vkctx, shd, "main"));
RET(ff_vk_init_pipeline_layout(ctx, s->pl_hor));
RET(ff_vk_init_compute_pipeline(ctx, s->pl_hor));
RET(ff_vk_init_pipeline_layout(&s->vkctx, s->pl_hor));
RET(ff_vk_init_compute_pipeline(&s->vkctx, s->pl_hor));
RET(ff_vk_create_buf(ctx, &s->params_buf_hor, sizeof(float) * s->kernel_size,
RET(ff_vk_create_buf(&s->vkctx, &s->params_buf_hor, sizeof(float) * s->kernel_size,
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
RET(ff_vk_map_buffers(ctx, &s->params_buf_hor, &kernel_mapped, 1, 0));
RET(ff_vk_map_buffers(&s->vkctx, &s->params_buf_hor, &kernel_mapped, 1, 0));
init_gaussian_kernel((float *)kernel_mapped, s->sigma, s->kernel_size);
RET(ff_vk_unmap_buffers(ctx, &s->params_buf_hor, 1, 1));
RET(ff_vk_unmap_buffers(&s->vkctx, &s->params_buf_hor, 1, 1));
s->params_desc_hor.buffer = s->params_buf_hor.buf;
s->params_desc_hor.range = VK_WHOLE_SIZE;
ff_vk_update_descriptor_set(ctx, s->pl_hor, 1);
ff_vk_update_descriptor_set(&s->vkctx, s->pl_hor, 1);
}
{ /* Create shader for the vertical pass */
@ -238,21 +238,21 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
image_descs[1].updater = s->output_images;
buf_desc.updater = &s->params_desc_ver;
s->pl_ver = ff_vk_create_pipeline(ctx, &s->qf);
s->pl_ver = ff_vk_create_pipeline(&s->vkctx, &s->qf);
if (!s->pl_ver) {
err = AVERROR(ENOMEM);
goto fail;
}
shd = ff_vk_init_shader(ctx, s->pl_ver, "gblur_compute_ver", image_descs[0].stages);
shd = ff_vk_init_shader(s->pl_ver, "gblur_compute_ver", image_descs[0].stages);
if (!shd) {
err = AVERROR(ENOMEM);
goto fail;
}
ff_vk_set_compute_shader_sizes(ctx, shd, (int [3]){ CGS, CGS, 1 });
RET(ff_vk_add_descriptor_set(ctx, s->pl_ver, shd, image_descs, FF_ARRAY_ELEMS(image_descs), 0));
RET(ff_vk_add_descriptor_set(ctx, s->pl_ver, shd, &buf_desc, 1, 0));
ff_vk_set_compute_shader_sizes(shd, (int [3]){ CGS, CGS, 1 });
RET(ff_vk_add_descriptor_set(&s->vkctx, s->pl_ver, shd, image_descs, FF_ARRAY_ELEMS(image_descs), 0));
RET(ff_vk_add_descriptor_set(&s->vkctx, s->pl_ver, shd, &buf_desc, 1, 0));
GLSLD( gblur_vertical );
GLSLC(0, void main() );
@ -273,26 +273,26 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
}
GLSLC(0, } );
RET(ff_vk_compile_shader(ctx, shd, "main"));
RET(ff_vk_compile_shader(&s->vkctx, shd, "main"));
RET(ff_vk_init_pipeline_layout(ctx, s->pl_ver));
RET(ff_vk_init_compute_pipeline(ctx, s->pl_ver));
RET(ff_vk_init_pipeline_layout(&s->vkctx, s->pl_ver));
RET(ff_vk_init_compute_pipeline(&s->vkctx, s->pl_ver));
RET(ff_vk_create_buf(ctx, &s->params_buf_ver, sizeof(float) * s->kernel_size,
RET(ff_vk_create_buf(&s->vkctx, &s->params_buf_ver, sizeof(float) * s->kernel_size,
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
RET(ff_vk_map_buffers(ctx, &s->params_buf_ver, &kernel_mapped, 1, 0));
RET(ff_vk_map_buffers(&s->vkctx, &s->params_buf_ver, &kernel_mapped, 1, 0));
init_gaussian_kernel((float *)kernel_mapped, s->sigmaV, s->kernel_size);
RET(ff_vk_unmap_buffers(ctx, &s->params_buf_ver, 1, 1));
RET(ff_vk_unmap_buffers(&s->vkctx, &s->params_buf_ver, 1, 1));
s->params_desc_ver.buffer = s->params_buf_ver.buf;
s->params_desc_ver.range = VK_WHOLE_SIZE;
ff_vk_update_descriptor_set(ctx, s->pl_ver, 1);
ff_vk_update_descriptor_set(&s->vkctx, s->pl_ver, 1);
}
RET(ff_vk_create_exec_ctx(ctx, &s->exec, &s->qf));
RET(ff_vk_create_exec_ctx(&s->vkctx, &s->exec, &s->qf));
s->initialized = 1;
@ -307,9 +307,9 @@ static av_cold void gblur_vulkan_uninit(AVFilterContext *avctx)
av_frame_free(&s->tmpframe);
ff_vk_filter_uninit(avctx);
ff_vk_free_buf(avctx, &s->params_buf_hor);
ff_vk_free_buf(avctx, &s->params_buf_ver);
ff_vk_free_buf(&s->vkctx, &s->params_buf_hor);
ff_vk_free_buf(&s->vkctx, &s->params_buf_ver);
ff_vk_uninit(&s->vkctx);
s->initialized = 0;
}
@ -329,23 +329,23 @@ static int process_frames(AVFilterContext *avctx, AVFrame *outframe, AVFrame *in
int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
ff_vk_start_exec_recording(avctx, s->exec);
cmd_buf = ff_vk_get_exec_buf(avctx, s->exec);
ff_vk_start_exec_recording(&s->vkctx, s->exec);
cmd_buf = ff_vk_get_exec_buf(s->exec);
input_formats = av_vkfmt_from_pixfmt(s->vkctx.input_format);
output_formats = av_vkfmt_from_pixfmt(s->vkctx.output_format);
for (int i = 0; i < planes; i++) {
RET(ff_vk_create_imageview(avctx, s->exec, &s->input_images[i].imageView,
RET(ff_vk_create_imageview(&s->vkctx, s->exec, &s->input_images[i].imageView,
in->img[i],
input_formats[i],
ff_comp_identity_map));
RET(ff_vk_create_imageview(avctx, s->exec, &s->tmp_images[i].imageView,
RET(ff_vk_create_imageview(&s->vkctx, s->exec, &s->tmp_images[i].imageView,
tmp->img[i],
output_formats[i],
ff_comp_identity_map));
RET(ff_vk_create_imageview(avctx, s->exec, &s->output_images[i].imageView,
RET(ff_vk_create_imageview(&s->vkctx, s->exec, &s->output_images[i].imageView,
out->img[i],
output_formats[i],
ff_comp_identity_map));
@ -355,8 +355,8 @@ static int process_frames(AVFilterContext *avctx, AVFrame *outframe, AVFrame *in
s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
}
ff_vk_update_descriptor_set(avctx, s->pl_hor, 0);
ff_vk_update_descriptor_set(avctx, s->pl_ver, 0);
ff_vk_update_descriptor_set(&s->vkctx, s->pl_hor, 0);
ff_vk_update_descriptor_set(&s->vkctx, s->pl_ver, 0);
for (int i = 0; i < planes; i++) {
VkImageMemoryBarrier barriers[] = {
@ -415,20 +415,20 @@ static int process_frames(AVFilterContext *avctx, AVFrame *outframe, AVFrame *in
out->access[i] = barriers[2].dstAccessMask;
}
ff_vk_bind_pipeline_exec(avctx, s->exec, s->pl_hor);
ff_vk_bind_pipeline_exec(&s->vkctx, s->exec, s->pl_hor);
vk->CmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGS)/CGS,
FFALIGN(s->vkctx.output_height, CGS)/CGS, 1);
ff_vk_bind_pipeline_exec(avctx, s->exec, s->pl_ver);
ff_vk_bind_pipeline_exec(&s->vkctx, s->exec, s->pl_ver);
vk->CmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGS)/CGS,
FFALIGN(s->vkctx.output_height, CGS)/CGS, 1);
ff_vk_add_exec_dep(avctx, s->exec, inframe, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
ff_vk_add_exec_dep(avctx, s->exec, outframe, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
ff_vk_add_exec_dep(&s->vkctx, s->exec, inframe, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
ff_vk_add_exec_dep(&s->vkctx, s->exec, outframe, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
err = ff_vk_submit_exec_queue(avctx, s->exec);
err = ff_vk_submit_exec_queue(&s->vkctx, s->exec);
if (err)
return err;
@ -436,7 +436,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *outframe, AVFrame *in
return 0;
fail:
ff_vk_discard_exec_deps(avctx, s->exec);
ff_vk_discard_exec_deps(s->exec);
return err;
}

View File

@ -270,7 +270,7 @@ static void libplacebo_uninit(AVFilterContext *avctx)
pl_renderer_destroy(&s->renderer);
pl_vulkan_destroy(&s->vulkan);
pl_log_destroy(&s->log);
ff_vk_filter_uninit(avctx);
ff_vk_uninit(&s->vkctx);
s->initialized = 0;
s->gpu = NULL;
}

View File

@ -82,15 +82,16 @@ static av_cold int init_filter(AVFilterContext *ctx)
int err;
FFVkSampler *sampler;
OverlayVulkanContext *s = ctx->priv;
FFVulkanContext *vkctx = &s->vkctx;
const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
ff_vk_qf_init(ctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0);
ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0);
sampler = ff_vk_init_sampler(ctx, 1, VK_FILTER_NEAREST);
sampler = ff_vk_init_sampler(vkctx, 1, VK_FILTER_NEAREST);
if (!sampler)
return AVERROR_EXTERNAL;
s->pl = ff_vk_create_pipeline(ctx, &s->qf);
s->pl = ff_vk_create_pipeline(vkctx, &s->qf);
if (!s->pl)
return AVERROR(ENOMEM);
@ -138,15 +139,15 @@ static av_cold int init_filter(AVFilterContext *ctx)
.buf_content = "ivec2 o_offset[3], o_size[3];",
};
FFSPIRVShader *shd = ff_vk_init_shader(ctx, s->pl, "overlay_compute",
VK_SHADER_STAGE_COMPUTE_BIT);
FFVkSPIRVShader *shd = ff_vk_init_shader(s->pl, "overlay_compute",
VK_SHADER_STAGE_COMPUTE_BIT);
if (!shd)
return AVERROR(ENOMEM);
ff_vk_set_compute_shader_sizes(ctx, shd, CGROUPS);
ff_vk_set_compute_shader_sizes(shd, CGROUPS);
RET(ff_vk_add_descriptor_set(ctx, s->pl, shd, desc_i, 3, 0)); /* set 0 */
RET(ff_vk_add_descriptor_set(ctx, s->pl, shd, &desc_b, 1, 0)); /* set 1 */
RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, desc_i, 3, 0)); /* set 0 */
RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, &desc_b, 1, 0)); /* set 1 */
GLSLD( overlay_noalpha );
GLSLD( overlay_alpha );
@ -162,11 +163,11 @@ static av_cold int init_filter(AVFilterContext *ctx)
GLSLC(1, } );
GLSLC(0, } );
RET(ff_vk_compile_shader(ctx, shd, "main"));
RET(ff_vk_compile_shader(vkctx, shd, "main"));
}
RET(ff_vk_init_pipeline_layout(ctx, s->pl));
RET(ff_vk_init_compute_pipeline(ctx, s->pl));
RET(ff_vk_init_pipeline_layout(vkctx, s->pl));
RET(ff_vk_init_compute_pipeline(vkctx, s->pl));
{ /* Create and update buffer */
const AVPixFmtDescriptor *desc;
@ -179,14 +180,14 @@ static av_cold int init_filter(AVFilterContext *ctx)
int32_t o_size[2*3];
} *par;
err = ff_vk_create_buf(ctx, &s->params_buf,
err = ff_vk_create_buf(vkctx, &s->params_buf,
sizeof(*par),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
if (err)
return err;
err = ff_vk_map_buffers(ctx, &s->params_buf, (uint8_t **)&par, 1, 0);
err = ff_vk_map_buffers(vkctx, &s->params_buf, (uint8_t **)&par, 1, 0);
if (err)
return err;
@ -206,18 +207,18 @@ static av_cold int init_filter(AVFilterContext *ctx)
par->o_size[4] = par->o_size[0] >> desc->log2_chroma_w;
par->o_size[5] = par->o_size[1] >> desc->log2_chroma_h;
err = ff_vk_unmap_buffers(ctx, &s->params_buf, 1, 1);
err = ff_vk_unmap_buffers(vkctx, &s->params_buf, 1, 1);
if (err)
return err;
s->params_desc.buffer = s->params_buf.buf;
s->params_desc.range = VK_WHOLE_SIZE;
ff_vk_update_descriptor_set(ctx, s->pl, 1);
ff_vk_update_descriptor_set(vkctx, s->pl, 1);
}
/* Execution context */
RET(ff_vk_create_exec_ctx(ctx, &s->exec, &s->qf));
RET(ff_vk_create_exec_ctx(vkctx, &s->exec, &s->qf));
s->initialized = 1;
@ -233,7 +234,8 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f,
int err;
VkCommandBuffer cmd_buf;
OverlayVulkanContext *s = avctx->priv;
FFVulkanFunctions *vk = &s->vkctx.vkfn;
FFVulkanContext *vkctx = &s->vkctx;
FFVulkanFunctions *vk = &vkctx->vkfn;
int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
AVVkFrame *out = (AVVkFrame *)out_f->data[0];
@ -244,22 +246,22 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f,
AVHWFramesContext *overlay_fc = (AVHWFramesContext*)overlay_f->hw_frames_ctx->data;
/* Update descriptors and init the exec context */
ff_vk_start_exec_recording(avctx, s->exec);
cmd_buf = ff_vk_get_exec_buf(avctx, s->exec);
ff_vk_start_exec_recording(vkctx, s->exec);
cmd_buf = ff_vk_get_exec_buf(s->exec);
for (int i = 0; i < planes; i++) {
RET(ff_vk_create_imageview(avctx, s->exec, &s->main_images[i].imageView,
main->img[i],
RET(ff_vk_create_imageview(vkctx, s->exec,
&s->main_images[i].imageView, main->img[i],
av_vkfmt_from_pixfmt(main_fc->sw_format)[i],
ff_comp_identity_map));
RET(ff_vk_create_imageview(avctx, s->exec, &s->overlay_images[i].imageView,
overlay->img[i],
RET(ff_vk_create_imageview(vkctx, s->exec,
&s->overlay_images[i].imageView, overlay->img[i],
av_vkfmt_from_pixfmt(overlay_fc->sw_format)[i],
ff_comp_identity_map));
RET(ff_vk_create_imageview(avctx, s->exec, &s->output_images[i].imageView,
out->img[i],
RET(ff_vk_create_imageview(vkctx, s->exec,
&s->output_images[i].imageView, out->img[i],
av_vkfmt_from_pixfmt(s->vkctx.output_format)[i],
ff_comp_identity_map));
@ -268,7 +270,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f,
s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
}
ff_vk_update_descriptor_set(avctx, s->pl, 0);
ff_vk_update_descriptor_set(vkctx, s->pl, 0);
for (int i = 0; i < planes; i++) {
VkImageMemoryBarrier bar[3] = {
@ -327,17 +329,17 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f,
out->access[i] = bar[2].dstAccessMask;
}
ff_vk_bind_pipeline_exec(avctx, s->exec, s->pl);
ff_vk_bind_pipeline_exec(vkctx, s->exec, s->pl);
vk->CmdDispatch(cmd_buf,
FFALIGN(s->vkctx.output_width, CGROUPS[0])/CGROUPS[0],
FFALIGN(s->vkctx.output_height, CGROUPS[1])/CGROUPS[1], 1);
ff_vk_add_exec_dep(avctx, s->exec, main_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
ff_vk_add_exec_dep(avctx, s->exec, overlay_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
ff_vk_add_exec_dep(avctx, s->exec, out_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
ff_vk_add_exec_dep(vkctx, s->exec, main_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
ff_vk_add_exec_dep(vkctx, s->exec, overlay_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
ff_vk_add_exec_dep(vkctx, s->exec, out_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
err = ff_vk_submit_exec_queue(avctx, s->exec);
err = ff_vk_submit_exec_queue(vkctx, s->exec);
if (err)
return err;
@ -346,7 +348,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f,
return err;
fail:
ff_vk_discard_exec_deps(avctx, s->exec);
ff_vk_discard_exec_deps(s->exec);
return err;
}
@ -438,11 +440,10 @@ static void overlay_vulkan_uninit(AVFilterContext *avctx)
{
OverlayVulkanContext *s = avctx->priv;
ff_vk_filter_uninit(avctx);
ff_vk_free_buf(&s->vkctx, &s->params_buf);
ff_vk_uninit(&s->vkctx);
ff_framesync_uninit(&s->fs);
ff_vk_free_buf(avctx, &s->params_buf);
s->initialized = 0;
}

View File

@ -111,6 +111,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
FFVkSampler *sampler;
VkFilter sampler_mode;
ScaleVulkanContext *s = ctx->priv;
FFVulkanContext *vkctx = &s->vkctx;
int crop_x = in->crop_left;
int crop_y = in->crop_top;
@ -118,7 +119,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
int crop_h = in->height - (in->crop_top + in->crop_bottom);
int in_planes = av_pix_fmt_count_planes(s->vkctx.input_format);
ff_vk_qf_init(ctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0);
ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0);
switch (s->scaler) {
case F_NEAREST:
@ -130,11 +131,11 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
};
/* Create a sampler */
sampler = ff_vk_init_sampler(ctx, 0, sampler_mode);
sampler = ff_vk_init_sampler(vkctx, 0, sampler_mode);
if (!sampler)
return AVERROR_EXTERNAL;
s->pl = ff_vk_create_pipeline(ctx, &s->qf);
s->pl = ff_vk_create_pipeline(vkctx, &s->qf);
if (!s->pl)
return AVERROR(ENOMEM);
@ -171,15 +172,15 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
.buf_content = "mat4 yuv_matrix;",
};
FFSPIRVShader *shd = ff_vk_init_shader(ctx, s->pl, "scale_compute",
VK_SHADER_STAGE_COMPUTE_BIT);
FFVkSPIRVShader *shd = ff_vk_init_shader(s->pl, "scale_compute",
VK_SHADER_STAGE_COMPUTE_BIT);
if (!shd)
return AVERROR(ENOMEM);
ff_vk_set_compute_shader_sizes(ctx, shd, CGROUPS);
ff_vk_set_compute_shader_sizes(shd, CGROUPS);
RET(ff_vk_add_descriptor_set(ctx, s->pl, shd, desc_i, 2, 0)); /* set 0 */
RET(ff_vk_add_descriptor_set(ctx, s->pl, shd, &desc_b, 1, 0)); /* set 1 */
RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, desc_i, 2, 0)); /* set 0 */
RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, &desc_b, 1, 0)); /* set 1 */
GLSLD( scale_bilinear );
@ -229,11 +230,11 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
GLSLC(0, } );
RET(ff_vk_compile_shader(ctx, shd, "main"));
RET(ff_vk_compile_shader(vkctx, shd, "main"));
}
RET(ff_vk_init_pipeline_layout(ctx, s->pl));
RET(ff_vk_init_compute_pipeline(ctx, s->pl));
RET(ff_vk_init_pipeline_layout(vkctx, s->pl));
RET(ff_vk_init_compute_pipeline(vkctx, s->pl));
if (s->vkctx.output_format != s->vkctx.input_format) {
const struct LumaCoefficients *lcoeffs;
@ -249,14 +250,14 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
return AVERROR(EINVAL);
}
err = ff_vk_create_buf(ctx, &s->params_buf,
err = ff_vk_create_buf(vkctx, &s->params_buf,
sizeof(*par),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
if (err)
return err;
err = ff_vk_map_buffers(ctx, &s->params_buf, (uint8_t **)&par, 1, 0);
err = ff_vk_map_buffers(vkctx, &s->params_buf, (uint8_t **)&par, 1, 0);
if (err)
return err;
@ -270,18 +271,18 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
par->yuv_matrix[3][3] = 1.0;
err = ff_vk_unmap_buffers(ctx, &s->params_buf, 1, 1);
err = ff_vk_unmap_buffers(vkctx, &s->params_buf, 1, 1);
if (err)
return err;
s->params_desc.buffer = s->params_buf.buf;
s->params_desc.range = VK_WHOLE_SIZE;
ff_vk_update_descriptor_set(ctx, s->pl, 1);
ff_vk_update_descriptor_set(vkctx, s->pl, 1);
}
/* Execution context */
RET(ff_vk_create_exec_ctx(ctx, &s->exec, &s->qf));
RET(ff_vk_create_exec_ctx(vkctx, &s->exec, &s->qf));
s->initialized = 1;
@ -296,19 +297,20 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f)
int err = 0;
VkCommandBuffer cmd_buf;
ScaleVulkanContext *s = avctx->priv;
FFVulkanFunctions *vk = &s->vkctx.vkfn;
FFVulkanContext *vkctx = &s->vkctx;
FFVulkanFunctions *vk = &vkctx->vkfn;
AVVkFrame *in = (AVVkFrame *)in_f->data[0];
AVVkFrame *out = (AVVkFrame *)out_f->data[0];
VkImageMemoryBarrier barriers[AV_NUM_DATA_POINTERS*2];
int barrier_count = 0;
/* Update descriptors and init the exec context */
ff_vk_start_exec_recording(avctx, s->exec);
cmd_buf = ff_vk_get_exec_buf(avctx, s->exec);
ff_vk_start_exec_recording(vkctx, s->exec);
cmd_buf = ff_vk_get_exec_buf(s->exec);
for (int i = 0; i < av_pix_fmt_count_planes(s->vkctx.input_format); i++) {
RET(ff_vk_create_imageview(avctx, s->exec, &s->input_images[i].imageView,
in->img[i],
RET(ff_vk_create_imageview(vkctx, s->exec,
&s->input_images[i].imageView, in->img[i],
av_vkfmt_from_pixfmt(s->vkctx.input_format)[i],
ff_comp_identity_map));
@ -316,15 +318,15 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f)
}
for (int i = 0; i < av_pix_fmt_count_planes(s->vkctx.output_format); i++) {
RET(ff_vk_create_imageview(avctx, s->exec, &s->output_images[i].imageView,
out->img[i],
RET(ff_vk_create_imageview(vkctx, s->exec,
&s->output_images[i].imageView, out->img[i],
av_vkfmt_from_pixfmt(s->vkctx.output_format)[i],
ff_comp_identity_map));
s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
}
ff_vk_update_descriptor_set(avctx, s->pl, 0);
ff_vk_update_descriptor_set(vkctx, s->pl, 0);
for (int i = 0; i < av_pix_fmt_count_planes(s->vkctx.input_format); i++) {
VkImageMemoryBarrier bar = {
@ -372,16 +374,16 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f)
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0,
0, NULL, 0, NULL, barrier_count, barriers);
ff_vk_bind_pipeline_exec(avctx, s->exec, s->pl);
ff_vk_bind_pipeline_exec(vkctx, s->exec, s->pl);
vk->CmdDispatch(cmd_buf,
FFALIGN(s->vkctx.output_width, CGROUPS[0])/CGROUPS[0],
FFALIGN(s->vkctx.output_height, CGROUPS[1])/CGROUPS[1], 1);
FFALIGN(vkctx->output_width, CGROUPS[0])/CGROUPS[0],
FFALIGN(vkctx->output_height, CGROUPS[1])/CGROUPS[1], 1);
ff_vk_add_exec_dep(avctx, s->exec, in_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
ff_vk_add_exec_dep(avctx, s->exec, out_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
ff_vk_add_exec_dep(vkctx, s->exec, in_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
ff_vk_add_exec_dep(vkctx, s->exec, out_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
err = ff_vk_submit_exec_queue(avctx, s->exec);
err = ff_vk_submit_exec_queue(vkctx, s->exec);
if (err)
return err;
@ -390,7 +392,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f)
return err;
fail:
ff_vk_discard_exec_deps(avctx, s->exec);
ff_vk_discard_exec_deps(s->exec);
return err;
}
@ -436,11 +438,12 @@ static int scale_vulkan_config_output(AVFilterLink *outlink)
int err;
AVFilterContext *avctx = outlink->src;
ScaleVulkanContext *s = avctx->priv;
FFVulkanContext *vkctx = &s->vkctx;
AVFilterLink *inlink = outlink->src->inputs[0];
err = ff_scale_eval_dimensions(s, s->w_expr, s->h_expr, inlink, outlink,
&s->vkctx.output_width,
&s->vkctx.output_height);
&vkctx->output_width,
&vkctx->output_height);
if (err < 0)
return err;
@ -481,8 +484,8 @@ static void scale_vulkan_uninit(AVFilterContext *avctx)
{
ScaleVulkanContext *s = avctx->priv;
ff_vk_filter_uninit(avctx);
ff_vk_free_buf(avctx, &s->params_buf);
ff_vk_free_buf(&s->vkctx, &s->params_buf);
ff_vk_uninit(&s->vkctx);
s->initialized = 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -19,197 +19,8 @@
#ifndef AVFILTER_VULKAN_H
#define AVFILTER_VULKAN_H
#define VK_NO_PROTOTYPES
#define VK_ENABLE_BETA_EXTENSIONS
#include "avfilter.h"
#include "libavutil/pixdesc.h"
#include "libavutil/bprint.h"
#include "libavutil/hwcontext.h"
#include "libavutil/hwcontext_vulkan.h"
#include "libavutil/vulkan_functions.h"
/* GLSL management macros */
#define INDENT(N) INDENT_##N
#define INDENT_0
#define INDENT_1 INDENT_0 " "
#define INDENT_2 INDENT_1 INDENT_1
#define INDENT_3 INDENT_2 INDENT_1
#define INDENT_4 INDENT_3 INDENT_1
#define INDENT_5 INDENT_4 INDENT_1
#define INDENT_6 INDENT_5 INDENT_1
#define C(N, S) INDENT(N) #S "\n"
#define GLSLC(N, S) av_bprintf(&shd->src, C(N, S))
#define GLSLA(...) av_bprintf(&shd->src, __VA_ARGS__)
#define GLSLF(N, S, ...) av_bprintf(&shd->src, C(N, S), __VA_ARGS__)
#define GLSLD(D) GLSLC(0, ); \
av_bprint_append_data(&shd->src, D, strlen(D)); \
GLSLC(0, )
/* Helper, pretty much every Vulkan return value needs to be checked */
#define RET(x) \
do { \
if ((err = (x)) < 0) \
goto fail; \
} while (0)
typedef struct FFSPIRVShader {
const char *name; /* Name for id/debugging purposes */
AVBPrint src;
int local_size[3]; /* Compute shader workgroup sizes */
VkPipelineShaderStageCreateInfo shader;
} FFSPIRVShader;
typedef struct FFVkSampler {
VkSampler sampler[4];
} FFVkSampler;
typedef struct FFVulkanDescriptorSetBinding {
const char *name;
VkDescriptorType type;
const char *mem_layout; /* Storage images (rgba8, etc.) and buffers (std430, etc.) */
const char *mem_quali; /* readonly, writeonly, etc. */
const char *buf_content; /* For buffers */
uint32_t dimensions; /* Needed for e.g. sampler%iD */
uint32_t elems; /* 0 - scalar, 1 or more - vector */
VkShaderStageFlags stages;
FFVkSampler *sampler; /* Sampler to use for all elems */
void *updater; /* Pointer to VkDescriptor*Info */
} FFVulkanDescriptorSetBinding;
typedef struct FFVkBuffer {
VkBuffer buf;
VkDeviceMemory mem;
VkMemoryPropertyFlagBits flags;
} FFVkBuffer;
typedef struct FFVkQueueFamilyCtx {
int queue_family;
int nb_queues;
int cur_queue;
int actual_queues;
} FFVkQueueFamilyCtx;
typedef struct FFVulkanPipeline {
FFVkQueueFamilyCtx *qf;
VkPipelineBindPoint bind_point;
/* Contexts */
VkPipelineLayout pipeline_layout;
VkPipeline pipeline;
/* Shaders */
FFSPIRVShader **shaders;
int shaders_num;
/* Push consts */
VkPushConstantRange *push_consts;
int push_consts_num;
/* Descriptors */
VkDescriptorSetLayout *desc_layout;
VkDescriptorPool desc_pool;
VkDescriptorSet *desc_set;
void **desc_staging;
VkDescriptorSetLayoutBinding **desc_binding;
VkDescriptorUpdateTemplate *desc_template;
int *desc_set_initialized;
int desc_layout_num;
int descriptor_sets_num;
int total_descriptor_sets;
int pool_size_desc_num;
/* Temporary, used to store data in between initialization stages */
VkDescriptorUpdateTemplateCreateInfo *desc_template_info;
VkDescriptorPoolSize *pool_size_desc;
} FFVulkanPipeline;
typedef struct FFVkQueueCtx {
VkFence fence;
VkQueue queue;
/* Buffer dependencies */
AVBufferRef **buf_deps;
int nb_buf_deps;
int buf_deps_alloc_size;
/* Frame dependencies */
AVFrame **frame_deps;
int nb_frame_deps;
int frame_deps_alloc_size;
} FFVkQueueCtx;
typedef struct FFVkExecContext {
FFVkQueueFamilyCtx *qf;
VkCommandPool pool;
VkCommandBuffer *bufs;
FFVkQueueCtx *queues;
AVBufferRef ***deps;
int *nb_deps;
int *dep_alloc_size;
FFVulkanPipeline *bound_pl;
VkSemaphore *sem_wait;
int sem_wait_alloc; /* Allocated sem_wait */
int sem_wait_cnt;
uint64_t *sem_wait_val;
int sem_wait_val_alloc;
VkPipelineStageFlagBits *sem_wait_dst;
int sem_wait_dst_alloc; /* Allocated sem_wait_dst */
VkSemaphore *sem_sig;
int sem_sig_alloc; /* Allocated sem_sig */
int sem_sig_cnt;
uint64_t *sem_sig_val;
int sem_sig_val_alloc;
uint64_t **sem_sig_val_dst;
int sem_sig_val_dst_alloc;
} FFVkExecContext;
typedef struct FFVulkanContext {
const AVClass *class;
FFVulkanFunctions vkfn;
FFVulkanExtensions extensions;
VkPhysicalDeviceProperties props;
VkPhysicalDeviceMemoryProperties mprops;
AVBufferRef *device_ref;
AVBufferRef *frames_ref; /* For in-place filtering */
AVHWDeviceContext *device;
AVVulkanDeviceContext *hwctx;
/* Properties */
int output_width;
int output_height;
enum AVPixelFormat output_format;
enum AVPixelFormat input_format;
/* Samplers */
FFVkSampler **samplers;
int samplers_num;
/* Exec contexts */
FFVkExecContext **exec_ctx;
int exec_ctx_num;
/* Pipelines (each can have 1 shader of each type) */
FFVulkanPipeline **pipelines;
int pipelines_num;
void *scratch; /* Scratch memory used only in functions */
unsigned int scratch_size;
} FFVulkanContext;
/* Identity mapping - r = r, b = b, g = g, a = a */
extern const VkComponentMapping ff_comp_identity_map;
#include "libavutil/vulkan.h"
/**
* General lavfi IO functions
@ -218,194 +29,5 @@ int ff_vk_filter_init (AVFilterContext *avctx);
int ff_vk_filter_config_input (AVFilterLink *inlink);
int ff_vk_filter_config_output (AVFilterLink *outlink);
int ff_vk_filter_config_output_inplace(AVFilterLink *outlink);
void ff_vk_filter_uninit (AVFilterContext *avctx);
/**
* Converts Vulkan return values to strings
*/
const char *ff_vk_ret2str(VkResult res);
/**
* Returns 1 if the image is any sort of supported RGB
*/
int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt);
/**
* Gets the glsl format string for a pixel format
*/
const char *ff_vk_shader_rep_fmt(enum AVPixelFormat pixfmt);
/**
* Initialize a queue family with a specific number of queues.
* If nb_queues == 0, use however many queues the queue family has.
*/
void ff_vk_qf_init(AVFilterContext *avctx, FFVkQueueFamilyCtx *qf,
VkQueueFlagBits dev_family, int nb_queues);
/**
* Rotate through the queues in a queue family.
*/
void ff_vk_qf_rotate(FFVkQueueFamilyCtx *qf);
/**
* Create a Vulkan sampler, will be auto-freed in ff_vk_filter_uninit()
*/
FFVkSampler *ff_vk_init_sampler(AVFilterContext *avctx, int unnorm_coords,
VkFilter filt);
/**
* Create an imageview.
* Guaranteed to remain alive until the queue submission has finished executing,
* and will be destroyed after that.
*/
int ff_vk_create_imageview(AVFilterContext *avctx, FFVkExecContext *e,
VkImageView *v, VkImage img, VkFormat fmt,
const VkComponentMapping map);
/**
* Define a push constant for a given stage into a pipeline.
* Must be called before the pipeline layout has been initialized.
*/
int ff_vk_add_push_constant(AVFilterContext *avctx, FFVulkanPipeline *pl,
int offset, int size, VkShaderStageFlagBits stage);
/**
* Inits a pipeline. Everything in it will be auto-freed when calling
* ff_vk_filter_uninit().
*/
FFVulkanPipeline *ff_vk_create_pipeline(AVFilterContext *avctx,
FFVkQueueFamilyCtx *qf);
/**
* Inits a shader for a specific pipeline. Will be auto-freed on uninit.
*/
FFSPIRVShader *ff_vk_init_shader(AVFilterContext *avctx, FFVulkanPipeline *pl,
const char *name, VkShaderStageFlags stage);
/**
* Writes the workgroup size for a shader.
*/
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, FFVulkanPipeline *pl,
FFSPIRVShader *shd, FFVulkanDescriptorSetBinding *desc,
int num, int only_print_to_shader);
/**
* Compiles the shader, entrypoint must be set to "main".
*/
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.
*/
int ff_vk_init_pipeline_layout(AVFilterContext *avctx, FFVulkanPipeline *pl);
/**
* Initializes a compute pipeline. Will pick the first shader with the
* COMPUTE flag set.
*/
int ff_vk_init_compute_pipeline(AVFilterContext *avctx, FFVulkanPipeline *pl);
/**
* Updates a descriptor set via the updaters defined.
* Can be called immediately after pipeline creation, but must be called
* at least once before queue submission.
*/
void ff_vk_update_descriptor_set(AVFilterContext *avctx, FFVulkanPipeline *pl,
int set_id);
/**
* Init an execution context for command recording and queue submission.
* WIll be auto-freed on uninit.
*/
int ff_vk_create_exec_ctx(AVFilterContext *avctx, FFVkExecContext **ctx,
FFVkQueueFamilyCtx *qf);
/**
* Begin recording to the command buffer. Previous execution must have been
* completed, which ff_vk_submit_exec_queue() will ensure.
*/
int ff_vk_start_exec_recording(AVFilterContext *avctx, FFVkExecContext *e);
/**
* Add a command to bind the completed pipeline and its descriptor sets.
* Must be called after ff_vk_start_exec_recording() and before submission.
*/
void ff_vk_bind_pipeline_exec(AVFilterContext *avctx, FFVkExecContext *e,
FFVulkanPipeline *pl);
/**
* Updates push constants.
* Must be called after binding a pipeline if any push constants were defined.
*/
void ff_vk_update_push_exec(AVFilterContext *avctx, FFVkExecContext *e,
VkShaderStageFlagBits stage, int offset,
size_t size, void *src);
/**
* Gets the command buffer to use for this submission from the exe context.
*/
VkCommandBuffer ff_vk_get_exec_buf(AVFilterContext *avctx, FFVkExecContext *e);
/**
* Adds a generic AVBufferRef as a queue depenency.
*/
int ff_vk_add_dep_exec_ctx(AVFilterContext *avctx, FFVkExecContext *e,
AVBufferRef **deps, int nb_deps);
/**
* Discards all queue dependencies
*/
void ff_vk_discard_exec_deps(AVFilterContext *avctx, FFVkExecContext *e);
/**
* Adds a frame as a queue dependency. This also manages semaphore signalling.
* Must be called before submission.
*/
int ff_vk_add_exec_dep(AVFilterContext *avctx, FFVkExecContext *e,
AVFrame *frame, VkPipelineStageFlagBits in_wait_dst_flag);
/**
* Submits a command buffer to the queue for execution.
* Will block until execution has finished in order to simplify resource
* management.
*/
int ff_vk_submit_exec_queue(AVFilterContext *avctx, FFVkExecContext *e);
/**
* Create a VkBuffer with the specified parameters.
*/
int ff_vk_create_buf(AVFilterContext *avctx, FFVkBuffer *buf, size_t size,
VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags);
/**
* Maps the buffer to userspace. Set invalidate to 1 if reading the contents
* is necessary.
*/
int ff_vk_map_buffers(AVFilterContext *avctx, FFVkBuffer *buf, uint8_t *mem[],
int nb_buffers, int invalidate);
/**
* Unmaps the buffer from userspace. Set flush to 1 to write and sync.
*/
int ff_vk_unmap_buffers(AVFilterContext *avctx, FFVkBuffer *buf, int nb_buffers,
int flush);
/**
* Frees a buffer.
*/
void ff_vk_free_buf(AVFilterContext *avctx, FFVkBuffer *buf);
#endif /* AVFILTER_VULKAN_H */

View File

@ -38,6 +38,7 @@
#include "hwcontext_internal.h"
#include "hwcontext_vulkan.h"
#include "vulkan.h"
#include "vulkan_loader.h"
#if CONFIG_LIBDRM
@ -131,11 +132,6 @@ typedef struct AVVkFrameInternal {
#endif
} AVVkFrameInternal;
#define DEFAULT_USAGE_FLAGS (VK_IMAGE_USAGE_SAMPLED_BIT | \
VK_IMAGE_USAGE_STORAGE_BIT | \
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | \
VK_IMAGE_USAGE_TRANSFER_DST_BIT)
#define ADD_VAL_TO_LIST(list, count, val) \
do { \
list = av_realloc_array(list, sizeof(*list), ++count); \
@ -251,7 +247,7 @@ static int pixfmt_is_supported(AVHWDeviceContext *dev_ctx, enum AVPixelFormat p,
vk->GetPhysicalDeviceFormatProperties2(hwctx->phys_dev, fmt[i], &prop);
flags = linear ? prop.formatProperties.linearTilingFeatures :
prop.formatProperties.optimalTilingFeatures;
if (!(flags & DEFAULT_USAGE_FLAGS))
if (!(flags & FF_VK_DEFAULT_USAGE_FLAGS))
return 0;
}
@ -2041,7 +2037,7 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc)
VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
if (!hwctx->usage)
hwctx->usage = DEFAULT_USAGE_FLAGS;
hwctx->usage = FF_VK_DEFAULT_USAGE_FLAGS;
err = create_exec_ctx(hwfc, &fp->conv_ctx,
dev_hwctx->queue_family_comp_index,

1392
libavutil/vulkan.c Normal file

File diff suppressed because it is too large Load Diff

413
libavutil/vulkan.h Normal file
View File

@ -0,0 +1,413 @@
/*
* 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_VULKAN_H
#define AVUTIL_VULKAN_H
#define VK_NO_PROTOTYPES
#define VK_ENABLE_BETA_EXTENSIONS
#include "pixdesc.h"
#include "bprint.h"
#include "hwcontext.h"
#include "hwcontext_vulkan.h"
#include "vulkan_functions.h"
#define FF_VK_DEFAULT_USAGE_FLAGS (VK_IMAGE_USAGE_SAMPLED_BIT | \
VK_IMAGE_USAGE_STORAGE_BIT | \
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | \
VK_IMAGE_USAGE_TRANSFER_DST_BIT)
/* GLSL management macros */
#define INDENT(N) INDENT_##N
#define INDENT_0
#define INDENT_1 INDENT_0 " "
#define INDENT_2 INDENT_1 INDENT_1
#define INDENT_3 INDENT_2 INDENT_1
#define INDENT_4 INDENT_3 INDENT_1
#define INDENT_5 INDENT_4 INDENT_1
#define INDENT_6 INDENT_5 INDENT_1
#define C(N, S) INDENT(N) #S "\n"
#define GLSLC(N, S) av_bprintf(&shd->src, C(N, S))
#define GLSLA(...) av_bprintf(&shd->src, __VA_ARGS__)
#define GLSLF(N, S, ...) av_bprintf(&shd->src, C(N, S), __VA_ARGS__)
#define GLSLD(D) GLSLC(0, ); \
av_bprint_append_data(&shd->src, D, strlen(D)); \
GLSLC(0, )
/* Helper, pretty much every Vulkan return value needs to be checked */
#define RET(x) \
do { \
if ((err = (x)) < 0) \
goto fail; \
} while (0)
typedef struct FFVkSPIRVShader {
const char *name; /* Name for id/debugging purposes */
AVBPrint src;
int local_size[3]; /* Compute shader workgroup sizes */
VkPipelineShaderStageCreateInfo shader;
} FFVkSPIRVShader;
typedef struct FFVkSampler {
VkSampler sampler[4];
} FFVkSampler;
typedef struct FFVulkanDescriptorSetBinding {
const char *name;
VkDescriptorType type;
const char *mem_layout; /* Storage images (rgba8, etc.) and buffers (std430, etc.) */
const char *mem_quali; /* readonly, writeonly, etc. */
const char *buf_content; /* For buffers */
uint32_t dimensions; /* Needed for e.g. sampler%iD */
uint32_t elems; /* 0 - scalar, 1 or more - vector */
VkShaderStageFlags stages;
FFVkSampler *sampler; /* Sampler to use for all elems */
void *updater; /* Pointer to VkDescriptor*Info */
} FFVulkanDescriptorSetBinding;
typedef struct FFVkBuffer {
VkBuffer buf;
VkDeviceMemory mem;
VkMemoryPropertyFlagBits flags;
} FFVkBuffer;
typedef struct FFVkQueueFamilyCtx {
int queue_family;
int nb_queues;
int cur_queue;
int actual_queues;
} FFVkQueueFamilyCtx;
typedef struct FFVulkanPipeline {
FFVkQueueFamilyCtx *qf;
VkPipelineBindPoint bind_point;
/* Contexts */
VkPipelineLayout pipeline_layout;
VkPipeline pipeline;
/* Shaders */
FFVkSPIRVShader **shaders;
int shaders_num;
/* Push consts */
VkPushConstantRange *push_consts;
int push_consts_num;
/* Descriptors */
VkDescriptorSetLayout *desc_layout;
VkDescriptorPool desc_pool;
VkDescriptorSet *desc_set;
void **desc_staging;
VkDescriptorSetLayoutBinding **desc_binding;
VkDescriptorUpdateTemplate *desc_template;
int *desc_set_initialized;
int desc_layout_num;
int descriptor_sets_num;
int total_descriptor_sets;
int pool_size_desc_num;
/* Temporary, used to store data in between initialization stages */
VkDescriptorUpdateTemplateCreateInfo *desc_template_info;
VkDescriptorPoolSize *pool_size_desc;
} FFVulkanPipeline;
typedef struct FFVkQueueCtx {
VkFence fence;
VkQueue queue;
/* Buffer dependencies */
AVBufferRef **buf_deps;
int nb_buf_deps;
int buf_deps_alloc_size;
/* Frame dependencies */
AVFrame **frame_deps;
int nb_frame_deps;
int frame_deps_alloc_size;
} FFVkQueueCtx;
typedef struct FFVkExecContext {
FFVkQueueFamilyCtx *qf;
VkCommandPool pool;
VkCommandBuffer *bufs;
FFVkQueueCtx *queues;
AVBufferRef ***deps;
int *nb_deps;
int *dep_alloc_size;
FFVulkanPipeline *bound_pl;
VkSemaphore *sem_wait;
int sem_wait_alloc; /* Allocated sem_wait */
int sem_wait_cnt;
uint64_t *sem_wait_val;
int sem_wait_val_alloc;
VkPipelineStageFlagBits *sem_wait_dst;
int sem_wait_dst_alloc; /* Allocated sem_wait_dst */
VkSemaphore *sem_sig;
int sem_sig_alloc; /* Allocated sem_sig */
int sem_sig_cnt;
uint64_t *sem_sig_val;
int sem_sig_val_alloc;
uint64_t **sem_sig_val_dst;
int sem_sig_val_dst_alloc;
} FFVkExecContext;
typedef struct FFVulkanContext {
const AVClass *class; /* Filters and encoders use this */
FFVulkanFunctions vkfn;
FFVulkanExtensions extensions;
VkPhysicalDeviceProperties props;
VkPhysicalDeviceMemoryProperties mprops;
AVBufferRef *device_ref;
AVHWDeviceContext *device;
AVVulkanDeviceContext *hwctx;
AVBufferRef *frames_ref;
AVHWFramesContext *frames;
AVVulkanFramesContext *hwfc;
/* Properties */
int output_width;
int output_height;
enum AVPixelFormat output_format;
enum AVPixelFormat input_format;
/* Samplers */
FFVkSampler **samplers;
int samplers_num;
/* Exec contexts */
FFVkExecContext **exec_ctx;
int exec_ctx_num;
/* Pipelines (each can have 1 shader of each type) */
FFVulkanPipeline **pipelines;
int pipelines_num;
void *scratch; /* Scratch memory used only in functions */
unsigned int scratch_size;
} FFVulkanContext;
/* Identity mapping - r = r, b = b, g = g, a = a */
extern const VkComponentMapping ff_comp_identity_map;
/**
* Converts Vulkan return values to strings
*/
const char *ff_vk_ret2str(VkResult res);
/**
* Returns 1 if the image is any sort of supported RGB
*/
int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt);
/**
* Gets the glsl format string for a pixel format
*/
const char *ff_vk_shader_rep_fmt(enum AVPixelFormat pixfmt);
/**
* Initialize a queue family with a specific number of queues.
* If nb_queues == 0, use however many queues the queue family has.
*/
void ff_vk_qf_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf,
VkQueueFlagBits dev_family, int nb_queues);
/**
* Rotate through the queues in a queue family.
*/
void ff_vk_qf_rotate(FFVkQueueFamilyCtx *qf);
/**
* Create a Vulkan sampler, will be auto-freed in ff_vk_filter_uninit()
*/
FFVkSampler *ff_vk_init_sampler(FFVulkanContext *s, int unnorm_coords,
VkFilter filt);
/**
* Create an imageview.
* Guaranteed to remain alive until the queue submission has finished executing,
* and will be destroyed after that.
*/
int ff_vk_create_imageview(FFVulkanContext *s, FFVkExecContext *e,
VkImageView *v, VkImage img, VkFormat fmt,
const VkComponentMapping map);
/**
* Define a push constant for a given stage into a pipeline.
* Must be called before the pipeline layout has been initialized.
*/
int ff_vk_add_push_constant(FFVulkanPipeline *pl, int offset, int size,
VkShaderStageFlagBits stage);
/**
* Inits a pipeline. Everything in it will be auto-freed when calling
* ff_vk_filter_uninit().
*/
FFVulkanPipeline *ff_vk_create_pipeline(FFVulkanContext *s, FFVkQueueFamilyCtx *qf);
/**
* Inits a shader for a specific pipeline. Will be auto-freed on uninit.
*/
FFVkSPIRVShader *ff_vk_init_shader(FFVulkanPipeline *pl, const char *name,
VkShaderStageFlags stage);
/**
* Writes the workgroup size for a shader.
*/
void ff_vk_set_compute_shader_sizes(FFVkSPIRVShader *shd, int local_size[3]);
/**
* Adds a descriptor set to the shader and registers them in the pipeline.
*/
int ff_vk_add_descriptor_set(FFVulkanContext *s, FFVulkanPipeline *pl,
FFVkSPIRVShader *shd, FFVulkanDescriptorSetBinding *desc,
int num, int only_print_to_shader);
/**
* Compiles the shader, entrypoint must be set to "main".
*/
int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd,
const char *entrypoint);
/**
* Pretty print shader, mainly used by shader compilers.
*/
void ff_vk_print_shader(void *ctx, FFVkSPIRVShader *shd, int prio);
/**
* Initializes the pipeline layout after all shaders and descriptor sets have
* been finished.
*/
int ff_vk_init_pipeline_layout(FFVulkanContext *s, FFVulkanPipeline *pl);
/**
* Initializes a compute pipeline. Will pick the first shader with the
* COMPUTE flag set.
*/
int ff_vk_init_compute_pipeline(FFVulkanContext *s, FFVulkanPipeline *pl);
/**
* Updates a descriptor set via the updaters defined.
* Can be called immediately after pipeline creation, but must be called
* at least once before queue submission.
*/
void ff_vk_update_descriptor_set(FFVulkanContext *s, FFVulkanPipeline *pl,
int set_id);
/**
* Init an execution context for command recording and queue submission.
* WIll be auto-freed on uninit.
*/
int ff_vk_create_exec_ctx(FFVulkanContext *s, FFVkExecContext **ctx,
FFVkQueueFamilyCtx *qf);
/**
* Begin recording to the command buffer. Previous execution must have been
* completed, which ff_vk_submit_exec_queue() will ensure.
*/
int ff_vk_start_exec_recording(FFVulkanContext *s, FFVkExecContext *e);
/**
* Add a command to bind the completed pipeline and its descriptor sets.
* Must be called after ff_vk_start_exec_recording() and before submission.
*/
void ff_vk_bind_pipeline_exec(FFVulkanContext *s, FFVkExecContext *e,
FFVulkanPipeline *pl);
/**
* Updates push constants.
* Must be called after binding a pipeline if any push constants were defined.
*/
void ff_vk_update_push_exec(FFVulkanContext *s, FFVkExecContext *e,
VkShaderStageFlagBits stage, int offset,
size_t size, void *src);
/**
* Gets the command buffer to use for this submission from the exe context.
*/
VkCommandBuffer ff_vk_get_exec_buf(FFVkExecContext *e);
/**
* Adds a generic AVBufferRef as a queue depenency.
*/
int ff_vk_add_dep_exec_ctx(FFVulkanContext *s, FFVkExecContext *e,
AVBufferRef **deps, int nb_deps);
/**
* Discards all queue dependencies
*/
void ff_vk_discard_exec_deps(FFVkExecContext *e);
/**
* Adds a frame as a queue dependency. This also manages semaphore signalling.
* Must be called before submission.
*/
int ff_vk_add_exec_dep(FFVulkanContext *s, FFVkExecContext *e, AVFrame *frame,
VkPipelineStageFlagBits in_wait_dst_flag);
/**
* Submits a command buffer to the queue for execution.
* Will block until execution has finished in order to simplify resource
* management.
*/
int ff_vk_submit_exec_queue(FFVulkanContext *s, FFVkExecContext *e);
/**
* Create a VkBuffer with the specified parameters.
*/
int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size,
VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags);
/**
* Maps the buffer to userspace. Set invalidate to 1 if reading the contents
* is necessary.
*/
int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer *buf, uint8_t *mem[],
int nb_buffers, int invalidate);
/**
* Unmaps the buffer from userspace. Set flush to 1 to write and sync.
*/
int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer *buf, int nb_buffers,
int flush);
/**
* Frees a buffer.
*/
void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf);
/**
* Frees the main Vulkan context.
*/
void ff_vk_uninit(FFVulkanContext *s);
#endif /* AVUTIL_VULKAN_H */

256
libavutil/vulkan_glslang.c Normal file
View File

@ -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 "mem.h"
#include "avassert.h"
#include "vulkan_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(void *avctx, FFVkSPIRVShader *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);
}

View File

@ -16,8 +16,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVFILTER_GLSLANG_H
#define AVFILTER_GLSLANG_H
#ifndef AVUTIL_GLSLANG_H
#define AVUTIL_GLSLANG_H
#include "vulkan.h"
@ -30,7 +30,7 @@ void ff_vk_glslang_uninit(void);
/**
* Compile GLSL into SPIR-V using glslang.
*/
int ff_vk_glslang_shader_compile(AVFilterContext *avctx, FFSPIRVShader *shd,
int ff_vk_glslang_shader_compile(void *avctx, FFVkSPIRVShader *shd,
uint8_t **data, size_t *size, void **opaque);
/**
@ -38,4 +38,4 @@ int ff_vk_glslang_shader_compile(AVFilterContext *avctx, FFSPIRVShader *shd,
*/
void ff_vk_glslang_shader_free(void *opaque);
#endif /* AVFILTER_GLSLANG_H */
#endif /* AVUTIL_GLSLANG_H */