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