mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
lavu/vulkan: move common Vulkan code from libavfilter to libavutil
This commit is contained in:
parent
8c150d3d97
commit
d1133e8c44
2
configure
vendored
2
configure
vendored
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
1391
libavfilter/vulkan.c
1391
libavfilter/vulkan.c
File diff suppressed because it is too large
Load Diff
@ -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 */
|
||||
|
@ -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
1392
libavutil/vulkan.c
Normal file
File diff suppressed because it is too large
Load Diff
413
libavutil/vulkan.h
Normal file
413
libavutil/vulkan.h
Normal 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
256
libavutil/vulkan_glslang.c
Normal 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);
|
||||
}
|
@ -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 */
|
Loading…
Reference in New Issue
Block a user