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 AVUTIL_VULKAN_H
20 #define AVUTIL_VULKAN_H
22 #define VK_NO_PROTOTYPES
24 #include <stdatomic.h>
28 #include "hwcontext.h"
29 #include "vulkan_functions.h"
30 #include "hwcontext_vulkan.h"
32 /* GLSL management macros */
33 #define INDENT(N) INDENT_##N
35 #define INDENT_1 INDENT_0 " "
36 #define INDENT_2 INDENT_1 INDENT_1
37 #define INDENT_3 INDENT_2 INDENT_1
38 #define INDENT_4 INDENT_3 INDENT_1
39 #define INDENT_5 INDENT_4 INDENT_1
40 #define INDENT_6 INDENT_5 INDENT_1
41 #define C(N, S) INDENT(N) #S "\n"
45 av_bprintf(&shd->src, C(N, S)); \
50 av_bprintf(&shd->src, __VA_ARGS__); \
53 #define GLSLF(N, S, ...) \
55 av_bprintf(&shd->src, C(N, S), __VA_ARGS__); \
60 av_bprintf(&shd->src, "\n"); \
61 av_bprint_append_data(&shd->src, D, strlen(D)); \
62 av_bprintf(&shd->src, "\n"); \
65 /* Helper, pretty much every Vulkan return value needs to be checked */
68 if ((err = (x)) < 0) \
72 #define DUP_SAMPLER(x) { x, x, x, x }
74 typedef struct FFVulkanDescriptorSetBinding
{
76 VkDescriptorType type
;
77 const char *mem_layout
; /* Storage images (rgba8, etc.) and buffers (std430, etc.) */
78 const char *mem_quali
; /* readonly, writeonly, etc. */
79 const char *buf_content
; /* For buffers */
80 uint32_t dimensions
; /* Needed for e.g. sampler%iD */
81 uint32_t elems
; /* 0 - scalar, 1 or more - vector */
82 VkShaderStageFlags stages
;
83 uint32_t buf_elems
; /* Appends [buf_elems] to the contents. Avoids manually printing to a string. */
84 VkSampler samplers
[4]; /* Sampler to use for all elems */
85 } FFVulkanDescriptorSetBinding
;
87 typedef struct FFVkBuffer
{
90 VkMemoryPropertyFlagBits flags
;
92 VkDeviceAddress address
;
95 VkPipelineStageFlags2 stage
;
96 VkAccessFlags2 access
;
98 /* Only valid when allocated via ff_vk_get_pooled_buffer with HOST_VISIBLE or
99 * via ff_vk_host_map_buffer */
102 /* Set by ff_vk_host_map_buffer. This is the offset at which the buffer data
103 * actually begins at.
104 * The address and mapped_mem fields will be offset by this amount. */
105 size_t virtual_offset
;
107 /* If host mapping, reference to the backing host memory buffer */
108 AVBufferRef
*host_ref
;
111 typedef struct FFVkExecContext
{
113 const struct FFVkExecPool
*parent
;
116 /* Queue for the execution context */
121 /* Command buffer for the context */
124 /* Fence for the command buffer */
127 /* Opaque data, untouched, free to use by users */
133 /* Buffer dependencies */
134 AVBufferRef
**buf_deps
;
136 unsigned int buf_deps_alloc_size
;
138 /* Frame dependencies */
139 AVFrame
**frame_deps
;
140 unsigned int frame_deps_alloc_size
;
143 /* Software frame dependencies */
144 AVFrame
**sw_frame_deps
;
145 unsigned int sw_frame_deps_alloc_size
;
146 int nb_sw_frame_deps
;
148 VkSemaphoreSubmitInfo
*sem_wait
;
149 unsigned int sem_wait_alloc
;
152 VkSemaphoreSubmitInfo
*sem_sig
;
153 unsigned int sem_sig_alloc
;
156 uint64_t **sem_sig_val_dst
;
157 unsigned int sem_sig_val_dst_alloc
;
158 int sem_sig_val_dst_cnt
;
160 uint8_t *frame_locked
;
161 unsigned int frame_locked_alloc_size
;
163 VkAccessFlagBits
*access_dst
;
164 unsigned int access_dst_alloc
;
166 VkImageLayout
*layout_dst
;
167 unsigned int layout_dst_alloc
;
169 uint32_t *queue_family_dst
;
170 unsigned int queue_family_dst_alloc
;
172 uint8_t *frame_update
;
173 unsigned int frame_update_alloc_size
;
176 typedef struct FFVulkanDescriptorSet
{
177 /* Descriptor buffer */
178 VkDeviceSize layout_size
;
179 VkDeviceSize aligned_size
; /* descriptorBufferOffsetAlignment */
180 VkBufferUsageFlags usage
;
182 VkDescriptorSetLayoutBinding
*binding
;
183 VkDeviceSize
*binding_offset
;
186 /* Descriptor set is shared between all submissions */
188 } FFVulkanDescriptorSet
;
190 typedef struct FFVulkanShader
{
191 /* Name for id/debugging purposes */
197 /* Compute shader local group sizes */
200 /* Shader bind point/type */
201 VkPipelineStageFlags stage
;
202 VkPipelineBindPoint bind_point
;
205 VkPipelineShaderStageRequiredSubgroupSizeCreateInfo subgroup_info
;
207 /* Base shader object */
211 /* Pipeline layout */
212 VkPipelineLayout pipeline_layout
;
215 VkPushConstantRange
*push_consts
;
218 /* Descriptor sets */
219 FFVulkanDescriptorSet
*desc_set
;
220 int nb_descriptor_sets
;
222 /* Descriptor buffer */
223 VkDescriptorSetLayout
*desc_layout
;
224 uint32_t *bound_buffer_indices
;
226 /* Descriptor pool */
228 VkDescriptorPoolSize
*desc_pool_size
;
229 int nb_desc_pool_size
;
232 typedef struct FFVulkanDescriptorSetData
{
233 /* Descriptor buffer */
236 } FFVulkanDescriptorSetData
;
238 typedef struct FFVulkanShaderData
{
239 /* Shader to which this data belongs to */
241 int nb_descriptor_sets
;
243 /* Descriptor buffer */
244 FFVulkanDescriptorSetData
*desc_set_buf
;
245 VkDescriptorBufferBindingInfoEXT
*desc_bind
;
247 /* Descriptor pools */
248 VkDescriptorSet
*desc_sets
;
249 VkDescriptorPool desc_pool
;
250 } FFVulkanShaderData
;
252 typedef struct FFVkExecPool
{
253 FFVkExecContext
*contexts
;
254 atomic_uint_least64_t idx
;
256 VkCommandPool
*cmd_buf_pools
;
257 VkCommandBuffer
*cmd_bufs
;
260 VkQueryPool query_pool
;
265 int query_status_stride
;
269 /* Registered shaders' data */
270 FFVulkanShaderData
*reg_shd
;
274 typedef struct FFVulkanContext
{
275 const AVClass
*class;
278 FFVulkanFunctions vkfn
;
279 FFVulkanExtensions extensions
;
280 VkPhysicalDeviceProperties2 props
;
281 VkPhysicalDeviceVulkan11Properties props_11
;
282 VkPhysicalDeviceDriverProperties driver_props
;
283 VkPhysicalDeviceMemoryProperties mprops
;
284 VkPhysicalDeviceExternalMemoryHostPropertiesEXT hprops
;
285 VkPhysicalDeviceDescriptorBufferPropertiesEXT desc_buf_props
;
286 VkPhysicalDeviceSubgroupSizeControlProperties subgroup_props
;
287 VkPhysicalDeviceCooperativeMatrixPropertiesKHR coop_matrix_props
;
288 VkPhysicalDevicePushDescriptorPropertiesKHR push_desc_props
;
289 VkPhysicalDeviceOpticalFlowPropertiesNV optical_flow_props
;
290 VkQueueFamilyQueryResultStatusPropertiesKHR
*query_props
;
291 VkQueueFamilyVideoPropertiesKHR
*video_props
;
292 VkQueueFamilyProperties2
*qf_props
;
294 VkPhysicalDeviceHostImageCopyPropertiesEXT host_image_props
;
295 VkImageLayout
*host_image_copy_layouts
;
297 VkCooperativeMatrixPropertiesKHR
*coop_mat_props
;
298 uint32_t coop_mat_props_nb
;
300 VkPhysicalDeviceShaderAtomicFloatFeaturesEXT atomic_float_feats
;
301 VkPhysicalDeviceVulkan12Features feats_12
;
302 VkPhysicalDeviceFeatures2 feats
;
304 AVBufferRef
*device_ref
;
305 AVHWDeviceContext
*device
;
306 AVVulkanDeviceContext
*hwctx
;
308 AVBufferRef
*input_frames_ref
;
309 AVBufferRef
*frames_ref
;
310 AVHWFramesContext
*frames
;
311 AVVulkanFramesContext
*hwfc
;
319 enum AVPixelFormat output_format
;
320 enum AVPixelFormat input_format
;
323 static inline int ff_vk_count_images(AVVkFrame
*f
)
326 while (cnt
< FF_ARRAY_ELEMS(f
->img
) && f
->img
[cnt
])
332 static inline const void *ff_vk_find_struct(const void *chain
, VkStructureType stype
)
334 const VkBaseInStructure
*in
= chain
;
336 if (in
->sType
== stype
)
345 static inline void ff_vk_link_struct(void *chain
, const void *in
)
347 VkBaseOutStructure
*out
= chain
;
351 out
->pNext
= (void *)in
;
354 #define FF_VK_STRUCT_EXT(CTX, BASE, STRUCT_P, EXT_FLAG, TYPE) \
356 if ((EXT_FLAG == FF_VK_EXT_NO_FLAG) || \
357 ((CTX)->extensions & EXT_FLAG)) { \
358 (STRUCT_P)->sType = TYPE; \
359 ff_vk_link_struct(BASE, STRUCT_P); \
363 /* Identity mapping - r = r, b = b, g = g, a = a */
364 extern const VkComponentMapping ff_comp_identity_map
;
367 * Initializes the AVClass, in case this context is not used
368 * as the main user's context.
369 * May use either a frames context reference, or a device context reference.
371 int ff_vk_init(FFVulkanContext
*s
, void *log_parent
,
372 AVBufferRef
*device_ref
, AVBufferRef
*frames_ref
);
375 * Converts Vulkan return values to strings
377 const char *ff_vk_ret2str(VkResult res
);
380 * Map between usage and features.
382 VkImageUsageFlags
ff_vk_map_feats_to_usage(VkFormatFeatureFlagBits2 feats
);
383 VkFormatFeatureFlagBits2
ff_vk_map_usage_to_feats(VkImageUsageFlags usage
);
386 * Returns 1 if pixfmt is a usable RGB format.
388 int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt
);
391 * Since storage images may not be swizzled, we have to do this in the
392 * shader itself. This fills in a lookup table to do it.
394 void ff_vk_set_perm(enum AVPixelFormat pix_fmt
, int lut
[4], int inv
);
397 * Get the aspect flag for a plane from an image.
399 VkImageAspectFlags
ff_vk_aspect_flag(AVFrame
*f
, int p
);
402 * Returns the format to use for images in shaders.
404 enum FFVkShaderRepFormat
{
405 /* Native format with no conversion. May require casting. */
406 FF_VK_REP_NATIVE
= 0,
407 /* Float conversion of the native format. */
409 /* Signed integer version of the native format */
411 /* Unsigned integer version of the native format */
414 const char *ff_vk_shader_rep_fmt(enum AVPixelFormat pix_fmt
,
415 enum FFVkShaderRepFormat rep_fmt
);
418 * Loads props/mprops/driver_props
420 int ff_vk_load_props(FFVulkanContext
*s
);
423 * Chooses an appropriate QF.
425 AVVulkanDeviceQueueFamily
*ff_vk_qf_find(FFVulkanContext
*s
,
426 VkQueueFlagBits dev_family
,
427 VkVideoCodecOperationFlagBitsKHR vid_ops
);
430 * Allocates/frees an execution pool.
431 * If used in a multi-threaded context, there must be at least as many contexts
432 * as there are threads.
433 * ff_vk_exec_pool_init_desc() MUST be called if ff_vk_exec_descriptor_set_add()
436 int ff_vk_exec_pool_init(FFVulkanContext
*s
, AVVulkanDeviceQueueFamily
*qf
,
437 FFVkExecPool
*pool
, int nb_contexts
,
438 int nb_queries
, VkQueryType query_type
, int query_64bit
,
439 const void *query_create_pnext
);
440 void ff_vk_exec_pool_free(FFVulkanContext
*s
, FFVkExecPool
*pool
);
443 * Retrieve an execution pool. Threadsafe.
445 FFVkExecContext
*ff_vk_exec_get(FFVulkanContext
*s
, FFVkExecPool
*pool
);
448 * Performs nb_queries queries and returns their results and statuses.
449 * 64_BIT and WITH_STATUS flags are ignored as 64_BIT must be specified via
450 * query_64bit in ff_vk_exec_pool_init() and WITH_STATUS is always enabled.
452 VkResult
ff_vk_exec_get_query(FFVulkanContext
*s
, FFVkExecContext
*e
,
453 void **data
, VkQueryResultFlagBits flags
);
456 * Start/submit/wait an execution.
457 * ff_vk_exec_start() always waits on a submission, so using ff_vk_exec_wait()
458 * is not necessary (unless using it is just better).
460 int ff_vk_exec_start(FFVulkanContext
*s
, FFVkExecContext
*e
);
461 int ff_vk_exec_submit(FFVulkanContext
*s
, FFVkExecContext
*e
);
462 void ff_vk_exec_wait(FFVulkanContext
*s
, FFVkExecContext
*e
);
465 * Execution dependency management.
466 * Can attach buffers to executions that will only be unref'd once the
467 * buffer has finished executing.
468 * Adding a frame dep will *lock the frame*, until either the dependencies
469 * are discarded, the execution is submitted, or a failure happens.
470 * update_frame will update the frame's properties before it is unlocked,
471 * only if submission was successful.
473 int ff_vk_exec_add_dep_buf(FFVulkanContext
*s
, FFVkExecContext
*e
,
474 AVBufferRef
**deps
, int nb_deps
, int ref
);
475 int ff_vk_exec_add_dep_wait_sem(FFVulkanContext
*s
, FFVkExecContext
*e
,
476 VkSemaphore sem
, uint64_t val
,
477 VkPipelineStageFlagBits2 stage
);
478 int ff_vk_exec_add_dep_bool_sem(FFVulkanContext
*s
, FFVkExecContext
*e
,
479 VkSemaphore
*sem
, int nb
,
480 VkPipelineStageFlagBits2 stage
,
481 int wait
); /* Ownership transferred if !wait */
482 int ff_vk_exec_add_dep_frame(FFVulkanContext
*s
, FFVkExecContext
*e
, AVFrame
*f
,
483 VkPipelineStageFlagBits2 wait_stage
,
484 VkPipelineStageFlagBits2 signal_stage
);
485 int ff_vk_exec_add_dep_sw_frame(FFVulkanContext
*s
, FFVkExecContext
*e
,
487 void ff_vk_exec_update_frame(FFVulkanContext
*s
, FFVkExecContext
*e
, AVFrame
*f
,
488 VkImageMemoryBarrier2
*bar
, uint32_t *nb_img_bar
);
489 int ff_vk_exec_mirror_sem_value(FFVulkanContext
*s
, FFVkExecContext
*e
,
490 VkSemaphore
*dst
, uint64_t *dst_val
,
492 void ff_vk_exec_discard_deps(FFVulkanContext
*s
, FFVkExecContext
*e
);
495 * Create a single imageview for a given plane.
497 int ff_vk_create_imageview(FFVulkanContext
*s
,
498 VkImageView
*img_view
, VkImageAspectFlags
*aspect
,
499 AVFrame
*f
, int plane
, enum FFVkShaderRepFormat rep_fmt
);
502 * Create an imageview and add it as a dependency to an execution.
504 int ff_vk_create_imageviews(FFVulkanContext
*s
, FFVkExecContext
*e
,
505 VkImageView views
[AV_NUM_DATA_POINTERS
],
506 AVFrame
*f
, enum FFVkShaderRepFormat rep_fmt
);
508 void ff_vk_frame_barrier(FFVulkanContext
*s
, FFVkExecContext
*e
,
509 AVFrame
*pic
, VkImageMemoryBarrier2
*bar
, int *nb_bar
,
510 VkPipelineStageFlags2 src_stage
,
511 VkPipelineStageFlags2 dst_stage
,
512 VkAccessFlagBits2 new_access
,
513 VkImageLayout new_layout
,
517 * Memory/buffer/image allocation helpers.
519 int ff_vk_alloc_mem(FFVulkanContext
*s
, VkMemoryRequirements
*req
,
520 VkMemoryPropertyFlagBits req_flags
, void *alloc_extension
,
521 VkMemoryPropertyFlagBits
*mem_flags
, VkDeviceMemory
*mem
);
522 int ff_vk_create_buf(FFVulkanContext
*s
, FFVkBuffer
*buf
, size_t size
,
523 void *pNext
, void *alloc_pNext
,
524 VkBufferUsageFlags usage
, VkMemoryPropertyFlagBits flags
);
527 * Flush or invalidate a single buffer, with a given size and offset.
529 int ff_vk_flush_buffer(FFVulkanContext
*s
, FFVkBuffer
*buf
,
530 size_t offset
, size_t mem_size
,
534 * Buffer management code.
536 int ff_vk_map_buffers(FFVulkanContext
*s
, FFVkBuffer
**buf
, uint8_t *mem
[],
537 int nb_buffers
, int invalidate
);
538 int ff_vk_unmap_buffers(FFVulkanContext
*s
, FFVkBuffer
**buf
, int nb_buffers
,
541 static inline int ff_vk_map_buffer(FFVulkanContext
*s
, FFVkBuffer
*buf
, uint8_t **mem
,
544 return ff_vk_map_buffers(s
, (FFVkBuffer
*[]){ buf
}, mem
,
548 static inline int ff_vk_unmap_buffer(FFVulkanContext
*s
, FFVkBuffer
*buf
, int flush
)
550 return ff_vk_unmap_buffers(s
, (FFVkBuffer
*[]){ buf
}, 1, flush
);
553 void ff_vk_free_buf(FFVulkanContext
*s
, FFVkBuffer
*buf
);
555 /** Initialize a pool and create AVBufferRefs containing FFVkBuffer.
556 * Threadsafe to use. Buffers are automatically mapped on creation if
557 * VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT is set in mem_props. Users should
558 * synchronize access themselvesd. Mainly meant for device-local buffers. */
559 int ff_vk_get_pooled_buffer(FFVulkanContext
*ctx
, AVBufferPool
**buf_pool
,
560 AVBufferRef
**buf
, VkBufferUsageFlags usage
,
561 void *create_pNext
, size_t size
,
562 VkMemoryPropertyFlagBits mem_props
);
564 /** Maps a system RAM buffer into a Vulkan buffer.
565 * References the source buffer.
567 int ff_vk_host_map_buffer(FFVulkanContext
*s
, AVBufferRef
**dst
,
568 uint8_t *src_data
, const AVBufferRef
*src_buf
,
569 VkBufferUsageFlags usage
);
574 int ff_vk_init_sampler(FFVulkanContext
*s
, VkSampler
*sampler
,
575 int unnorm_coords
, VkFilter filt
);
578 * Initialize a shader object, with a specific set of extensions, type+bind,
579 * local group size, and subgroup requirements.
581 int ff_vk_shader_init(FFVulkanContext
*s
, FFVulkanShader
*shd
, const char *name
,
582 VkPipelineStageFlags stage
,
583 const char *extensions
[], int nb_extensions
,
584 int lg_x
, int lg_y
, int lg_z
,
585 uint32_t required_subgroup_size
);
588 * Output the shader code as logging data, with a specific
591 void ff_vk_shader_print(void *ctx
, FFVulkanShader
*shd
, int prio
);
594 * Link a shader into an executable.
596 int ff_vk_shader_link(FFVulkanContext
*s
, FFVulkanShader
*shd
,
597 uint8_t *spirv
, size_t spirv_len
,
598 const char *entrypoint
);
601 * Add/update push constants for execution.
603 int ff_vk_shader_add_push_const(FFVulkanShader
*shd
, int offset
, int size
,
604 VkShaderStageFlagBits stage
);
607 * Add descriptor to a shader. Must be called before shader init.
609 int ff_vk_shader_add_descriptor_set(FFVulkanContext
*s
, FFVulkanShader
*shd
,
610 FFVulkanDescriptorSetBinding
*desc
, int nb
,
611 int singular
, int print_to_shader_only
);
614 * Register a shader with an exec pool.
615 * Pool may be NULL if all descriptor sets are read-only.
617 int ff_vk_shader_register_exec(FFVulkanContext
*s
, FFVkExecPool
*pool
,
618 FFVulkanShader
*shd
);
623 void ff_vk_exec_bind_shader(FFVulkanContext
*s
, FFVkExecContext
*e
,
624 FFVulkanShader
*shd
);
627 * Update push constant in a shader.
628 * Must be called before binding the shader.
630 void ff_vk_shader_update_push_const(FFVulkanContext
*s
, FFVkExecContext
*e
,
632 VkShaderStageFlagBits stage
,
633 int offset
, size_t size
, void *src
);
636 * Update a descriptor in a buffer with a buffer.
637 * Must be called before binding the shader.
639 int ff_vk_shader_update_desc_buffer(FFVulkanContext
*s
, FFVkExecContext
*e
,
641 int set
, int bind
, int elem
,
642 FFVkBuffer
*buf
, VkDeviceSize offset
, VkDeviceSize len
,
646 * Sets an image descriptor for specified shader and binding.
648 int ff_vk_shader_update_img(FFVulkanContext
*s
, FFVkExecContext
*e
,
649 FFVulkanShader
*shd
, int set
, int bind
, int offs
,
650 VkImageView view
, VkImageLayout layout
,
654 * Update a descriptor in a buffer with an image array..
655 * Must be called before binding the shader.
657 void ff_vk_shader_update_img_array(FFVulkanContext
*s
, FFVkExecContext
*e
,
658 FFVulkanShader
*shd
, AVFrame
*f
,
659 VkImageView
*views
, int set
, int binding
,
660 VkImageLayout layout
, VkSampler sampler
);
665 void ff_vk_shader_free(FFVulkanContext
*s
, FFVulkanShader
*shd
);
668 * Frees main context.
670 void ff_vk_uninit(FFVulkanContext
*s
);
672 #endif /* AVUTIL_VULKAN_H */