• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
58 typedef 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 
65 typedef 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 
74 typedef struct FFVkSampler {
75     VkSampler sampler[4];
76 } FFVkSampler;
77 
78 typedef 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 
91 typedef struct FFVkBuffer {
92     VkBuffer buf;
93     VkDeviceMemory mem;
94     VkMemoryPropertyFlagBits flags;
95 } FFVkBuffer;
96 
97 typedef struct FFVkQueueFamilyCtx {
98     int queue_family;
99     int nb_queues;
100     int cur_queue;
101     int actual_queues;
102 } FFVkQueueFamilyCtx;
103 
104 typedef 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 
143 typedef 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 
158 typedef 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 
192 typedef 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 */
233 extern const VkComponentMapping ff_comp_identity_map;
234 
235 /**
236  * Converts Vulkan return values to strings
237  */
238 const char *ff_vk_ret2str(VkResult res);
239 
240 /**
241  * Returns 1 if the image is any sort of supported RGB
242  */
243 int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt);
244 
245 /**
246  * Gets the glsl format string for a pixel format
247  */
248 const 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  */
254 void 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  */
260 void ff_vk_qf_rotate(FFVkQueueFamilyCtx *qf);
261 
262 /**
263  * Create a Vulkan sampler, will be auto-freed in ff_vk_filter_uninit()
264  */
265 FFVkSampler *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  */
273 int 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  */
281 int 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  */
288 FFVulkanPipeline *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  */
293 FFVkSPIRVShader *ff_vk_init_shader(FFVulkanPipeline *pl, const char *name,
294                                    VkShaderStageFlags stage);
295 
296 /**
297  * Writes the workgroup size for a shader.
298  */
299 void 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  */
304 int 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  */
311 int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd,
312                          const char *entrypoint);
313 
314 /**
315  * Pretty print shader, mainly used by shader compilers.
316  */
317 void 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  */
323 int 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  */
329 int 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  */
336 void 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  */
343 int 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  */
350 int 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  */
356 void 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  */
363 void 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  */
370 VkCommandBuffer ff_vk_get_exec_buf(FFVkExecContext *e);
371 
372 /**
373  * Adds a generic AVBufferRef as a queue depenency.
374  */
375 int ff_vk_add_dep_exec_ctx(FFVulkanContext *s, FFVkExecContext *e,
376                            AVBufferRef **deps, int nb_deps);
377 
378 /**
379  * Discards all queue dependencies
380  */
381 void 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  */
387 int 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  */
395 int ff_vk_submit_exec_queue(FFVulkanContext *s, FFVkExecContext *e);
396 
397 /**
398  * Create a VkBuffer with the specified parameters.
399  */
400 int 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  */
407 int 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  */
413 int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer *buf, int nb_buffers,
414                         int flush);
415 
416 /**
417  * Frees a buffer.
418  */
419 void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf);
420 
421 /**
422  * Frees the main Vulkan context.
423  */
424 void ff_vk_uninit(FFVulkanContext *s);
425 
426 #endif /* AVUTIL_VULKAN_H */
427