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