123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524 |
- /*
- * 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 AVUTIL_VULKAN_H
- #define AVUTIL_VULKAN_H
- #define VK_NO_PROTOTYPES
- #include <stdatomic.h>
- #include "thread.h"
- #include "pixdesc.h"
- #include "bprint.h"
- #include "hwcontext.h"
- #include "vulkan_functions.h"
- #include "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) \
- do { \
- av_bprintf(&shd->src, C(N, S)); \
- } while (0)
- #define GLSLA(...) \
- do { \
- av_bprintf(&shd->src, __VA_ARGS__); \
- } while (0)
- #define GLSLF(N, S, ...) \
- do { \
- av_bprintf(&shd->src, C(N, S), __VA_ARGS__); \
- } while (0)
- #define GLSLD(D) \
- do { \
- av_bprintf(&shd->src, "\n"); \
- av_bprint_append_data(&shd->src, D, strlen(D)); \
- av_bprintf(&shd->src, "\n"); \
- } while (0)
- /* Helper, pretty much every Vulkan return value needs to be checked */
- #define RET(x) \
- do { \
- if ((err = (x)) < 0) \
- goto fail; \
- } while (0)
- #define DUP_SAMPLER(x) { x, x, x, x }
- typedef struct FFVkSPIRVShader {
- const char *name; /* Name for id/debugging purposes */
- AVBPrint src;
- int local_size[3]; /* Compute shader workgroup sizes */
- VkPipelineShaderStageCreateInfo shader;
- VkPipelineShaderStageRequiredSubgroupSizeCreateInfo subgroup_info;
- } FFVkSPIRVShader;
- typedef struct FFVulkanDescriptorSetBinding {
- 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;
- VkSampler samplers[4]; /* Sampler to use for all elems */
- } FFVulkanDescriptorSetBinding;
- typedef struct FFVkBuffer {
- VkBuffer buf;
- VkDeviceMemory mem;
- VkMemoryPropertyFlagBits flags;
- size_t size;
- VkDeviceAddress address;
- /* Local use only */
- VkPipelineStageFlags2 stage;
- VkAccessFlags2 access;
- /* Only valid when allocated via ff_vk_get_pooled_buffer with HOST_VISIBLE */
- uint8_t *mapped_mem;
- } FFVkBuffer;
- typedef struct FFVkQueueFamilyCtx {
- int queue_family;
- int nb_queues;
- } FFVkQueueFamilyCtx;
- typedef struct FFVulkanDescriptorSet {
- VkDescriptorSetLayout layout;
- FFVkBuffer buf;
- uint8_t *desc_mem;
- VkDeviceSize layout_size;
- VkDeviceSize aligned_size; /* descriptorBufferOffsetAlignment */
- VkDeviceSize total_size; /* Once registered to an exec context */
- VkBufferUsageFlags usage;
- VkDescriptorSetLayoutBinding *binding;
- VkDeviceSize *binding_offset;
- int nb_bindings;
- /* Descriptor set is shared between all submissions */
- int singular;
- } FFVulkanDescriptorSet;
- typedef struct FFVulkanPipeline {
- VkPipelineBindPoint bind_point;
- /* Contexts */
- VkPipelineLayout pipeline_layout;
- VkPipeline pipeline;
- /* Push consts */
- VkPushConstantRange *push_consts;
- int push_consts_num;
- /* Workgroup */
- int wg_size[3];
- /* Descriptors */
- FFVulkanDescriptorSet *desc_set;
- VkDescriptorBufferBindingInfoEXT *desc_bind;
- uint32_t *bound_buffer_indices;
- int nb_descriptor_sets;
- } FFVulkanPipeline;
- typedef struct FFVkExecContext {
- uint32_t idx;
- const struct FFVkExecPool *parent;
- pthread_mutex_t lock;
- int had_submission;
- /* Queue for the execution context */
- VkQueue queue;
- int qf;
- int qi;
- /* Command buffer for the context */
- VkCommandBuffer buf;
- /* Fence for the command buffer */
- VkFence fence;
- void *query_data;
- int query_idx;
- /* Buffer dependencies */
- AVBufferRef **buf_deps;
- int nb_buf_deps;
- unsigned int buf_deps_alloc_size;
- /* Frame dependencies */
- AVFrame **frame_deps;
- unsigned int frame_deps_alloc_size;
- int nb_frame_deps;
- VkSemaphoreSubmitInfo *sem_wait;
- unsigned int sem_wait_alloc;
- int sem_wait_cnt;
- VkSemaphoreSubmitInfo *sem_sig;
- unsigned int sem_sig_alloc;
- int sem_sig_cnt;
- uint64_t **sem_sig_val_dst;
- unsigned int sem_sig_val_dst_alloc;
- int sem_sig_val_dst_cnt;
- uint8_t *frame_locked;
- unsigned int frame_locked_alloc_size;
- VkAccessFlagBits *access_dst;
- unsigned int access_dst_alloc;
- VkImageLayout *layout_dst;
- unsigned int layout_dst_alloc;
- uint32_t *queue_family_dst;
- unsigned int queue_family_dst_alloc;
- uint8_t *frame_update;
- unsigned int frame_update_alloc_size;
- } FFVkExecContext;
- typedef struct FFVkExecPool {
- FFVkExecContext *contexts;
- atomic_int_least64_t idx;
- VkCommandPool cmd_buf_pool;
- VkCommandBuffer *cmd_bufs;
- int pool_size;
- VkQueryPool query_pool;
- void *query_data;
- int query_results;
- int query_statuses;
- int query_64bit;
- int query_status_stride;
- int nb_queries;
- size_t qd_size;
- } FFVkExecPool;
- typedef struct FFVulkanContext {
- const AVClass *class;
- void *log_parent;
- FFVulkanFunctions vkfn;
- FFVulkanExtensions extensions;
- VkPhysicalDeviceProperties2 props;
- VkPhysicalDeviceDriverProperties driver_props;
- VkPhysicalDeviceMemoryProperties mprops;
- VkPhysicalDeviceExternalMemoryHostPropertiesEXT hprops;
- VkPhysicalDeviceDescriptorBufferPropertiesEXT desc_buf_props;
- VkPhysicalDeviceSubgroupSizeControlProperties subgroup_props;
- VkPhysicalDeviceCooperativeMatrixPropertiesKHR coop_matrix_props;
- VkPhysicalDeviceOpticalFlowPropertiesNV optical_flow_props;
- VkQueueFamilyQueryResultStatusPropertiesKHR *query_props;
- VkQueueFamilyVideoPropertiesKHR *video_props;
- VkQueueFamilyProperties2 *qf_props;
- int tot_nb_qfs;
- VkCooperativeMatrixPropertiesKHR *coop_mat_props;
- uint32_t coop_mat_props_nb;
- VkPhysicalDeviceShaderAtomicFloatFeaturesEXT atomic_float_feats;
- VkPhysicalDeviceVulkan12Features feats_12;
- VkPhysicalDeviceFeatures2 feats;
- AVBufferRef *device_ref;
- AVHWDeviceContext *device;
- AVVulkanDeviceContext *hwctx;
- AVBufferRef *input_frames_ref;
- AVBufferRef *frames_ref;
- AVHWFramesContext *frames;
- AVVulkanFramesContext *hwfc;
- uint32_t qfs[64];
- int nb_qfs;
- /* Properties */
- int output_width;
- int output_height;
- enum AVPixelFormat output_format;
- enum AVPixelFormat input_format;
- } FFVulkanContext;
- static inline int ff_vk_count_images(AVVkFrame *f)
- {
- int cnt = 0;
- while (cnt < FF_ARRAY_ELEMS(f->img) && f->img[cnt])
- cnt++;
- return cnt;
- }
- static inline const void *ff_vk_find_struct(const void *chain, VkStructureType stype)
- {
- const VkBaseInStructure *in = chain;
- while (in) {
- if (in->sType == stype)
- return in;
- in = in->pNext;
- }
- return NULL;
- }
- static inline void ff_vk_link_struct(void *chain, const void *in)
- {
- VkBaseOutStructure *out = chain;
- while (out->pNext)
- out = out->pNext;
- out->pNext = (void *)in;
- }
- /* Identity mapping - r = r, b = b, g = g, a = a */
- extern const VkComponentMapping ff_comp_identity_map;
- /**
- * Initializes the AVClass, in case this context is not used
- * as the main user's context.
- * May use either a frames context reference, or a device context reference.
- */
- int ff_vk_init(FFVulkanContext *s, void *log_parent,
- AVBufferRef *device_ref, AVBufferRef *frames_ref);
- /**
- * Converts Vulkan return values to strings
- */
- const char *ff_vk_ret2str(VkResult res);
- /**
- * Returns 1 if pixfmt is a usable RGB format.
- */
- int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt);
- /**
- * Returns the format to use for images in shaders.
- */
- const char *ff_vk_shader_rep_fmt(enum AVPixelFormat pixfmt);
- /**
- * Loads props/mprops/driver_props
- */
- int ff_vk_load_props(FFVulkanContext *s);
- /**
- * Chooses a QF and loads it into a context.
- */
- int ff_vk_qf_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf,
- VkQueueFlagBits dev_family);
- /**
- * Allocates/frees an execution pool.
- * ff_vk_exec_pool_init_desc() MUST be called if ff_vk_exec_descriptor_set_add()
- * has been called.
- */
- int ff_vk_exec_pool_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf,
- FFVkExecPool *pool, int nb_contexts,
- int nb_queries, VkQueryType query_type, int query_64bit,
- const void *query_create_pnext);
- void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool);
- /**
- * Retrieve an execution pool. Threadsafe.
- */
- FFVkExecContext *ff_vk_exec_get(FFVkExecPool *pool);
- /**
- * Performs nb_queries queries and returns their results and statuses.
- * 64_BIT and WITH_STATUS flags are ignored as 64_BIT must be specified via
- * query_64bit in ff_vk_exec_pool_init() and WITH_STATUS is always enabled.
- */
- VkResult ff_vk_exec_get_query(FFVulkanContext *s, FFVkExecContext *e,
- void **data, VkQueryResultFlagBits flags);
- /**
- * Start/submit/wait an execution.
- * ff_vk_exec_start() always waits on a submission, so using ff_vk_exec_wait()
- * is not necessary (unless using it is just better).
- */
- int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e);
- int ff_vk_exec_submit(FFVulkanContext *s, FFVkExecContext *e);
- void ff_vk_exec_wait(FFVulkanContext *s, FFVkExecContext *e);
- /**
- * Execution dependency management.
- * Can attach buffers to executions that will only be unref'd once the
- * buffer has finished executing.
- * Adding a frame dep will *lock the frame*, until either the dependencies
- * are discarded, the execution is submitted, or a failure happens.
- * update_frame will update the frame's properties before it is unlocked,
- * only if submission was successful.
- */
- int ff_vk_exec_add_dep_buf(FFVulkanContext *s, FFVkExecContext *e,
- AVBufferRef **deps, int nb_deps, int ref);
- int ff_vk_exec_add_dep_bool_sem(FFVulkanContext *s, FFVkExecContext *e,
- VkSemaphore *sem, int nb,
- VkPipelineStageFlagBits2 stage,
- int wait); /* Ownership transferred if !wait */
- int ff_vk_exec_add_dep_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f,
- VkPipelineStageFlagBits2 wait_stage,
- VkPipelineStageFlagBits2 signal_stage);
- void ff_vk_exec_update_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f,
- VkImageMemoryBarrier2 *bar, uint32_t *nb_img_bar);
- int ff_vk_exec_mirror_sem_value(FFVulkanContext *s, FFVkExecContext *e,
- VkSemaphore *dst, uint64_t *dst_val,
- AVFrame *f);
- void ff_vk_exec_discard_deps(FFVulkanContext *s, FFVkExecContext *e);
- /**
- * Create an imageview and add it as a dependency to an execution.
- */
- int ff_vk_create_imageviews(FFVulkanContext *s, FFVkExecContext *e,
- VkImageView views[AV_NUM_DATA_POINTERS],
- AVFrame *f);
- void ff_vk_frame_barrier(FFVulkanContext *s, FFVkExecContext *e,
- AVFrame *pic, VkImageMemoryBarrier2 *bar, int *nb_bar,
- VkPipelineStageFlags src_stage,
- VkPipelineStageFlags dst_stage,
- VkAccessFlagBits new_access,
- VkImageLayout new_layout,
- uint32_t new_qf);
- /**
- * Memory/buffer/image allocation helpers.
- */
- int ff_vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req,
- VkMemoryPropertyFlagBits req_flags, void *alloc_extension,
- VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem);
- int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size,
- void *pNext, void *alloc_pNext,
- VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags);
- int ff_vk_create_avbuf(FFVulkanContext *s, AVBufferRef **ref, size_t size,
- void *pNext, void *alloc_pNext,
- VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags);
- /**
- * Buffer management code.
- */
- int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer **buf, uint8_t *mem[],
- int nb_buffers, int invalidate);
- int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer **buf, int nb_buffers,
- int flush);
- static inline int ff_vk_map_buffer(FFVulkanContext *s, FFVkBuffer *buf, uint8_t **mem,
- int invalidate)
- {
- return ff_vk_map_buffers(s, (FFVkBuffer *[]){ buf }, mem,
- 1, invalidate);
- }
- static inline int ff_vk_unmap_buffer(FFVulkanContext *s, FFVkBuffer *buf, int flush)
- {
- return ff_vk_unmap_buffers(s, (FFVkBuffer *[]){ buf }, 1, flush);
- }
- void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf);
- /** Initialize a pool and create AVBufferRefs containing FFVkBuffer.
- * Threadsafe to use. Buffers are automatically mapped on creation if
- * VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT is set in mem_props. Users should
- * synchronize access themselvesd. Mainly meant for device-local buffers. */
- int ff_vk_get_pooled_buffer(FFVulkanContext *ctx, AVBufferPool **buf_pool,
- AVBufferRef **buf, VkBufferUsageFlags usage,
- void *create_pNext, size_t size,
- VkMemoryPropertyFlagBits mem_props);
- /**
- * Create a sampler.
- */
- int ff_vk_init_sampler(FFVulkanContext *s, VkSampler *sampler,
- int unnorm_coords, VkFilter filt);
- /**
- * Shader management.
- */
- int ff_vk_shader_init(FFVulkanPipeline *pl, FFVkSPIRVShader *shd, const char *name,
- VkShaderStageFlags stage, uint32_t required_subgroup_size);
- void ff_vk_shader_set_compute_sizes(FFVkSPIRVShader *shd, int x, int y, int z);
- void ff_vk_shader_print(void *ctx, FFVkSPIRVShader *shd, int prio);
- int ff_vk_shader_create(FFVulkanContext *s, FFVkSPIRVShader *shd,
- uint8_t *spirv, size_t spirv_size, const char *entrypoint);
- void ff_vk_shader_free(FFVulkanContext *s, FFVkSPIRVShader *shd);
- /**
- * Add/update push constants for execution.
- */
- int ff_vk_add_push_constant(FFVulkanPipeline *pl, int offset, int size,
- VkShaderStageFlagBits stage);
- void ff_vk_update_push_exec(FFVulkanContext *s, FFVkExecContext *e,
- FFVulkanPipeline *pl,
- VkShaderStageFlagBits stage,
- int offset, size_t size, void *src);
- /**
- * Add descriptor to a pipeline. Must be called before pipeline init.
- */
- int ff_vk_pipeline_descriptor_set_add(FFVulkanContext *s, FFVulkanPipeline *pl,
- FFVkSPIRVShader *shd,
- FFVulkanDescriptorSetBinding *desc, int nb,
- int singular, int print_to_shader_only);
- /* Initialize/free a pipeline. */
- int ff_vk_init_compute_pipeline(FFVulkanContext *s, FFVulkanPipeline *pl,
- FFVkSPIRVShader *shd);
- void ff_vk_pipeline_free(FFVulkanContext *s, FFVulkanPipeline *pl);
- /**
- * Register a pipeline with an exec pool.
- * Pool may be NULL if all descriptor sets are read-only.
- */
- int ff_vk_exec_pipeline_register(FFVulkanContext *s, FFVkExecPool *pool,
- FFVulkanPipeline *pl);
- /* Bind pipeline */
- void ff_vk_exec_bind_pipeline(FFVulkanContext *s, FFVkExecContext *e,
- FFVulkanPipeline *pl);
- int ff_vk_set_descriptor_buffer(FFVulkanContext *s, FFVulkanPipeline *pl,
- FFVkExecContext *e, int set, int bind, int offs,
- VkDeviceAddress addr, VkDeviceSize len, VkFormat fmt);
- void ff_vk_update_descriptor_img_array(FFVulkanContext *s, FFVulkanPipeline *pl,
- FFVkExecContext *e, AVFrame *f,
- VkImageView *views, int set, int binding,
- VkImageLayout layout, VkSampler sampler);
- /**
- * Frees main context.
- */
- void ff_vk_uninit(FFVulkanContext *s);
- #endif /* AVUTIL_VULKAN_H */
|