FFmpeg
Loading...
Searching...
No Matches
vulkan.c
Go to the documentation of this file.
1/*
2 * Copyright (c) Lynne
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "config.h"
22#include "avassert.h"
23#include "mem.h"
24#include "random_seed.h"
25#include "refstruct.h"
26
27#include "vulkan.h"
29
30#if CONFIG_SHADER_COMPRESSION
32#endif
33
34const VkComponentMapping ff_comp_identity_map = {
35 .r = VK_COMPONENT_SWIZZLE_IDENTITY,
36 .g = VK_COMPONENT_SWIZZLE_IDENTITY,
37 .b = VK_COMPONENT_SWIZZLE_IDENTITY,
38 .a = VK_COMPONENT_SWIZZLE_IDENTITY,
39};
40
41/* Converts return values to strings */
42const char *ff_vk_ret2str(VkResult res)
43{
44#define CASE(VAL) case VAL: return #VAL
45 switch (res) {
46 CASE(VK_SUCCESS);
47 CASE(VK_NOT_READY);
48 CASE(VK_TIMEOUT);
49 CASE(VK_EVENT_SET);
50 CASE(VK_EVENT_RESET);
51 CASE(VK_INCOMPLETE);
52 CASE(VK_ERROR_OUT_OF_HOST_MEMORY);
53 CASE(VK_ERROR_OUT_OF_DEVICE_MEMORY);
54 CASE(VK_ERROR_INITIALIZATION_FAILED);
55 CASE(VK_ERROR_DEVICE_LOST);
56 CASE(VK_ERROR_MEMORY_MAP_FAILED);
57 CASE(VK_ERROR_LAYER_NOT_PRESENT);
58 CASE(VK_ERROR_EXTENSION_NOT_PRESENT);
59 CASE(VK_ERROR_FEATURE_NOT_PRESENT);
60 CASE(VK_ERROR_INCOMPATIBLE_DRIVER);
61 CASE(VK_ERROR_TOO_MANY_OBJECTS);
62 CASE(VK_ERROR_FORMAT_NOT_SUPPORTED);
63 CASE(VK_ERROR_FRAGMENTED_POOL);
64 CASE(VK_ERROR_UNKNOWN);
65 CASE(VK_ERROR_OUT_OF_POOL_MEMORY);
66 CASE(VK_ERROR_INVALID_EXTERNAL_HANDLE);
67 CASE(VK_ERROR_FRAGMENTATION);
68 CASE(VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS);
69 CASE(VK_PIPELINE_COMPILE_REQUIRED);
70 CASE(VK_ERROR_SURFACE_LOST_KHR);
71 CASE(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR);
72 CASE(VK_SUBOPTIMAL_KHR);
73 CASE(VK_ERROR_OUT_OF_DATE_KHR);
74 CASE(VK_ERROR_INCOMPATIBLE_DISPLAY_KHR);
75 CASE(VK_ERROR_VALIDATION_FAILED_EXT);
76 CASE(VK_ERROR_INVALID_SHADER_NV);
77 CASE(VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR);
78 CASE(VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR);
79 CASE(VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR);
80 CASE(VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR);
81 CASE(VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR);
82 CASE(VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT);
83 CASE(VK_ERROR_NOT_PERMITTED_KHR);
84 CASE(VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT);
85 CASE(VK_THREAD_IDLE_KHR);
86 CASE(VK_THREAD_DONE_KHR);
87 CASE(VK_OPERATION_DEFERRED_KHR);
88 CASE(VK_OPERATION_NOT_DEFERRED_KHR);
89 default: return "Unknown error";
90 }
91#undef CASE
92}
93
94/* Malitia pura, Khronos */
95#define FN_MAP_TO(dst_t, dst_name, src_t, src_name) \
96 dst_t ff_vk_map_ ##src_name## _to_ ##dst_name(src_t src) \
97 { \
98 dst_t dst = 0x0; \
99 MAP_TO(VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT, \
100 VK_IMAGE_USAGE_SAMPLED_BIT); \
101 MAP_TO(VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT, \
102 VK_IMAGE_USAGE_TRANSFER_SRC_BIT); \
103 MAP_TO(VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT, \
104 VK_IMAGE_USAGE_TRANSFER_DST_BIT); \
105 MAP_TO(VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT, \
106 VK_IMAGE_USAGE_STORAGE_BIT); \
107 MAP_TO(VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT, \
108 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); \
109 MAP_TO(VK_FORMAT_FEATURE_2_VIDEO_DECODE_OUTPUT_BIT_KHR, \
110 VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR); \
111 MAP_TO(VK_FORMAT_FEATURE_2_VIDEO_DECODE_DPB_BIT_KHR, \
112 VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR); \
113 MAP_TO(VK_FORMAT_FEATURE_2_VIDEO_ENCODE_DPB_BIT_KHR, \
114 VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR); \
115 MAP_TO(VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR, \
116 VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR); \
117 MAP_TO(VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT, \
118 VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT); \
119 return dst; \
120 }
121
122#define MAP_TO(flag1, flag2) if (src & flag2) dst |= flag1;
123FN_MAP_TO(VkFormatFeatureFlagBits2, feats, VkImageUsageFlags, usage)
124#undef MAP_TO
125#define MAP_TO(flag1, flag2) if (src & flag1) dst |= flag2;
126FN_MAP_TO(VkImageUsageFlags, usage, VkFormatFeatureFlagBits2, feats)
127#undef MAP_TO
128#undef FN_MAP_TO
129
131{
132 s->nb_qfs = 0;
133 for (int i = 0; i < s->hwctx->nb_qf; i++) {
134 /* Skip duplicates */
135 int skip = 0;
136 for (int j = 0; j < s->nb_qfs; j++) {
137 if (s->qfs[j] == s->hwctx->qf[i].idx) {
138 skip = 1;
139 break;
140 }
141 }
142 if (skip)
143 continue;
144
145 s->qfs[s->nb_qfs++] = s->hwctx->qf[i].idx;
146 }
147}
148
149static void reset_imageviews(AVRefStructOpaque unused, void *obj);
150
152{
153 FFVulkanFunctions *vk = &s->vkfn;
154
155 s->props = (VkPhysicalDeviceProperties2) {
156 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
157 };
158
159 FF_VK_STRUCT_EXT(s, &s->props, &s->props_11, FF_VK_EXT_NO_FLAG,
160 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES);
161 FF_VK_STRUCT_EXT(s, &s->props, &s->driver_props, FF_VK_EXT_NO_FLAG,
162 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES);
163 FF_VK_STRUCT_EXT(s, &s->props, &s->subgroup_props, FF_VK_EXT_NO_FLAG,
164 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES);
165
166 FF_VK_STRUCT_EXT(s, &s->props, &s->push_desc_props, FF_VK_EXT_PUSH_DESCRIPTOR,
167 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR);
169 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT);
170 FF_VK_STRUCT_EXT(s, &s->props, &s->coop_matrix_props, FF_VK_EXT_COOP_MATRIX,
171 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_KHR);
172 FF_VK_STRUCT_EXT(s, &s->props, &s->optical_flow_props, FF_VK_EXT_OPTICAL_FLOW,
173 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_PROPERTIES_NV);
174 FF_VK_STRUCT_EXT(s, &s->props, &s->host_image_props, FF_VK_EXT_HOST_IMAGE_COPY,
175 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES_EXT);
176
177#ifdef VK_EXT_shader_long_vector
178 FF_VK_STRUCT_EXT(s, &s->props, &s->long_vector_props, FF_VK_EXT_LONG_VECTOR,
179 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_LONG_VECTOR_PROPERTIES_EXT);
180#endif
181
182 s->feats = (VkPhysicalDeviceFeatures2) {
183 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
184 };
185
186 FF_VK_STRUCT_EXT(s, &s->feats, &s->feats_12, FF_VK_EXT_NO_FLAG,
187 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES);
188 FF_VK_STRUCT_EXT(s, &s->feats, &s->atomic_float_feats, FF_VK_EXT_ATOMIC_FLOAT,
189 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT);
190#ifdef VK_KHR_unified_image_layouts
191 FF_VK_STRUCT_EXT(s, &s->feats, &s->unified_layout_feats, FF_VK_EXT_UNIFIED_IMAGE_LAYOUTS,
192 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFIED_IMAGE_LAYOUTS_FEATURES_KHR);
193#endif
194
195 if (!s->imageviews_pool) {
196 s->imageviews_pool = av_refstruct_pool_alloc_ext(sizeof(FFVkImageViews), 0,
198 NULL, NULL);
199 if (!s->imageviews_pool)
200 return AVERROR(ENOMEM);
201 }
202
203 /* Try allocating 1024 layouts */
204 s->host_image_copy_layouts = av_malloc(sizeof(*s->host_image_copy_layouts)*1024);
205 s->host_image_props.pCopySrcLayouts = s->host_image_copy_layouts;
206 s->host_image_props.copySrcLayoutCount = 512;
207 s->host_image_props.pCopyDstLayouts = s->host_image_copy_layouts + 512;
208 s->host_image_props.copyDstLayoutCount = 512;
209
210 vk->GetPhysicalDeviceProperties2(s->hwctx->phys_dev, &s->props);
211
212 /* Check if we had enough memory for all layouts */
213 if (s->host_image_props.copySrcLayoutCount == 512 ||
214 s->host_image_props.copyDstLayoutCount == 512) {
215 VkImageLayout *new_array;
216 size_t new_size;
217 s->host_image_props.pCopySrcLayouts =
218 s->host_image_props.pCopyDstLayouts = NULL;
219 s->host_image_props.copySrcLayoutCount =
220 s->host_image_props.copyDstLayoutCount = 0;
221 vk->GetPhysicalDeviceProperties2(s->hwctx->phys_dev, &s->props);
222
223 new_size = s->host_image_props.copySrcLayoutCount +
224 s->host_image_props.copyDstLayoutCount;
225 new_size *= sizeof(*s->host_image_copy_layouts);
226 new_array = av_realloc(s->host_image_copy_layouts, new_size);
227 if (!new_array)
228 return AVERROR(ENOMEM);
229
230 s->host_image_copy_layouts = new_array;
231 s->host_image_props.pCopySrcLayouts = new_array;
232 s->host_image_props.pCopyDstLayouts = new_array + s->host_image_props.copySrcLayoutCount;
233 vk->GetPhysicalDeviceProperties2(s->hwctx->phys_dev, &s->props);
234 }
235
236 vk->GetPhysicalDeviceMemoryProperties(s->hwctx->phys_dev, &s->mprops);
237 vk->GetPhysicalDeviceFeatures2(s->hwctx->phys_dev, &s->feats);
238
239 for (int i = 0; i < s->mprops.memoryTypeCount; i++)
240 s->host_cached_flag |= s->mprops.memoryTypes[i].propertyFlags &
241 VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
242
244
245 if (s->qf_props)
246 return 0;
247
248 vk->GetPhysicalDeviceQueueFamilyProperties2(s->hwctx->phys_dev, &s->tot_nb_qfs, NULL);
249
250 s->qf_props = av_calloc(s->tot_nb_qfs, sizeof(*s->qf_props));
251 if (!s->qf_props)
252 return AVERROR(ENOMEM);
253
254 s->query_props = av_calloc(s->tot_nb_qfs, sizeof(*s->query_props));
255 if (!s->qf_props) {
256 av_freep(&s->qf_props);
257 return AVERROR(ENOMEM);
258 }
259
260 s->video_props = av_calloc(s->tot_nb_qfs, sizeof(*s->video_props));
261 if (!s->video_props) {
262 av_freep(&s->qf_props);
263 av_freep(&s->query_props);
264 return AVERROR(ENOMEM);
265 }
266
267#ifdef VK_KHR_maintenance9
268 s->ownership_props = av_calloc(s->tot_nb_qfs, sizeof(*s->ownership_props));
269 if (!s->ownership_props) {
270 av_freep(&s->qf_props);
271 av_freep(&s->query_props);
272 av_freep(&s->video_props);
273 return AVERROR(ENOMEM);
274 }
275#endif
276
277 for (uint32_t i = 0; i < s->tot_nb_qfs; i++) {
278 s->qf_props[i] = (VkQueueFamilyProperties2) {
279 .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2,
280 };
281
282 FF_VK_STRUCT_EXT(s, &s->qf_props[i], &s->query_props[i], FF_VK_EXT_VIDEO_QUEUE,
283 VK_STRUCTURE_TYPE_QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_KHR);
284 FF_VK_STRUCT_EXT(s, &s->qf_props[i], &s->video_props[i], FF_VK_EXT_VIDEO_QUEUE,
285 VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR);
286#ifdef VK_KHR_maintenance9
287 FF_VK_STRUCT_EXT(s, &s->qf_props[i], &s->ownership_props[i], FF_VK_EXT_MAINTENANCE_9,
288 VK_STRUCTURE_TYPE_QUEUE_FAMILY_OWNERSHIP_TRANSFER_PROPERTIES_KHR);
289#endif
290 }
291
292 vk->GetPhysicalDeviceQueueFamilyProperties2(s->hwctx->phys_dev, &s->tot_nb_qfs, s->qf_props);
293
294 if (s->extensions & FF_VK_EXT_COOP_MATRIX) {
295 vk->GetPhysicalDeviceCooperativeMatrixPropertiesKHR(s->hwctx->phys_dev,
296 &s->coop_mat_props_nb, NULL);
297
298 if (s->coop_mat_props_nb) {
299 s->coop_mat_props = av_malloc_array(s->coop_mat_props_nb,
300 sizeof(VkCooperativeMatrixPropertiesKHR));
301 for (int i = 0; i < s->coop_mat_props_nb; i++) {
302 s->coop_mat_props[i] = (VkCooperativeMatrixPropertiesKHR) {
303 .sType = VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_KHR,
304 };
305 }
306
307 vk->GetPhysicalDeviceCooperativeMatrixPropertiesKHR(s->hwctx->phys_dev,
308 &s->coop_mat_props_nb,
309 s->coop_mat_props);
310 }
311 }
312
313 return 0;
314}
315
317 VkQueueFlagBits dev_family,
318 VkVideoCodecOperationFlagBitsKHR vid_ops)
319{
320 for (int i = 0; i < s->hwctx->nb_qf; i++) {
321 if ((s->hwctx->qf[i].flags & dev_family) &&
322 (s->hwctx->qf[i].video_caps & vid_ops) == vid_ops) {
323 return &s->hwctx->qf[i];
324 }
325 }
326 return NULL;
327}
328
330
332{
333 FFVulkanFunctions *vk = &s->vkfn;
334
335 for (int i = 0; i < pool->pool_size; i++) {
336 FFVkExecContext *e = &pool->contexts[i];
337
338 if (e->sem) {
339 VkSemaphoreWaitInfo sem_wait_info = {
340 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
341 .semaphoreCount = 1,
342 .pSemaphores = &e->sem,
343 .pValues = &e->sem_value,
344 };
345 vk->WaitSemaphores(s->hwctx->act_dev, &sem_wait_info, UINT64_MAX);
346 vk->DestroySemaphore(s->hwctx->act_dev, e->sem, s->hwctx->alloc);
347 }
348
351 }
352
353 /* Free shader-specific data */
354 for (int i = 0; i < pool->nb_reg_shd; i++) {
355 FFVulkanShaderData *sd = &pool->reg_shd[i];
356
357 if (sd->desc_pool)
358 vk->DestroyDescriptorPool(s->hwctx->act_dev, sd->desc_pool,
359 s->hwctx->alloc);
360
361 av_freep(&sd->desc_sets);
362 }
363 pool->nb_reg_shd = 0;
364
365 for (int i = 0; i < pool->pool_size; i++) {
366 if (pool->cmd_buf_pools[i])
367 vk->FreeCommandBuffers(s->hwctx->act_dev, pool->cmd_buf_pools[i],
368 1, &pool->cmd_bufs[i]);
369
370 if (pool->cmd_buf_pools[i])
371 vk->DestroyCommandPool(s->hwctx->act_dev, pool->cmd_buf_pools[i], s->hwctx->alloc);
372 }
373 if (pool->query_pool)
374 vk->DestroyQueryPool(s->hwctx->act_dev, pool->query_pool, s->hwctx->alloc);
375
376 av_free(pool->query_data);
377 av_free(pool->cmd_buf_pools);
378 av_free(pool->cmd_bufs);
379 av_free(pool->contexts);
380 pool->pool_size = 0;
381}
382
383/* Per-family, per-library queue selection phases; each library links its own
384 * copy, and pools which benefit from spreading are created by the same one */
387
388static void exec_pool_phase_seed(void)
389{
390 uint32_t seed = av_get_random_seed();
391 for (int i = 0; i < FF_ARRAY_ELEMS(exec_pool_phase); i++)
392 atomic_store_explicit(&exec_pool_phase[i], seed, memory_order_relaxed);
393}
394
396 FFVkExecPool *pool, int nb_contexts,
397 int nb_queries, VkQueryType query_type, int query_64bit,
398 const void *query_create_pnext)
399{
400 int err;
401 VkResult ret;
402 FFVulkanFunctions *vk = &s->vkfn;
403
404 VkCommandPoolCreateInfo cqueue_create;
405 VkCommandBufferAllocateInfo cbuf_create;
406
407 const VkQueryPoolVideoEncodeFeedbackCreateInfoKHR *ef = NULL;
408
409 atomic_init(&pool->idx, 0);
410
411 if (query_type == VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR) {
412 ef = ff_vk_find_struct(query_create_pnext,
413 VK_STRUCTURE_TYPE_QUERY_POOL_VIDEO_ENCODE_FEEDBACK_CREATE_INFO_KHR);
414 if (!ef)
415 return AVERROR(EINVAL);
416 }
417
418 /* Allocate space for command buffer pools */
419 pool->cmd_buf_pools = av_malloc(nb_contexts*sizeof(*pool->cmd_buf_pools));
420 if (!pool->cmd_buf_pools) {
421 err = AVERROR(ENOMEM);
422 goto fail;
423 }
424
425 /* Allocate space for command buffers */
426 pool->cmd_bufs = av_malloc(nb_contexts*sizeof(*pool->cmd_bufs));
427 if (!pool->cmd_bufs) {
428 err = AVERROR(ENOMEM);
429 goto fail;
430 }
431
432 for (int i = 0; i < nb_contexts; i++) {
433 /* Create command pool */
434 cqueue_create = (VkCommandPoolCreateInfo) {
435 .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
436 .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT |
437 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
438 .queueFamilyIndex = qf->idx,
439 };
440
441 ret = vk->CreateCommandPool(s->hwctx->act_dev, &cqueue_create,
442 s->hwctx->alloc, &pool->cmd_buf_pools[i]);
443 if (ret != VK_SUCCESS) {
444 av_log(s, AV_LOG_ERROR, "Command pool creation failure: %s\n",
445 ff_vk_ret2str(ret));
446 err = AVERROR_EXTERNAL;
447 goto fail;
448 }
449
450 /* Allocate command buffer */
451 cbuf_create = (VkCommandBufferAllocateInfo) {
452 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
453 .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
454 .commandPool = pool->cmd_buf_pools[i],
455 .commandBufferCount = 1,
456 };
457 ret = vk->AllocateCommandBuffers(s->hwctx->act_dev, &cbuf_create,
458 &pool->cmd_bufs[i]);
459 if (ret != VK_SUCCESS) {
460 av_log(s, AV_LOG_ERROR, "Command buffer alloc failure: %s\n",
461 ff_vk_ret2str(ret));
462 err = AVERROR_EXTERNAL;
463 goto fail;
464 }
465 }
466
467 /* Query pool */
468 if (nb_queries) {
469 VkQueryPoolCreateInfo query_pool_info = {
470 .sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
471 .pNext = query_create_pnext,
472 .queryType = query_type,
473 .queryCount = nb_queries*nb_contexts,
474 };
475 ret = vk->CreateQueryPool(s->hwctx->act_dev, &query_pool_info,
476 s->hwctx->alloc, &pool->query_pool);
477 if (ret != VK_SUCCESS) {
478 av_log(s, AV_LOG_ERROR, "Query pool alloc failure: %s\n",
479 ff_vk_ret2str(ret));
480 err = AVERROR_EXTERNAL;
481 goto fail;
482 }
483
484 pool->nb_queries = nb_queries;
485 pool->query_status_stride = 1 + 1; /* One result, one status by default */
486 pool->query_results = nb_queries;
487 pool->query_statuses = nb_queries;
488
489 /* Video encode queries produce two results per query */
490 if (query_type == VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR) {
491 int nb_results = av_popcount(ef->encodeFeedbackFlags);
492 pool->query_status_stride = nb_results + 1;
493 pool->query_results *= nb_results;
494 } else if (query_type == VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR) {
495 pool->query_status_stride = 1;
496 pool->query_results = 0;
497 }
498
499 pool->qd_size = (pool->query_results + pool->query_statuses)*(query_64bit ? 8 : 4);
500
501 /* Allocate space for the query data */
502 pool->query_data = av_calloc(nb_contexts, pool->qd_size);
503 if (!pool->query_data) {
504 err = AVERROR(ENOMEM);
505 goto fail;
506 }
507 }
508
509 /* Allocate space for the contexts */
510 pool->contexts = av_calloc(nb_contexts, sizeof(*pool->contexts));
511 if (!pool->contexts) {
512 err = AVERROR(ENOMEM);
513 goto fail;
514 }
515
516 pool->pool_size = nb_contexts;
517
518 for (int i = 0; i < pool->pool_size; i++)
520
521#ifdef VK_KHR_internally_synchronized_queues
522 /* Check if the extension and its flag are actually enabled */
523 int internal_queue_sync = 0;
524 if (s->extensions & FF_VK_EXT_INTERNAL_QUEUE_SYNC) {
525 const VkPhysicalDeviceInternallySynchronizedQueuesFeaturesKHR *iqs;
526 iqs = ff_vk_find_struct(s->hwctx->device_features.pNext,
527 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INTERNALLY_SYNCHRONIZED_QUEUES_FEATURES_KHR);
528 internal_queue_sync = iqs && iqs->internallySynchronizedQueues;
529 }
530#endif
531
532 /* Video pools are pinned to the phase-picked queue (sessions order their
533 * execution anyway); all other pools rotate starting from it, so pools
534 * advancing in lockstep do not collide. */
537 uint32_t phase = atomic_fetch_add(&exec_pool_phase[qf->idx], 1);
538 int pin_queue = qf->flags & (VK_QUEUE_VIDEO_DECODE_BIT_KHR |
539 VK_QUEUE_VIDEO_ENCODE_BIT_KHR);
540
541 /* Init contexts */
542 for (int i = 0; i < pool->pool_size; i++) {
543 FFVkExecContext *e = &pool->contexts[i];
544 VkSemaphoreTypeCreateInfo sem_type = {
545 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
546 .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE,
547 };
548 VkSemaphoreCreateInfo sem_create = {
549 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
550 .pNext = &sem_type,
551 };
552
553 /* Timeline semaphore carrying the busy state */
554 ret = vk->CreateSemaphore(s->hwctx->act_dev, &sem_create, s->hwctx->alloc,
555 &e->sem);
556 if (ret != VK_SUCCESS) {
557 av_log(s, AV_LOG_ERROR, "Failed to create submission semaphore: %s\n",
558 ff_vk_ret2str(ret));
559 return AVERROR_EXTERNAL;
560 }
561
562 e->idx = i;
563 e->parent = pool;
564
565 /* Query data */
566 e->query_data = ((uint8_t *)pool->query_data) + pool->qd_size*i;
567 e->query_idx = nb_queries*i;
568
569 /* Command buffer */
570 e->buf = pool->cmd_bufs[i];
571
572 /* Queue index distribution */
573 e->qi = pin_queue ? phase % qf->num : (i + phase) % qf->num;
574 e->qf = qf->idx;
575 VkDeviceQueueInfo2 qinfo = {
576 .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2,
577#ifdef VK_KHR_internally_synchronized_queues
578 .flags = internal_queue_sync ?
579 VK_DEVICE_QUEUE_CREATE_INTERNALLY_SYNCHRONIZED_BIT_KHR : 0,
580#endif
581 .queueFamilyIndex = qf->idx,
582 .queueIndex = e->qi,
583 };
584 vk->GetDeviceQueue2(s->hwctx->act_dev, &qinfo, &e->queue);
585 }
586
587 return 0;
588
589fail:
590 ff_vk_exec_pool_free(s, pool);
591 return err;
592}
593
595 void **data, VkQueryResultFlagBits flags)
596{
597 FFVulkanFunctions *vk = &s->vkfn;
598 const FFVkExecPool *pool = e->parent;
599 VkQueryResultFlags qf = flags & ~(VK_QUERY_RESULT_64_BIT |
600 VK_QUERY_RESULT_WITH_STATUS_BIT_KHR);
601
602 if (!e->query_data) {
603 av_log(s, AV_LOG_ERROR, "Requested a query with a NULL query_data pointer!\n");
604 return VK_INCOMPLETE;
605 }
606
607 qf |= pool->query_64bit ?
608 VK_QUERY_RESULT_64_BIT : 0x0;
609 qf |= pool->query_statuses ?
610 VK_QUERY_RESULT_WITH_STATUS_BIT_KHR : 0x0;
611
612 if (data)
613 *data = e->query_data;
614
615 return vk->GetQueryPoolResults(s->hwctx->act_dev, pool->query_pool,
616 e->query_idx,
617 pool->nb_queries,
618 pool->qd_size, e->query_data,
619 pool->qd_size, qf);
620}
621
623{
624 FFVulkanFunctions *vk = &s->vkfn;
625
626 /* Release the dependencies of every completed context, rather than leaving them held until reuse */
627 for (int i = 0; i < pool->pool_size; i++) {
628 uint64_t sem_val;
629 FFVkExecContext *e = &pool->contexts[i];
631 continue; /* In use by a recording or submitting thread */
632 /* Busy contexts (counter below sem_value) are claimed or executing:
633 * their dependency lists are off-limits */
634 if (vk->GetSemaphoreCounterValue(s->hwctx->act_dev, e->sem, &sem_val) == VK_SUCCESS &&
635 sem_val >= e->sem_value &&
636 (e->nb_buf_deps || e->nb_refstruct_deps || e->nb_obj_deps ||
640 }
641
642 return &pool->contexts[atomic_fetch_add(&pool->idx, 1) % pool->pool_size];
643}
644
646{
647 FFVulkanFunctions *vk = &s->vkfn;
648 VkSemaphoreWaitInfo sem_wait_info = {
649 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
650 .semaphoreCount = 1,
651 .pSemaphores = &e->sem,
652 .pValues = &e->sem_value,
653 };
655 vk->WaitSemaphores(s->hwctx->act_dev, &sem_wait_info, UINT64_MAX);
658}
659
661{
662 VkResult ret;
663 FFVulkanFunctions *vk = &s->vkfn;
664 const FFVkExecPool *pool = e->parent;
665
666 VkCommandBufferBeginInfo cmd_start = {
667 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
668 .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
669 };
670 VkSemaphoreWaitInfo sem_wait_info = {
671 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
672 .semaphoreCount = 1,
673 .pSemaphores = &e->sem,
674 .pValues = &e->sem_value,
675 };
676
678
679 /* Wait out the context's previous execution */
680 vk->WaitSemaphores(s->hwctx->act_dev, &sem_wait_info, UINT64_MAX);
681
682 /* Discard queue dependencies */
684
685 ret = vk->BeginCommandBuffer(e->buf, &cmd_start);
686 if (ret != VK_SUCCESS) {
687 av_log(s, AV_LOG_ERROR, "Failed to start command recoding: %s\n",
688 ff_vk_ret2str(ret));
690 return AVERROR_EXTERNAL;
691 }
692
693 if (pool->nb_queries)
694 vk->CmdResetQueryPool(e->buf, pool->query_pool,
695 e->query_idx, pool->nb_queries);
696
697 /* Claim: the semaphore stays below this value until submission completes
698 * or the recording is discarded, keeping every other user away */
699 e->sem_value++;
700 e->sem_sig[e->sem_sig_cnt++] = (VkSemaphoreSubmitInfo) {
701 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
702 .semaphore = e->sem,
703 .value = e->sem_value,
704 .stageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
705 };
706
708
709 return 0;
710}
711
713{
714 FFVulkanFunctions *vk = &s->vkfn;
715
716 for (int j = 0; j < e->nb_buf_deps; j++)
718 e->nb_buf_deps = 0;
719
720 for (int j = 0; j < e->nb_refstruct_deps; j++)
722 e->nb_refstruct_deps = 0;
723
724 for (int j = 0; j < e->nb_obj_deps; j++) {
725 FFVkExecObjDep *od = &e->obj_deps[j];
726 switch (od->type) {
727 case VK_OBJECT_TYPE_IMAGE_VIEW:
728 vk->DestroyImageView(s->hwctx->act_dev,
729 (VkImageView)od->obj, s->hwctx->alloc);
730 break;
731 case VK_OBJECT_TYPE_SEMAPHORE:
732 vk->DestroySemaphore(s->hwctx->act_dev,
733 (VkSemaphore)od->obj, s->hwctx->alloc);
734 break;
735 default:
736 av_assert1(0);
737 }
738 }
739 e->nb_obj_deps = 0;
740
741 for (int j = 0; j < e->nb_sw_frame_deps; j++)
743 e->nb_sw_frame_deps = 0;
744
745 for (int j = 0; j < e->nb_frame_deps; j++) {
746 AVFrame *f = e->frame_deps[j];
747 if (e->frame_locked[j]) {
748 AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
749 AVVulkanFramesContext *vkfc = hwfc->hwctx;
750 AVVkFrame *vkf = (AVVkFrame *)f->data[0];
751 vkfc->unlock_frame(hwfc, vkf);
752 e->frame_locked[j] = 0;
753 }
754 e->frame_update[j] = 0;
755 }
756 e->nb_frame_deps = 0;
757
758 e->sem_wait_cnt = 0;
759 e->sem_sig_cnt = 0;
760 e->sem_sig_val_dst_cnt = 0;
761}
762
764{
765 FFVulkanFunctions *vk = &s->vkfn;
766 VkSemaphoreSignalInfo sig_info = {
767 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO,
768 .semaphore = e->sem,
769 .value = e->sem_value,
770 };
771
772 /* An abandoned recording is exclusively the claimer's: free everything
773 * without the mutex, and un-claim last by signalling the burnt generation */
775 vk->ResetCommandBuffer(e->buf, 0);
776 vk->SignalSemaphore(s->hwctx->act_dev, &sig_info);
777}
778
785
787 void *obj)
788{
789 void **ptr = obj;
790
792
793 for (int i = 0; i < e->nb_refstruct_deps; i++) {
794 if (e->refstruct_deps[i] == *ptr) {
796 return;
797 }
798 }
799
800 e->refstruct_deps[e->nb_refstruct_deps++] = *ptr;
801 *ptr = NULL;
802}
803
805 VkObjectType type, uint64_t obj)
806{
808 e->obj_deps[e->nb_obj_deps++] = (FFVkExecObjDep) { obj, type };
809}
810
824
826 VkSemaphore sem, uint64_t val,
827 VkPipelineStageFlagBits2 stage)
828{
830
831 e->sem_wait[e->sem_wait_cnt++] = (VkSemaphoreSubmitInfo) {
832 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
833 .semaphore = sem,
834 .value = val,
835 .stageMask = stage,
836 };
837}
838
840 VkSemaphore *sem, int nb,
841 VkPipelineStageFlagBits2 stage,
842 int wait)
843{
844 /* Do not transfer ownership if we're signalling a binary semaphore,
845 * since we're probably exporting it. */
846 if (!wait) {
848 for (int i = 0; i < nb; i++) {
849 e->sem_sig[e->sem_sig_cnt++] = (VkSemaphoreSubmitInfo) {
850 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
851 .semaphore = sem[i],
852 .stageMask = stage,
853 };
854 }
855
856 return;
857 }
858
859 /* Ownership of each semaphore passes to the execution */
860 for (int i = 0; i < nb; i++) {
861 ff_vk_exec_add_dep_obj(s, e, VK_OBJECT_TYPE_SEMAPHORE,
862 (uint64_t)sem[i]);
863 ff_vk_exec_add_dep_wait_sem(s, e, sem[i], 0, stage);
864 }
865}
866
868 VkPipelineStageFlagBits2 wait_stage,
869 VkPipelineStageFlagBits2 signal_stage)
870{
871 AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
872 AVVulkanFramesContext *vkfc = hwfc->hwctx;
873 AVVkFrame *vkf = (AVVkFrame *)f->data[0];
874 int nb_images = ff_vk_count_images(vkf);
875
876 /* Don't add duplicates */
877 for (int i = 0; i < e->nb_frame_deps; i++)
878 if (e->frame_deps[i]->data[0] == f->data[0])
879 return 1;
880
883 av_assert1((e->sem_sig_cnt + nb_images) <= FF_VK_EXEC_MAX_SEM_OPS);
884
885 /* prepare_frame in hwcontext_vulkan.c uses the regular frame management
886 * code but has no frame yet, and it doesn't need to actually store a ref
887 * to the frame. */
888 if (f->buf[0]) {
890 e->buf_deps[e->nb_buf_deps] = av_buffer_ref(f->buf[0]);
891 if (!e->buf_deps[e->nb_buf_deps])
892 return AVERROR(ENOMEM);
893 e->nb_buf_deps++;
894 }
895
896 e->frame_deps[e->nb_frame_deps] = f;
897
898 vkfc->lock_frame(hwfc, vkf);
899 e->frame_locked[e->nb_frame_deps] = 1;
900 e->frame_update[e->nb_frame_deps] = 0;
901 e->nb_frame_deps++;
902
903 for (int i = 0; i < nb_images; i++) {
904 e->sem_wait[e->sem_wait_cnt++] = (VkSemaphoreSubmitInfo) {
905 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
906 .semaphore = vkf->sem[i],
907 .value = vkf->sem_value[i],
908 .stageMask = wait_stage,
909 };
910
911 e->sem_sig[e->sem_sig_cnt++] = (VkSemaphoreSubmitInfo) {
912 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
913 .semaphore = vkf->sem[i],
914 .value = vkf->sem_value[i] + 1,
915 .stageMask = signal_stage,
916 };
917
920 }
921
922 return 0;
923}
924
926 VkImageMemoryBarrier2 *bar, uint32_t *nb_img_bar)
927{
928 int i;
929 for (i = 0; i < e->nb_frame_deps; i++)
930 if (e->frame_deps[i]->data[0] == f->data[0])
931 break;
932 av_assert0(i < e->nb_frame_deps);
933
934 /* Don't update duplicates */
935 if (nb_img_bar && !e->frame_update[i])
936 (*nb_img_bar)++;
937
938 e->queue_family_dst[i] = bar->dstQueueFamilyIndex;
939 e->access_dst[i] = bar->dstAccessMask;
940 e->layout_dst[i] = bar->newLayout;
941 e->frame_update[i] = 1;
942}
943
945 VkSemaphore *dst, uint64_t *dst_val,
946 AVFrame *f)
947{
948 AVVkFrame *vkf = (AVVkFrame *)f->data[0];
949
950 /* Reject unknown frames */
951 int i;
952 for (i = 0; i < e->nb_frame_deps; i++)
953 if (e->frame_deps[i]->data[0] == f->data[0])
954 break;
955 if (i == e->nb_frame_deps)
956 return AVERROR(EINVAL);
957
959
960 *dst = vkf->sem[0];
961 *dst_val = vkf->sem_value[0];
962
963 e->sem_sig_val_dst[e->sem_sig_val_dst_cnt] = dst_val;
965
966 return 0;
967}
968
970{
971 VkResult ret;
972 FFVulkanFunctions *vk = &s->vkfn;
973 VkCommandBufferSubmitInfo cmd_buf_info = (VkCommandBufferSubmitInfo) {
974 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
975 .commandBuffer = e->buf,
976 };
977 VkSubmitInfo2 submit_info = (VkSubmitInfo2) {
978 .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
979 .pCommandBufferInfos = &cmd_buf_info,
980 .commandBufferInfoCount = 1,
981 .pWaitSemaphoreInfos = e->sem_wait,
982 .waitSemaphoreInfoCount = e->sem_wait_cnt,
983 .pSignalSemaphoreInfos = e->sem_sig,
984 .signalSemaphoreInfoCount = e->sem_sig_cnt,
985 };
986
987 ret = vk->EndCommandBuffer(e->buf);
988 if (ret != VK_SUCCESS) {
989 av_log(s, AV_LOG_ERROR, "Unable to finish command buffer: %s\n",
990 ff_vk_ret2str(ret));
992 return AVERROR_EXTERNAL;
993 }
994
995#if FF_API_VULKAN_SYNC_QUEUES
997 s->hwctx->lock_queue(s->device, e->qf, e->qi);
999#endif
1000 ret = vk->QueueSubmit2(e->queue, 1, &submit_info, VK_NULL_HANDLE);
1001#if FF_API_VULKAN_SYNC_QUEUES
1003 s->hwctx->unlock_queue(s->device, e->qf, e->qi);
1005#endif
1006
1007 if (ret != VK_SUCCESS) {
1008 av_log(s, AV_LOG_ERROR, "Unable to submit command buffer: %s\n",
1009 ff_vk_ret2str(ret));
1010 /* This also un-claims the context by signalling its semaphore */
1012 return AVERROR_EXTERNAL;
1013 }
1014
1015 for (int i = 0; i < e->sem_sig_val_dst_cnt; i++)
1016 *e->sem_sig_val_dst[i] += 1;
1017
1018 /* Unlock all frames */
1019 for (int j = 0; j < e->nb_frame_deps; j++) {
1020 if (e->frame_locked[j]) {
1021 AVFrame *f = e->frame_deps[j];
1022 AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
1023 AVVulkanFramesContext *vkfc = hwfc->hwctx;
1024 AVVkFrame *vkf = (AVVkFrame *)f->data[0];
1025
1026 if (e->frame_update[j]) {
1027 int nb_images = ff_vk_count_images(vkf);
1028 for (int i = 0; i < nb_images; i++) {
1029 vkf->layout[i] = e->layout_dst[j];
1030 vkf->access[i] = e->access_dst[j];
1031 vkf->queue_family[i] = e->queue_family_dst[j];
1032 }
1033 }
1034 vkfc->unlock_frame(hwfc, vkf);
1035 e->frame_locked[j] = 0;
1036 }
1037 }
1038
1039 e->had_submission = 1;
1040
1041 return 0;
1042}
1043
1044int ff_vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req,
1045 VkMemoryPropertyFlagBits req_flags, void *alloc_extension,
1046 VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem)
1047{
1048 VkResult ret;
1049 int index = -1;
1050 FFVulkanFunctions *vk = &s->vkfn;
1051
1052 VkMemoryAllocateInfo alloc_info = {
1053 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
1054 .pNext = alloc_extension,
1055 };
1056
1057 alloc_info.allocationSize = req->size;
1058
1059 /* The vulkan spec requires memory types to be sorted in the "optimal"
1060 * order, so the first matching type we find will be the best/fastest one */
1061 for (int i = 0; i < s->mprops.memoryTypeCount; i++) {
1062 /* The memory type must be supported by the requirements (bitfield) */
1063 if (!(req->memoryTypeBits & (1 << i)))
1064 continue;
1065
1066 /* The memory type flags must include our properties */
1067 if ((req_flags != UINT32_MAX) &&
1068 ((s->mprops.memoryTypes[i].propertyFlags & req_flags) != req_flags))
1069 continue;
1070
1071 /* Found a suitable memory type */
1072 index = i;
1073 break;
1074 }
1075
1076 if (index < 0) {
1077 av_log(s, AV_LOG_ERROR, "No memory type found for flags 0x%x\n",
1078 req_flags);
1079 return AVERROR(EINVAL);
1080 }
1081
1082 alloc_info.memoryTypeIndex = index;
1083
1084 ret = vk->AllocateMemory(s->hwctx->act_dev, &alloc_info,
1085 s->hwctx->alloc, mem);
1086 if (ret != VK_SUCCESS)
1087 return AVERROR(ENOMEM);
1088
1089 if (mem_flags)
1090 *mem_flags |= s->mprops.memoryTypes[index].propertyFlags;
1091
1092 return 0;
1093}
1094
1095int ff_vk_image_create(FFVulkanContext *s, VkImage *img, VkDeviceMemory *mem,
1096 int width, int height, VkFormat format, int nb_layers,
1097 VkImageTiling tiling, VkImageUsageFlags usage,
1098 VkImageCreateFlags flags, void *create_pnext)
1099{
1100 int err;
1101 VkResult ret;
1102 FFVulkanFunctions *vk = &s->vkfn;
1103 VkMemoryPropertyFlagBits mem_flags;
1104
1105 VkImageCreateInfo create_info = {
1106 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
1107 .pNext = create_pnext,
1108 .flags = flags,
1109 .imageType = VK_IMAGE_TYPE_2D,
1110 .format = format,
1111 .extent = { width, height, 1 },
1112 .mipLevels = 1,
1113 .arrayLayers = nb_layers,
1114 .tiling = tiling,
1115 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
1116 .usage = usage,
1117 .samples = VK_SAMPLE_COUNT_1_BIT,
1118 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
1119 };
1120 VkMemoryDedicatedAllocateInfo ded_alloc = {
1121 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
1122 };
1123 VkMemoryRequirements2 req = {
1124 .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
1125 };
1126 VkImageMemoryRequirementsInfo2 req_desc = {
1127 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
1128 };
1129 VkBindImageMemoryInfo bind_info = {
1130 .sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
1131 };
1132
1133 *img = VK_NULL_HANDLE;
1134 *mem = VK_NULL_HANDLE;
1135
1136 ret = vk->CreateImage(s->hwctx->act_dev, &create_info,
1137 s->hwctx->alloc, img);
1138 if (ret != VK_SUCCESS) {
1139 av_log(s, AV_LOG_ERROR, "Image creation failure: %s\n",
1140 ff_vk_ret2str(ret));
1141 return AVERROR_EXTERNAL;
1142 }
1143
1144 req_desc.image = *img;
1145 vk->GetImageMemoryRequirements2(s->hwctx->act_dev, &req_desc, &req);
1146
1147 /* Never shared with another image, so always dedicated */
1148 ded_alloc.image = *img;
1149 err = ff_vk_alloc_mem(s, &req.memoryRequirements,
1150 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
1151 &ded_alloc, &mem_flags, mem);
1152 if (err < 0)
1153 goto fail;
1154
1155 bind_info.image = *img;
1156 bind_info.memory = *mem;
1157 ret = vk->BindImageMemory2(s->hwctx->act_dev, 1, &bind_info);
1158 if (ret != VK_SUCCESS) {
1159 av_log(s, AV_LOG_ERROR, "Failed to bind image memory: %s\n",
1160 ff_vk_ret2str(ret));
1161 err = AVERROR_EXTERNAL;
1162 goto fail;
1163 }
1164
1165 return 0;
1166
1167fail:
1168 ff_vk_image_free(s, img, mem);
1169 return err;
1170}
1171
1172void ff_vk_image_free(FFVulkanContext *s, VkImage *img, VkDeviceMemory *mem)
1173{
1174 FFVulkanFunctions *vk = &s->vkfn;
1175
1176 if (*img) {
1177 vk->DestroyImage(s->hwctx->act_dev, *img, s->hwctx->alloc);
1178 *img = VK_NULL_HANDLE;
1179 }
1180 if (*mem) {
1181 vk->FreeMemory(s->hwctx->act_dev, *mem, s->hwctx->alloc);
1182 *mem = VK_NULL_HANDLE;
1183 }
1184}
1185
1187 void *pNext, void *alloc_pNext,
1188 VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags)
1189{
1190 int err;
1191 VkResult ret;
1192 int use_ded_mem;
1193 FFVulkanFunctions *vk = &s->vkfn;
1194
1195 VkBufferCreateInfo buf_spawn = {
1196 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1197 .pNext = pNext,
1198 .usage = usage,
1199 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
1200 .size = flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT ?
1201 FFALIGN(size, s->props.properties.limits.minMemoryMapAlignment) :
1202 size,
1203 };
1204
1205 VkMemoryAllocateFlagsInfo alloc_flags = {
1206 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
1207 .flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT,
1208 };
1209 VkBufferMemoryRequirementsInfo2 req_desc = {
1210 .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
1211 };
1212 VkMemoryDedicatedAllocateInfo ded_alloc = {
1213 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
1214 .pNext = alloc_pNext,
1215 };
1216 VkMemoryDedicatedRequirements ded_req = {
1217 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
1218 };
1219 VkMemoryRequirements2 req = {
1220 .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
1221 .pNext = &ded_req,
1222 };
1223
1224 av_log(s, AV_LOG_DEBUG, "Creating a buffer of %zu bytes, "
1225 "usage: 0x%x, flags: 0x%x\n",
1226 size, usage, flags);
1227
1228 ret = vk->CreateBuffer(s->hwctx->act_dev, &buf_spawn, s->hwctx->alloc, &buf->buf);
1229 if (ret != VK_SUCCESS) {
1230 av_log(s, AV_LOG_ERROR, "Failed to create buffer: %s\n",
1231 ff_vk_ret2str(ret));
1232 return AVERROR_EXTERNAL;
1233 }
1234
1235 req_desc.buffer = buf->buf;
1236
1237 vk->GetBufferMemoryRequirements2(s->hwctx->act_dev, &req_desc, &req);
1238
1239 /* In case the implementation prefers/requires dedicated allocation */
1240 use_ded_mem = ded_req.prefersDedicatedAllocation |
1241 ded_req.requiresDedicatedAllocation;
1242 if (use_ded_mem) {
1243 ded_alloc.buffer = buf->buf;
1244 ded_alloc.pNext = alloc_pNext;
1245 alloc_pNext = &ded_alloc;
1246 }
1247
1248 if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) {
1249 alloc_flags.pNext = alloc_pNext;
1250 alloc_pNext = &alloc_flags;
1251 }
1252
1253 err = ff_vk_alloc_mem(s, &req.memoryRequirements, flags, alloc_pNext,
1254 &buf->flags, &buf->mem);
1255 if (err)
1256 return err;
1257
1258 ret = vk->BindBufferMemory(s->hwctx->act_dev, buf->buf, buf->mem, 0);
1259 if (ret != VK_SUCCESS) {
1260 av_log(s, AV_LOG_ERROR, "Failed to bind memory to buffer: %s\n",
1261 ff_vk_ret2str(ret));
1262 return AVERROR_EXTERNAL;
1263 }
1264
1265 if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) {
1266 VkBufferDeviceAddressInfo address_info = {
1267 .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
1268 .buffer = buf->buf,
1269 };
1270 buf->address = vk->GetBufferDeviceAddress(s->hwctx->act_dev, &address_info);
1271 }
1272
1273 buf->size = size;
1274
1275 return 0;
1276}
1277
1278int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer **buf, uint8_t *mem[],
1279 int nb_buffers, int invalidate)
1280{
1281 VkResult ret;
1282 FFVulkanFunctions *vk = &s->vkfn;
1283 VkMappedMemoryRange inval_list[64];
1284 int inval_count = 0;
1285
1286 for (int i = 0; i < nb_buffers; i++) {
1287 void *dst;
1288 ret = vk->MapMemory(s->hwctx->act_dev, buf[i]->mem, 0,
1289 VK_WHOLE_SIZE, 0, &dst);
1290 if (ret != VK_SUCCESS) {
1291 av_log(s, AV_LOG_ERROR, "Failed to map buffer memory: %s\n",
1292 ff_vk_ret2str(ret));
1293 return AVERROR_EXTERNAL;
1294 }
1295 buf[i]->mapped_mem = dst;
1296 if (mem)
1297 mem[i] = dst;
1298 }
1299
1300 if (!invalidate)
1301 return 0;
1302
1303 for (int i = 0; i < nb_buffers; i++) {
1304 const VkMappedMemoryRange ival_buf = {
1305 .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
1306 .memory = buf[i]->mem,
1307 .size = VK_WHOLE_SIZE,
1308 };
1309 if (buf[i]->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
1310 continue;
1311 inval_list[inval_count++] = ival_buf;
1312 }
1313
1314 if (inval_count) {
1315 ret = vk->InvalidateMappedMemoryRanges(s->hwctx->act_dev, inval_count,
1316 inval_list);
1317 if (ret != VK_SUCCESS) {
1318 av_log(s, AV_LOG_ERROR, "Failed to invalidate memory: %s\n",
1319 ff_vk_ret2str(ret));
1320 return AVERROR_EXTERNAL;
1321 }
1322 }
1323
1324 return 0;
1325}
1326
1328 VkDeviceSize offset, VkDeviceSize mem_size,
1329 int flush)
1330{
1331 VkResult ret;
1332 FFVulkanFunctions *vk = &s->vkfn;
1333
1334 if (buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
1335 return 0;
1336
1337 const VkMappedMemoryRange flush_data = {
1338 .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
1339 .memory = buf->mem,
1340 .offset = offset,
1341 .size = mem_size,
1342 };
1343
1344 if (flush)
1345 ret = vk->FlushMappedMemoryRanges(s->hwctx->act_dev, 1, &flush_data);
1346 else
1347 ret = vk->InvalidateMappedMemoryRanges(s->hwctx->act_dev, 1, &flush_data);
1348
1349 if (ret != VK_SUCCESS) {
1350 av_log(s, AV_LOG_ERROR, "Failed to flush memory: %s\n",
1351 ff_vk_ret2str(ret));
1352 return AVERROR_EXTERNAL;
1353 }
1354
1355 return 0;
1356}
1357
1359 int flush)
1360{
1361 int err = 0;
1362 VkResult ret;
1363 FFVulkanFunctions *vk = &s->vkfn;
1364 VkMappedMemoryRange flush_list[64];
1365 int flush_count = 0;
1366
1367 if (flush) {
1368 for (int i = 0; i < nb_buffers; i++) {
1369 const VkMappedMemoryRange flush_buf = {
1370 .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
1371 .memory = buf[i]->mem,
1372 .size = VK_WHOLE_SIZE,
1373 };
1374
1375 av_assert0(!buf[i]->host_ref);
1376 if (buf[i]->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
1377 continue;
1378 flush_list[flush_count++] = flush_buf;
1379 }
1380 }
1381
1382 if (flush_count) {
1383 ret = vk->FlushMappedMemoryRanges(s->hwctx->act_dev, flush_count,
1384 flush_list);
1385 if (ret != VK_SUCCESS) {
1386 av_log(s, AV_LOG_ERROR, "Failed to flush memory: %s\n",
1387 ff_vk_ret2str(ret));
1388 err = AVERROR_EXTERNAL; /* We still want to try to unmap them */
1389 }
1390 }
1391
1392 for (int i = 0; i < nb_buffers; i++) {
1393 vk->UnmapMemory(s->hwctx->act_dev, buf[i]->mem);
1394 buf[i]->mapped_mem = NULL;
1395 }
1396
1397 return err;
1398}
1399
1401{
1402 FFVulkanFunctions *vk = &s->vkfn;
1403
1404 if (!buf || !s->hwctx)
1405 return;
1406
1407 if (buf->mapped_mem && !buf->host_ref)
1408 ff_vk_unmap_buffer(s, buf, 0);
1409 if (buf->buf != VK_NULL_HANDLE)
1410 vk->DestroyBuffer(s->hwctx->act_dev, buf->buf, s->hwctx->alloc);
1411 if (buf->mem != VK_NULL_HANDLE)
1412 vk->FreeMemory(s->hwctx->act_dev, buf->mem, s->hwctx->alloc);
1413 if (buf->host_ref)
1415
1416 buf->buf = VK_NULL_HANDLE;
1417 buf->mem = VK_NULL_HANDLE;
1418 buf->mapped_mem = NULL;
1419}
1420
1421static void pooled_buf_free(AVRefStructOpaque opaque, void *obj)
1422{
1423 ff_vk_free_buf(opaque.nc, obj);
1424}
1425
1427 FFVkBuffer **buf, VkBufferUsageFlags usage,
1428 void *create_pNext, size_t size,
1429 VkMemoryPropertyFlagBits mem_props)
1430{
1431 int err;
1433
1434 if (!(*buf_pool)) {
1435 *buf_pool = av_refstruct_pool_alloc_ext(sizeof(FFVkBuffer), 0, ctx,
1437 NULL);
1438 if (!(*buf_pool))
1439 return AVERROR(ENOMEM);
1440 }
1441
1442 *buf = data = av_refstruct_pool_get(*buf_pool);
1443 if (!data)
1444 return AVERROR(ENOMEM);
1445
1446 if (data->size >= size)
1447 return 0;
1448
1450 memset(data, 0, sizeof(*data));
1451
1452 err = ff_vk_create_buf(ctx, data, size,
1453 create_pNext, NULL, usage,
1454 mem_props);
1455 if (err < 0) {
1456 av_refstruct_unref(buf);
1457 return err;
1458 }
1459
1460 if (mem_props & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
1461 err = ff_vk_map_buffer(ctx, data, &data->mapped_mem, 0);
1462 if (err < 0) {
1463 av_refstruct_unref(buf);
1464 return err;
1465 }
1466 }
1467
1468 return 0;
1469}
1470
1472 FFVkBuffer *vkb, VkBufferUsageFlags usage,
1473 size_t size,
1474 VkExternalMemoryBufferCreateInfo *create_desc,
1475 VkImportMemoryHostPointerInfoEXT *import_desc,
1476 VkMemoryHostPointerPropertiesEXT props)
1477{
1478 int err;
1479 VkResult ret;
1480 FFVulkanFunctions *vk = &s->vkfn;
1481
1482 VkBufferCreateInfo buf_spawn = {
1483 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1484 .pNext = create_desc,
1485 .usage = usage,
1486 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
1487 .size = size,
1488 };
1489 VkMemoryRequirements req = {
1490 .size = size,
1491 .alignment = s->hprops.minImportedHostPointerAlignment,
1492 .memoryTypeBits = props.memoryTypeBits,
1493 };
1494
1495 err = ff_vk_alloc_mem(s, &req,
1496 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
1497 import_desc, &vkb->flags, &vkb->mem);
1498 if (err < 0)
1499 return err;
1500
1501 ret = vk->CreateBuffer(s->hwctx->act_dev, &buf_spawn, s->hwctx->alloc, &vkb->buf);
1502 if (ret != VK_SUCCESS) {
1503 vk->FreeMemory(s->hwctx->act_dev, vkb->mem, s->hwctx->alloc);
1504 return AVERROR_EXTERNAL;
1505 }
1506
1507 ret = vk->BindBufferMemory(s->hwctx->act_dev, vkb->buf, vkb->mem, 0);
1508 if (ret != VK_SUCCESS) {
1509 vk->FreeMemory(s->hwctx->act_dev, vkb->mem, s->hwctx->alloc);
1510 vk->DestroyBuffer(s->hwctx->act_dev, vkb->buf, s->hwctx->alloc);
1511 return AVERROR_EXTERNAL;
1512 }
1513
1514 return 0;
1515}
1516
1517static void host_map_free(AVRefStructOpaque opaque, void *obj)
1518{
1519 ff_vk_free_buf(opaque.nc, obj);
1520}
1521
1523 uint8_t *src_data, VkDeviceSize size,
1524 const AVBufferRef *src_buf,
1525 VkBufferUsageFlags usage)
1526{
1527 int err;
1528 VkResult ret;
1529 FFVulkanFunctions *vk = &s->vkfn;
1530
1531 VkExternalMemoryBufferCreateInfo create_desc = {
1532 .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
1533 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT,
1534 };
1535 VkMemoryAllocateFlagsInfo alloc_flags = {
1536 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
1537 .flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT,
1538 };
1539 VkImportMemoryHostPointerInfoEXT import_desc = {
1540 .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT,
1541 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT,
1542 .pNext = usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT ? &alloc_flags : NULL,
1543 };
1544 VkMemoryHostPointerPropertiesEXT props;
1545
1547 FFVkBuffer *vkb;
1548 size_t offs;
1549 size_t buffer_size;
1550
1551 *dst = NULL;
1552
1553 /* Get the previous point at which mapping was possible and use it */
1554 offs = (uintptr_t)src_data % s->hprops.minImportedHostPointerAlignment;
1555 import_desc.pHostPointer = src_data - offs;
1556
1557 props = (VkMemoryHostPointerPropertiesEXT) {
1558 VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT,
1559 };
1560 ret = vk->GetMemoryHostPointerPropertiesEXT(s->hwctx->act_dev,
1561 import_desc.handleType,
1562 import_desc.pHostPointer,
1563 &props);
1564 if (!(ret == VK_SUCCESS && props.memoryTypeBits))
1565 return AVERROR(EINVAL);
1566
1567 /* Ref the source buffer */
1568 ref = av_buffer_ref(src_buf);
1569 if (!ref)
1570 return AVERROR(ENOMEM);
1571
1572 /* Add the offset at the start, which gets ignored. */
1573 const VkDeviceSize src_avail = src_buf->size - (src_data - src_buf->data);
1574 buffer_size = offs + FFMIN(size, src_avail);
1575 buffer_size = FFALIGN(buffer_size, s->props.properties.limits.minMemoryMapAlignment);
1576 buffer_size = FFALIGN(buffer_size, s->hprops.minImportedHostPointerAlignment);
1577
1578 /* Create a buffer struct */
1579 vkb = av_refstruct_alloc_ext(sizeof(*vkb), 0, s, host_map_free);
1580 if (!vkb) {
1582 return AVERROR(ENOMEM);
1583 }
1584
1585 err = create_mapped_buffer(s, vkb, usage,
1586 buffer_size, &create_desc, &import_desc,
1587 props);
1588 if (err < 0) {
1590 av_refstruct_unref(&vkb);
1591 return err;
1592 }
1593
1594 if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) {
1595 VkBufferDeviceAddressInfo address_info = {
1596 .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
1597 .buffer = vkb->buf,
1598 };
1599 vkb->address = vk->GetBufferDeviceAddress(s->hwctx->act_dev, &address_info);
1600 }
1601
1602 vkb->host_ref = ref;
1603 vkb->virtual_offset = offs;
1604 vkb->address += offs;
1605 vkb->mapped_mem = src_data;
1606 vkb->size = buffer_size - offs;
1607
1608 *dst = vkb;
1609
1610 return 0;
1611}
1612
1614 VkShaderStageFlagBits stage)
1615{
1616 VkPushConstantRange *pc = &shd->push_consts[shd->push_consts_num++];
1618 pc->stageFlags = stage;
1619 pc->offset = offset;
1620 pc->size = size;
1621 return 0;
1622}
1623
1624int ff_vk_init_sampler(FFVulkanContext *s, VkSampler *sampler,
1625 int unnorm_coords, VkFilter filt)
1626{
1627 VkResult ret;
1628 FFVulkanFunctions *vk = &s->vkfn;
1629
1630 VkSamplerCreateInfo sampler_info = {
1631 .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
1632 .magFilter = filt,
1633 .minFilter = sampler_info.magFilter,
1634 .mipmapMode = unnorm_coords ? VK_SAMPLER_MIPMAP_MODE_NEAREST :
1635 VK_SAMPLER_MIPMAP_MODE_LINEAR,
1636 .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1637 .addressModeV = sampler_info.addressModeU,
1638 .addressModeW = sampler_info.addressModeU,
1639 .anisotropyEnable = VK_FALSE,
1640 .compareOp = VK_COMPARE_OP_NEVER,
1641 .borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
1642 .unnormalizedCoordinates = unnorm_coords,
1643 };
1644
1645 ret = vk->CreateSampler(s->hwctx->act_dev, &sampler_info,
1646 s->hwctx->alloc, sampler);
1647 if (ret != VK_SUCCESS) {
1648 av_log(s, AV_LOG_ERROR, "Unable to init sampler: %s\n",
1649 ff_vk_ret2str(ret));
1650 return AVERROR_EXTERNAL;
1651 }
1652
1653 return 0;
1654}
1655
1656VkImageAspectFlags ff_vk_aspect_flag(AVFrame *f, int p)
1657{
1658 AVVkFrame *vkf = (AVVkFrame *)f->data[0];
1659 AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
1660 int nb_images = ff_vk_count_images(vkf);
1661 int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format);
1662
1663 static const VkImageAspectFlags plane_aspect[] = { VK_IMAGE_ASPECT_PLANE_0_BIT,
1664 VK_IMAGE_ASPECT_PLANE_1_BIT,
1665 VK_IMAGE_ASPECT_PLANE_2_BIT, };
1666
1667 if (ff_vk_mt_is_np_rgb(hwfc->sw_format) || (nb_planes == nb_images))
1668 return VK_IMAGE_ASPECT_COLOR_BIT;
1669
1670 return plane_aspect[p];
1671}
1672
1695
1696void ff_vk_set_perm(enum AVPixelFormat pix_fmt, int lut[4], int inv)
1697{
1698 switch (pix_fmt) {
1699 case AV_PIX_FMT_GBRP:
1700 case AV_PIX_FMT_GBRAP:
1701 case AV_PIX_FMT_GBRAP10:
1702 case AV_PIX_FMT_GBRAP12:
1703 case AV_PIX_FMT_GBRAP14:
1704 case AV_PIX_FMT_GBRAP16:
1706 case AV_PIX_FMT_GBRP10:
1707 case AV_PIX_FMT_GBRP12:
1708 case AV_PIX_FMT_GBRP14:
1709 case AV_PIX_FMT_GBRP16:
1710 case AV_PIX_FMT_GBRPF16:
1711 case AV_PIX_FMT_GBRPF32:
1712 case AV_PIX_FMT_GBRAP32:
1714 lut[0] = 1;
1715 lut[1] = 2;
1716 lut[2] = 0;
1717 lut[3] = 3;
1718 break;
1719 case AV_PIX_FMT_X2BGR10:
1720 lut[0] = 0;
1721 lut[1] = 2;
1722 lut[2] = 1;
1723 lut[3] = 3;
1724 break;
1725 case AV_PIX_FMT_BGRA:
1726 case AV_PIX_FMT_BGR0:
1727 /* Stored in RGBA images, so reverse them */
1728 lut[0] = 2;
1729 lut[1] = 1;
1730 lut[2] = 0;
1731 lut[3] = 3;
1732 break;
1733 default:
1734 lut[0] = 0;
1735 lut[1] = 1;
1736 lut[2] = 2;
1737 lut[3] = 3;
1738 break;
1739 }
1740
1741 if (inv) {
1742 int lut_tmp[4] = { lut[0], lut[1], lut[2], lut[3] };
1743 for (int i = 0; i < 4; i++)
1744 lut[lut_tmp[i]] = i;
1745 }
1746
1747 return;
1748}
1749
1751 enum FFVkShaderRepFormat rep_fmt)
1752{
1753 switch (pix_fmt) {
1754 case AV_PIX_FMT_RGBA:
1755 case AV_PIX_FMT_BGRA:
1756 case AV_PIX_FMT_RGB24:
1757 case AV_PIX_FMT_BGR24:
1758 case AV_PIX_FMT_BGR0:
1759 case AV_PIX_FMT_RGB0:
1760 case AV_PIX_FMT_RGB565:
1761 case AV_PIX_FMT_BGR565:
1762 case AV_PIX_FMT_UYVA:
1763 case AV_PIX_FMT_YUYV422:
1764 case AV_PIX_FMT_UYVY422: {
1765 const char *rep_tab[] = {
1766 [FF_VK_REP_NATIVE] = "rgba8ui",
1767 [FF_VK_REP_FLOAT] = "rgba8",
1768 [FF_VK_REP_INT] = "rgba8i",
1769 [FF_VK_REP_UINT] = "rgba8ui",
1770 };
1771 return rep_tab[rep_fmt];
1772 }
1773 case AV_PIX_FMT_X2RGB10:
1774 case AV_PIX_FMT_X2BGR10:
1775 case AV_PIX_FMT_Y210:
1776 case AV_PIX_FMT_XV30: {
1777 const char *rep_tab[] = {
1778 [FF_VK_REP_NATIVE] = "rgb10_a2ui",
1779 [FF_VK_REP_FLOAT] = "rgb10_a2",
1780 [FF_VK_REP_INT] = NULL,
1781 [FF_VK_REP_UINT] = "rgb10_a2ui",
1782 };
1783 return rep_tab[rep_fmt];
1784 }
1785 case AV_PIX_FMT_RGB48:
1786 case AV_PIX_FMT_RGBA64:
1787 case AV_PIX_FMT_Y212:
1788 case AV_PIX_FMT_Y216:
1789 case AV_PIX_FMT_XV36:
1790 case AV_PIX_FMT_XV48: {
1791 const char *rep_tab[] = {
1792 [FF_VK_REP_NATIVE] = "rgba16ui",
1793 [FF_VK_REP_FLOAT] = "rgba16",
1794 [FF_VK_REP_INT] = "rgba16i",
1795 [FF_VK_REP_UINT] = "rgba16ui",
1796 };
1797 return rep_tab[rep_fmt];
1798 }
1799 case AV_PIX_FMT_RGBAF16: {
1800 const char *rep_tab[] = {
1801 [FF_VK_REP_NATIVE] = "rgba16f",
1802 [FF_VK_REP_FLOAT] = "rgba16f",
1803 [FF_VK_REP_INT] = "rgba32i",
1804 [FF_VK_REP_UINT] = "rgba16u",
1805 };
1806 return rep_tab[rep_fmt];
1807 }
1808 case AV_PIX_FMT_RGBF32:
1809 case AV_PIX_FMT_RGBAF32: {
1810 const char *rep_tab[] = {
1811 [FF_VK_REP_NATIVE] = "rgba32f",
1812 [FF_VK_REP_FLOAT] = "rgba32f",
1813 [FF_VK_REP_INT] = "rgba32i",
1814 [FF_VK_REP_UINT] = "rgba32ui",
1815 };
1816 return rep_tab[rep_fmt];
1817 }
1818 case AV_PIX_FMT_RGB96:
1819 case AV_PIX_FMT_RGBA128: {
1820 const char *rep_tab[] = {
1821 [FF_VK_REP_NATIVE] = "rgba32ui",
1823 [FF_VK_REP_INT] = "rgba32i",
1824 [FF_VK_REP_UINT] = "rgba32ui",
1825 };
1826 return rep_tab[rep_fmt];
1827 }
1828 case AV_PIX_FMT_GBRP:
1829 case AV_PIX_FMT_GRAY8:
1830 case AV_PIX_FMT_GBRAP:
1831 case AV_PIX_FMT_YUV420P:
1832 case AV_PIX_FMT_YUV422P:
1833 case AV_PIX_FMT_YUV444P:
1836 case AV_PIX_FMT_YUVA444P: {
1837 const char *rep_tab[] = {
1838 [FF_VK_REP_NATIVE] = "r8ui",
1839 [FF_VK_REP_FLOAT] = "r8",
1840 [FF_VK_REP_INT] = "r8i",
1841 [FF_VK_REP_UINT] = "r8ui",
1842 };
1843 return rep_tab[rep_fmt];
1844 };
1845 case AV_PIX_FMT_GRAY10:
1846 case AV_PIX_FMT_GRAY12:
1847 case AV_PIX_FMT_GRAY14:
1848 case AV_PIX_FMT_GRAY16:
1849 case AV_PIX_FMT_GBRAP10:
1850 case AV_PIX_FMT_GBRAP12:
1851 case AV_PIX_FMT_GBRAP14:
1852 case AV_PIX_FMT_GBRAP16:
1854 case AV_PIX_FMT_GBRP10:
1855 case AV_PIX_FMT_GBRP12:
1856 case AV_PIX_FMT_GBRP14:
1857 case AV_PIX_FMT_GBRP16:
1858 case AV_PIX_FMT_GBRPF16:
1877 const char *rep_tab[] = {
1878 [FF_VK_REP_NATIVE] = "r16ui",
1879 [FF_VK_REP_FLOAT] = "r16f",
1880 [FF_VK_REP_INT] = "r16i",
1881 [FF_VK_REP_UINT] = "r16ui",
1882 };
1883 return rep_tab[rep_fmt];
1884 };
1885 case AV_PIX_FMT_GRAY32:
1886 case AV_PIX_FMT_GRAYF32:
1887 case AV_PIX_FMT_GBRPF32:
1888 case AV_PIX_FMT_GBRAPF32: {
1889 const char *rep_tab[] = {
1890 [FF_VK_REP_NATIVE] = "r32f",
1891 [FF_VK_REP_FLOAT] = "r32f",
1892 [FF_VK_REP_INT] = "r32i",
1893 [FF_VK_REP_UINT] = "r32ui",
1894 };
1895 return rep_tab[rep_fmt];
1896 };
1897 case AV_PIX_FMT_GBRAP32: {
1898 const char *rep_tab[] = {
1899 [FF_VK_REP_NATIVE] = "r32ui",
1901 [FF_VK_REP_INT] = "r32i",
1902 [FF_VK_REP_UINT] = "r32ui",
1903 };
1904 return rep_tab[rep_fmt];
1905 };
1906 case AV_PIX_FMT_NV12:
1907 case AV_PIX_FMT_NV16:
1908 case AV_PIX_FMT_NV24: {
1909 const char *rep_tab[] = {
1910 [FF_VK_REP_NATIVE] = "rg8ui",
1911 [FF_VK_REP_FLOAT] = "rg8",
1912 [FF_VK_REP_INT] = "rg8i",
1913 [FF_VK_REP_UINT] = "rg8ui",
1914 };
1915 return rep_tab[rep_fmt];
1916 };
1917 case AV_PIX_FMT_P010:
1918 case AV_PIX_FMT_P210:
1919 case AV_PIX_FMT_P410: {
1920 const char *rep_tab[] = {
1921 [FF_VK_REP_NATIVE] = "rgb10_a2ui",
1922 [FF_VK_REP_FLOAT] = "rgb10_a2",
1923 [FF_VK_REP_INT] = NULL,
1924 [FF_VK_REP_UINT] = "rgb10_a2ui",
1925 };
1926 return rep_tab[rep_fmt];
1927 };
1928 case AV_PIX_FMT_P012:
1929 case AV_PIX_FMT_P016:
1930 case AV_PIX_FMT_P212:
1931 case AV_PIX_FMT_P216:
1932 case AV_PIX_FMT_P412:
1933 case AV_PIX_FMT_P416: {
1934 const char *rep_tab[] = {
1935 [FF_VK_REP_NATIVE] = "rg16ui",
1936 [FF_VK_REP_FLOAT] = "rg16",
1937 [FF_VK_REP_INT] = "rg16i",
1938 [FF_VK_REP_UINT] = "rg16ui",
1939 };
1940 return rep_tab[rep_fmt];
1941 };
1942 default:
1943 return "rgba32f";
1944 }
1945}
1946
1947static void reset_imageviews(AVRefStructOpaque unused, void *obj)
1948{
1949 FFVkImageViews *iv = obj;
1950
1951 for (int i = 0; i < iv->nb_views; i++) {
1952 if (iv->views[i])
1953 iv->destroy_image_view(iv->dev, iv->views[i], iv->alloc);
1954 }
1955
1956 memset(iv->views, 0, sizeof(iv->views));
1957}
1958
1960{
1961 FFVulkanFunctions *vk = &s->vkfn;
1962 FFVkImageViews *iv;
1963
1964 av_assert1(nb_views <= AV_NUM_DATA_POINTERS);
1965
1966 iv = av_refstruct_pool_get(s->imageviews_pool);
1967 if (!iv)
1968 return NULL;
1969
1970 iv->nb_views = nb_views;
1971 iv->dev = s->hwctx->act_dev;
1972 iv->alloc = s->hwctx->alloc;
1973 iv->destroy_image_view = vk->DestroyImageView;
1974
1975 return iv;
1976}
1977
1979{
1980#define REPS_FMT(fmt) \
1981 [FF_VK_REP_NATIVE] = fmt ## _UINT, \
1982 [FF_VK_REP_FLOAT] = fmt ## _UNORM, \
1983 [FF_VK_REP_INT] = fmt ## _SINT, \
1984 [FF_VK_REP_UINT] = fmt ## _UINT,
1985
1986#define REPS_FMT_PACK(fmt, num) \
1987 [FF_VK_REP_NATIVE] = fmt ## _UINT_PACK ## num, \
1988 [FF_VK_REP_FLOAT] = fmt ## _UNORM_PACK ## num, \
1989 [FF_VK_REP_INT] = fmt ## _SINT_PACK ## num, \
1990 [FF_VK_REP_UINT] = fmt ## _UINT_PACK ## num,
1991
1992 const VkFormat fmts_map[][4] = {
1993 { REPS_FMT_PACK(VK_FORMAT_A2B10G10R10, 32) },
1994 { REPS_FMT_PACK(VK_FORMAT_A2R10G10B10, 32) },
1995 {
1996 VK_FORMAT_B5G6R5_UNORM_PACK16,
1997 VK_FORMAT_B5G6R5_UNORM_PACK16,
1998 VK_FORMAT_UNDEFINED,
1999 VK_FORMAT_UNDEFINED,
2000 },
2001 {
2002 VK_FORMAT_R5G6B5_UNORM_PACK16,
2003 VK_FORMAT_R5G6B5_UNORM_PACK16,
2004 VK_FORMAT_UNDEFINED,
2005 VK_FORMAT_UNDEFINED,
2006 },
2007 { REPS_FMT(VK_FORMAT_B8G8R8) },
2008 { REPS_FMT(VK_FORMAT_B8G8R8A8) },
2009 { REPS_FMT(VK_FORMAT_R8) },
2010 { REPS_FMT(VK_FORMAT_R8G8) },
2011 { REPS_FMT(VK_FORMAT_R8G8B8) },
2012 { REPS_FMT(VK_FORMAT_R8G8B8A8) },
2013 { REPS_FMT(VK_FORMAT_R16) },
2014 { REPS_FMT(VK_FORMAT_R16G16) },
2015 { REPS_FMT(VK_FORMAT_R16G16B16) },
2016 { REPS_FMT(VK_FORMAT_R16G16B16A16) },
2017 {
2018 VK_FORMAT_R32_UINT,
2019 VK_FORMAT_R32_SFLOAT,
2020 VK_FORMAT_R32_SINT,
2021 VK_FORMAT_R32_UINT,
2022 },
2023 {
2024 VK_FORMAT_R32G32B32_SFLOAT,
2025 VK_FORMAT_R32G32B32_SFLOAT,
2026 VK_FORMAT_UNDEFINED,
2027 VK_FORMAT_UNDEFINED,
2028 },
2029 {
2030 VK_FORMAT_R16G16B16A16_SFLOAT,
2031 VK_FORMAT_R16G16B16A16_SFLOAT,
2032 VK_FORMAT_UNDEFINED,
2033 VK_FORMAT_UNDEFINED,
2034 },
2035 {
2036 VK_FORMAT_R32G32B32A32_SFLOAT,
2037 VK_FORMAT_R32G32B32A32_SFLOAT,
2038 VK_FORMAT_UNDEFINED,
2039 VK_FORMAT_UNDEFINED,
2040 },
2041 {
2042 VK_FORMAT_R32G32B32_UINT,
2043 VK_FORMAT_UNDEFINED,
2044 VK_FORMAT_R32G32B32_SINT,
2045 VK_FORMAT_R32G32B32_UINT,
2046 },
2047 {
2048 VK_FORMAT_R32G32B32A32_UINT,
2049 VK_FORMAT_UNDEFINED,
2050 VK_FORMAT_R32G32B32A32_SINT,
2051 VK_FORMAT_R32G32B32A32_UINT,
2052 },
2053 {
2054 VK_FORMAT_R16_SFLOAT,
2055 VK_FORMAT_R16_SFLOAT,
2056 VK_FORMAT_R16_SINT,
2057 VK_FORMAT_R16_UINT,
2058 },
2059 };
2060#undef REPS_FMT_PACK
2061#undef REPS_FMT
2062
2063 if (fmt == VK_FORMAT_UNDEFINED)
2064 return VK_FORMAT_UNDEFINED;
2065
2066 for (int i = 0; i < FF_ARRAY_ELEMS(fmts_map); i++) {
2067 if (fmts_map[i][FF_VK_REP_NATIVE] == fmt ||
2068 fmts_map[i][FF_VK_REP_FLOAT] == fmt ||
2069 fmts_map[i][FF_VK_REP_INT] == fmt ||
2070 fmts_map[i][FF_VK_REP_UINT] == fmt)
2071 return fmts_map[i][rep_fmt];
2072 }
2073
2074 return VK_FORMAT_UNDEFINED;
2075}
2076
2078 VkImageView *img_view, VkImageAspectFlags *aspect,
2079 AVFrame *f, int plane, enum FFVkShaderRepFormat rep_fmt)
2080{
2081 VkResult ret;
2082 FFVulkanFunctions *vk = &s->vkfn;
2083 AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
2084 AVVulkanFramesContext *vkfc = hwfc->hwctx;
2085 const VkFormat *rep_fmts = av_vkfmt_from_pixfmt(hwfc->sw_format);
2086 AVVkFrame *vkf = (AVVkFrame *)f->data[0];
2087 const int nb_images = ff_vk_count_images(vkf);
2088
2089 VkImageViewUsageCreateInfo view_usage_info = {
2090 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
2091 .usage = vkfc->usage &
2092 (~(VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR |
2093 VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR)),
2094 };
2095 VkImageViewCreateInfo view_create_info = {
2096 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
2097 .pNext = &view_usage_info,
2098 .image = vkf->img[FFMIN(plane, nb_images - 1)],
2099 .viewType = VK_IMAGE_VIEW_TYPE_2D,
2100 .format = map_fmt_to_rep(rep_fmts[plane], rep_fmt),
2101 .components = ff_comp_identity_map,
2102 .subresourceRange = {
2103 .aspectMask = ff_vk_aspect_flag(f, plane),
2104 .levelCount = 1,
2105 .layerCount = 1,
2106 },
2107 };
2108 if (view_create_info.format == VK_FORMAT_UNDEFINED) {
2109 av_log(s, AV_LOG_ERROR, "Unable to find a compatible representation "
2110 "of format %i and mode %i\n",
2111 rep_fmts[plane], rep_fmt);
2112 return AVERROR(EINVAL);
2113 }
2114
2115 ret = vk->CreateImageView(s->hwctx->act_dev, &view_create_info,
2116 s->hwctx->alloc, img_view);
2117 if (ret != VK_SUCCESS) {
2118 av_log(s, AV_LOG_ERROR, "Failed to create imageview: %s\n",
2119 ff_vk_ret2str(ret));
2120 return AVERROR_EXTERNAL;
2121 }
2122
2123 *aspect = view_create_info.subresourceRange.aspectMask;
2124
2125 return 0;
2126}
2127
2129 VkImageView views[AV_NUM_DATA_POINTERS],
2130 AVFrame *f, enum FFVkShaderRepFormat rep_fmt)
2131{
2132 int err = 0;
2133 VkResult ret;
2134 FFVulkanFunctions *vk = &s->vkfn;
2135 AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
2136 AVVulkanFramesContext *vkfc = hwfc->hwctx;
2137 const VkFormat *rep_fmts = av_vkfmt_from_pixfmt(hwfc->sw_format);
2138 AVVkFrame *vkf = (AVVkFrame *)f->data[0];
2139 const int nb_images = ff_vk_count_images(vkf);
2140 const int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format);
2141 VkImageView tmp_views[AV_NUM_DATA_POINTERS] = { 0 };
2142
2143 for (int i = 0; i < nb_planes; i++) {
2144 VkImageViewUsageCreateInfo view_usage_info = {
2145 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
2146 .usage = vkfc->usage &
2147 (~(VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR |
2148 VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR)),
2149 };
2150 VkImageViewCreateInfo view_create_info = {
2151 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
2152 .pNext = &view_usage_info,
2153 .image = vkf->img[FFMIN(i, nb_images - 1)],
2154 .viewType = VK_IMAGE_VIEW_TYPE_2D,
2155 .format = map_fmt_to_rep(rep_fmts[i], rep_fmt),
2156 .components = ff_comp_identity_map,
2157 .subresourceRange = {
2158 .aspectMask = ff_vk_aspect_flag(f, i),
2159 .levelCount = 1,
2160 .layerCount = 1,
2161 },
2162 };
2163 if (view_create_info.format == VK_FORMAT_UNDEFINED) {
2164 av_log(s, AV_LOG_ERROR, "Unable to find a compatible representation "
2165 "of format %i and mode %i\n",
2166 rep_fmts[i], rep_fmt);
2167 err = AVERROR(EINVAL);
2168 goto fail;
2169 }
2170
2171 ret = vk->CreateImageView(s->hwctx->act_dev, &view_create_info,
2172 s->hwctx->alloc, &tmp_views[i]);
2173 if (ret != VK_SUCCESS) {
2174 av_log(s, AV_LOG_ERROR, "Failed to create imageview: %s\n",
2175 ff_vk_ret2str(ret));
2176 err = AVERROR_EXTERNAL;
2177 goto fail;
2178 }
2179 }
2180
2181 /* The execution context owns the views, destroying them on completion */
2182 for (int i = 0; i < nb_planes; i++)
2183 ff_vk_exec_add_dep_obj(s, e, VK_OBJECT_TYPE_IMAGE_VIEW,
2184 (uint64_t)tmp_views[i]);
2185
2186 memcpy(views, tmp_views, nb_planes*sizeof(*views));
2187
2188 return 0;
2189
2190fail:
2191 for (int i = 0; i < nb_planes; i++)
2192 if (tmp_views[i])
2193 vk->DestroyImageView(s->hwctx->act_dev, tmp_views[i], s->hwctx->alloc);
2194 return err;
2195}
2196
2198 AVFrame *pic, VkImageMemoryBarrier2 *bar, int *nb_bar,
2199 VkPipelineStageFlags2 src_stage,
2200 VkPipelineStageFlags2 dst_stage,
2201 VkAccessFlagBits2 new_access,
2202 VkImageLayout new_layout,
2203 uint32_t new_qf)
2204{
2205 int found = -1;
2206 AVVkFrame *vkf = (AVVkFrame *)pic->data[0];
2207 const int nb_images = ff_vk_count_images(vkf);
2208 for (int i = 0; i < e->nb_frame_deps; i++)
2209 if (e->frame_deps[i]->data[0] == pic->data[0]) {
2210 if (e->frame_update[i])
2211 found = i;
2212 break;
2213 }
2214
2215 for (int i = 0; i < nb_images; i++) {
2216 bar[*nb_bar] = (VkImageMemoryBarrier2) {
2217 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
2218 .pNext = NULL,
2219 .srcStageMask = src_stage,
2220 .dstStageMask = dst_stage,
2221 .srcAccessMask = found >= 0 ? e->access_dst[found] : vkf->access[i],
2222 .dstAccessMask = new_access,
2223 .oldLayout = found >= 0 ? e->layout_dst[found] : vkf->layout[0],
2224 .newLayout = new_layout,
2225 .srcQueueFamilyIndex = found >= 0 ? e->queue_family_dst[found] : vkf->queue_family[0],
2226 .dstQueueFamilyIndex = new_qf,
2227 .image = vkf->img[i],
2228 .subresourceRange = (VkImageSubresourceRange) {
2229 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
2230 .layerCount = 1,
2231 .levelCount = 1,
2232 },
2233 };
2234 *nb_bar += 1;
2235 }
2236
2237 ff_vk_exec_update_frame(s, e, pic, &bar[*nb_bar - nb_images], NULL);
2238}
2239
2241 VkPipelineStageFlags stage, VkSpecializationInfo *spec,
2242 uint32_t wg_size[3], uint32_t required_subgroup_size)
2243{
2244 shd->stage = stage;
2245 shd->precompiled = 1;
2246 shd->specialization_info = spec;
2247 memcpy(shd->lg_size, wg_size, 3*sizeof(uint32_t));
2248
2249 shd->subgroup_info = (VkPipelineShaderStageRequiredSubgroupSizeCreateInfo) {
2250 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO,
2251 .requiredSubgroupSize = required_subgroup_size,
2252 };
2253
2254 switch (shd->stage) {
2255 case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
2256 case VK_SHADER_STAGE_CALLABLE_BIT_KHR:
2257 case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
2258 case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
2259 case VK_SHADER_STAGE_MISS_BIT_KHR:
2260 case VK_SHADER_STAGE_RAYGEN_BIT_KHR:
2261 shd->bind_point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
2262 break;
2263 case VK_SHADER_STAGE_COMPUTE_BIT:
2264 shd->bind_point = VK_PIPELINE_BIND_POINT_COMPUTE;
2265 break;
2266 default:
2267 shd->bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS;
2268 break;
2269 };
2270
2271 return 0;
2272}
2273
2275{
2276 VkResult ret;
2277 FFVulkanFunctions *vk = &s->vkfn;
2278 VkPipelineLayoutCreateInfo pipeline_layout_info;
2279
2280 /* Finally create the pipeline layout */
2281 pipeline_layout_info = (VkPipelineLayoutCreateInfo) {
2282 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
2283 .pSetLayouts = shd->desc_layout,
2284 .setLayoutCount = shd->nb_descriptor_sets,
2285 .pushConstantRangeCount = shd->push_consts_num,
2286 .pPushConstantRanges = shd->push_consts,
2287 };
2288
2289 ret = vk->CreatePipelineLayout(s->hwctx->act_dev, &pipeline_layout_info,
2290 s->hwctx->alloc, &shd->pipeline_layout);
2291 if (ret != VK_SUCCESS) {
2292 av_log(s, AV_LOG_ERROR, "Unable to init pipeline layout: %s\n",
2293 ff_vk_ret2str(ret));
2294 return AVERROR_EXTERNAL;
2295 }
2296
2297 return 0;
2298}
2299
2301 VkShaderModule *mod,
2302 const uint8_t *spirv, size_t spirv_len)
2303{
2304 VkResult ret;
2305 FFVulkanFunctions *vk = &s->vkfn;
2306
2307 VkShaderModuleCreateInfo shader_module_info = {
2308 .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
2309 .pNext = NULL,
2310 .flags = 0x0,
2311 .pCode = (void *)spirv,
2312 .codeSize = spirv_len,
2313 };
2314
2315 ret = vk->CreateShaderModule(s->hwctx->act_dev, &shader_module_info,
2316 s->hwctx->alloc, mod);
2317 if (ret != VK_SUCCESS) {
2318 av_log(s, AV_LOG_ERROR, "Error creating shader module: %s\n",
2319 ff_vk_ret2str(ret));
2320 return AVERROR_EXTERNAL;
2321 }
2322
2323 return 0;
2324}
2325
2327 VkShaderModule mod, const char *entrypoint)
2328{
2329 VkResult ret;
2330 FFVulkanFunctions *vk = &s->vkfn;
2331
2332 VkComputePipelineCreateInfo pipeline_create_info = {
2333 .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
2334 .flags = 0x0,
2335 .layout = shd->pipeline_layout,
2336 .stage = (VkPipelineShaderStageCreateInfo) {
2337 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
2338 .pNext = shd->subgroup_info.requiredSubgroupSize ?
2339 &shd->subgroup_info : NULL,
2340 .pName = entrypoint,
2341 .flags = shd->subgroup_info.requiredSubgroupSize ?
2342 VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT : 0x0,
2343 .stage = shd->stage,
2344 .module = mod,
2345 .pSpecializationInfo = shd->specialization_info,
2346 },
2347 };
2348
2349 ret = vk->CreateComputePipelines(s->hwctx->act_dev, VK_NULL_HANDLE, 1,
2350 &pipeline_create_info,
2351 s->hwctx->alloc, &shd->pipeline);
2352 if (ret != VK_SUCCESS) {
2353 av_log(s, AV_LOG_ERROR, "Unable to init compute pipeline: %s\n",
2354 ff_vk_ret2str(ret));
2355 return AVERROR_EXTERNAL;
2356 }
2357
2358 return 0;
2359}
2360
2362 const uint8_t *spirv, size_t spirv_len,
2363 size_t *binary_size, const char *entrypoint)
2364{
2365 VkResult ret;
2366 FFVulkanFunctions *vk = &s->vkfn;
2367
2368 VkShaderCreateInfoEXT shader_obj_create = {
2369 .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,
2370 .pNext = shd->subgroup_info.requiredSubgroupSize ?
2371 &shd->subgroup_info : NULL,
2372 .flags = shd->subgroup_info.requiredSubgroupSize ?
2373 VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT : 0x0,
2374 .stage = shd->stage,
2375 .nextStage = 0,
2376 .codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT,
2377 .pCode = spirv,
2378 .codeSize = spirv_len,
2379 .pName = entrypoint,
2380 .pSetLayouts = shd->desc_layout,
2381 .setLayoutCount = shd->nb_descriptor_sets,
2382 .pushConstantRangeCount = shd->push_consts_num,
2383 .pPushConstantRanges = shd->push_consts,
2384 .pSpecializationInfo = shd->specialization_info,
2385 };
2386
2387 ret = vk->CreateShadersEXT(s->hwctx->act_dev, 1, &shader_obj_create,
2388 s->hwctx->alloc, &shd->object);
2389 if (ret != VK_SUCCESS) {
2390 av_log(s, AV_LOG_ERROR, "Unable to create shader object: %s\n",
2391 ff_vk_ret2str(ret));
2392 return AVERROR_EXTERNAL;
2393 }
2394
2395 if (vk->GetShaderBinaryDataEXT(s->hwctx->act_dev, shd->object,
2396 binary_size, NULL) != VK_SUCCESS)
2397 return AVERROR_EXTERNAL;
2398
2399 return 0;
2400}
2401
2403{
2404 VkResult ret;
2405 FFVulkanFunctions *vk = &s->vkfn;
2406
2407 int has_singular = 0;
2408 int max_descriptors = 0;
2409 for (int i = 0; i < shd->nb_descriptor_sets; i++) {
2410 max_descriptors = FFMAX(max_descriptors, shd->desc_set[i].nb_bindings);
2411 if (shd->desc_set[i].singular)
2412 has_singular = 1;
2413 }
2414 shd->use_push = (s->extensions & FF_VK_EXT_PUSH_DESCRIPTOR) &&
2415 (max_descriptors <= s->push_desc_props.maxPushDescriptors) &&
2416 (shd->nb_descriptor_sets == 1) &&
2417 (has_singular == 0);
2418
2419 for (int i = 0; i < shd->nb_descriptor_sets; i++) {
2421 VkDescriptorSetLayoutCreateInfo desc_layout_create = {
2422 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
2423 .bindingCount = set->nb_bindings,
2424 .pBindings = set->binding,
2425 .flags = (shd->use_push) ?
2426 VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR :
2427 0x0,
2428 };
2429
2430 ret = vk->CreateDescriptorSetLayout(s->hwctx->act_dev,
2431 &desc_layout_create,
2432 s->hwctx->alloc,
2433 &shd->desc_layout[i]);
2434 if (ret != VK_SUCCESS) {
2435 av_log(s, AV_LOG_ERROR, "Unable to create descriptor set layout: %s",
2436 ff_vk_ret2str(ret));
2437 return AVERROR_EXTERNAL;
2438 }
2439 }
2440
2441 return 0;
2442}
2443
2445 const char *spirv, size_t spirv_len,
2446 const char *entrypoint)
2447{
2448 int err;
2449 FFVulkanFunctions *vk = &s->vkfn;
2450 VkSpecializationMapEntry spec_entries[3];
2451 VkSpecializationInfo spec_info;
2452 size_t input_size = spirv_len, binary_size = 0;
2453
2454 if (shd->precompiled) {
2455 if (!shd->specialization_info) {
2456 spec_info = (VkSpecializationInfo) {
2457 .pMapEntries = spec_entries,
2458 .mapEntryCount = 0,
2459 .pData = shd->lg_size,
2460 .dataSize = 0,
2461 };
2462 shd->specialization_info = &spec_info;
2463 }
2464
2465 VkSpecializationMapEntry *spe = (void *)shd->specialization_info->pMapEntries;
2466 for (int i = 0; i < 3; i++) {
2467 spe[shd->specialization_info->mapEntryCount++] = (VkSpecializationMapEntry) {
2468 .constantID = 253 + i,
2469 .offset = shd->specialization_info->dataSize + i*sizeof(uint32_t),
2470 .size = sizeof(uint32_t),
2471 };
2472 }
2473
2474 uint8_t *spd = (uint8_t *)shd->specialization_info->pData;
2475 memcpy(&spd[shd->specialization_info->dataSize],
2476 shd->lg_size, 3*sizeof(uint32_t));
2477 shd->specialization_info->dataSize += 3*sizeof(uint32_t);
2478
2479#if CONFIG_SHADER_COMPRESSION
2480 uint8_t *out;
2481 size_t out_len;
2482 int ret = ff_zlib_expand(s, &out, &out_len, spirv, spirv_len);
2483 if (ret < 0)
2484 return ret;
2485 spirv = out;
2486 spirv_len = out_len;
2487#endif
2488 }
2489
2490 err = init_descriptors(s, shd);
2491 if (err < 0)
2492 goto end;
2493
2494 err = init_pipeline_layout(s, shd);
2495 if (err < 0)
2496 goto end;
2497
2498 if (s->extensions & FF_VK_EXT_SHADER_OBJECT) {
2499 err = create_shader_object(s, shd, spirv, spirv_len,
2500 &binary_size, entrypoint);
2501 if (err < 0)
2502 goto end;
2503 } else {
2504 VkShaderModule mod;
2505 err = create_shader_module(s, shd, &mod, spirv, spirv_len);
2506 if (err < 0)
2507 goto end;
2508
2509 switch (shd->bind_point) {
2510 case VK_PIPELINE_BIND_POINT_COMPUTE:
2511 err = init_compute_pipeline(s, shd, mod, entrypoint);
2512 break;
2513 default:
2514 av_log(s, AV_LOG_ERROR, "Unsupported shader type: %i\n",
2515 shd->bind_point);
2516 err = AVERROR(EINVAL);
2517 goto end;
2518 break;
2519 };
2520
2521 vk->DestroyShaderModule(s->hwctx->act_dev, mod, s->hwctx->alloc);
2522 if (err < 0)
2523 goto end;
2524 }
2525
2526 if (shd->name)
2527 av_log(s, AV_LOG_VERBOSE, "Shader %s linked, size:", shd->name);
2528 else
2529 av_log(s, AV_LOG_VERBOSE, "Shader linked, size:");
2530
2531 if (input_size != spirv_len)
2532 av_log(s, AV_LOG_VERBOSE, " %zu compressed,", input_size);
2533 av_log(s, AV_LOG_VERBOSE, " %zu SPIR-V", spirv_len);
2534 if (binary_size != spirv_len)
2535 av_log(s, AV_LOG_VERBOSE, ", %zu binary", binary_size);
2536 av_log(s, AV_LOG_VERBOSE, "\n");
2537
2538end:
2539 if (shd->precompiled) {
2540 shd->specialization_info->mapEntryCount -= 3;
2541 shd->specialization_info->dataSize -= 3*sizeof(uint32_t);
2542 }
2543#if CONFIG_SHADER_COMPRESSION
2544 if (shd->precompiled)
2545 av_free((void *)spirv);
2546#endif
2547 return err;
2548}
2549
2551 const FFVulkanDescriptorSetBinding *desc, int nb,
2552 int singular)
2553{
2557
2558 for (int i = 0; i < nb; i++) {
2559 set->binding[i].binding = i;
2560 set->binding[i].descriptorType = desc[i].type;
2561 set->binding[i].descriptorCount = FFMAX(desc[i].elems, 1);
2562 set->binding[i].stageFlags = desc[i].stages;
2563 set->binding[i].pImmutableSamplers = desc[i].samplers;
2564 }
2565
2566 for (int i = 0; i < nb; i++) {
2567 int j;
2568 for (j = 0; j < shd->nb_desc_pool_size; j++)
2569 if (shd->desc_pool_size[j].type == desc[i].type)
2570 break;
2571 if (j >= shd->nb_desc_pool_size) {
2572 shd->nb_desc_pool_size++;
2574 }
2575
2576 shd->desc_pool_size[j].type = desc[i].type;
2577 shd->desc_pool_size[j].descriptorCount += FFMAX(desc[i].elems, 1);
2578 }
2579
2580 set->singular = singular;
2581 set->nb_bindings = nb;
2582}
2583
2585 FFVulkanShader *shd)
2586{
2587 if (!shd->nb_descriptor_sets)
2588 return 0;
2589
2590 FFVulkanShaderData *sd = &pool->reg_shd[pool->nb_reg_shd++];
2592
2593 sd->shd = shd;
2595
2596 if (!shd->use_push) {
2597 VkResult ret;
2598 FFVulkanFunctions *vk = &s->vkfn;
2599 VkDescriptorSetLayout *tmp_layouts;
2600 VkDescriptorSetAllocateInfo set_alloc_info;
2601 VkDescriptorPoolCreateInfo pool_create_info;
2602
2603 for (int i = 0; i < shd->nb_desc_pool_size; i++)
2604 shd->desc_pool_size[i].descriptorCount *= pool->pool_size;
2605
2606 pool_create_info = (VkDescriptorPoolCreateInfo) {
2607 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
2608 .flags = 0,
2609 .pPoolSizes = shd->desc_pool_size,
2610 .poolSizeCount = shd->nb_desc_pool_size,
2611 .maxSets = sd->nb_descriptor_sets*pool->pool_size,
2612 };
2613
2614 ret = vk->CreateDescriptorPool(s->hwctx->act_dev, &pool_create_info,
2615 s->hwctx->alloc, &sd->desc_pool);
2616 if (ret != VK_SUCCESS) {
2617 av_log(s, AV_LOG_ERROR, "Unable to create descriptor pool: %s\n",
2618 ff_vk_ret2str(ret));
2619 return AVERROR_EXTERNAL;
2620 }
2621
2622 tmp_layouts = av_malloc_array(pool_create_info.maxSets, sizeof(*tmp_layouts));
2623 if (!tmp_layouts)
2624 return AVERROR(ENOMEM);
2625
2626 /* Colate each execution context's descriptor set layouts */
2627 for (int i = 0; i < pool->pool_size; i++)
2628 for (int j = 0; j < sd->nb_descriptor_sets; j++)
2629 tmp_layouts[i*sd->nb_descriptor_sets + j] = shd->desc_layout[j];
2630
2631 set_alloc_info = (VkDescriptorSetAllocateInfo) {
2632 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
2633 .descriptorPool = sd->desc_pool,
2634 .pSetLayouts = tmp_layouts,
2635 .descriptorSetCount = pool_create_info.maxSets,
2636 };
2637
2638 sd->desc_sets = av_malloc_array(pool_create_info.maxSets,
2639 sizeof(*tmp_layouts));
2640 if (!sd->desc_sets) {
2641 av_free(tmp_layouts);
2642 return AVERROR(ENOMEM);
2643 }
2644 ret = vk->AllocateDescriptorSets(s->hwctx->act_dev, &set_alloc_info,
2645 sd->desc_sets);
2646 av_free(tmp_layouts);
2647 if (ret != VK_SUCCESS) {
2648 av_log(s, AV_LOG_ERROR, "Unable to allocate descriptor set: %s\n",
2649 ff_vk_ret2str(ret));
2650 av_freep(&sd->desc_sets);
2651 return AVERROR_EXTERNAL;
2652 }
2653 }
2654
2655 return 0;
2656}
2657
2659 const FFVulkanShader *shd)
2660{
2661 for (int i = 0; i < e->parent->nb_reg_shd; i++)
2662 if (e->parent->reg_shd[i].shd == shd)
2663 return &e->parent->reg_shd[i];
2664 return NULL;
2665}
2666
2668 FFVulkanShader *shd, int set,
2669 VkWriteDescriptorSet *write_info)
2670{
2671 FFVulkanFunctions *vk = &s->vkfn;
2672 FFVulkanDescriptorSet *desc_set = &shd->desc_set[set];
2673 const FFVulkanShaderData *sd = get_shd_data(e, shd);
2674
2675 if (desc_set->singular) {
2676 for (int i = 0; i < e->parent->pool_size; i++) {
2677 write_info->dstSet = sd->desc_sets[i*sd->nb_descriptor_sets + set];
2678 vk->UpdateDescriptorSets(s->hwctx->act_dev, 1, write_info, 0, NULL);
2679 }
2680 } else {
2681 if (shd->use_push) {
2682 vk->CmdPushDescriptorSetKHR(e->buf,
2683 shd->bind_point,
2684 shd->pipeline_layout,
2685 set, 1,
2686 write_info);
2687 } else {
2688 write_info->dstSet = sd->desc_sets[e->idx*sd->nb_descriptor_sets + set];
2689 vk->UpdateDescriptorSets(s->hwctx->act_dev, 1, write_info, 0, NULL);
2690 }
2691 }
2692}
2693
2695 FFVulkanShader *shd, int set, int bind, int offs,
2696 VkImageView view, VkImageLayout layout,
2697 VkSampler sampler)
2698{
2699 FFVulkanDescriptorSet *desc_set = &shd->desc_set[set];
2700
2701 VkDescriptorImageInfo desc_pool_write_info_img = {
2702 .sampler = sampler,
2703 .imageView = view,
2704 .imageLayout = layout,
2705 };
2706 VkWriteDescriptorSet desc_pool_write_info = {
2707 .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
2708 .dstBinding = bind,
2709 .descriptorCount = 1,
2710 .dstArrayElement = offs,
2711 .descriptorType = desc_set->binding[bind].descriptorType,
2712 .pImageInfo = &desc_pool_write_info_img,
2713 };
2714 update_set_pool_write(s, e, shd, set, &desc_pool_write_info);
2715
2716 return 0;
2717}
2718
2720 FFVulkanShader *shd, AVFrame *f,
2721 VkImageView *views, int set, int binding,
2722 VkImageLayout layout, VkSampler sampler)
2723{
2724 AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
2725 const int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format);
2726
2727 for (int i = 0; i < nb_planes; i++)
2728 ff_vk_shader_update_img(s, e, shd, set, binding, i,
2729 views[i], layout, sampler);
2730}
2731
2733 FFVulkanShader *shd,
2734 int set, int bind, int elem,
2735 FFVkBuffer *buf, VkDeviceSize offset, VkDeviceSize len,
2736 VkFormat fmt)
2737{
2738 FFVulkanDescriptorSet *desc_set = &shd->desc_set[set];
2739
2740 VkDescriptorBufferInfo desc_pool_write_info_buf = {
2741 .buffer = buf->buf,
2742 .offset = buf->virtual_offset + offset,
2743 .range = len,
2744 };
2745 VkWriteDescriptorSet desc_pool_write_info = {
2746 .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
2747 .dstBinding = bind,
2748 .descriptorCount = 1,
2749 .dstArrayElement = elem,
2750 .descriptorType = desc_set->binding[bind].descriptorType,
2751 .pBufferInfo = &desc_pool_write_info_buf,
2752 };
2753 update_set_pool_write(s, e, shd, set, &desc_pool_write_info);
2754
2755 return 0;
2756}
2757
2759 FFVulkanShader *shd,
2760 VkShaderStageFlagBits stage,
2761 int offset, size_t size, void *src)
2762{
2763 FFVulkanFunctions *vk = &s->vkfn;
2764 vk->CmdPushConstants(e->buf, shd->pipeline_layout,
2765 stage, offset, size, src);
2766}
2767
2769 const FFVulkanShader *shd)
2770{
2771 FFVulkanFunctions *vk = &s->vkfn;
2772 const FFVulkanShaderData *sd = get_shd_data(e, shd);
2773
2774 if (s->extensions & FF_VK_EXT_SHADER_OBJECT) {
2775 VkShaderStageFlagBits stages = shd->stage;
2776 vk->CmdBindShadersEXT(e->buf, 1, &stages, &shd->object);
2777 } else {
2778 vk->CmdBindPipeline(e->buf, shd->bind_point, shd->pipeline);
2779 }
2780
2781 if (sd && sd->nb_descriptor_sets) {
2782 if (!shd->use_push) {
2783 vk->CmdBindDescriptorSets(e->buf, shd->bind_point, shd->pipeline_layout,
2784 0, sd->nb_descriptor_sets,
2785 &sd->desc_sets[e->idx*sd->nb_descriptor_sets],
2786 0, NULL);
2787 }
2788 }
2789}
2790
2792{
2793 FFVulkanFunctions *vk = &s->vkfn;
2794
2795#if 0
2796 if (shd->shader.module)
2797 vk->DestroyShaderModule(s->hwctx->act_dev, shd->shader.module,
2798 s->hwctx->alloc);
2799#endif
2800
2801 if (shd->object)
2802 vk->DestroyShaderEXT(s->hwctx->act_dev, shd->object, s->hwctx->alloc);
2803 if (shd->pipeline)
2804 vk->DestroyPipeline(s->hwctx->act_dev, shd->pipeline, s->hwctx->alloc);
2805 if (shd->pipeline_layout)
2806 vk->DestroyPipelineLayout(s->hwctx->act_dev, shd->pipeline_layout,
2807 s->hwctx->alloc);
2808
2809 for (int i = 0; i < shd->nb_descriptor_sets; i++)
2810 if (shd->desc_layout[i])
2811 vk->DestroyDescriptorSetLayout(s->hwctx->act_dev, shd->desc_layout[i],
2812 s->hwctx->alloc);
2813}
2814
2816{
2817 av_freep(&s->query_props);
2818 av_freep(&s->qf_props);
2819 av_freep(&s->video_props);
2820#ifdef VK_KHR_maintenance9
2821 av_freep(&s->ownership_props);
2822#endif
2823 av_freep(&s->coop_mat_props);
2824 av_freep(&s->host_image_copy_layouts);
2825 av_refstruct_pool_uninit(&s->imageviews_pool);
2826
2827 av_buffer_unref(&s->device_ref);
2828 av_buffer_unref(&s->frames_ref);
2829}
2830
2831int ff_vk_init(FFVulkanContext *s, void *log_parent,
2832 AVBufferRef *device_ref, AVBufferRef *frames_ref)
2833{
2834 int err;
2835
2836 static const AVClass vulkan_context_class = {
2837 .class_name = "vk",
2838 .version = LIBAVUTIL_VERSION_INT,
2839 .parent_log_context_offset = offsetof(FFVulkanContext, log_parent),
2840 };
2841
2842 memset(s, 0, sizeof(*s));
2843 s->log_parent = log_parent;
2844 s->class = &vulkan_context_class;
2845
2846 if (frames_ref) {
2847 s->frames_ref = av_buffer_ref(frames_ref);
2848 if (!s->frames_ref)
2849 return AVERROR(ENOMEM);
2850
2851 s->frames = (AVHWFramesContext *)s->frames_ref->data;
2852 s->hwfc = s->frames->hwctx;
2853
2854 device_ref = s->frames->device_ref;
2855 }
2856
2857 s->device_ref = av_buffer_ref(device_ref);
2858 if (!s->device_ref) {
2859 ff_vk_uninit(s);
2860 return AVERROR(ENOMEM);
2861 }
2862
2863 s->device = (AVHWDeviceContext *)s->device_ref->data;
2864 s->hwctx = s->device->hwctx;
2865
2866 s->extensions = ff_vk_extensions_to_mask(s->hwctx->enabled_dev_extensions,
2867 s->hwctx->nb_enabled_dev_extensions);
2868 s->extensions |= ff_vk_extensions_to_mask(s->hwctx->enabled_inst_extensions,
2869 s->hwctx->nb_enabled_inst_extensions);
2870
2871 err = ff_vk_load_functions(s->device, &s->vkfn, s->extensions, 1, 1);
2872 if (err < 0) {
2873 ff_vk_uninit(s);
2874 return err;
2875 }
2876
2877 err = ff_vk_load_props(s);
2878 if (err < 0) {
2879 ff_vk_uninit(s);
2880 return err;
2881 }
2882
2883 return 0;
2884}
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
static double val(void *priv, double ch)
Definition aeval.c:77
static const char *const format[]
Definition af_aiir.c:444
static cqueue * cqueue_create(int size, int max_size)
static const int8_t filt[NUMTAPS *2]
Definition af_earwax.c:40
static FILE * out
static AVFormatContext * ctx
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition avassert.h:58
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
static void BS_FUNC skip(BSCTX *bc, unsigned int n)
Skip n bits in the buffer.
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define f(width, name)
Definition cbs_vp8.c:236
#define s(width, name)
Definition cbs_vp9.c:198
#define av_popcount
Definition common.h:154
#define NULL
Definition coverity.c:32
static enum AVPixelFormat pix_fmt
void(* flush)(AVBSFContext *ctx)
Definition dts2pts.c:610
intptr_t atomic_uint
Definition stdatomic.h:56
#define atomic_store_explicit(object, desired, order)
Definition stdatomic.h:90
#define atomic_init(obj, value)
Definition stdatomic.h:33
const char * usage
#define AV_NUM_DATA_POINTERS
Definition frame.h:473
#define fail
Definition test.h:479
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition buffer.c:139
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition buffer.c:103
uint32_t av_get_random_seed(void)
Get a seed to use in conjunction with random functions.
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition error.h:59
#define AVERROR(e)
Definition error.h:45
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
Definition frame.c:483
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_VERBOSE
Detailed information.
Definition log.h:226
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
#define LIBAVUTIL_VERSION_INT
Definition version.h:85
int index
Definition gxfenc.c:90
cl_device_type type
const VkFormat * av_vkfmt_from_pixfmt(enum AVPixelFormat p)
Returns the optimal per-plane Vulkan format for a given sw_format, one for each plane.
enum VkFormat VkFormat
unsigned offset
Definition libaomenc.c:763
#define FF_DISABLE_DEPRECATION_WARNINGS
Definition internal.h:66
#define FF_ENABLE_DEPRECATION_WARNINGS
Definition internal.h:67
#define AVOnce
Definition thread.h:202
static int ff_thread_once(char *control, void(*routine)(void))
Definition thread.h:205
#define AV_ONCE_INIT
Definition thread.h:203
void ff_vk_set_perm(enum AVPixelFormat pix_fmt, int lut[4], int inv)
Since storage images may not be swizzled, we have to do this in the shader itself.
Definition vulkan.c:1696
static int init_pipeline_layout(FFVulkanContext *s, FFVulkanShader *shd)
Definition vulkan.c:2274
void ff_vk_shader_update_img_array(FFVulkanContext *s, FFVkExecContext *e, FFVulkanShader *shd, AVFrame *f, VkImageView *views, int set, int binding, VkImageLayout layout, VkSampler sampler)
Update a descriptor in a buffer with an image array.
Definition vulkan.c:2719
#define REPS_FMT(fmt)
#define REPS_FMT_PACK(fmt, num)
int ff_vk_shader_load(FFVulkanShader *shd, VkPipelineStageFlags stage, VkSpecializationInfo *spec, uint32_t wg_size[3], uint32_t required_subgroup_size)
Initialize a shader object.
Definition vulkan.c:2240
#define CASE(VAL)
void ff_vk_shader_add_descriptor_set(FFVulkanContext *s, FFVulkanShader *shd, const FFVulkanDescriptorSetBinding *desc, int nb, int singular)
Add descriptor to a shader.
Definition vulkan.c:2550
void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool)
Definition vulkan.c:331
const char * ff_vk_shader_rep_fmt(enum AVPixelFormat pix_fmt, enum FFVkShaderRepFormat rep_fmt)
Definition vulkan.c:1750
int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer **buf, int nb_buffers, int flush)
Definition vulkan.c:1358
VkImageAspectFlags ff_vk_aspect_flag(AVFrame *f, int p)
Get the aspect flag for a plane from an image.
Definition vulkan.c:1656
int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size, void *pNext, void *alloc_pNext, VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags)
Definition vulkan.c:1186
static void exec_pool_phase_seed(void)
Definition vulkan.c:388
int ff_vk_exec_pool_init(FFVulkanContext *s, AVVulkanDeviceQueueFamily *qf, FFVkExecPool *pool, int nb_contexts, int nb_queries, VkQueryType query_type, int query_64bit, const void *query_create_pnext)
Allocates/frees an execution pool.
Definition vulkan.c:395
static const FFVulkanShaderData * get_shd_data(FFVkExecContext *e, const FFVulkanShader *shd)
Definition vulkan.c:2658
void ff_vk_image_free(FFVulkanContext *s, VkImage *img, VkDeviceMemory *mem)
Free an image created by ff_vk_image_create(); all GPU use must have completed.
Definition vulkan.c:1172
void ff_vk_exec_wait(FFVulkanContext *s, FFVkExecContext *e)
Definition vulkan.c:645
static int init_compute_pipeline(FFVulkanContext *s, FFVulkanShader *shd, VkShaderModule mod, const char *entrypoint)
Definition vulkan.c:2326
int ff_vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req, VkMemoryPropertyFlagBits req_flags, void *alloc_extension, VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem)
Definition vulkan.c:1044
int ff_vk_image_create(FFVulkanContext *s, VkImage *img, VkDeviceMemory *mem, int width, int height, VkFormat format, int nb_layers, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, void *create_pnext)
Memory/buffer/image allocation helpers.
Definition vulkan.c:1095
int ff_vk_shader_add_push_const(FFVulkanShader *shd, int offset, int size, VkShaderStageFlagBits stage)
Add/update push constants for execution.
Definition vulkan.c:1613
int ff_vk_shader_update_img(FFVulkanContext *s, FFVkExecContext *e, FFVulkanShader *shd, int set, int bind, int offs, VkImageView view, VkImageLayout layout, VkSampler sampler)
Sets an image descriptor for specified shader and binding.
Definition vulkan.c:2694
void ff_vk_uninit(FFVulkanContext *s)
Frees main context.
Definition vulkan.c:2815
int ff_vk_load_props(FFVulkanContext *s)
Loads props/mprops/driver_props.
Definition vulkan.c:151
int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer **buf, uint8_t *mem[], int nb_buffers, int invalidate)
Buffer management code.
Definition vulkan.c:1278
const char * ff_vk_ret2str(VkResult res)
Converts Vulkan return values to strings.
Definition vulkan.c:42
static void host_map_free(AVRefStructOpaque opaque, void *obj)
Definition vulkan.c:1517
int ff_vk_init(FFVulkanContext *s, void *log_parent, AVBufferRef *device_ref, AVBufferRef *frames_ref)
Initializes the AVClass, in case this context is not used as the main user's context.
Definition vulkan.c:2831
int ff_vk_exec_add_dep_sw_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f)
Definition vulkan.c:811
void ff_vk_exec_add_dep_obj(FFVulkanContext *s, FFVkExecContext *e, VkObjectType type, uint64_t obj)
Definition vulkan.c:804
static void pooled_buf_free(AVRefStructOpaque opaque, void *obj)
Definition vulkan.c:1421
void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf)
Definition vulkan.c:1400
const VkComponentMapping ff_comp_identity_map
Definition vulkan.c:34
void ff_vk_frame_barrier(FFVulkanContext *s, FFVkExecContext *e, AVFrame *pic, VkImageMemoryBarrier2 *bar, int *nb_bar, VkPipelineStageFlags2 src_stage, VkPipelineStageFlags2 dst_stage, VkAccessFlagBits2 new_access, VkImageLayout new_layout, uint32_t new_qf)
Definition vulkan.c:2197
int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e)
Start/submit/wait an execution.
Definition vulkan.c:660
int ff_vk_create_imageviews(FFVulkanContext *s, FFVkExecContext *e, VkImageView views[AV_NUM_DATA_POINTERS], AVFrame *f, enum FFVkShaderRepFormat rep_fmt)
Create an imageview and add it as a dependency to an execution.
Definition vulkan.c:2128
static int create_shader_module(FFVulkanContext *s, FFVulkanShader *shd, VkShaderModule *mod, const uint8_t *spirv, size_t spirv_len)
Definition vulkan.c:2300
static int create_mapped_buffer(FFVulkanContext *s, FFVkBuffer *vkb, VkBufferUsageFlags usage, size_t size, VkExternalMemoryBufferCreateInfo *create_desc, VkImportMemoryHostPointerInfoEXT *import_desc, VkMemoryHostPointerPropertiesEXT props)
Definition vulkan.c:1471
static AVOnce exec_pool_phase_seeded
Definition vulkan.c:386
void ff_vk_shader_free(FFVulkanContext *s, FFVulkanShader *shd)
Free a shader.
Definition vulkan.c:2791
FFVkImageViews * ff_vk_imageviews_alloc(FFVulkanContext *s, int nb_views)
Allocate a reference-counted set of image views, zero-initialized for the caller to create.
Definition vulkan.c:1959
VkResult ff_vk_exec_get_query(FFVulkanContext *s, FFVkExecContext *e, void **data, VkQueryResultFlagBits flags)
Performs nb_queries queries and returns their results and statuses.
Definition vulkan.c:594
int ff_vk_shader_register_exec(FFVulkanContext *s, FFVkExecPool *pool, FFVulkanShader *shd)
Register a shader with an exec pool.
Definition vulkan.c:2584
int ff_vk_init_sampler(FFVulkanContext *s, VkSampler *sampler, int unnorm_coords, VkFilter filt)
Create a sampler.
Definition vulkan.c:1624
void ff_vk_exec_update_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f, VkImageMemoryBarrier2 *bar, uint32_t *nb_img_bar)
Definition vulkan.c:925
FFVkExecContext * ff_vk_exec_get(FFVulkanContext *s, FFVkExecPool *pool)
Retrieve an execution pool.
Definition vulkan.c:622
int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt)
Returns 1 if pixfmt is a usable RGB format.
Definition vulkan.c:1673
static void reset_imageviews(AVRefStructOpaque unused, void *obj)
Definition vulkan.c:1947
static int init_descriptors(FFVulkanContext *s, FFVulkanShader *shd)
Definition vulkan.c:2402
static void update_set_pool_write(FFVulkanContext *s, FFVkExecContext *e, FFVulkanShader *shd, int set, VkWriteDescriptorSet *write_info)
Definition vulkan.c:2667
int ff_vk_exec_submit(FFVulkanContext *s, FFVkExecContext *e)
Definition vulkan.c:969
void ff_vk_exec_bind_shader(FFVulkanContext *s, FFVkExecContext *e, const FFVulkanShader *shd)
Bind a shader.
Definition vulkan.c:2768
void ff_vk_exec_move_dep_refstruct(FFVulkanContext *s, FFVkExecContext *e, void *obj)
Definition vulkan.c:786
int ff_vk_shader_update_desc_buffer(FFVulkanContext *s, FFVkExecContext *e, FFVulkanShader *shd, int set, int bind, int elem, FFVkBuffer *buf, VkDeviceSize offset, VkDeviceSize len, VkFormat fmt)
Update a descriptor in a buffer with a buffer.
Definition vulkan.c:2732
static int create_shader_object(FFVulkanContext *s, FFVulkanShader *shd, const uint8_t *spirv, size_t spirv_len, size_t *binary_size, const char *entrypoint)
Definition vulkan.c:2361
#define FN_MAP_TO(dst_t, dst_name, src_t, src_name)
Definition vulkan.c:95
AVVulkanDeviceQueueFamily * ff_vk_qf_find(FFVulkanContext *s, VkQueueFlagBits dev_family, VkVideoCodecOperationFlagBitsKHR vid_ops)
Chooses an appropriate QF.
Definition vulkan.c:316
int ff_vk_host_map_buffer(FFVulkanContext *s, FFVkBuffer **dst, uint8_t *src_data, VkDeviceSize size, const AVBufferRef *src_buf, VkBufferUsageFlags usage)
Maps a system RAM buffer into a Vulkan buffer.
Definition vulkan.c:1522
void ff_vk_exec_add_dep_refstruct(FFVulkanContext *s, FFVkExecContext *e, void *obj)
Execution dependency management.
Definition vulkan.c:779
int ff_vk_create_imageview(FFVulkanContext *s, VkImageView *img_view, VkImageAspectFlags *aspect, AVFrame *f, int plane, enum FFVkShaderRepFormat rep_fmt)
Create a single imageview for a given plane.
Definition vulkan.c:2077
int ff_vk_get_pooled_buffer(FFVulkanContext *ctx, AVRefStructPool **buf_pool, FFVkBuffer **buf, VkBufferUsageFlags usage, void *create_pNext, size_t size, VkMemoryPropertyFlagBits mem_props)
Initialize a pool and create AVBufferRefs containing FFVkBuffer.
Definition vulkan.c:1426
static void load_enabled_qfs(FFVulkanContext *s)
Definition vulkan.c:130
static VkFormat map_fmt_to_rep(VkFormat fmt, enum FFVkShaderRepFormat rep_fmt)
Definition vulkan.c:1978
int ff_vk_flush_buffer(FFVulkanContext *s, FFVkBuffer *buf, VkDeviceSize offset, VkDeviceSize mem_size, int flush)
Flush or invalidate a single buffer, with a given size and offset.
Definition vulkan.c:1327
static atomic_uint exec_pool_phase[FF_ARRAY_ELEMS(((AVVulkanDeviceContext *) NULL) ->qf)]
Definition vulkan.c:385
int ff_vk_exec_mirror_sem_value(FFVulkanContext *s, FFVkExecContext *e, VkSemaphore *dst, uint64_t *dst_val, AVFrame *f)
Definition vulkan.c:944
static void exec_discard_deps(FFVulkanContext *s, FFVkExecContext *e)
Definition vulkan.c:712
void ff_vk_exec_discard(FFVulkanContext *s, FFVkExecContext *e)
Definition vulkan.c:763
void ff_vk_exec_add_dep_bool_sem(FFVulkanContext *s, FFVkExecContext *e, VkSemaphore *sem, int nb, VkPipelineStageFlagBits2 stage, int wait)
Definition vulkan.c:839
int ff_vk_shader_link(FFVulkanContext *s, FFVulkanShader *shd, const char *spirv, size_t spirv_len, const char *entrypoint)
Link a shader into an executable.
Definition vulkan.c:2444
int ff_vk_exec_add_dep_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f, VkPipelineStageFlagBits2 wait_stage, VkPipelineStageFlagBits2 signal_stage)
Definition vulkan.c:867
void ff_vk_shader_update_push_const(FFVulkanContext *s, FFVkExecContext *e, FFVulkanShader *shd, VkShaderStageFlagBits stage, int offset, size_t size, void *src)
Update push constant in a shader.
Definition vulkan.c:2758
void ff_vk_exec_add_dep_wait_sem(FFVulkanContext *s, FFVkExecContext *e, VkSemaphore sem, uint64_t val, VkPipelineStageFlagBits2 stage)
Definition vulkan.c:825
const char * desc
Definition libsvtav1.c:83
#define FFMIN(a, b)
Definition macros.h:49
#define FFMAX(a, b)
Definition macros.h:47
#define FFALIGN(x, a)
Definition macros.h:78
uint64_t layout
void * av_calloc(size_t nmemb, size_t size)
Definition mem.c:264
Memory handling functions.
const char data[16]
Definition mxf.c:149
#define av_realloc(p, s)
Definition ops_static.c:54
#define av_malloc(s)
Definition ops_static.c:52
static av_always_inline int pthread_mutex_lock(pthread_mutex_t *mutex)
Definition os2threads.h:119
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
Definition os2threads.h:104
static av_always_inline int pthread_mutex_unlock(pthread_mutex_t *mutex)
Definition os2threads.h:126
static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
Definition os2threads.h:112
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3500
#define AV_PIX_FMT_GBRAP12
Definition pixfmt.h:569
#define AV_PIX_FMT_YUV420P16
Definition pixfmt.h:556
#define AV_PIX_FMT_GBRPF32
Definition pixfmt.h:584
#define AV_PIX_FMT_P212
Definition pixfmt.h:624
#define AV_PIX_FMT_YUV444P12
Definition pixfmt.h:552
#define AV_PIX_FMT_RGBF32
Definition pixfmt.h:632
#define AV_PIX_FMT_YUV420P10
Definition pixfmt.h:545
#define AV_PIX_FMT_RGBAF32
Definition pixfmt.h:633
#define AV_PIX_FMT_RGBAF16
Definition pixfmt.h:630
#define AV_PIX_FMT_GBRAP16
Definition pixfmt.h:571
#define AV_PIX_FMT_P412
Definition pixfmt.h:625
#define AV_PIX_FMT_P210
Definition pixfmt.h:622
#define AV_PIX_FMT_YUVA444P10
Definition pixfmt.h:598
#define AV_PIX_FMT_P012
Definition pixfmt.h:609
#define AV_PIX_FMT_YUVA420P16
Definition pixfmt.h:601
#define AV_PIX_FMT_P216
Definition pixfmt.h:626
#define AV_PIX_FMT_GBRAP32
Definition pixfmt.h:572
#define AV_PIX_FMT_YUV420P12
Definition pixfmt.h:549
#define AV_PIX_FMT_YUVA420P10
Definition pixfmt.h:596
#define AV_PIX_FMT_YUV422P12
Definition pixfmt.h:550
#define AV_PIX_FMT_Y210
Definition pixfmt.h:612
#define AV_PIX_FMT_GBRAP14
Definition pixfmt.h:570
#define AV_PIX_FMT_P010
Definition pixfmt.h:608
#define AV_PIX_FMT_P016
Definition pixfmt.h:610
#define AV_PIX_FMT_GBRP10
Definition pixfmt.h:564
#define AV_PIX_FMT_GRAY32
Definition pixfmt.h:529
#define AV_PIX_FMT_RGBA128
Definition pixfmt.h:636
#define AV_PIX_FMT_YUV422P10
Definition pixfmt.h:546
#define AV_PIX_FMT_GRAY12
Definition pixfmt.h:526
#define AV_PIX_FMT_GBRAPF16
Definition pixfmt.h:583
#define AV_PIX_FMT_RGBA64
Definition pixfmt.h:535
#define AV_PIX_FMT_XV30
Definition pixfmt.h:615
#define AV_PIX_FMT_GBRP12
Definition pixfmt.h:565
#define AV_PIX_FMT_RGB48
Definition pixfmt.h:531
#define AV_PIX_FMT_BAYER_RGGB16
Definition pixfmt.h:578
#define AV_PIX_FMT_YUVA422P10
Definition pixfmt.h:597
#define AV_PIX_FMT_X2RGB10
Definition pixfmt.h:619
#define AV_PIX_FMT_GRAYF32
Definition pixfmt.h:588
#define AV_PIX_FMT_XV48
Definition pixfmt.h:617
#define AV_PIX_FMT_P410
Definition pixfmt.h:623
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ AV_PIX_FMT_UYVA
packed UYVA 4:4:4:4, 32bpp (1 Cr & Cb sample per 1x1 Y & A samples), UYVAUYVA...
Definition pixfmt.h:444
@ AV_PIX_FMT_NV12
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition pixfmt.h:96
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition pixfmt.h:75
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition pixfmt.h:73
@ AV_PIX_FMT_BGR0
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
Definition pixfmt.h:265
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition pixfmt.h:77
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition pixfmt.h:102
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition pixfmt.h:81
@ AV_PIX_FMT_UYVY422
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
Definition pixfmt.h:88
@ AV_PIX_FMT_ABGR
packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
Definition pixfmt.h:101
@ AV_PIX_FMT_YUVA420P
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
Definition pixfmt.h:108
@ AV_PIX_FMT_NV24
planar YUV 4:4:4, 24bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition pixfmt.h:371
@ AV_PIX_FMT_0BGR
packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined
Definition pixfmt.h:264
@ AV_PIX_FMT_NV16
interleaved chroma YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition pixfmt.h:198
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition pixfmt.h:100
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition pixfmt.h:78
@ AV_PIX_FMT_YUVA444P
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
Definition pixfmt.h:174
@ AV_PIX_FMT_GBRAP
planar GBRA 4:4:4:4 32bpp
Definition pixfmt.h:212
@ AV_PIX_FMT_RGB0
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
Definition pixfmt.h:263
@ AV_PIX_FMT_YUVA422P
planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)
Definition pixfmt.h:173
@ AV_PIX_FMT_YUYV422
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Definition pixfmt.h:74
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition pixfmt.h:76
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
Definition pixfmt.h:165
#define AV_PIX_FMT_YUVA422P12
Definition pixfmt.h:599
#define AV_PIX_FMT_RGB96
Definition pixfmt.h:635
#define AV_PIX_FMT_P416
Definition pixfmt.h:627
#define AV_PIX_FMT_X2BGR10
Definition pixfmt.h:620
#define AV_PIX_FMT_BGR565
Definition pixfmt.h:537
#define AV_PIX_FMT_Y216
Definition pixfmt.h:614
#define AV_PIX_FMT_GRAY10
Definition pixfmt.h:525
#define AV_PIX_FMT_RGB565
Definition pixfmt.h:532
#define AV_PIX_FMT_GRAY14
Definition pixfmt.h:527
#define AV_PIX_FMT_GBRPF16
Definition pixfmt.h:582
#define AV_PIX_FMT_YUV422P16
Definition pixfmt.h:557
#define AV_PIX_FMT_GRAY16
Definition pixfmt.h:528
#define AV_PIX_FMT_GBRAP10
Definition pixfmt.h:568
#define AV_PIX_FMT_Y212
Definition pixfmt.h:613
#define AV_PIX_FMT_YUVA444P16
Definition pixfmt.h:603
#define AV_PIX_FMT_YUVA422P16
Definition pixfmt.h:602
#define AV_PIX_FMT_GBRP16
Definition pixfmt.h:567
#define AV_PIX_FMT_XV36
Definition pixfmt.h:616
#define AV_PIX_FMT_GBRP14
Definition pixfmt.h:566
#define AV_PIX_FMT_YUVA444P12
Definition pixfmt.h:600
#define AV_PIX_FMT_GBRAPF32
Definition pixfmt.h:585
#define AV_PIX_FMT_YUV444P16
Definition pixfmt.h:558
#define AV_PIX_FMT_YUV444P10
Definition pixfmt.h:548
void av_refstruct_unref(void *objp)
Decrement the reference count of the underlying object and automatically free the object if there are...
Definition refstruct.c:120
void * av_refstruct_pool_get(AVRefStructPool *pool)
Get an object from the pool, reusing an old one from the pool when available.
Definition refstruct.c:297
void * av_refstruct_ref(void *obj)
Create a new reference to an object managed via this API, i.e.
Definition refstruct.c:140
static void av_refstruct_pool_uninit(AVRefStructPool **poolp)
Mark the pool as being available for freeing.
Definition refstruct.h:292
static void * av_refstruct_alloc_ext(size_t size, unsigned flags, void *opaque, void(*free_cb)(AVRefStructOpaque opaque, void *obj))
A wrapper around av_refstruct_alloc_ext_c() for the common case of a non-const qualified opaque.
Definition refstruct.h:94
static AVRefStructPool * av_refstruct_pool_alloc_ext(size_t size, unsigned flags, void *opaque, int(*init_cb)(AVRefStructOpaque opaque, void *obj), void(*reset_cb)(AVRefStructOpaque opaque, void *obj), void(*free_entry_cb)(AVRefStructOpaque opaque, void *obj), void(*free_cb)(AVRefStructOpaque opaque))
A wrapper around av_refstruct_pool_alloc_ext_c() for the common case of a non-const qualified opaque.
Definition refstruct.h:258
#define FF_ARRAY_ELEMS(a)
A reference to a data buffer.
Definition buffer.h:82
uint8_t * data
The data buffer.
Definition buffer.h:90
size_t size
Size of data in bytes.
Definition buffer.h:94
Describe the class of an AVClass context structure.
Definition log.h:76
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition frame.h:493
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition hwcontext.h:63
This struct describes a set or pool of "hardware" frames (i.e.
Definition hwcontext.h:118
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition hwcontext.h:153
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition hwcontext.h:213
AVRefStructPool is an API for a thread-safe pool of objects managed via the RefStruct API.
Definition refstruct.c:183
VkImageLayout layout[AV_NUM_DATA_POINTERS]
VkSemaphore sem[AV_NUM_DATA_POINTERS]
Synchronization timeline semaphores, one for each VkImage.
uint32_t queue_family[AV_NUM_DATA_POINTERS]
Queue family of the images.
VkAccessFlagBits2 access[AV_NUM_DATA_POINTERS]
Updated after every barrier.
uint64_t sem_value[AV_NUM_DATA_POINTERS]
Up to date semaphore value at which each image becomes accessible.
VkImage img[AV_NUM_DATA_POINTERS]
Vulkan images to which the memory is bound to.
Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
Allocated as AVHWFramesContext.hwctx, used to set pool-specific options.
VkImageUsageFlagBits usage
Defines extra usage of output frames.
void(* lock_frame)(struct AVHWFramesContext *fc, AVVkFrame *vkf)
Locks a frame, preventing other threads from changing frame properties.
void(* unlock_frame)(struct AVHWFramesContext *fc, AVVkFrame *vkf)
Similar to lock_frame(), unlocks a frame.
VkBuffer buf
Definition vulkan.h:95
VkDeviceAddress address
Definition vulkan.h:99
size_t size
Definition vulkan.h:98
VkMemoryPropertyFlagBits flags
Definition vulkan.h:97
AVBufferRef * host_ref
Definition vulkan.h:111
size_t virtual_offset
Definition vulkan.h:108
VkDeviceMemory mem
Definition vulkan.h:96
uint8_t * mapped_mem
Definition vulkan.h:103
VkAccessFlagBits access_dst[FF_VK_EXEC_MAX_FRAME_DEPS]
Definition vulkan.h:189
AVBufferRef * buf_deps[FF_VK_EXEC_MAX_BUF_DEPS]
Definition vulkan.h:160
uint32_t idx
Definition vulkan.h:129
uint8_t frame_update[FF_VK_EXEC_MAX_FRAME_DEPS]
Definition vulkan.h:192
void * query_data
Definition vulkan.h:156
uint64_t sem_value
Definition vulkan.h:147
VkSemaphoreSubmitInfo sem_wait[FF_VK_EXEC_MAX_SEM_OPS]
Definition vulkan.h:179
FFVkExecObjDep obj_deps[FF_VK_EXEC_MAX_BUF_DEPS]
Definition vulkan.h:168
VkQueue queue
Definition vulkan.h:137
AVFrame * sw_frame_deps[FF_VK_EXEC_MAX_SW_FRAME_DEPS]
Definition vulkan.h:176
pthread_mutex_t lock
Definition vulkan.h:151
uint32_t queue_family_dst[FF_VK_EXEC_MAX_FRAME_DEPS]
Definition vulkan.h:191
uint64_t * sem_sig_val_dst[FF_VK_EXEC_MAX_SEM_OPS]
Definition vulkan.h:185
VkSemaphoreSubmitInfo sem_sig[FF_VK_EXEC_MAX_SEM_OPS]
Definition vulkan.h:182
const struct FFVkExecPool * parent
Definition vulkan.h:130
int had_submission
Definition vulkan.h:134
int sem_sig_val_dst_cnt
Definition vulkan.h:186
int nb_sw_frame_deps
Definition vulkan.h:177
VkSemaphore sem
Definition vulkan.h:146
uint8_t frame_locked[FF_VK_EXEC_MAX_FRAME_DEPS]
Definition vulkan.h:188
void * refstruct_deps[FF_VK_EXEC_MAX_BUF_DEPS]
Definition vulkan.h:164
VkImageLayout layout_dst[FF_VK_EXEC_MAX_FRAME_DEPS]
Definition vulkan.h:190
AVFrame * frame_deps[FF_VK_EXEC_MAX_FRAME_DEPS]
Definition vulkan.h:172
int nb_frame_deps
Definition vulkan.h:173
int nb_refstruct_deps
Definition vulkan.h:165
VkCommandBuffer buf
Definition vulkan.h:142
VkObjectType type
Definition vulkan.h:125
uint64_t obj
Definition vulkan.h:124
FFVulkanShaderData reg_shd[FF_VK_MAX_SHADERS]
Definition vulkan.h:290
int query_results
Definition vulkan.h:282
atomic_uint_least64_t idx
Definition vulkan.h:274
VkQueryPool query_pool
Definition vulkan.h:280
FFVkExecContext * contexts
Definition vulkan.h:273
VkCommandBuffer * cmd_bufs
Definition vulkan.h:277
int pool_size
Definition vulkan.h:278
int nb_queries
Definition vulkan.h:286
VkCommandPool * cmd_buf_pools
Definition vulkan.h:276
int nb_reg_shd
Definition vulkan.h:291
void * query_data
Definition vulkan.h:281
size_t qd_size
Definition vulkan.h:287
int query_status_stride
Definition vulkan.h:285
int query_statuses
Definition vulkan.h:283
int query_64bit
Definition vulkan.h:284
PFN_vkDestroyImageView destroy_image_view
Definition vulkan.h:557
const VkAllocationCallbacks * alloc
Definition vulkan.h:556
VkImageView views[AV_NUM_DATA_POINTERS]
Definition vulkan.h:559
VkDevice dev
Definition vulkan.h:555
VkDescriptorSetLayoutBinding binding[FF_VK_MAX_DESCRIPTOR_BINDINGS]
Definition vulkan.h:201
VkDescriptorSet * desc_sets
Definition vulkan.h:268
FFVulkanShader * shd
Definition vulkan.h:260
VkDescriptorPool desc_pool
Definition vulkan.h:269
VkPipelineLayout pipeline_layout
Definition vulkan.h:233
FFVulkanDescriptorSet desc_set[FF_VK_MAX_DESCRIPTOR_SETS]
Definition vulkan.h:240
VkPipeline pipeline
Definition vulkan.h:230
VkPipelineShaderStageRequiredSubgroupSizeCreateInfo subgroup_info
Definition vulkan.h:226
VkPipelineStageFlags stage
Definition vulkan.h:222
int push_consts_num
Definition vulkan.h:237
VkSpecializationInfo * specialization_info
Definition vulkan.h:216
int nb_descriptor_sets
Definition vulkan.h:241
int precompiled
Definition vulkan.h:215
VkPushConstantRange push_consts[FF_VK_MAX_PUSH_CONSTS]
Definition vulkan.h:236
uint32_t lg_size[3]
Definition vulkan.h:219
const char * name
Definition vulkan.h:212
VkDescriptorSetLayout desc_layout[FF_VK_MAX_DESCRIPTOR_SETS]
Definition vulkan.h:244
VkPipelineBindPoint bind_point
Definition vulkan.h:223
VkDescriptorPoolSize desc_pool_size[FF_VK_MAX_DESCRIPTOR_TYPES]
Definition vulkan.h:248
int nb_desc_pool_size
Definition vulkan.h:249
VkShaderEXT object
Definition vulkan.h:229
#define av_free(p)
#define av_malloc_array(a, b)
#define av_freep(p)
#define av_log(a,...)
#define src
Definition vp8dsp.c:248
static int ref[MAX_W *MAX_W]
#define height
Definition dsp.h:89
#define width
Definition dsp.h:89
static void set(uint8_t *a[], int ch, int index, int ch_count, enum AVSampleFormat f, double v)
Definition swresample.c:55
int size
RefStruct is an API for creating reference-counted objects with minimal overhead.
Definition refstruct.h:58
#define img
static int mod(int a, int b)
Modulo operation with only positive remainders.
Definition vf_v360.c:755
static unsigned int seed
Definition videogen.c:78
int len
FFVkShaderRepFormat
Returns the format to use for images in shaders.
Definition vulkan.h:437
@ FF_VK_REP_UINT
Definition vulkan.h:445
@ FF_VK_REP_INT
Definition vulkan.h:443
@ FF_VK_REP_NATIVE
Definition vulkan.h:439
@ FF_VK_REP_FLOAT
Definition vulkan.h:441
#define FF_VK_STRUCT_EXT(CTX, BASE, STRUCT_P, EXT_FLAG, TYPE)
Definition vulkan.h:387
#define FF_VK_EXEC_MAX_SEM_OPS
Definition vulkan.h:118
static const void * ff_vk_find_struct(const void *chain, VkStructureType stype)
Definition vulkan.h:365
#define FF_VK_MAX_SHADERS
Definition vulkan.h:79
static int ff_vk_unmap_buffer(FFVulkanContext *s, FFVkBuffer *buf, int flush)
Definition vulkan.h:649
#define FF_VK_EXEC_MAX_FRAME_DEPS
Definition vulkan.h:115
static int ff_vk_count_images(AVVkFrame *f)
Definition vulkan.h:356
#define FF_VK_MAX_PUSH_CONSTS
Definition vulkan.h:78
#define FF_VK_MAX_DESCRIPTOR_BINDINGS
Definition vulkan.h:76
#define FF_VK_EXEC_MAX_BUF_DEPS
Definition vulkan.h:116
#define FF_VK_EXEC_MAX_SW_FRAME_DEPS
Definition vulkan.h:117
#define FF_VK_MAX_DESCRIPTOR_SETS
Definition vulkan.h:75
static int ff_vk_map_buffer(FFVulkanContext *s, FFVkBuffer *buf, uint8_t **mem, int invalidate)
Definition vulkan.h:642
#define FF_VK_MAX_DESCRIPTOR_TYPES
Definition vulkan.h:77
#define FF_VK_EXT_SHADER_OBJECT
#define FF_VK_EXT_VIDEO_QUEUE
#define FF_VK_EXT_UNIFIED_IMAGE_LAYOUTS
#define FF_VK_EXT_COOP_MATRIX
#define FF_VK_EXT_INTERNAL_QUEUE_SYNC
#define FF_VK_EXT_NO_FLAG
#define FF_VK_EXT_OPTICAL_FLOW
#define FF_VK_EXT_PUSH_DESCRIPTOR
#define FF_VK_EXT_LONG_VECTOR
#define FF_VK_EXT_MAINTENANCE_9
#define FF_VK_EXT_HOST_IMAGE_COPY
#define FF_VK_EXT_ATOMIC_FLOAT
#define FF_VK_EXT_EXTERNAL_HOST_MEMORY
static uint64_t ff_vk_extensions_to_mask(const char *const *extensions, int nb_extensions)
static int ff_vk_load_functions(AVHWDeviceContext *ctx, FFVulkanFunctions *vk, uint64_t extensions_mask, int has_inst, int has_dev)
Function loader.
static int pthread_mutex_trylock(pthread_mutex_t *m)
#define atomic_fetch_add(object, operand)
Definition stdatomic.h:137
static int ff_zlib_expand(void *ctx, uint8_t **out, size_t *out_len, const uint8_t *src, int src_len)
Definition zlib_utils.h:30