summaryrefslogtreecommitdiff
path: root/libavutil/vulkan.h
diff options
context:
space:
mode:
authorLynne <dev@lynne.ee>2021-11-19 07:46:15 +0100
committerLynne <dev@lynne.ee>2021-11-19 13:44:45 +0100
commitd1133e8c44f457f0698c48f2efcedbd8626b3cee (patch)
tree034ac8f51d6225eca4a9408c30be20335adced06 /libavutil/vulkan.h
parent8c150d3d9794c29a54bbdf2f2a88066277c7197e (diff)
downloadffmpeg-d1133e8c44f457f0698c48f2efcedbd8626b3cee.tar.gz
lavu/vulkan: move common Vulkan code from libavfilter to libavutil
Diffstat (limited to 'libavutil/vulkan.h')
-rw-r--r--libavutil/vulkan.h413
1 files changed, 413 insertions, 0 deletions
diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h
new file mode 100644
index 0000000000..14c69ce015
--- /dev/null
+++ b/libavutil/vulkan.h
@@ -0,0 +1,413 @@
+/*
+ * 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
+#define VK_ENABLE_BETA_EXTENSIONS
+
+#include "pixdesc.h"
+#include "bprint.h"
+#include "hwcontext.h"
+#include "hwcontext_vulkan.h"
+#include "vulkan_functions.h"
+
+#define FF_VK_DEFAULT_USAGE_FLAGS (VK_IMAGE_USAGE_SAMPLED_BIT | \
+ VK_IMAGE_USAGE_STORAGE_BIT | \
+ VK_IMAGE_USAGE_TRANSFER_SRC_BIT | \
+ VK_IMAGE_USAGE_TRANSFER_DST_BIT)
+
+/* 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) av_bprintf(&shd->src, C(N, S))
+#define GLSLA(...) av_bprintf(&shd->src, __VA_ARGS__)
+#define GLSLF(N, S, ...) av_bprintf(&shd->src, C(N, S), __VA_ARGS__)
+#define GLSLD(D) GLSLC(0, ); \
+ av_bprint_append_data(&shd->src, D, strlen(D)); \
+ GLSLC(0, )
+
+/* Helper, pretty much every Vulkan return value needs to be checked */
+#define RET(x) \
+ do { \
+ if ((err = (x)) < 0) \
+ goto fail; \
+ } while (0)
+
+typedef struct FFVkSPIRVShader {
+ const char *name; /* Name for id/debugging purposes */
+ AVBPrint src;
+ int local_size[3]; /* Compute shader workgroup sizes */
+ VkPipelineShaderStageCreateInfo shader;
+} FFVkSPIRVShader;
+
+typedef struct FFVkSampler {
+ VkSampler sampler[4];
+} FFVkSampler;
+
+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;
+ FFVkSampler *sampler; /* Sampler to use for all elems */
+ void *updater; /* Pointer to VkDescriptor*Info */
+} FFVulkanDescriptorSetBinding;
+
+typedef struct FFVkBuffer {
+ VkBuffer buf;
+ VkDeviceMemory mem;
+ VkMemoryPropertyFlagBits flags;
+} FFVkBuffer;
+
+typedef struct FFVkQueueFamilyCtx {
+ int queue_family;
+ int nb_queues;
+ int cur_queue;
+ int actual_queues;
+} FFVkQueueFamilyCtx;
+
+typedef struct FFVulkanPipeline {
+ FFVkQueueFamilyCtx *qf;
+
+ VkPipelineBindPoint bind_point;
+
+ /* Contexts */
+ VkPipelineLayout pipeline_layout;
+ VkPipeline pipeline;
+
+ /* Shaders */
+ FFVkSPIRVShader **shaders;
+ int shaders_num;
+
+ /* Push consts */
+ VkPushConstantRange *push_consts;
+ int push_consts_num;
+
+ /* Descriptors */
+ VkDescriptorSetLayout *desc_layout;
+ VkDescriptorPool desc_pool;
+ VkDescriptorSet *desc_set;
+ void **desc_staging;
+ VkDescriptorSetLayoutBinding **desc_binding;
+ VkDescriptorUpdateTemplate *desc_template;
+ int *desc_set_initialized;
+ int desc_layout_num;
+ int descriptor_sets_num;
+ int total_descriptor_sets;
+ int pool_size_desc_num;
+
+ /* Temporary, used to store data in between initialization stages */
+ VkDescriptorUpdateTemplateCreateInfo *desc_template_info;
+ VkDescriptorPoolSize *pool_size_desc;
+} FFVulkanPipeline;
+
+typedef struct FFVkQueueCtx {
+ VkFence fence;
+ VkQueue queue;
+
+ /* Buffer dependencies */
+ AVBufferRef **buf_deps;
+ int nb_buf_deps;
+ int buf_deps_alloc_size;
+
+ /* Frame dependencies */
+ AVFrame **frame_deps;
+ int nb_frame_deps;
+ int frame_deps_alloc_size;
+} FFVkQueueCtx;
+
+typedef struct FFVkExecContext {
+ FFVkQueueFamilyCtx *qf;
+
+ VkCommandPool pool;
+ VkCommandBuffer *bufs;
+ FFVkQueueCtx *queues;
+
+ AVBufferRef ***deps;
+ int *nb_deps;
+ int *dep_alloc_size;
+
+ FFVulkanPipeline *bound_pl;
+
+ VkSemaphore *sem_wait;
+ int sem_wait_alloc; /* Allocated sem_wait */
+ int sem_wait_cnt;
+
+ uint64_t *sem_wait_val;
+ int sem_wait_val_alloc;
+
+ VkPipelineStageFlagBits *sem_wait_dst;
+ int sem_wait_dst_alloc; /* Allocated sem_wait_dst */
+
+ VkSemaphore *sem_sig;
+ int sem_sig_alloc; /* Allocated sem_sig */
+ int sem_sig_cnt;
+
+ uint64_t *sem_sig_val;
+ int sem_sig_val_alloc;
+
+ uint64_t **sem_sig_val_dst;
+ int sem_sig_val_dst_alloc;
+} FFVkExecContext;
+
+typedef struct FFVulkanContext {
+ const AVClass *class; /* Filters and encoders use this */
+
+ FFVulkanFunctions vkfn;
+ FFVulkanExtensions extensions;
+ VkPhysicalDeviceProperties props;
+ VkPhysicalDeviceMemoryProperties mprops;
+
+ AVBufferRef *device_ref;
+ AVHWDeviceContext *device;
+ AVVulkanDeviceContext *hwctx;
+
+ AVBufferRef *frames_ref;
+ AVHWFramesContext *frames;
+ AVVulkanFramesContext *hwfc;
+
+ /* Properties */
+ int output_width;
+ int output_height;
+ enum AVPixelFormat output_format;
+ enum AVPixelFormat input_format;
+
+ /* Samplers */
+ FFVkSampler **samplers;
+ int samplers_num;
+
+ /* Exec contexts */
+ FFVkExecContext **exec_ctx;
+ int exec_ctx_num;
+
+ /* Pipelines (each can have 1 shader of each type) */
+ FFVulkanPipeline **pipelines;
+ int pipelines_num;
+
+ void *scratch; /* Scratch memory used only in functions */
+ unsigned int scratch_size;
+} FFVulkanContext;
+
+/* Identity mapping - r = r, b = b, g = g, a = a */
+extern const VkComponentMapping ff_comp_identity_map;
+
+/**
+ * Converts Vulkan return values to strings
+ */
+const char *ff_vk_ret2str(VkResult res);
+
+/**
+ * Returns 1 if the image is any sort of supported RGB
+ */
+int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt);
+
+/**
+ * Gets the glsl format string for a pixel format
+ */
+const char *ff_vk_shader_rep_fmt(enum AVPixelFormat pixfmt);
+
+/**
+ * Initialize a queue family with a specific number of queues.
+ * If nb_queues == 0, use however many queues the queue family has.
+ */
+void ff_vk_qf_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf,
+ VkQueueFlagBits dev_family, int nb_queues);
+
+/**
+ * Rotate through the queues in a queue family.
+ */
+void ff_vk_qf_rotate(FFVkQueueFamilyCtx *qf);
+
+/**
+ * Create a Vulkan sampler, will be auto-freed in ff_vk_filter_uninit()
+ */
+FFVkSampler *ff_vk_init_sampler(FFVulkanContext *s, int unnorm_coords,
+ VkFilter filt);
+
+/**
+ * Create an imageview.
+ * Guaranteed to remain alive until the queue submission has finished executing,
+ * and will be destroyed after that.
+ */
+int ff_vk_create_imageview(FFVulkanContext *s, FFVkExecContext *e,
+ VkImageView *v, VkImage img, VkFormat fmt,
+ const VkComponentMapping map);
+
+/**
+ * Define a push constant for a given stage into a pipeline.
+ * Must be called before the pipeline layout has been initialized.
+ */
+int ff_vk_add_push_constant(FFVulkanPipeline *pl, int offset, int size,
+ VkShaderStageFlagBits stage);
+
+/**
+ * Inits a pipeline. Everything in it will be auto-freed when calling
+ * ff_vk_filter_uninit().
+ */
+FFVulkanPipeline *ff_vk_create_pipeline(FFVulkanContext *s, FFVkQueueFamilyCtx *qf);
+
+/**
+ * Inits a shader for a specific pipeline. Will be auto-freed on uninit.
+ */
+FFVkSPIRVShader *ff_vk_init_shader(FFVulkanPipeline *pl, const char *name,
+ VkShaderStageFlags stage);
+
+/**
+ * Writes the workgroup size for a shader.
+ */
+void ff_vk_set_compute_shader_sizes(FFVkSPIRVShader *shd, int local_size[3]);
+
+/**
+ * Adds a descriptor set to the shader and registers them in the pipeline.
+ */
+int ff_vk_add_descriptor_set(FFVulkanContext *s, FFVulkanPipeline *pl,
+ FFVkSPIRVShader *shd, FFVulkanDescriptorSetBinding *desc,
+ int num, int only_print_to_shader);
+
+/**
+ * Compiles the shader, entrypoint must be set to "main".
+ */
+int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd,
+ const char *entrypoint);
+
+/**
+ * Pretty print shader, mainly used by shader compilers.
+ */
+void ff_vk_print_shader(void *ctx, FFVkSPIRVShader *shd, int prio);
+
+/**
+ * Initializes the pipeline layout after all shaders and descriptor sets have
+ * been finished.
+ */
+int ff_vk_init_pipeline_layout(FFVulkanContext *s, FFVulkanPipeline *pl);
+
+/**
+ * Initializes a compute pipeline. Will pick the first shader with the
+ * COMPUTE flag set.
+ */
+int ff_vk_init_compute_pipeline(FFVulkanContext *s, FFVulkanPipeline *pl);
+
+/**
+ * Updates a descriptor set via the updaters defined.
+ * Can be called immediately after pipeline creation, but must be called
+ * at least once before queue submission.
+ */
+void ff_vk_update_descriptor_set(FFVulkanContext *s, FFVulkanPipeline *pl,
+ int set_id);
+
+/**
+ * Init an execution context for command recording and queue submission.
+ * WIll be auto-freed on uninit.
+ */
+int ff_vk_create_exec_ctx(FFVulkanContext *s, FFVkExecContext **ctx,
+ FFVkQueueFamilyCtx *qf);
+
+/**
+ * Begin recording to the command buffer. Previous execution must have been
+ * completed, which ff_vk_submit_exec_queue() will ensure.
+ */
+int ff_vk_start_exec_recording(FFVulkanContext *s, FFVkExecContext *e);
+
+/**
+ * Add a command to bind the completed pipeline and its descriptor sets.
+ * Must be called after ff_vk_start_exec_recording() and before submission.
+ */
+void ff_vk_bind_pipeline_exec(FFVulkanContext *s, FFVkExecContext *e,
+ FFVulkanPipeline *pl);
+
+/**
+ * Updates push constants.
+ * Must be called after binding a pipeline if any push constants were defined.
+ */
+void ff_vk_update_push_exec(FFVulkanContext *s, FFVkExecContext *e,
+ VkShaderStageFlagBits stage, int offset,
+ size_t size, void *src);
+
+/**
+ * Gets the command buffer to use for this submission from the exe context.
+ */
+VkCommandBuffer ff_vk_get_exec_buf(FFVkExecContext *e);
+
+/**
+ * Adds a generic AVBufferRef as a queue depenency.
+ */
+int ff_vk_add_dep_exec_ctx(FFVulkanContext *s, FFVkExecContext *e,
+ AVBufferRef **deps, int nb_deps);
+
+/**
+ * Discards all queue dependencies
+ */
+void ff_vk_discard_exec_deps(FFVkExecContext *e);
+
+/**
+ * Adds a frame as a queue dependency. This also manages semaphore signalling.
+ * Must be called before submission.
+ */
+int ff_vk_add_exec_dep(FFVulkanContext *s, FFVkExecContext *e, AVFrame *frame,
+ VkPipelineStageFlagBits in_wait_dst_flag);
+
+/**
+ * Submits a command buffer to the queue for execution.
+ * Will block until execution has finished in order to simplify resource
+ * management.
+ */
+int ff_vk_submit_exec_queue(FFVulkanContext *s, FFVkExecContext *e);
+
+/**
+ * Create a VkBuffer with the specified parameters.
+ */
+int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size,
+ VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags);
+
+/**
+ * Maps the buffer to userspace. Set invalidate to 1 if reading the contents
+ * is necessary.
+ */
+int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer *buf, uint8_t *mem[],
+ int nb_buffers, int invalidate);
+
+/**
+ * Unmaps the buffer from userspace. Set flush to 1 to write and sync.
+ */
+int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer *buf, int nb_buffers,
+ int flush);
+
+/**
+ * Frees a buffer.
+ */
+void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf);
+
+/**
+ * Frees the main Vulkan context.
+ */
+void ff_vk_uninit(FFVulkanContext *s);
+
+#endif /* AVUTIL_VULKAN_H */