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"
|
kerndeint_filter_deps="gpl"
|
||||||
ladspa_filter_deps="ladspa libdl"
|
ladspa_filter_deps="ladspa libdl"
|
||||||
lensfun_filter_deps="liblensfun version3"
|
lensfun_filter_deps="liblensfun version3"
|
||||||
libplacebo_filter_deps="libplacebo vulkan libglslang"
|
libplacebo_filter_deps="libplacebo vulkan"
|
||||||
lv2_filter_deps="lv2"
|
lv2_filter_deps="lv2"
|
||||||
mcdeint_filter_deps="avcodec gpl"
|
mcdeint_filter_deps="avcodec gpl"
|
||||||
metadata_filter_deps="avformat"
|
metadata_filter_deps="avformat"
|
||||||
|
@ -16,241 +16,4 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <pthread.h>
|
#include "libavutil/vulkan_glslang.c"
|
||||||
|
|
||||||
#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);
|
|
||||||
}
|
|
||||||
|
@ -71,8 +71,9 @@ static const char blur_kernel[] = {
|
|||||||
static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
|
static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
FFSPIRVShader *shd;
|
FFVkSPIRVShader *shd;
|
||||||
AvgBlurVulkanContext *s = ctx->priv;
|
AvgBlurVulkanContext *s = ctx->priv;
|
||||||
|
FFVulkanContext *vkctx = &s->vkctx;
|
||||||
const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
|
const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
|
||||||
|
|
||||||
FFVulkanDescriptorSetBinding desc_i[2] = {
|
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)
|
if (!desc_i[0].sampler)
|
||||||
return AVERROR_EXTERNAL;
|
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[0].updater = s->input_images;
|
||||||
desc_i[1].updater = s->tmp_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)
|
if (!s->pl_hor)
|
||||||
return AVERROR(ENOMEM);
|
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);
|
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);
|
GLSLF(0, #define FILTER_RADIUS (%i) ,s->size_x - 1);
|
||||||
GLSLC(0, #define INC(x) (ivec2(x, 0)) );
|
GLSLC(0, #define INC(x) (ivec2(x, 0)) );
|
||||||
@ -137,26 +138,26 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
|
|||||||
}
|
}
|
||||||
GLSLC(0, } );
|
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_pipeline_layout(vkctx, s->pl_hor));
|
||||||
RET(ff_vk_init_compute_pipeline(ctx, s->pl_hor));
|
RET(ff_vk_init_compute_pipeline(vkctx, s->pl_hor));
|
||||||
}
|
}
|
||||||
|
|
||||||
{ /* Create shader for the vertical pass */
|
{ /* Create shader for the vertical pass */
|
||||||
desc_i[0].updater = s->tmp_images;
|
desc_i[0].updater = s->tmp_images;
|
||||||
desc_i[1].updater = s->output_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)
|
if (!s->pl_ver)
|
||||||
return AVERROR(ENOMEM);
|
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);
|
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);
|
GLSLF(0, #define FILTER_RADIUS (%i) ,s->size_y - 1);
|
||||||
GLSLC(0, #define INC(x) (ivec2(0, x)) );
|
GLSLC(0, #define INC(x) (ivec2(0, x)) );
|
||||||
@ -180,14 +181,14 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
|
|||||||
}
|
}
|
||||||
GLSLC(0, } );
|
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_pipeline_layout(vkctx, s->pl_ver));
|
||||||
RET(ff_vk_init_compute_pipeline(ctx, s->pl_ver));
|
RET(ff_vk_init_compute_pipeline(vkctx, s->pl_ver));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Execution context */
|
/* 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;
|
s->initialized = 1;
|
||||||
|
|
||||||
@ -202,29 +203,30 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *tmp_f
|
|||||||
int err;
|
int err;
|
||||||
VkCommandBuffer cmd_buf;
|
VkCommandBuffer cmd_buf;
|
||||||
AvgBlurVulkanContext *s = avctx->priv;
|
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 *in = (AVVkFrame *)in_f->data[0];
|
||||||
AVVkFrame *tmp = (AVVkFrame *)tmp_f->data[0];
|
AVVkFrame *tmp = (AVVkFrame *)tmp_f->data[0];
|
||||||
AVVkFrame *out = (AVVkFrame *)out_f->data[0];
|
AVVkFrame *out = (AVVkFrame *)out_f->data[0];
|
||||||
int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
|
int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
|
||||||
|
|
||||||
/* Update descriptors and init the exec context */
|
/* Update descriptors and init the exec context */
|
||||||
ff_vk_start_exec_recording(avctx, s->exec);
|
ff_vk_start_exec_recording(vkctx, s->exec);
|
||||||
cmd_buf = ff_vk_get_exec_buf(avctx, s->exec);
|
cmd_buf = ff_vk_get_exec_buf(s->exec);
|
||||||
|
|
||||||
for (int i = 0; i < planes; i++) {
|
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(vkctx, s->exec,
|
||||||
in->img[i],
|
&s->input_images[i].imageView, in->img[i],
|
||||||
av_vkfmt_from_pixfmt(s->vkctx.input_format)[i],
|
av_vkfmt_from_pixfmt(s->vkctx.input_format)[i],
|
||||||
ff_comp_identity_map));
|
ff_comp_identity_map));
|
||||||
|
|
||||||
RET(ff_vk_create_imageview(avctx, s->exec, &s->tmp_images[i].imageView,
|
RET(ff_vk_create_imageview(vkctx, s->exec,
|
||||||
tmp->img[i],
|
&s->tmp_images[i].imageView, tmp->img[i],
|
||||||
av_vkfmt_from_pixfmt(s->vkctx.output_format)[i],
|
av_vkfmt_from_pixfmt(s->vkctx.output_format)[i],
|
||||||
ff_comp_identity_map));
|
ff_comp_identity_map));
|
||||||
|
|
||||||
RET(ff_vk_create_imageview(avctx, s->exec, &s->output_images[i].imageView,
|
RET(ff_vk_create_imageview(vkctx, s->exec,
|
||||||
out->img[i],
|
&s->output_images[i].imageView, out->img[i],
|
||||||
av_vkfmt_from_pixfmt(s->vkctx.output_format)[i],
|
av_vkfmt_from_pixfmt(s->vkctx.output_format)[i],
|
||||||
ff_comp_identity_map));
|
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;
|
s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ff_vk_update_descriptor_set(avctx, s->pl_hor, 0);
|
ff_vk_update_descriptor_set(vkctx, s->pl_hor, 0);
|
||||||
ff_vk_update_descriptor_set(avctx, s->pl_ver, 0);
|
ff_vk_update_descriptor_set(vkctx, s->pl_ver, 0);
|
||||||
|
|
||||||
for (int i = 0; i < planes; i++) {
|
for (int i = 0; i < planes; i++) {
|
||||||
VkImageMemoryBarrier bar[] = {
|
VkImageMemoryBarrier bar[] = {
|
||||||
@ -293,20 +295,20 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *tmp_f
|
|||||||
out->access[i] = bar[2].dstAccessMask;
|
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,
|
vk->CmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGS)/CGS,
|
||||||
s->vkctx.output_height, 1);
|
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,
|
vk->CmdDispatch(cmd_buf, s->vkctx.output_width,
|
||||||
FFALIGN(s->vkctx.output_height, CGS)/CGS, 1);
|
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(vkctx, 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, 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)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -315,7 +317,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *tmp_f
|
|||||||
return err;
|
return err;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
ff_vk_discard_exec_deps(avctx, s->exec);
|
ff_vk_discard_exec_deps(s->exec);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,7 +366,7 @@ static void avgblur_vulkan_uninit(AVFilterContext *avctx)
|
|||||||
{
|
{
|
||||||
AvgBlurVulkanContext *s = avctx->priv;
|
AvgBlurVulkanContext *s = avctx->priv;
|
||||||
|
|
||||||
ff_vk_filter_uninit(avctx);
|
ff_vk_uninit(&s->vkctx);
|
||||||
|
|
||||||
s->initialized = 0;
|
s->initialized = 0;
|
||||||
}
|
}
|
||||||
|
@ -70,16 +70,17 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
|
|||||||
int err;
|
int err;
|
||||||
FFVkSampler *sampler;
|
FFVkSampler *sampler;
|
||||||
ChromaticAberrationVulkanContext *s = ctx->priv;
|
ChromaticAberrationVulkanContext *s = ctx->priv;
|
||||||
|
FFVulkanContext *vkctx = &s->vkctx;
|
||||||
const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
|
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 */
|
/* 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)
|
if (!sampler)
|
||||||
return AVERROR_EXTERNAL;
|
return AVERROR_EXTERNAL;
|
||||||
|
|
||||||
s->pl = ff_vk_create_pipeline(ctx, &s->qf);
|
s->pl = ff_vk_create_pipeline(vkctx, &s->qf);
|
||||||
if (!s->pl)
|
if (!s->pl)
|
||||||
return AVERROR(ENOMEM);
|
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",
|
FFVkSPIRVShader *shd = ff_vk_init_shader(s->pl, "chromaber_compute",
|
||||||
VK_SHADER_STAGE_COMPUTE_BIT);
|
VK_SHADER_STAGE_COMPUTE_BIT);
|
||||||
if (!shd)
|
if (!shd)
|
||||||
return AVERROR(ENOMEM);
|
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(0, layout(push_constant, std430) uniform pushConstants { );
|
||||||
GLSLC(1, vec2 dist; );
|
GLSLC(1, vec2 dist; );
|
||||||
GLSLC(0, }; );
|
GLSLC(0, }; );
|
||||||
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);
|
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 );
|
GLSLD( distort_chroma_kernel );
|
||||||
GLSLC(0, void main() );
|
GLSLC(0, void main() );
|
||||||
@ -152,14 +153,14 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
|
|||||||
}
|
}
|
||||||
GLSLC(0, } );
|
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_pipeline_layout(vkctx, s->pl));
|
||||||
RET(ff_vk_init_compute_pipeline(ctx, s->pl));
|
RET(ff_vk_init_compute_pipeline(vkctx, s->pl));
|
||||||
|
|
||||||
/* Execution context */
|
/* 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;
|
s->initialized = 1;
|
||||||
|
|
||||||
@ -174,23 +175,24 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f)
|
|||||||
int err = 0;
|
int err = 0;
|
||||||
VkCommandBuffer cmd_buf;
|
VkCommandBuffer cmd_buf;
|
||||||
ChromaticAberrationVulkanContext *s = avctx->priv;
|
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 *in = (AVVkFrame *)in_f->data[0];
|
||||||
AVVkFrame *out = (AVVkFrame *)out_f->data[0];
|
AVVkFrame *out = (AVVkFrame *)out_f->data[0];
|
||||||
int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
|
int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
|
||||||
|
|
||||||
/* Update descriptors and init the exec context */
|
/* Update descriptors and init the exec context */
|
||||||
ff_vk_start_exec_recording(avctx, s->exec);
|
ff_vk_start_exec_recording(vkctx, s->exec);
|
||||||
cmd_buf = ff_vk_get_exec_buf(avctx, s->exec);
|
cmd_buf = ff_vk_get_exec_buf(s->exec);
|
||||||
|
|
||||||
for (int i = 0; i < planes; i++) {
|
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(vkctx, s->exec,
|
||||||
in->img[i],
|
&s->input_images[i].imageView, in->img[i],
|
||||||
av_vkfmt_from_pixfmt(s->vkctx.input_format)[i],
|
av_vkfmt_from_pixfmt(s->vkctx.input_format)[i],
|
||||||
ff_comp_identity_map));
|
ff_comp_identity_map));
|
||||||
|
|
||||||
RET(ff_vk_create_imageview(avctx, s->exec, &s->output_images[i].imageView,
|
RET(ff_vk_create_imageview(vkctx, s->exec,
|
||||||
out->img[i],
|
&s->output_images[i].imageView, out->img[i],
|
||||||
av_vkfmt_from_pixfmt(s->vkctx.output_format)[i],
|
av_vkfmt_from_pixfmt(s->vkctx.output_format)[i],
|
||||||
ff_comp_identity_map));
|
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;
|
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++) {
|
for (int i = 0; i < planes; i++) {
|
||||||
VkImageMemoryBarrier bar[2] = {
|
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;
|
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);
|
0, sizeof(s->opts), &s->opts);
|
||||||
|
|
||||||
vk->CmdDispatch(cmd_buf,
|
vk->CmdDispatch(cmd_buf,
|
||||||
FFALIGN(s->vkctx.output_width, CGROUPS[0])/CGROUPS[0],
|
FFALIGN(s->vkctx.output_width, CGROUPS[0])/CGROUPS[0],
|
||||||
FFALIGN(s->vkctx.output_height, CGROUPS[1])/CGROUPS[1], 1);
|
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(vkctx, 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, 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)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -262,7 +264,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f)
|
|||||||
return err;
|
return err;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
ff_vk_discard_exec_deps(avctx, s->exec);
|
ff_vk_discard_exec_deps(s->exec);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,7 +304,7 @@ static void chromaber_vulkan_uninit(AVFilterContext *avctx)
|
|||||||
{
|
{
|
||||||
ChromaticAberrationVulkanContext *s = avctx->priv;
|
ChromaticAberrationVulkanContext *s = avctx->priv;
|
||||||
|
|
||||||
ff_vk_filter_uninit(avctx);
|
ff_vk_uninit(&s->vkctx);
|
||||||
|
|
||||||
s->initialized = 0;
|
s->initialized = 0;
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
|
|||||||
int err = 0;
|
int err = 0;
|
||||||
char *kernel_def;
|
char *kernel_def;
|
||||||
uint8_t *kernel_mapped;
|
uint8_t *kernel_mapped;
|
||||||
FFSPIRVShader *shd;
|
FFVkSPIRVShader *shd;
|
||||||
GBlurVulkanContext *s = ctx->priv;
|
GBlurVulkanContext *s = ctx->priv;
|
||||||
const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
|
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,
|
.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)
|
if (!image_descs[0].sampler)
|
||||||
return AVERROR_EXTERNAL;
|
return AVERROR_EXTERNAL;
|
||||||
|
|
||||||
@ -172,28 +172,28 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
|
|||||||
|
|
||||||
buf_desc.buf_content = kernel_def;
|
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 */
|
{ /* Create shader for the horizontal pass */
|
||||||
image_descs[0].updater = s->input_images;
|
image_descs[0].updater = s->input_images;
|
||||||
image_descs[1].updater = s->tmp_images;
|
image_descs[1].updater = s->tmp_images;
|
||||||
buf_desc.updater = &s->params_desc_hor;
|
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) {
|
if (!s->pl_hor) {
|
||||||
err = AVERROR(ENOMEM);
|
err = AVERROR(ENOMEM);
|
||||||
goto fail;
|
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) {
|
if (!shd) {
|
||||||
err = AVERROR(ENOMEM);
|
err = AVERROR(ENOMEM);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
ff_vk_set_compute_shader_sizes(ctx, shd, (int [3]){ CGS, CGS, 1 });
|
ff_vk_set_compute_shader_sizes(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(&s->vkctx, 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));
|
RET(ff_vk_add_descriptor_set(&s->vkctx, s->pl_hor, shd, &buf_desc, 1, 0));
|
||||||
|
|
||||||
GLSLD( gblur_horizontal );
|
GLSLD( gblur_horizontal );
|
||||||
GLSLC(0, void main() );
|
GLSLC(0, void main() );
|
||||||
@ -214,23 +214,23 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
|
|||||||
}
|
}
|
||||||
GLSLC(0, } );
|
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_pipeline_layout(&s->vkctx, s->pl_hor));
|
||||||
RET(ff_vk_init_compute_pipeline(ctx, 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));
|
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);
|
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.buffer = s->params_buf_hor.buf;
|
||||||
s->params_desc_hor.range = VK_WHOLE_SIZE;
|
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 */
|
{ /* 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;
|
image_descs[1].updater = s->output_images;
|
||||||
buf_desc.updater = &s->params_desc_ver;
|
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) {
|
if (!s->pl_ver) {
|
||||||
err = AVERROR(ENOMEM);
|
err = AVERROR(ENOMEM);
|
||||||
goto fail;
|
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) {
|
if (!shd) {
|
||||||
err = AVERROR(ENOMEM);
|
err = AVERROR(ENOMEM);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
ff_vk_set_compute_shader_sizes(ctx, shd, (int [3]){ CGS, CGS, 1 });
|
ff_vk_set_compute_shader_sizes(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(&s->vkctx, 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));
|
RET(ff_vk_add_descriptor_set(&s->vkctx, s->pl_ver, shd, &buf_desc, 1, 0));
|
||||||
|
|
||||||
GLSLD( gblur_vertical );
|
GLSLD( gblur_vertical );
|
||||||
GLSLC(0, void main() );
|
GLSLC(0, void main() );
|
||||||
@ -273,26 +273,26 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
|
|||||||
}
|
}
|
||||||
GLSLC(0, } );
|
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_pipeline_layout(&s->vkctx, s->pl_ver));
|
||||||
RET(ff_vk_init_compute_pipeline(ctx, 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));
|
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);
|
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.buffer = s->params_buf_ver.buf;
|
||||||
s->params_desc_ver.range = VK_WHOLE_SIZE;
|
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;
|
s->initialized = 1;
|
||||||
|
|
||||||
@ -307,9 +307,9 @@ static av_cold void gblur_vulkan_uninit(AVFilterContext *avctx)
|
|||||||
|
|
||||||
av_frame_free(&s->tmpframe);
|
av_frame_free(&s->tmpframe);
|
||||||
|
|
||||||
ff_vk_filter_uninit(avctx);
|
ff_vk_free_buf(&s->vkctx, &s->params_buf_hor);
|
||||||
ff_vk_free_buf(avctx, &s->params_buf_hor);
|
ff_vk_free_buf(&s->vkctx, &s->params_buf_ver);
|
||||||
ff_vk_free_buf(avctx, &s->params_buf_ver);
|
ff_vk_uninit(&s->vkctx);
|
||||||
|
|
||||||
s->initialized = 0;
|
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);
|
int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
|
||||||
|
|
||||||
ff_vk_start_exec_recording(avctx, s->exec);
|
ff_vk_start_exec_recording(&s->vkctx, s->exec);
|
||||||
cmd_buf = ff_vk_get_exec_buf(avctx, s->exec);
|
cmd_buf = ff_vk_get_exec_buf(s->exec);
|
||||||
|
|
||||||
input_formats = av_vkfmt_from_pixfmt(s->vkctx.input_format);
|
input_formats = av_vkfmt_from_pixfmt(s->vkctx.input_format);
|
||||||
output_formats = av_vkfmt_from_pixfmt(s->vkctx.output_format);
|
output_formats = av_vkfmt_from_pixfmt(s->vkctx.output_format);
|
||||||
for (int i = 0; i < planes; i++) {
|
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],
|
in->img[i],
|
||||||
input_formats[i],
|
input_formats[i],
|
||||||
ff_comp_identity_map));
|
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],
|
tmp->img[i],
|
||||||
output_formats[i],
|
output_formats[i],
|
||||||
ff_comp_identity_map));
|
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],
|
out->img[i],
|
||||||
output_formats[i],
|
output_formats[i],
|
||||||
ff_comp_identity_map));
|
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;
|
s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ff_vk_update_descriptor_set(avctx, s->pl_hor, 0);
|
ff_vk_update_descriptor_set(&s->vkctx, s->pl_hor, 0);
|
||||||
ff_vk_update_descriptor_set(avctx, s->pl_ver, 0);
|
ff_vk_update_descriptor_set(&s->vkctx, s->pl_ver, 0);
|
||||||
|
|
||||||
for (int i = 0; i < planes; i++) {
|
for (int i = 0; i < planes; i++) {
|
||||||
VkImageMemoryBarrier barriers[] = {
|
VkImageMemoryBarrier barriers[] = {
|
||||||
@ -415,20 +415,20 @@ static int process_frames(AVFilterContext *avctx, AVFrame *outframe, AVFrame *in
|
|||||||
out->access[i] = barriers[2].dstAccessMask;
|
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,
|
vk->CmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGS)/CGS,
|
||||||
FFALIGN(s->vkctx.output_height, CGS)/CGS, 1);
|
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,
|
vk->CmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGS)/CGS,
|
||||||
FFALIGN(s->vkctx.output_height, CGS)/CGS, 1);
|
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(&s->vkctx, 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, 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)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -436,7 +436,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *outframe, AVFrame *in
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
fail:
|
fail:
|
||||||
ff_vk_discard_exec_deps(avctx, s->exec);
|
ff_vk_discard_exec_deps(s->exec);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,7 +270,7 @@ static void libplacebo_uninit(AVFilterContext *avctx)
|
|||||||
pl_renderer_destroy(&s->renderer);
|
pl_renderer_destroy(&s->renderer);
|
||||||
pl_vulkan_destroy(&s->vulkan);
|
pl_vulkan_destroy(&s->vulkan);
|
||||||
pl_log_destroy(&s->log);
|
pl_log_destroy(&s->log);
|
||||||
ff_vk_filter_uninit(avctx);
|
ff_vk_uninit(&s->vkctx);
|
||||||
s->initialized = 0;
|
s->initialized = 0;
|
||||||
s->gpu = NULL;
|
s->gpu = NULL;
|
||||||
}
|
}
|
||||||
|
@ -82,15 +82,16 @@ static av_cold int init_filter(AVFilterContext *ctx)
|
|||||||
int err;
|
int err;
|
||||||
FFVkSampler *sampler;
|
FFVkSampler *sampler;
|
||||||
OverlayVulkanContext *s = ctx->priv;
|
OverlayVulkanContext *s = ctx->priv;
|
||||||
|
FFVulkanContext *vkctx = &s->vkctx;
|
||||||
const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
|
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)
|
if (!sampler)
|
||||||
return AVERROR_EXTERNAL;
|
return AVERROR_EXTERNAL;
|
||||||
|
|
||||||
s->pl = ff_vk_create_pipeline(ctx, &s->qf);
|
s->pl = ff_vk_create_pipeline(vkctx, &s->qf);
|
||||||
if (!s->pl)
|
if (!s->pl)
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
@ -138,15 +139,15 @@ static av_cold int init_filter(AVFilterContext *ctx)
|
|||||||
.buf_content = "ivec2 o_offset[3], o_size[3];",
|
.buf_content = "ivec2 o_offset[3], o_size[3];",
|
||||||
};
|
};
|
||||||
|
|
||||||
FFSPIRVShader *shd = ff_vk_init_shader(ctx, s->pl, "overlay_compute",
|
FFVkSPIRVShader *shd = ff_vk_init_shader(s->pl, "overlay_compute",
|
||||||
VK_SHADER_STAGE_COMPUTE_BIT);
|
VK_SHADER_STAGE_COMPUTE_BIT);
|
||||||
if (!shd)
|
if (!shd)
|
||||||
return AVERROR(ENOMEM);
|
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(vkctx, 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_b, 1, 0)); /* set 1 */
|
||||||
|
|
||||||
GLSLD( overlay_noalpha );
|
GLSLD( overlay_noalpha );
|
||||||
GLSLD( overlay_alpha );
|
GLSLD( overlay_alpha );
|
||||||
@ -162,11 +163,11 @@ static av_cold int init_filter(AVFilterContext *ctx)
|
|||||||
GLSLC(1, } );
|
GLSLC(1, } );
|
||||||
GLSLC(0, } );
|
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_pipeline_layout(vkctx, s->pl));
|
||||||
RET(ff_vk_init_compute_pipeline(ctx, s->pl));
|
RET(ff_vk_init_compute_pipeline(vkctx, s->pl));
|
||||||
|
|
||||||
{ /* Create and update buffer */
|
{ /* Create and update buffer */
|
||||||
const AVPixFmtDescriptor *desc;
|
const AVPixFmtDescriptor *desc;
|
||||||
@ -179,14 +180,14 @@ static av_cold int init_filter(AVFilterContext *ctx)
|
|||||||
int32_t o_size[2*3];
|
int32_t o_size[2*3];
|
||||||
} *par;
|
} *par;
|
||||||
|
|
||||||
err = ff_vk_create_buf(ctx, &s->params_buf,
|
err = ff_vk_create_buf(vkctx, &s->params_buf,
|
||||||
sizeof(*par),
|
sizeof(*par),
|
||||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
|
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
|
||||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
|
||||||
if (err)
|
if (err)
|
||||||
return 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)
|
if (err)
|
||||||
return 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[4] = par->o_size[0] >> desc->log2_chroma_w;
|
||||||
par->o_size[5] = par->o_size[1] >> desc->log2_chroma_h;
|
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)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
s->params_desc.buffer = s->params_buf.buf;
|
s->params_desc.buffer = s->params_buf.buf;
|
||||||
s->params_desc.range = VK_WHOLE_SIZE;
|
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 */
|
/* 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;
|
s->initialized = 1;
|
||||||
|
|
||||||
@ -233,7 +234,8 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f,
|
|||||||
int err;
|
int err;
|
||||||
VkCommandBuffer cmd_buf;
|
VkCommandBuffer cmd_buf;
|
||||||
OverlayVulkanContext *s = avctx->priv;
|
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);
|
int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
|
||||||
|
|
||||||
AVVkFrame *out = (AVVkFrame *)out_f->data[0];
|
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;
|
AVHWFramesContext *overlay_fc = (AVHWFramesContext*)overlay_f->hw_frames_ctx->data;
|
||||||
|
|
||||||
/* Update descriptors and init the exec context */
|
/* Update descriptors and init the exec context */
|
||||||
ff_vk_start_exec_recording(avctx, s->exec);
|
ff_vk_start_exec_recording(vkctx, s->exec);
|
||||||
cmd_buf = ff_vk_get_exec_buf(avctx, s->exec);
|
cmd_buf = ff_vk_get_exec_buf(s->exec);
|
||||||
|
|
||||||
for (int i = 0; i < planes; i++) {
|
for (int i = 0; i < planes; i++) {
|
||||||
RET(ff_vk_create_imageview(avctx, s->exec, &s->main_images[i].imageView,
|
RET(ff_vk_create_imageview(vkctx, s->exec,
|
||||||
main->img[i],
|
&s->main_images[i].imageView, main->img[i],
|
||||||
av_vkfmt_from_pixfmt(main_fc->sw_format)[i],
|
av_vkfmt_from_pixfmt(main_fc->sw_format)[i],
|
||||||
ff_comp_identity_map));
|
ff_comp_identity_map));
|
||||||
|
|
||||||
RET(ff_vk_create_imageview(avctx, s->exec, &s->overlay_images[i].imageView,
|
RET(ff_vk_create_imageview(vkctx, s->exec,
|
||||||
overlay->img[i],
|
&s->overlay_images[i].imageView, overlay->img[i],
|
||||||
av_vkfmt_from_pixfmt(overlay_fc->sw_format)[i],
|
av_vkfmt_from_pixfmt(overlay_fc->sw_format)[i],
|
||||||
ff_comp_identity_map));
|
ff_comp_identity_map));
|
||||||
|
|
||||||
RET(ff_vk_create_imageview(avctx, s->exec, &s->output_images[i].imageView,
|
RET(ff_vk_create_imageview(vkctx, s->exec,
|
||||||
out->img[i],
|
&s->output_images[i].imageView, out->img[i],
|
||||||
av_vkfmt_from_pixfmt(s->vkctx.output_format)[i],
|
av_vkfmt_from_pixfmt(s->vkctx.output_format)[i],
|
||||||
ff_comp_identity_map));
|
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;
|
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++) {
|
for (int i = 0; i < planes; i++) {
|
||||||
VkImageMemoryBarrier bar[3] = {
|
VkImageMemoryBarrier bar[3] = {
|
||||||
@ -327,17 +329,17 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f,
|
|||||||
out->access[i] = bar[2].dstAccessMask;
|
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,
|
vk->CmdDispatch(cmd_buf,
|
||||||
FFALIGN(s->vkctx.output_width, CGROUPS[0])/CGROUPS[0],
|
FFALIGN(s->vkctx.output_width, CGROUPS[0])/CGROUPS[0],
|
||||||
FFALIGN(s->vkctx.output_height, CGROUPS[1])/CGROUPS[1], 1);
|
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(vkctx, 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(vkctx, 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, 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)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -346,7 +348,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f,
|
|||||||
return err;
|
return err;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
ff_vk_discard_exec_deps(avctx, s->exec);
|
ff_vk_discard_exec_deps(s->exec);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -438,11 +440,10 @@ static void overlay_vulkan_uninit(AVFilterContext *avctx)
|
|||||||
{
|
{
|
||||||
OverlayVulkanContext *s = avctx->priv;
|
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_framesync_uninit(&s->fs);
|
||||||
|
|
||||||
ff_vk_free_buf(avctx, &s->params_buf);
|
|
||||||
|
|
||||||
s->initialized = 0;
|
s->initialized = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,6 +111,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
|
|||||||
FFVkSampler *sampler;
|
FFVkSampler *sampler;
|
||||||
VkFilter sampler_mode;
|
VkFilter sampler_mode;
|
||||||
ScaleVulkanContext *s = ctx->priv;
|
ScaleVulkanContext *s = ctx->priv;
|
||||||
|
FFVulkanContext *vkctx = &s->vkctx;
|
||||||
|
|
||||||
int crop_x = in->crop_left;
|
int crop_x = in->crop_left;
|
||||||
int crop_y = in->crop_top;
|
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 crop_h = in->height - (in->crop_top + in->crop_bottom);
|
||||||
int in_planes = av_pix_fmt_count_planes(s->vkctx.input_format);
|
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) {
|
switch (s->scaler) {
|
||||||
case F_NEAREST:
|
case F_NEAREST:
|
||||||
@ -130,11 +131,11 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Create a sampler */
|
/* Create a sampler */
|
||||||
sampler = ff_vk_init_sampler(ctx, 0, sampler_mode);
|
sampler = ff_vk_init_sampler(vkctx, 0, sampler_mode);
|
||||||
if (!sampler)
|
if (!sampler)
|
||||||
return AVERROR_EXTERNAL;
|
return AVERROR_EXTERNAL;
|
||||||
|
|
||||||
s->pl = ff_vk_create_pipeline(ctx, &s->qf);
|
s->pl = ff_vk_create_pipeline(vkctx, &s->qf);
|
||||||
if (!s->pl)
|
if (!s->pl)
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
@ -171,15 +172,15 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
|
|||||||
.buf_content = "mat4 yuv_matrix;",
|
.buf_content = "mat4 yuv_matrix;",
|
||||||
};
|
};
|
||||||
|
|
||||||
FFSPIRVShader *shd = ff_vk_init_shader(ctx, s->pl, "scale_compute",
|
FFVkSPIRVShader *shd = ff_vk_init_shader(s->pl, "scale_compute",
|
||||||
VK_SHADER_STAGE_COMPUTE_BIT);
|
VK_SHADER_STAGE_COMPUTE_BIT);
|
||||||
if (!shd)
|
if (!shd)
|
||||||
return AVERROR(ENOMEM);
|
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(vkctx, 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_b, 1, 0)); /* set 1 */
|
||||||
|
|
||||||
GLSLD( scale_bilinear );
|
GLSLD( scale_bilinear );
|
||||||
|
|
||||||
@ -229,11 +230,11 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
|
|||||||
|
|
||||||
GLSLC(0, } );
|
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_pipeline_layout(vkctx, s->pl));
|
||||||
RET(ff_vk_init_compute_pipeline(ctx, s->pl));
|
RET(ff_vk_init_compute_pipeline(vkctx, s->pl));
|
||||||
|
|
||||||
if (s->vkctx.output_format != s->vkctx.input_format) {
|
if (s->vkctx.output_format != s->vkctx.input_format) {
|
||||||
const struct LumaCoefficients *lcoeffs;
|
const struct LumaCoefficients *lcoeffs;
|
||||||
@ -249,14 +250,14 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
|
|||||||
return AVERROR(EINVAL);
|
return AVERROR(EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ff_vk_create_buf(ctx, &s->params_buf,
|
err = ff_vk_create_buf(vkctx, &s->params_buf,
|
||||||
sizeof(*par),
|
sizeof(*par),
|
||||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
|
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
|
||||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
|
||||||
if (err)
|
if (err)
|
||||||
return 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)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -270,18 +271,18 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
|
|||||||
|
|
||||||
par->yuv_matrix[3][3] = 1.0;
|
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)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
s->params_desc.buffer = s->params_buf.buf;
|
s->params_desc.buffer = s->params_buf.buf;
|
||||||
s->params_desc.range = VK_WHOLE_SIZE;
|
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 */
|
/* 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;
|
s->initialized = 1;
|
||||||
|
|
||||||
@ -296,19 +297,20 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f)
|
|||||||
int err = 0;
|
int err = 0;
|
||||||
VkCommandBuffer cmd_buf;
|
VkCommandBuffer cmd_buf;
|
||||||
ScaleVulkanContext *s = avctx->priv;
|
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 *in = (AVVkFrame *)in_f->data[0];
|
||||||
AVVkFrame *out = (AVVkFrame *)out_f->data[0];
|
AVVkFrame *out = (AVVkFrame *)out_f->data[0];
|
||||||
VkImageMemoryBarrier barriers[AV_NUM_DATA_POINTERS*2];
|
VkImageMemoryBarrier barriers[AV_NUM_DATA_POINTERS*2];
|
||||||
int barrier_count = 0;
|
int barrier_count = 0;
|
||||||
|
|
||||||
/* Update descriptors and init the exec context */
|
/* Update descriptors and init the exec context */
|
||||||
ff_vk_start_exec_recording(avctx, s->exec);
|
ff_vk_start_exec_recording(vkctx, s->exec);
|
||||||
cmd_buf = ff_vk_get_exec_buf(avctx, 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++) {
|
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,
|
RET(ff_vk_create_imageview(vkctx, s->exec,
|
||||||
in->img[i],
|
&s->input_images[i].imageView, in->img[i],
|
||||||
av_vkfmt_from_pixfmt(s->vkctx.input_format)[i],
|
av_vkfmt_from_pixfmt(s->vkctx.input_format)[i],
|
||||||
ff_comp_identity_map));
|
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++) {
|
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,
|
RET(ff_vk_create_imageview(vkctx, s->exec,
|
||||||
out->img[i],
|
&s->output_images[i].imageView, out->img[i],
|
||||||
av_vkfmt_from_pixfmt(s->vkctx.output_format)[i],
|
av_vkfmt_from_pixfmt(s->vkctx.output_format)[i],
|
||||||
ff_comp_identity_map));
|
ff_comp_identity_map));
|
||||||
|
|
||||||
s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
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++) {
|
for (int i = 0; i < av_pix_fmt_count_planes(s->vkctx.input_format); i++) {
|
||||||
VkImageMemoryBarrier bar = {
|
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,
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0,
|
||||||
0, NULL, 0, NULL, barrier_count, barriers);
|
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,
|
vk->CmdDispatch(cmd_buf,
|
||||||
FFALIGN(s->vkctx.output_width, CGROUPS[0])/CGROUPS[0],
|
FFALIGN(vkctx->output_width, CGROUPS[0])/CGROUPS[0],
|
||||||
FFALIGN(s->vkctx.output_height, CGROUPS[1])/CGROUPS[1], 1);
|
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(vkctx, 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, 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)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -390,7 +392,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f)
|
|||||||
return err;
|
return err;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
ff_vk_discard_exec_deps(avctx, s->exec);
|
ff_vk_discard_exec_deps(s->exec);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -436,11 +438,12 @@ static int scale_vulkan_config_output(AVFilterLink *outlink)
|
|||||||
int err;
|
int err;
|
||||||
AVFilterContext *avctx = outlink->src;
|
AVFilterContext *avctx = outlink->src;
|
||||||
ScaleVulkanContext *s = avctx->priv;
|
ScaleVulkanContext *s = avctx->priv;
|
||||||
|
FFVulkanContext *vkctx = &s->vkctx;
|
||||||
AVFilterLink *inlink = outlink->src->inputs[0];
|
AVFilterLink *inlink = outlink->src->inputs[0];
|
||||||
|
|
||||||
err = ff_scale_eval_dimensions(s, s->w_expr, s->h_expr, inlink, outlink,
|
err = ff_scale_eval_dimensions(s, s->w_expr, s->h_expr, inlink, outlink,
|
||||||
&s->vkctx.output_width,
|
&vkctx->output_width,
|
||||||
&s->vkctx.output_height);
|
&vkctx->output_height);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -481,8 +484,8 @@ static void scale_vulkan_uninit(AVFilterContext *avctx)
|
|||||||
{
|
{
|
||||||
ScaleVulkanContext *s = avctx->priv;
|
ScaleVulkanContext *s = avctx->priv;
|
||||||
|
|
||||||
ff_vk_filter_uninit(avctx);
|
ff_vk_free_buf(&s->vkctx, &s->params_buf);
|
||||||
ff_vk_free_buf(avctx, &s->params_buf);
|
ff_vk_uninit(&s->vkctx);
|
||||||
|
|
||||||
s->initialized = 0;
|
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
|
#ifndef AVFILTER_VULKAN_H
|
||||||
#define AVFILTER_VULKAN_H
|
#define AVFILTER_VULKAN_H
|
||||||
|
|
||||||
#define VK_NO_PROTOTYPES
|
|
||||||
#define VK_ENABLE_BETA_EXTENSIONS
|
|
||||||
|
|
||||||
#include "avfilter.h"
|
#include "avfilter.h"
|
||||||
#include "libavutil/pixdesc.h"
|
#include "libavutil/vulkan.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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* General lavfi IO functions
|
* 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_input (AVFilterLink *inlink);
|
||||||
int ff_vk_filter_config_output (AVFilterLink *outlink);
|
int ff_vk_filter_config_output (AVFilterLink *outlink);
|
||||||
int ff_vk_filter_config_output_inplace(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 */
|
#endif /* AVFILTER_VULKAN_H */
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#include "hwcontext_internal.h"
|
#include "hwcontext_internal.h"
|
||||||
#include "hwcontext_vulkan.h"
|
#include "hwcontext_vulkan.h"
|
||||||
|
|
||||||
|
#include "vulkan.h"
|
||||||
#include "vulkan_loader.h"
|
#include "vulkan_loader.h"
|
||||||
|
|
||||||
#if CONFIG_LIBDRM
|
#if CONFIG_LIBDRM
|
||||||
@ -131,11 +132,6 @@ typedef struct AVVkFrameInternal {
|
|||||||
#endif
|
#endif
|
||||||
} AVVkFrameInternal;
|
} 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) \
|
#define ADD_VAL_TO_LIST(list, count, val) \
|
||||||
do { \
|
do { \
|
||||||
list = av_realloc_array(list, sizeof(*list), ++count); \
|
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);
|
vk->GetPhysicalDeviceFormatProperties2(hwctx->phys_dev, fmt[i], &prop);
|
||||||
flags = linear ? prop.formatProperties.linearTilingFeatures :
|
flags = linear ? prop.formatProperties.linearTilingFeatures :
|
||||||
prop.formatProperties.optimalTilingFeatures;
|
prop.formatProperties.optimalTilingFeatures;
|
||||||
if (!(flags & DEFAULT_USAGE_FLAGS))
|
if (!(flags & FF_VK_DEFAULT_USAGE_FLAGS))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2041,7 +2037,7 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc)
|
|||||||
VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
|
VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
|
||||||
|
|
||||||
if (!hwctx->usage)
|
if (!hwctx->usage)
|
||||||
hwctx->usage = DEFAULT_USAGE_FLAGS;
|
hwctx->usage = FF_VK_DEFAULT_USAGE_FLAGS;
|
||||||
|
|
||||||
err = create_exec_ctx(hwfc, &fp->conv_ctx,
|
err = create_exec_ctx(hwfc, &fp->conv_ctx,
|
||||||
dev_hwctx->queue_family_comp_index,
|
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
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef AVFILTER_GLSLANG_H
|
#ifndef AVUTIL_GLSLANG_H
|
||||||
#define AVFILTER_GLSLANG_H
|
#define AVUTIL_GLSLANG_H
|
||||||
|
|
||||||
#include "vulkan.h"
|
#include "vulkan.h"
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ void ff_vk_glslang_uninit(void);
|
|||||||
/**
|
/**
|
||||||
* Compile GLSL into SPIR-V using glslang.
|
* 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);
|
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);
|
void ff_vk_glslang_shader_free(void *opaque);
|
||||||
|
|
||||||
#endif /* AVFILTER_GLSLANG_H */
|
#endif /* AVUTIL_GLSLANG_H */
|
Loading…
Reference in New Issue
Block a user