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