2 * This file is part of FFmpeg.
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 #ifndef AVFILTER_VULKAN_H
20 #define AVFILTER_VULKAN_H
23 #include "libavutil/pixdesc.h"
24 #include "libavutil/bprint.h"
25 #include "libavutil/hwcontext.h"
26 #include "libavutil/hwcontext_vulkan.h"
28 /* GLSL management macros */
29 #define INDENT(N) INDENT_##N
31 #define INDENT_1 INDENT_0 " "
32 #define INDENT_2 INDENT_1 INDENT_1
33 #define INDENT_3 INDENT_2 INDENT_1
34 #define INDENT_4 INDENT_3 INDENT_1
35 #define INDENT_5 INDENT_4 INDENT_1
36 #define INDENT_6 INDENT_5 INDENT_1
37 #define C(N, S) INDENT(N) #S "\n"
38 #define GLSLC(N, S) av_bprintf(&shd->src, C(N, S))
39 #define GLSLA(...) av_bprintf(&shd->src, __VA_ARGS__)
40 #define GLSLF(N, S, ...) av_bprintf(&shd->src, C(N, S), __VA_ARGS__)
41 #define GLSLD(D) GLSLC(0, ); \
42 av_bprint_append_data(&shd->src, D, strlen(D)); \
45 /* Helper, pretty much every Vulkan return value needs to be checked */
48 if ((err = (x)) < 0) \
52 /* Gets the queues count for a single queue family */
53 #define GET_QUEUE_COUNT(hwctx, graph, comp, tx) ( \
54 graph ? hwctx->nb_graphics_queues : \
55 comp ? (hwctx->nb_comp_queues ? \
56 hwctx->nb_comp_queues : hwctx->nb_graphics_queues) : \
57 tx ? (hwctx->nb_tx_queues ? hwctx->nb_tx_queues : \
58 (hwctx->nb_comp_queues ? \
59 hwctx->nb_comp_queues : hwctx->nb_graphics_queues)) : \
63 /* Useful for attaching immutable samplers to arrays */
64 #define DUP_SAMPLER_ARRAY4(x) (VkSampler []){ x, x, x, x, }
66 typedef struct SPIRVShader {
67 const char *name; /* Name for id/debugging purposes */
69 int local_size[3]; /* Compute shader workgroup sizes */
70 VkPipelineShaderStageCreateInfo shader;
73 typedef struct VulkanDescriptorSetBinding {
75 VkDescriptorType type;
76 const char *mem_layout; /* Storage images (rgba8, etc.) and buffers (std430, etc.) */
77 const char *mem_quali; /* readonly, writeonly, etc. */
78 const char *buf_content; /* For buffers */
79 uint32_t dimensions; /* Needed for e.g. sampler%iD */
80 uint32_t elems; /* 0 - scalar, 1 or more - vector */
81 VkShaderStageFlags stages;
82 const VkSampler *samplers; /* Immutable samplers, length - #elems */
83 void *updater; /* Pointer to VkDescriptor*Info */
84 } VulkanDescriptorSetBinding;
86 typedef struct FFVkBuffer {
89 VkMemoryPropertyFlagBits flags;
92 typedef struct VulkanPipeline {
93 VkPipelineBindPoint bind_point;
96 VkPipelineLayout pipeline_layout;
100 SPIRVShader **shaders;
104 VkPushConstantRange *push_consts;
108 VkDescriptorSetLayout *desc_layout;
109 VkDescriptorPool desc_pool;
110 VkDescriptorSet *desc_set;
111 VkDescriptorUpdateTemplate *desc_template;
113 int descriptor_sets_num;
114 int pool_size_desc_num;
116 /* Temporary, used to store data in between initialization stages */
117 VkDescriptorUpdateTemplateCreateInfo *desc_template_info;
118 VkDescriptorPoolSize *pool_size_desc;
121 typedef struct FFVkQueueCtx {
125 /* Buffer dependencies */
126 AVBufferRef **buf_deps;
128 int buf_deps_alloc_size;
130 /* Frame dependencies */
131 AVFrame **frame_deps;
133 int frame_deps_alloc_size;
136 typedef struct FFVkExecContext {
138 VkCommandBuffer *bufs;
139 FFVkQueueCtx *queues;
145 VulkanPipeline *bound_pl;
147 VkSemaphore *sem_wait;
148 int sem_wait_alloc; /* Allocated sem_wait */
151 VkPipelineStageFlagBits *sem_wait_dst;
152 int sem_wait_dst_alloc; /* Allocated sem_wait_dst */
154 VkSemaphore *sem_sig;
155 int sem_sig_alloc; /* Allocated sem_sig */
159 typedef struct VulkanFilterContext {
160 const AVClass *class;
162 AVBufferRef *device_ref;
163 AVBufferRef *frames_ref; /* For in-place filtering */
164 AVHWDeviceContext *device;
165 AVVulkanDeviceContext *hwctx;
167 /* State - mirrored with the exec ctx */
169 int queue_family_idx;
175 enum AVPixelFormat output_format;
176 enum AVPixelFormat input_format;
179 VkSampler **samplers;
183 FFVkExecContext **exec_ctx;
186 /* Pipelines (each can have 1 shader of each type) */
187 VulkanPipeline **pipelines;
190 void *scratch; /* Scratch memory used only in functions */
191 unsigned int scratch_size;
192 } VulkanFilterContext;
194 /* Identity mapping - r = r, b = b, g = g, a = a */
195 extern const VkComponentMapping ff_comp_identity_map;
198 * General lavfi IO functions
200 int ff_vk_filter_query_formats (AVFilterContext *avctx);
201 int ff_vk_filter_init (AVFilterContext *avctx);
202 int ff_vk_filter_config_input (AVFilterLink *inlink);
203 int ff_vk_filter_config_output (AVFilterLink *outlink);
204 int ff_vk_filter_config_output_inplace(AVFilterLink *outlink);
205 void ff_vk_filter_uninit (AVFilterContext *avctx);
208 * Converts Vulkan return values to strings
210 const char *ff_vk_ret2str(VkResult res);
213 * Returns 1 if the image is any sort of supported RGB
215 int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt);
218 * Gets the glsl format string for a pixel format
220 const char *ff_vk_shader_rep_fmt(enum AVPixelFormat pixfmt);
223 * Create a Vulkan sampler, will be auto-freed in ff_vk_filter_uninit()
225 VkSampler *ff_vk_init_sampler(AVFilterContext *avctx, int unnorm_coords,
229 * Create an imageview.
230 * Guaranteed to remain alive until the queue submission has finished executing,
231 * and will be destroyed after that.
233 int ff_vk_create_imageview(AVFilterContext *avctx, FFVkExecContext *e,
234 VkImageView *v, VkImage img, VkFormat fmt,
235 const VkComponentMapping map);
238 * Define a push constant for a given stage into a pipeline.
239 * Must be called before the pipeline layout has been initialized.
241 int ff_vk_add_push_constant(AVFilterContext *avctx, VulkanPipeline *pl,
242 int offset, int size, VkShaderStageFlagBits stage);
245 * Inits a pipeline. Everything in it will be auto-freed when calling
246 * ff_vk_filter_uninit().
248 VulkanPipeline *ff_vk_create_pipeline(AVFilterContext *avctx);
251 * Inits a shader for a specific pipeline. Will be auto-freed on uninit.
253 SPIRVShader *ff_vk_init_shader(AVFilterContext *avctx, VulkanPipeline *pl,
254 const char *name, VkShaderStageFlags stage);
257 * Writes the workgroup size for a shader.
259 void ff_vk_set_compute_shader_sizes(AVFilterContext *avctx, SPIRVShader *shd,
263 * Adds a descriptor set to the shader and registers them in the pipeline.
265 int ff_vk_add_descriptor_set(AVFilterContext *avctx, VulkanPipeline *pl,
266 SPIRVShader *shd, VulkanDescriptorSetBinding *desc,
267 int num, int only_print_to_shader);
270 * Compiles the shader, entrypoint must be set to "main".
272 int ff_vk_compile_shader(AVFilterContext *avctx, SPIRVShader *shd,
273 const char *entrypoint);
276 * Initializes the pipeline layout after all shaders and descriptor sets have
279 int ff_vk_init_pipeline_layout(AVFilterContext *avctx, VulkanPipeline *pl);
282 * Initializes a compute pipeline. Will pick the first shader with the
285 int ff_vk_init_compute_pipeline(AVFilterContext *avctx, VulkanPipeline *pl);
288 * Updates a descriptor set via the updaters defined.
289 * Can be called immediately after pipeline creation, but must be called
290 * at least once before queue submission.
292 void ff_vk_update_descriptor_set(AVFilterContext *avctx, VulkanPipeline *pl,
296 * Init an execution context for command recording and queue submission.
297 * WIll be auto-freed on uninit.
299 int ff_vk_create_exec_ctx(AVFilterContext *avctx, FFVkExecContext **ctx);
302 * Begin recording to the command buffer. Previous execution must have been
303 * completed, which ff_vk_submit_exec_queue() will ensure.
305 int ff_vk_start_exec_recording(AVFilterContext *avctx, FFVkExecContext *e);
308 * Add a command to bind the completed pipeline and its descriptor sets.
309 * Must be called after ff_vk_start_exec_recording() and before submission.
311 void ff_vk_bind_pipeline_exec(AVFilterContext *avctx, FFVkExecContext *e,
315 * Updates push constants.
316 * Must be called after binding a pipeline if any push constants were defined.
318 void ff_vk_update_push_exec(AVFilterContext *avctx, FFVkExecContext *e,
319 VkShaderStageFlagBits stage, int offset,
320 size_t size, void *src);
323 * Gets the command buffer to use for this submission from the exe context.
325 VkCommandBuffer ff_vk_get_exec_buf(AVFilterContext *avctx, FFVkExecContext *e);
328 * Adds a generic AVBufferRef as a queue depenency.
330 int ff_vk_add_dep_exec_ctx(AVFilterContext *avctx, FFVkExecContext *e,
331 AVBufferRef **deps, int nb_deps);
334 * Discards all queue dependencies
336 void ff_vk_discard_exec_deps(AVFilterContext *avctx, FFVkExecContext *e);
339 * Adds a frame as a queue dependency. This also manages semaphore signalling.
340 * Must be called before submission.
342 int ff_vk_add_exec_dep(AVFilterContext *avctx, FFVkExecContext *e,
343 AVFrame *frame, VkPipelineStageFlagBits in_wait_dst_flag);
346 * Submits a command buffer to the queue for execution.
347 * Will block until execution has finished in order to simplify resource
350 int ff_vk_submit_exec_queue(AVFilterContext *avctx, FFVkExecContext *e);
353 * Create a VkBuffer with the specified parameters.
355 int ff_vk_create_buf(AVFilterContext *avctx, FFVkBuffer *buf, size_t size,
356 VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags);
359 * Maps the buffer to userspace. Set invalidate to 1 if reading the contents
362 int ff_vk_map_buffers(AVFilterContext *avctx, FFVkBuffer *buf, uint8_t *mem[],
363 int nb_buffers, int invalidate);
366 * Unmaps the buffer from userspace. Set flush to 1 to write and sync.
368 int ff_vk_unmap_buffers(AVFilterContext *avctx, FFVkBuffer *buf, int nb_buffers,
374 void ff_vk_free_buf(AVFilterContext *avctx, FFVkBuffer *buf);
376 #endif /* AVFILTER_VULKAN_H */