| /* |
| * 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 AVFILTER_VULKAN_H |
| #define AVFILTER_VULKAN_H |
| |
| #include "avfilter.h" |
| #include "libavutil/pixdesc.h" |
| #include "libavutil/bprint.h" |
| #include "libavutil/hwcontext.h" |
| #include "libavutil/hwcontext_vulkan.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) |
| |
| /* Gets the queues count for a single queue family */ |
| #define GET_QUEUE_COUNT(hwctx, graph, comp, tx) ( \ |
| graph ? hwctx->nb_graphics_queues : \ |
| comp ? (hwctx->nb_comp_queues ? \ |
| hwctx->nb_comp_queues : hwctx->nb_graphics_queues) : \ |
| tx ? (hwctx->nb_tx_queues ? hwctx->nb_tx_queues : \ |
| (hwctx->nb_comp_queues ? \ |
| hwctx->nb_comp_queues : hwctx->nb_graphics_queues)) : \ |
| 0 \ |
| ) |
| |
| /* Useful for attaching immutable samplers to arrays */ |
| #define DUP_SAMPLER_ARRAY4(x) (VkSampler []){ x, x, x, x, } |
| |
| typedef struct SPIRVShader { |
| const char *name; /* Name for id/debugging purposes */ |
| AVBPrint src; |
| int local_size[3]; /* Compute shader workgroup sizes */ |
| VkPipelineShaderStageCreateInfo shader; |
| } SPIRVShader; |
| |
| typedef struct VulkanDescriptorSetBinding { |
| 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; |
| const VkSampler *samplers; /* Immutable samplers, length - #elems */ |
| void *updater; /* Pointer to VkDescriptor*Info */ |
| } VulkanDescriptorSetBinding; |
| |
| typedef struct FFVkBuffer { |
| VkBuffer buf; |
| VkDeviceMemory mem; |
| VkMemoryPropertyFlagBits flags; |
| } FFVkBuffer; |
| |
| typedef struct VulkanPipeline { |
| VkPipelineBindPoint bind_point; |
| |
| /* Contexts */ |
| VkPipelineLayout pipeline_layout; |
| VkPipeline pipeline; |
| |
| /* Shaders */ |
| SPIRVShader **shaders; |
| int shaders_num; |
| |
| /* Push consts */ |
| VkPushConstantRange *push_consts; |
| int push_consts_num; |
| |
| /* Descriptors */ |
| VkDescriptorSetLayout *desc_layout; |
| VkDescriptorPool desc_pool; |
| VkDescriptorSet *desc_set; |
| VkDescriptorUpdateTemplate *desc_template; |
| int desc_layout_num; |
| int descriptor_sets_num; |
| int pool_size_desc_num; |
| |
| /* Temporary, used to store data in between initialization stages */ |
| VkDescriptorUpdateTemplateCreateInfo *desc_template_info; |
| VkDescriptorPoolSize *pool_size_desc; |
| } VulkanPipeline; |
| |
| 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 { |
| VkCommandPool pool; |
| VkCommandBuffer *bufs; |
| FFVkQueueCtx *queues; |
| |
| AVBufferRef ***deps; |
| int *nb_deps; |
| int *dep_alloc_size; |
| |
| VulkanPipeline *bound_pl; |
| |
| VkSemaphore *sem_wait; |
| int sem_wait_alloc; /* Allocated sem_wait */ |
| int sem_wait_cnt; |
| |
| 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; |
| } FFVkExecContext; |
| |
| typedef struct VulkanFilterContext { |
| const AVClass *class; |
| |
| AVBufferRef *device_ref; |
| AVBufferRef *frames_ref; /* For in-place filtering */ |
| AVHWDeviceContext *device; |
| AVVulkanDeviceContext *hwctx; |
| |
| /* State - mirrored with the exec ctx */ |
| int cur_queue_idx; |
| int queue_family_idx; |
| int queue_count; |
| |
| /* Properties */ |
| int output_width; |
| int output_height; |
| enum AVPixelFormat output_format; |
| enum AVPixelFormat input_format; |
| |
| /* Samplers */ |
| VkSampler **samplers; |
| int samplers_num; |
| |
| /* Exec contexts */ |
| FFVkExecContext **exec_ctx; |
| int exec_ctx_num; |
| |
| /* Pipelines (each can have 1 shader of each type) */ |
| VulkanPipeline **pipelines; |
| int pipelines_num; |
| |
| void *scratch; /* Scratch memory used only in functions */ |
| unsigned int scratch_size; |
| } VulkanFilterContext; |
| |
| /* Identity mapping - r = r, b = b, g = g, a = a */ |
| extern const VkComponentMapping ff_comp_identity_map; |
| |
| /** |
| * General lavfi IO functions |
| */ |
| int ff_vk_filter_query_formats (AVFilterContext *avctx); |
| int ff_vk_filter_init (AVFilterContext *avctx); |
| int ff_vk_filter_config_input (AVFilterLink *inlink); |
| int ff_vk_filter_config_output (AVFilterLink *outlink); |
| int ff_vk_filter_config_output_inplace(AVFilterLink *outlink); |
| void ff_vk_filter_uninit (AVFilterContext *avctx); |
| |
| /** |
| * Converts Vulkan return values to strings |
| */ |
| const char *ff_vk_ret2str(VkResult res); |
| |
| /** |
| * Returns 1 if the image is any sort of supported RGB |
| */ |
| int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt); |
| |
| /** |
| * Gets the glsl format string for a pixel format |
| */ |
| const char *ff_vk_shader_rep_fmt(enum AVPixelFormat pixfmt); |
| |
| /** |
| * Create a Vulkan sampler, will be auto-freed in ff_vk_filter_uninit() |
| */ |
| VkSampler *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, VulkanPipeline *pl, |
| int offset, int size, VkShaderStageFlagBits stage); |
| |
| /** |
| * Inits a pipeline. Everything in it will be auto-freed when calling |
| * ff_vk_filter_uninit(). |
| */ |
| VulkanPipeline *ff_vk_create_pipeline(AVFilterContext *avctx); |
| |
| /** |
| * Inits a shader for a specific pipeline. Will be auto-freed on uninit. |
| */ |
| SPIRVShader *ff_vk_init_shader(AVFilterContext *avctx, VulkanPipeline *pl, |
| const char *name, VkShaderStageFlags stage); |
| |
| /** |
| * Writes the workgroup size for a shader. |
| */ |
| void ff_vk_set_compute_shader_sizes(AVFilterContext *avctx, SPIRVShader *shd, |
| int local_size[3]); |
| |
| /** |
| * Adds a descriptor set to the shader and registers them in the pipeline. |
| */ |
| int ff_vk_add_descriptor_set(AVFilterContext *avctx, VulkanPipeline *pl, |
| SPIRVShader *shd, VulkanDescriptorSetBinding *desc, |
| int num, int only_print_to_shader); |
| |
| /** |
| * Compiles the shader, entrypoint must be set to "main". |
| */ |
| int ff_vk_compile_shader(AVFilterContext *avctx, SPIRVShader *shd, |
| const char *entrypoint); |
| |
| /** |
| * Initializes the pipeline layout after all shaders and descriptor sets have |
| * been finished. |
| */ |
| int ff_vk_init_pipeline_layout(AVFilterContext *avctx, VulkanPipeline *pl); |
| |
| /** |
| * Initializes a compute pipeline. Will pick the first shader with the |
| * COMPUTE flag set. |
| */ |
| int ff_vk_init_compute_pipeline(AVFilterContext *avctx, VulkanPipeline *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, VulkanPipeline *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); |
| |
| /** |
| * 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, |
| VulkanPipeline *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 */ |