xref: /third_party/ffmpeg/libavutil/vulkan.h (revision cabdff1a)
1/*
2 * This file is part of FFmpeg.
3 *
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.
8 *
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.
13 *
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
17 */
18
19#ifndef AVUTIL_VULKAN_H
20#define AVUTIL_VULKAN_H
21
22#include "pixdesc.h"
23#include "bprint.h"
24#include "hwcontext.h"
25#include "vulkan_functions.h"
26#include "hwcontext_vulkan.h"
27#include "vulkan_loader.h"
28
29#define FF_VK_DEFAULT_USAGE_FLAGS (VK_IMAGE_USAGE_SAMPLED_BIT      |           \
30                                   VK_IMAGE_USAGE_STORAGE_BIT      |           \
31                                   VK_IMAGE_USAGE_TRANSFER_SRC_BIT |           \
32                                   VK_IMAGE_USAGE_TRANSFER_DST_BIT)
33
34/* GLSL management macros */
35#define INDENT(N) INDENT_##N
36#define INDENT_0
37#define INDENT_1 INDENT_0 "    "
38#define INDENT_2 INDENT_1 INDENT_1
39#define INDENT_3 INDENT_2 INDENT_1
40#define INDENT_4 INDENT_3 INDENT_1
41#define INDENT_5 INDENT_4 INDENT_1
42#define INDENT_6 INDENT_5 INDENT_1
43#define C(N, S)          INDENT(N) #S "\n"
44#define GLSLC(N, S)      av_bprintf(&shd->src, C(N, S))
45#define GLSLA(...)       av_bprintf(&shd->src, __VA_ARGS__)
46#define GLSLF(N, S, ...) av_bprintf(&shd->src, C(N, S), __VA_ARGS__)
47#define GLSLD(D)         GLSLC(0, );                                           \
48                         av_bprint_append_data(&shd->src, D, strlen(D));       \
49                         GLSLC(0, )
50
51/* Helper, pretty much every Vulkan return value needs to be checked */
52#define RET(x)                                                                 \
53    do {                                                                       \
54        if ((err = (x)) < 0)                                                   \
55            goto fail;                                                         \
56    } while (0)
57
58typedef struct FFVkSPIRVShader {
59    const char *name;                       /* Name for id/debugging purposes */
60    AVBPrint src;
61    int local_size[3];                      /* Compute shader workgroup sizes */
62    VkPipelineShaderStageCreateInfo shader;
63} FFVkSPIRVShader;
64
65typedef struct FFVkSPIRVCompiler {
66    void *priv;
67    int (*compile_shader)(struct FFVkSPIRVCompiler *ctx, void *avctx,
68                          struct FFVkSPIRVShader *shd, uint8_t **data,
69                          size_t *size, const char *entrypoint, void **opaque);
70    void (*free_shader)(struct FFVkSPIRVCompiler *ctx, void **opaque);
71    void (*uninit)(struct FFVkSPIRVCompiler **ctx);
72} FFVkSPIRVCompiler;
73
74typedef struct FFVkSampler {
75    VkSampler sampler[4];
76} FFVkSampler;
77
78typedef struct FFVulkanDescriptorSetBinding {
79    const char         *name;
80    VkDescriptorType    type;
81    const char         *mem_layout;  /* Storage images (rgba8, etc.) and buffers (std430, etc.) */
82    const char         *mem_quali;   /* readonly, writeonly, etc. */
83    const char         *buf_content; /* For buffers */
84    uint32_t            dimensions;  /* Needed for e.g. sampler%iD */
85    uint32_t            elems;       /* 0 - scalar, 1 or more - vector */
86    VkShaderStageFlags  stages;
87    FFVkSampler        *sampler;     /* Sampler to use for all elems */
88    void               *updater;     /* Pointer to VkDescriptor*Info */
89} FFVulkanDescriptorSetBinding;
90
91typedef struct FFVkBuffer {
92    VkBuffer buf;
93    VkDeviceMemory mem;
94    VkMemoryPropertyFlagBits flags;
95} FFVkBuffer;
96
97typedef struct FFVkQueueFamilyCtx {
98    int queue_family;
99    int nb_queues;
100    int cur_queue;
101    int actual_queues;
102} FFVkQueueFamilyCtx;
103
104typedef struct FFVulkanPipeline {
105    FFVkQueueFamilyCtx *qf;
106
107    VkPipelineBindPoint bind_point;
108
109    /* Contexts */
110    VkPipelineLayout pipeline_layout;
111    VkPipeline       pipeline;
112
113    /* Shaders */
114    FFVkSPIRVShader **shaders;
115    int shaders_num;
116
117    /* Push consts */
118    VkPushConstantRange *push_consts;
119    int push_consts_num;
120
121    /* Descriptors */
122    VkDescriptorSetLayout         *desc_layout;
123    VkDescriptorPool               desc_pool;
124    VkDescriptorSet               *desc_set;
125#if VK_USE_64_BIT_PTR_DEFINES == 1
126    void                         **desc_staging;
127#else
128    uint64_t                      *desc_staging;
129#endif
130    VkDescriptorSetLayoutBinding **desc_binding;
131    VkDescriptorUpdateTemplate    *desc_template;
132    int                           *desc_set_initialized;
133    int                            desc_layout_num;
134    int                            descriptor_sets_num;
135    int                            total_descriptor_sets;
136    int                            pool_size_desc_num;
137
138    /* Temporary, used to store data in between initialization stages */
139    VkDescriptorUpdateTemplateCreateInfo *desc_template_info;
140    VkDescriptorPoolSize *pool_size_desc;
141} FFVulkanPipeline;
142
143typedef struct FFVkQueueCtx {
144    VkFence fence;
145    VkQueue queue;
146
147    /* Buffer dependencies */
148    AVBufferRef **buf_deps;
149    int nb_buf_deps;
150    int buf_deps_alloc_size;
151
152    /* Frame dependencies */
153    AVFrame **frame_deps;
154    int nb_frame_deps;
155    int frame_deps_alloc_size;
156} FFVkQueueCtx;
157
158typedef struct FFVkExecContext {
159    FFVkQueueFamilyCtx *qf;
160
161    VkCommandPool pool;
162    VkCommandBuffer *bufs;
163    FFVkQueueCtx *queues;
164
165    AVBufferRef ***deps;
166    int *nb_deps;
167    int *dep_alloc_size;
168
169    FFVulkanPipeline *bound_pl;
170
171    VkSemaphore *sem_wait;
172    int sem_wait_alloc; /* Allocated sem_wait */
173    int sem_wait_cnt;
174
175    uint64_t *sem_wait_val;
176    int sem_wait_val_alloc;
177
178    VkPipelineStageFlagBits *sem_wait_dst;
179    int sem_wait_dst_alloc; /* Allocated sem_wait_dst */
180
181    VkSemaphore *sem_sig;
182    int sem_sig_alloc; /* Allocated sem_sig */
183    int sem_sig_cnt;
184
185    uint64_t *sem_sig_val;
186    int sem_sig_val_alloc;
187
188    uint64_t **sem_sig_val_dst;
189    int sem_sig_val_dst_alloc;
190} FFVkExecContext;
191
192typedef struct FFVulkanContext {
193    const AVClass *class; /* Filters and encoders use this */
194
195    FFVulkanFunctions     vkfn;
196    FFVulkanExtensions    extensions;
197    VkPhysicalDeviceProperties props;
198    VkPhysicalDeviceMemoryProperties mprops;
199
200    AVBufferRef           *device_ref;
201    AVHWDeviceContext     *device;
202    AVVulkanDeviceContext *hwctx;
203
204    AVBufferRef           *frames_ref;
205    AVHWFramesContext     *frames;
206    AVVulkanFramesContext *hwfc;
207
208    FFVkSPIRVCompiler     *spirv_compiler;
209
210    /* Properties */
211    int                 output_width;
212    int                output_height;
213    enum AVPixelFormat output_format;
214    enum AVPixelFormat  input_format;
215
216    /* Samplers */
217    FFVkSampler **samplers;
218    int samplers_num;
219
220    /* Exec contexts */
221    FFVkExecContext **exec_ctx;
222    int exec_ctx_num;
223
224    /* Pipelines (each can have 1 shader of each type) */
225    FFVulkanPipeline **pipelines;
226    int pipelines_num;
227
228    void *scratch; /* Scratch memory used only in functions */
229    unsigned int scratch_size;
230} FFVulkanContext;
231
232/* Identity mapping - r = r, b = b, g = g, a = a */
233extern const VkComponentMapping ff_comp_identity_map;
234
235/**
236 * Converts Vulkan return values to strings
237 */
238const char *ff_vk_ret2str(VkResult res);
239
240/**
241 * Returns 1 if the image is any sort of supported RGB
242 */
243int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt);
244
245/**
246 * Gets the glsl format string for a pixel format
247 */
248const char *ff_vk_shader_rep_fmt(enum AVPixelFormat pixfmt);
249
250/**
251 * Initialize a queue family with a specific number of queues.
252 * If nb_queues == 0, use however many queues the queue family has.
253 */
254void ff_vk_qf_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf,
255                   VkQueueFlagBits dev_family, int nb_queues);
256
257/**
258 * Rotate through the queues in a queue family.
259 */
260void ff_vk_qf_rotate(FFVkQueueFamilyCtx *qf);
261
262/**
263 * Create a Vulkan sampler, will be auto-freed in ff_vk_filter_uninit()
264 */
265FFVkSampler *ff_vk_init_sampler(FFVulkanContext *s, int unnorm_coords,
266                                VkFilter filt);
267
268/**
269 * Create an imageview.
270 * Guaranteed to remain alive until the queue submission has finished executing,
271 * and will be destroyed after that.
272 */
273int ff_vk_create_imageview(FFVulkanContext *s, FFVkExecContext *e,
274                           VkImageView *v, VkImage img, VkFormat fmt,
275                           const VkComponentMapping map);
276
277/**
278 * Define a push constant for a given stage into a pipeline.
279 * Must be called before the pipeline layout has been initialized.
280 */
281int ff_vk_add_push_constant(FFVulkanPipeline *pl, int offset, int size,
282                            VkShaderStageFlagBits stage);
283
284/**
285 * Inits a pipeline. Everything in it will be auto-freed when calling
286 * ff_vk_filter_uninit().
287 */
288FFVulkanPipeline *ff_vk_create_pipeline(FFVulkanContext *s, FFVkQueueFamilyCtx *qf);
289
290/**
291 * Inits a shader for a specific pipeline. Will be auto-freed on uninit.
292 */
293FFVkSPIRVShader *ff_vk_init_shader(FFVulkanPipeline *pl, const char *name,
294                                   VkShaderStageFlags stage);
295
296/**
297 * Writes the workgroup size for a shader.
298 */
299void ff_vk_set_compute_shader_sizes(FFVkSPIRVShader *shd, int local_size[3]);
300
301/**
302 * Adds a descriptor set to the shader and registers them in the pipeline.
303 */
304int ff_vk_add_descriptor_set(FFVulkanContext *s, FFVulkanPipeline *pl,
305                             FFVkSPIRVShader *shd, FFVulkanDescriptorSetBinding *desc,
306                             int num, int only_print_to_shader);
307
308/**
309 * Compiles the shader, entrypoint must be set to "main".
310 */
311int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd,
312                         const char *entrypoint);
313
314/**
315 * Pretty print shader, mainly used by shader compilers.
316 */
317void ff_vk_print_shader(void *ctx, FFVkSPIRVShader *shd, int prio);
318
319/**
320 * Initializes the pipeline layout after all shaders and descriptor sets have
321 * been finished.
322 */
323int ff_vk_init_pipeline_layout(FFVulkanContext *s, FFVulkanPipeline *pl);
324
325/**
326 * Initializes a compute pipeline. Will pick the first shader with the
327 * COMPUTE flag set.
328 */
329int ff_vk_init_compute_pipeline(FFVulkanContext *s, FFVulkanPipeline *pl);
330
331/**
332 * Updates a descriptor set via the updaters defined.
333 * Can be called immediately after pipeline creation, but must be called
334 * at least once before queue submission.
335 */
336void ff_vk_update_descriptor_set(FFVulkanContext *s, FFVulkanPipeline *pl,
337                                 int set_id);
338
339/**
340 * Init an execution context for command recording and queue submission.
341 * WIll be auto-freed on uninit.
342 */
343int ff_vk_create_exec_ctx(FFVulkanContext *s, FFVkExecContext **ctx,
344                          FFVkQueueFamilyCtx *qf);
345
346/**
347 * Begin recording to the command buffer. Previous execution must have been
348 * completed, which ff_vk_submit_exec_queue() will ensure.
349 */
350int ff_vk_start_exec_recording(FFVulkanContext *s,  FFVkExecContext *e);
351
352/**
353 * Add a command to bind the completed pipeline and its descriptor sets.
354 * Must be called after ff_vk_start_exec_recording() and before submission.
355 */
356void ff_vk_bind_pipeline_exec(FFVulkanContext *s, FFVkExecContext *e,
357                              FFVulkanPipeline *pl);
358
359/**
360 * Updates push constants.
361 * Must be called after binding a pipeline if any push constants were defined.
362 */
363void ff_vk_update_push_exec(FFVulkanContext *s, FFVkExecContext *e,
364                            VkShaderStageFlagBits stage, int offset,
365                            size_t size, void *src);
366
367/**
368 * Gets the command buffer to use for this submission from the exe context.
369 */
370VkCommandBuffer ff_vk_get_exec_buf(FFVkExecContext *e);
371
372/**
373 * Adds a generic AVBufferRef as a queue depenency.
374 */
375int ff_vk_add_dep_exec_ctx(FFVulkanContext *s, FFVkExecContext *e,
376                           AVBufferRef **deps, int nb_deps);
377
378/**
379 * Discards all queue dependencies
380 */
381void ff_vk_discard_exec_deps(FFVkExecContext *e);
382
383/**
384 * Adds a frame as a queue dependency. This also manages semaphore signalling.
385 * Must be called before submission.
386 */
387int ff_vk_add_exec_dep(FFVulkanContext *s, FFVkExecContext *e, AVFrame *frame,
388                       VkPipelineStageFlagBits in_wait_dst_flag);
389
390/**
391 * Submits a command buffer to the queue for execution.
392 * Will block until execution has finished in order to simplify resource
393 * management.
394 */
395int ff_vk_submit_exec_queue(FFVulkanContext *s, FFVkExecContext *e);
396
397/**
398 * Create a VkBuffer with the specified parameters.
399 */
400int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size,
401                     VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags);
402
403/**
404 * Maps the buffer to userspace. Set invalidate to 1 if reading the contents
405 * is necessary.
406 */
407int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer *buf, uint8_t *mem[],
408                      int nb_buffers, int invalidate);
409
410/**
411 * Unmaps the buffer from userspace. Set flush to 1 to write and sync.
412 */
413int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer *buf, int nb_buffers,
414                        int flush);
415
416/**
417 * Frees a buffer.
418 */
419void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf);
420
421/**
422 * Frees the main Vulkan context.
423 */
424void ff_vk_uninit(FFVulkanContext *s);
425
426#endif /* AVUTIL_VULKAN_H */
427