diff --git a/libavfilter/vf_scale_vulkan.c b/libavfilter/vf_scale_vulkan.c index 1d6492e213..46b1476933 100644 --- a/libavfilter/vf_scale_vulkan.c +++ b/libavfilter/vf_scale_vulkan.c @@ -112,85 +112,9 @@ static const char write_444[] = { C(0, } ) }; -static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) +static int init_scale_shader(ScaleVulkanContext *s, FFVulkanShader *shd, + FFVulkanDescriptorSetBinding *desc, AVFrame *in) { - int err; - uint8_t *spv_data; - size_t spv_len; - void *spv_opaque = NULL; - VkFilter sampler_mode; - ScaleVulkanContext *s = ctx->priv; - FFVulkanContext *vkctx = &s->vkctx; - FFVulkanShader *shd = &s->shd; - FFVkSPIRVCompiler *spv; - FFVulkanDescriptorSetBinding *desc; - - int in_planes = av_pix_fmt_count_planes(s->vkctx.input_format); - - switch (s->scaler) { - case F_NEAREST: - sampler_mode = VK_FILTER_NEAREST; - break; - case F_BILINEAR: - sampler_mode = VK_FILTER_LINEAR; - break; - }; - - spv = ff_vk_spirv_init(); - if (!spv) { - av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n"); - return AVERROR_EXTERNAL; - } - - s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0); - if (!s->qf) { - av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n"); - err = AVERROR(ENOTSUP); - goto fail; - } - - RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL)); - RET(ff_vk_init_sampler(vkctx, &s->sampler, 0, sampler_mode)); - RET(ff_vk_shader_init(vkctx, &s->shd, "scale", - VK_SHADER_STAGE_COMPUTE_BIT, - NULL, 0, - 32, 32, 1, - 0)); - - GLSLC(0, layout(push_constant, std430) uniform pushConstants { ); - GLSLC(1, mat4 yuv_matrix; ); - GLSLC(1, int crop_x; ); - GLSLC(1, int crop_y; ); - GLSLC(1, int crop_w; ); - GLSLC(1, int crop_h; ); - GLSLC(0, }; ); - GLSLC(0, ); - - ff_vk_shader_add_push_const(&s->shd, 0, sizeof(s->opts), - VK_SHADER_STAGE_COMPUTE_BIT); - - desc = (FFVulkanDescriptorSetBinding []) { - { - .name = "input_img", - .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .dimensions = 2, - .elems = in_planes, - .stages = VK_SHADER_STAGE_COMPUTE_BIT, - .samplers = DUP_SAMPLER(s->sampler), - }, - { - .name = "output_img", - .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, - .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format, FF_VK_REP_FLOAT), - .mem_quali = "writeonly", - .dimensions = 2, - .elems = av_pix_fmt_count_planes(s->vkctx.output_format), - .stages = VK_SHADER_STAGE_COMPUTE_BIT, - }, - }; - - RET(ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 2, 0, 0)); - GLSLD( scale_bilinear ); if (s->vkctx.output_format != s->vkctx.input_format) { @@ -245,7 +169,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) lcoeffs = av_csp_luma_coeffs_from_avcsp(in->colorspace); if (!lcoeffs) { - av_log(ctx, AV_LOG_ERROR, "Unsupported colorspace\n"); + av_log(s, AV_LOG_ERROR, "Unsupported colorspace\n"); return AVERROR(EINVAL); } @@ -257,6 +181,92 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) s->opts.yuv_matrix[3][3] = 1.0; } + return 0; +} + +static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) +{ + int err; + uint8_t *spv_data; + size_t spv_len; + void *spv_opaque = NULL; + VkFilter sampler_mode; + ScaleVulkanContext *s = ctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + FFVulkanShader *shd = &s->shd; + FFVkSPIRVCompiler *spv; + FFVulkanDescriptorSetBinding *desc; + + int in_planes = av_pix_fmt_count_planes(s->vkctx.input_format); + + switch (s->scaler) { + case F_NEAREST: + sampler_mode = VK_FILTER_NEAREST; + break; + case F_BILINEAR: + sampler_mode = VK_FILTER_LINEAR; + break; + }; + + spv = ff_vk_spirv_init(); + if (!spv) { + av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n"); + return AVERROR_EXTERNAL; + } + + s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0); + if (!s->qf) { + av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n"); + err = AVERROR(ENOTSUP); + goto fail; + } + + RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL)); + RET(ff_vk_init_sampler(vkctx, &s->sampler, 0, sampler_mode)); + RET(ff_vk_shader_init(vkctx, &s->shd, "scale", + VK_SHADER_STAGE_COMPUTE_BIT, + NULL, 0, + 32, 32, 1, + 0)); + + desc = (FFVulkanDescriptorSetBinding []) { + { + .name = "input_img", + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .dimensions = 2, + .elems = in_planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .samplers = DUP_SAMPLER(s->sampler), + }, + { + .name = "output_img", + .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format, FF_VK_REP_FLOAT), + .mem_quali = "writeonly", + .dimensions = 2, + .elems = av_pix_fmt_count_planes(s->vkctx.output_format), + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + }, + }; + + RET(ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 2, 0, 0)); + + GLSLC(0, layout(push_constant, std430) uniform pushConstants { ); + GLSLC(1, mat4 yuv_matrix; ); + GLSLC(1, int crop_x; ); + GLSLC(1, int crop_y; ); + GLSLC(1, int crop_w; ); + GLSLC(1, int crop_h; ); + GLSLC(0, }; ); + GLSLC(0, ); + + ff_vk_shader_add_push_const(&s->shd, 0, sizeof(s->opts), + VK_SHADER_STAGE_COMPUTE_BIT); + + err = init_scale_shader(s, shd, desc, in); + if (err < 0) + goto fail; + RET(spv->compile_shader(vkctx, spv, shd, &spv_data, &spv_len, "main", &spv_opaque)); RET(ff_vk_shader_link(vkctx, shd, spv_data, spv_len, "main"));