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 "avassert.h"
22 #include "mem.h"
23 
24 #include "vulkan.h"
25 
26 const VkComponentMapping ff_comp_identity_map = {
27  .r = VK_COMPONENT_SWIZZLE_IDENTITY,
28  .g = VK_COMPONENT_SWIZZLE_IDENTITY,
29  .b = VK_COMPONENT_SWIZZLE_IDENTITY,
30  .a = VK_COMPONENT_SWIZZLE_IDENTITY,
31 };
32 
33 /* Converts return values to strings */
34 const char *ff_vk_ret2str(VkResult res)
35 {
36 #define CASE(VAL) case VAL: return #VAL
37  switch (res) {
38  CASE(VK_SUCCESS);
39  CASE(VK_NOT_READY);
40  CASE(VK_TIMEOUT);
41  CASE(VK_EVENT_SET);
42  CASE(VK_EVENT_RESET);
43  CASE(VK_INCOMPLETE);
44  CASE(VK_ERROR_OUT_OF_HOST_MEMORY);
45  CASE(VK_ERROR_OUT_OF_DEVICE_MEMORY);
46  CASE(VK_ERROR_INITIALIZATION_FAILED);
47  CASE(VK_ERROR_DEVICE_LOST);
48  CASE(VK_ERROR_MEMORY_MAP_FAILED);
49  CASE(VK_ERROR_LAYER_NOT_PRESENT);
50  CASE(VK_ERROR_EXTENSION_NOT_PRESENT);
51  CASE(VK_ERROR_FEATURE_NOT_PRESENT);
52  CASE(VK_ERROR_INCOMPATIBLE_DRIVER);
53  CASE(VK_ERROR_TOO_MANY_OBJECTS);
54  CASE(VK_ERROR_FORMAT_NOT_SUPPORTED);
55  CASE(VK_ERROR_FRAGMENTED_POOL);
56  CASE(VK_ERROR_UNKNOWN);
57  CASE(VK_ERROR_OUT_OF_POOL_MEMORY);
58  CASE(VK_ERROR_INVALID_EXTERNAL_HANDLE);
59  CASE(VK_ERROR_FRAGMENTATION);
60  CASE(VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS);
61  CASE(VK_PIPELINE_COMPILE_REQUIRED);
62  CASE(VK_ERROR_SURFACE_LOST_KHR);
63  CASE(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR);
64  CASE(VK_SUBOPTIMAL_KHR);
65  CASE(VK_ERROR_OUT_OF_DATE_KHR);
66  CASE(VK_ERROR_INCOMPATIBLE_DISPLAY_KHR);
67  CASE(VK_ERROR_VALIDATION_FAILED_EXT);
68  CASE(VK_ERROR_INVALID_SHADER_NV);
69  CASE(VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR);
70  CASE(VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR);
71  CASE(VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR);
72  CASE(VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR);
73  CASE(VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR);
74  CASE(VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT);
75  CASE(VK_ERROR_NOT_PERMITTED_KHR);
76  CASE(VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT);
77  CASE(VK_THREAD_IDLE_KHR);
78  CASE(VK_THREAD_DONE_KHR);
79  CASE(VK_OPERATION_DEFERRED_KHR);
80  CASE(VK_OPERATION_NOT_DEFERRED_KHR);
81  default: return "Unknown error";
82  }
83 #undef CASE
84 }
85 
87 {
88  FFVulkanFunctions *vk = &s->vkfn;
89 
90  s->hprops = (VkPhysicalDeviceExternalMemoryHostPropertiesEXT) {
91  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT,
92  };
93  s->coop_matrix_props = (VkPhysicalDeviceCooperativeMatrixPropertiesKHR) {
94  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_KHR,
95  .pNext = &s->hprops,
96  };
97  s->subgroup_props = (VkPhysicalDeviceSubgroupSizeControlProperties) {
98  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES,
99  .pNext = &s->coop_matrix_props,
100  };
101  s->desc_buf_props = (VkPhysicalDeviceDescriptorBufferPropertiesEXT) {
102  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_PROPERTIES_EXT,
103  .pNext = &s->subgroup_props,
104  };
105  s->driver_props = (VkPhysicalDeviceDriverProperties) {
106  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES,
107  .pNext = &s->desc_buf_props,
108  };
109  s->props = (VkPhysicalDeviceProperties2) {
110  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
111  .pNext = &s->driver_props,
112  };
113 
114  s->atomic_float_feats = (VkPhysicalDeviceShaderAtomicFloatFeaturesEXT) {
115  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT,
116  };
117  s->feats_12 = (VkPhysicalDeviceVulkan12Features) {
118  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
119  .pNext = &s->atomic_float_feats,
120  };
121  s->feats = (VkPhysicalDeviceFeatures2) {
122  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
123  .pNext = &s->feats_12,
124  };
125 
126  vk->GetPhysicalDeviceProperties2(s->hwctx->phys_dev, &s->props);
127  vk->GetPhysicalDeviceMemoryProperties(s->hwctx->phys_dev, &s->mprops);
128  vk->GetPhysicalDeviceFeatures2(s->hwctx->phys_dev, &s->feats);
129 
130  if (s->qf_props)
131  return 0;
132 
133  vk->GetPhysicalDeviceQueueFamilyProperties2(s->hwctx->phys_dev, &s->tot_nb_qfs, NULL);
134 
135  s->qf_props = av_calloc(s->tot_nb_qfs, sizeof(*s->qf_props));
136  if (!s->qf_props)
137  return AVERROR(ENOMEM);
138 
139  s->query_props = av_calloc(s->tot_nb_qfs, sizeof(*s->query_props));
140  if (!s->qf_props) {
141  av_freep(&s->qf_props);
142  return AVERROR(ENOMEM);
143  }
144 
145  s->video_props = av_calloc(s->tot_nb_qfs, sizeof(*s->video_props));
146  if (!s->video_props) {
147  av_freep(&s->qf_props);
148  av_freep(&s->query_props);
149  return AVERROR(ENOMEM);
150  }
151 
152  for (uint32_t i = 0; i < s->tot_nb_qfs; i++) {
153  s->query_props[i] = (VkQueueFamilyQueryResultStatusPropertiesKHR) {
154  .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_KHR,
155  };
156  s->video_props[i] = (VkQueueFamilyVideoPropertiesKHR) {
157  .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR,
158  .pNext = &s->query_props[i],
159  };
160  s->qf_props[i] = (VkQueueFamilyProperties2) {
161  .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2,
162  .pNext = &s->video_props[i],
163  };
164  }
165 
166  vk->GetPhysicalDeviceQueueFamilyProperties2(s->hwctx->phys_dev, &s->tot_nb_qfs, s->qf_props);
167 
168  if (s->extensions & FF_VK_EXT_COOP_MATRIX) {
169  vk->GetPhysicalDeviceCooperativeMatrixPropertiesKHR(s->hwctx->phys_dev,
170  &s->coop_mat_props_nb, NULL);
171 
172  if (s->coop_mat_props_nb) {
173  s->coop_mat_props = av_malloc_array(s->coop_mat_props_nb,
174  sizeof(VkCooperativeMatrixPropertiesKHR));
175  for (int i = 0; i < s->coop_mat_props_nb; i++) {
176  s->coop_mat_props[i] = (VkCooperativeMatrixPropertiesKHR) {
177  .sType = VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_KHR,
178  };
179  }
180 
181  vk->GetPhysicalDeviceCooperativeMatrixPropertiesKHR(s->hwctx->phys_dev,
182  &s->coop_mat_props_nb,
183  s->coop_mat_props);
184  }
185  }
186 
187  return 0;
188 }
189 
190 static int vk_qf_get_index(FFVulkanContext *s, VkQueueFlagBits dev_family, int *nb)
191 {
192  int ret, num;
193 
194  switch (dev_family) {
195  case VK_QUEUE_GRAPHICS_BIT:
196  ret = s->hwctx->queue_family_index;
197  num = s->hwctx->nb_graphics_queues;
198  break;
199  case VK_QUEUE_COMPUTE_BIT:
200  ret = s->hwctx->queue_family_comp_index;
201  num = s->hwctx->nb_comp_queues;
202  break;
203  case VK_QUEUE_TRANSFER_BIT:
204  ret = s->hwctx->queue_family_tx_index;
205  num = s->hwctx->nb_tx_queues;
206  break;
207  case VK_QUEUE_VIDEO_ENCODE_BIT_KHR:
208  ret = s->hwctx->queue_family_encode_index;
209  num = s->hwctx->nb_encode_queues;
210  break;
211  case VK_QUEUE_VIDEO_DECODE_BIT_KHR:
212  ret = s->hwctx->queue_family_decode_index;
213  num = s->hwctx->nb_decode_queues;
214  break;
215  default:
216  av_assert0(0); /* Should never happen */
217  }
218 
219  if (nb)
220  *nb = num;
221 
222  return ret;
223 }
224 
226  VkQueueFlagBits dev_family)
227 {
228  /* Fill in queue families from context if not done yet */
229  if (!s->nb_qfs) {
230  s->nb_qfs = 0;
231 
232  /* Simply fills in all unique queues into s->qfs */
233  if (s->hwctx->queue_family_index >= 0)
234  s->qfs[s->nb_qfs++] = s->hwctx->queue_family_index;
235  if (!s->nb_qfs || s->qfs[0] != s->hwctx->queue_family_tx_index)
236  s->qfs[s->nb_qfs++] = s->hwctx->queue_family_tx_index;
237  if (!s->nb_qfs || (s->qfs[0] != s->hwctx->queue_family_comp_index &&
238  s->qfs[1] != s->hwctx->queue_family_comp_index))
239  s->qfs[s->nb_qfs++] = s->hwctx->queue_family_comp_index;
240  if (s->hwctx->queue_family_decode_index >= 0 &&
241  (s->qfs[0] != s->hwctx->queue_family_decode_index &&
242  s->qfs[1] != s->hwctx->queue_family_decode_index &&
243  s->qfs[2] != s->hwctx->queue_family_decode_index))
244  s->qfs[s->nb_qfs++] = s->hwctx->queue_family_decode_index;
245  if (s->hwctx->queue_family_encode_index >= 0 &&
246  (s->qfs[0] != s->hwctx->queue_family_encode_index &&
247  s->qfs[1] != s->hwctx->queue_family_encode_index &&
248  s->qfs[2] != s->hwctx->queue_family_encode_index &&
249  s->qfs[3] != s->hwctx->queue_family_encode_index))
250  s->qfs[s->nb_qfs++] = s->hwctx->queue_family_encode_index;
251  }
252 
253  return (qf->queue_family = vk_qf_get_index(s, dev_family, &qf->nb_queues));
254 }
255 
257 {
258  FFVulkanFunctions *vk = &s->vkfn;
259 
260  for (int i = 0; i < pool->pool_size; i++) {
261  FFVkExecContext *e = &pool->contexts[i];
262 
263  if (e->fence) {
264  vk->WaitForFences(s->hwctx->act_dev, 1, &e->fence, VK_TRUE, UINT64_MAX);
265  vk->DestroyFence(s->hwctx->act_dev, e->fence, s->hwctx->alloc);
266  }
268 
270 
271  av_free(e->frame_deps);
272  av_free(e->buf_deps);
274  av_free(e->layout_dst);
275  av_free(e->access_dst);
276  av_free(e->frame_update);
277  av_free(e->frame_locked);
278  av_free(e->sem_sig);
280  av_free(e->sem_wait);
281  }
282 
283  if (pool->cmd_bufs)
284  vk->FreeCommandBuffers(s->hwctx->act_dev, pool->cmd_buf_pool,
285  pool->pool_size, pool->cmd_bufs);
286  if (pool->cmd_buf_pool)
287  vk->DestroyCommandPool(s->hwctx->act_dev, pool->cmd_buf_pool, s->hwctx->alloc);
288  if (pool->query_pool)
289  vk->DestroyQueryPool(s->hwctx->act_dev, pool->query_pool, s->hwctx->alloc);
290 
291  av_free(pool->query_data);
292  av_free(pool->cmd_bufs);
293  av_free(pool->contexts);
294 }
295 
297  FFVkExecPool *pool, int nb_contexts,
298  int nb_queries, VkQueryType query_type, int query_64bit,
299  const void *query_create_pnext)
300 {
301  int err;
302  VkResult ret;
303  FFVulkanFunctions *vk = &s->vkfn;
304 
305  VkCommandPoolCreateInfo cqueue_create;
306  VkCommandBufferAllocateInfo cbuf_create;
307 
308  /* Create command pool */
309  cqueue_create = (VkCommandPoolCreateInfo) {
310  .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
311  .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT |
312  VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
313  .queueFamilyIndex = qf->queue_family,
314  };
315  ret = vk->CreateCommandPool(s->hwctx->act_dev, &cqueue_create,
316  s->hwctx->alloc, &pool->cmd_buf_pool);
317  if (ret != VK_SUCCESS) {
318  av_log(s, AV_LOG_ERROR, "Command pool creation failure: %s\n",
319  ff_vk_ret2str(ret));
320  err = AVERROR_EXTERNAL;
321  goto fail;
322  }
323 
324  /* Allocate space for command buffers */
325  pool->cmd_bufs = av_malloc(nb_contexts*sizeof(*pool->cmd_bufs));
326  if (!pool->cmd_bufs) {
327  err = AVERROR(ENOMEM);
328  goto fail;
329  }
330 
331  /* Allocate command buffer */
332  cbuf_create = (VkCommandBufferAllocateInfo) {
333  .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
334  .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
335  .commandPool = pool->cmd_buf_pool,
336  .commandBufferCount = nb_contexts,
337  };
338  ret = vk->AllocateCommandBuffers(s->hwctx->act_dev, &cbuf_create,
339  pool->cmd_bufs);
340  if (ret != VK_SUCCESS) {
341  av_log(s, AV_LOG_ERROR, "Command buffer alloc failure: %s\n",
342  ff_vk_ret2str(ret));
343  err = AVERROR_EXTERNAL;
344  goto fail;
345  }
346 
347  /* Query pool */
348  if (nb_queries) {
349  VkQueryPoolCreateInfo query_pool_info = {
350  .sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
351  .pNext = query_create_pnext,
352  .queryType = query_type,
353  .queryCount = nb_queries*nb_contexts,
354  };
355  ret = vk->CreateQueryPool(s->hwctx->act_dev, &query_pool_info,
356  s->hwctx->alloc, &pool->query_pool);
357  if (ret != VK_SUCCESS) {
358  av_log(s, AV_LOG_ERROR, "Query pool alloc failure: %s\n",
359  ff_vk_ret2str(ret));
360  err = AVERROR_EXTERNAL;
361  goto fail;
362  }
363 
364  pool->nb_queries = nb_queries;
365  pool->query_status_stride = 2;
366  pool->query_results = nb_queries;
367  pool->query_statuses = 0; /* if radv supports it, nb_queries; */
368 
369 #if 0 /* CONFIG_VULKAN_ENCODE */
370  /* Video encode quieries produce two results per query */
371  if (query_type == VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR) {
372  pool->query_status_stride = 3; /* skip,skip,result,skip,skip,result */
373  pool->query_results *= 2;
374  } else
375 #endif
376  if (query_type == VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR) {
377  pool->query_status_stride = 1;
378  pool->query_results = 0;
379  pool->query_statuses = nb_queries;
380  }
381 
382  pool->qd_size = (pool->query_results + pool->query_statuses)*(query_64bit ? 8 : 4);
383 
384  /* Allocate space for the query data */
385  pool->query_data = av_calloc(nb_contexts, pool->qd_size);
386  if (!pool->query_data) {
387  err = AVERROR(ENOMEM);
388  goto fail;
389  }
390  }
391 
392  /* Allocate space for the contexts */
393  pool->contexts = av_calloc(nb_contexts, sizeof(*pool->contexts));
394  if (!pool->contexts) {
395  err = AVERROR(ENOMEM);
396  goto fail;
397  }
398 
399  pool->pool_size = nb_contexts;
400 
401  /* Init contexts */
402  for (int i = 0; i < pool->pool_size; i++) {
403  FFVkExecContext *e = &pool->contexts[i];
404  VkFenceCreateInfo fence_create = {
405  .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
406  .flags = VK_FENCE_CREATE_SIGNALED_BIT,
407  };
408 
409  /* Mutex */
410  err = pthread_mutex_init(&e->lock, NULL);
411  if (err != 0)
412  return AVERROR(err);
413 
414  /* Fence */
415  ret = vk->CreateFence(s->hwctx->act_dev, &fence_create, s->hwctx->alloc,
416  &e->fence);
417  if (ret != VK_SUCCESS) {
418  av_log(s, AV_LOG_ERROR, "Failed to create submission fence: %s\n",
419  ff_vk_ret2str(ret));
420  return AVERROR_EXTERNAL;
421  }
422 
423  e->idx = i;
424  e->parent = pool;
425 
426  /* Query data */
427  e->query_data = ((uint8_t *)pool->query_data) + pool->qd_size*i;
428  e->query_idx = nb_queries*i;
429 
430  /* Command buffer */
431  e->buf = pool->cmd_bufs[i];
432 
433  /* Queue index distribution */
434  e->qi = i % qf->nb_queues;
435  e->qf = qf->queue_family;
436  vk->GetDeviceQueue(s->hwctx->act_dev, qf->queue_family,
437  e->qi, &e->queue);
438  }
439 
440  return 0;
441 
442 fail:
443  ff_vk_exec_pool_free(s, pool);
444  return err;
445 }
446 
448  void **data, int64_t *status)
449 {
450  VkResult ret;
451  FFVulkanFunctions *vk = &s->vkfn;
452  const FFVkExecPool *pool = e->parent;
453 
454  int32_t *res32 = e->query_data;
455  int64_t *res64 = e->query_data;
456  int64_t res = 0;
457  VkQueryResultFlags qf = 0;
458 
459  if (!e->had_submission)
460  return VK_NOT_READY;
461 
462  qf |= pool->query_64bit ?
463  VK_QUERY_RESULT_64_BIT : 0x0;
464  qf |= pool->query_statuses ?
465  VK_QUERY_RESULT_WITH_STATUS_BIT_KHR : 0x0;
466 
467  ret = vk->GetQueryPoolResults(s->hwctx->act_dev, pool->query_pool,
468  e->query_idx,
469  pool->nb_queries,
470  pool->qd_size, e->query_data,
471  pool->query_64bit ? 8 : 4, qf);
472  if (ret != VK_SUCCESS)
473  return ret;
474 
475  if (pool->query_statuses && pool->query_64bit) {
476  for (int i = 0; i < pool->query_statuses; i++) {
477  res = (res64[i] < res) || (res >= 0 && res64[i] > res) ?
478  res64[i] : res;
479  res64 += pool->query_status_stride;
480  }
481  } else if (pool->query_statuses) {
482  for (int i = 0; i < pool->query_statuses; i++) {
483  res = (res32[i] < res) || (res >= 0 && res32[i] > res) ?
484  res32[i] : res;
485  res32 += pool->query_status_stride;
486  }
487  }
488 
489  if (data)
490  *data = e->query_data;
491  if (status)
492  *status = res;
493 
494  return VK_SUCCESS;
495 }
496 
498 {
499  uint32_t idx = pool->idx++;
500  idx %= pool->pool_size;
501  return &pool->contexts[idx];
502 }
503 
505 {
506  FFVulkanFunctions *vk = &s->vkfn;
508  vk->WaitForFences(s->hwctx->act_dev, 1, &e->fence, VK_TRUE, UINT64_MAX);
511 }
512 
514 {
515  VkResult ret;
516  FFVulkanFunctions *vk = &s->vkfn;
517  const FFVkExecPool *pool = e->parent;
518 
519  VkCommandBufferBeginInfo cmd_start = {
520  .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
521  .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
522  };
523 
524  /* Wait for the fence to be signalled */
525  vk->WaitForFences(s->hwctx->act_dev, 1, &e->fence, VK_TRUE, UINT64_MAX);
526 
527  /* vkResetFences is defined as being host-synchronized */
529  vk->ResetFences(s->hwctx->act_dev, 1, &e->fence);
531 
532  /* Discard queue dependencies */
534 
535  ret = vk->BeginCommandBuffer(e->buf, &cmd_start);
536  if (ret != VK_SUCCESS) {
537  av_log(s, AV_LOG_ERROR, "Failed to start command recoding: %s\n",
538  ff_vk_ret2str(ret));
539  return AVERROR_EXTERNAL;
540  }
541 
542  if (pool->nb_queries)
543  vk->CmdResetQueryPool(e->buf, pool->query_pool,
544  e->query_idx, pool->nb_queries);
545 
546  return 0;
547 }
548 
550 {
551  for (int j = 0; j < e->nb_buf_deps; j++)
552  av_buffer_unref(&e->buf_deps[j]);
553  e->nb_buf_deps = 0;
554 
555  for (int j = 0; j < e->nb_frame_deps; j++) {
556  AVFrame *f = e->frame_deps[j];
557  if (e->frame_locked[j]) {
558  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
559  AVVulkanFramesContext *vkfc = hwfc->hwctx;
560  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
561  vkfc->unlock_frame(hwfc, vkf);
562  e->frame_locked[j] = 0;
563  }
564  e->frame_update[j] = 0;
565  if (f->buf[0])
566  av_frame_free(&e->frame_deps[j]);
567  }
568  e->nb_frame_deps = 0;
569 
570  e->sem_wait_cnt = 0;
571  e->sem_sig_cnt = 0;
572  e->sem_sig_val_dst_cnt = 0;
573 }
574 
576  AVBufferRef **deps, int nb_deps, int ref)
577 {
579  (e->nb_buf_deps + nb_deps) * sizeof(*dst));
580  if (!dst) {
582  return AVERROR(ENOMEM);
583  }
584 
585  e->buf_deps = dst;
586 
587  for (int i = 0; i < nb_deps; i++) {
588  e->buf_deps[e->nb_buf_deps] = ref ? av_buffer_ref(deps[i]) : deps[i];
589  if (!e->buf_deps[e->nb_buf_deps]) {
591  return AVERROR(ENOMEM);
592  }
593  e->nb_buf_deps++;
594  }
595 
596  return 0;
597 }
598 
600  VkPipelineStageFlagBits2 wait_stage,
601  VkPipelineStageFlagBits2 signal_stage)
602 {
603  uint8_t *frame_locked;
604  uint8_t *frame_update;
605  AVFrame **frame_deps;
606  VkImageLayout *layout_dst;
607  uint32_t *queue_family_dst;
608  VkAccessFlagBits *access_dst;
609 
610  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
611  AVVulkanFramesContext *vkfc = hwfc->hwctx;
612  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
613  int nb_images = ff_vk_count_images(vkf);
614 
615  /* Don't add duplicates */
616  for (int i = 0; i < e->nb_frame_deps; i++)
617  if (e->frame_deps[i]->data[0] == f->data[0])
618  return 1;
619 
620 #define ARR_REALLOC(str, arr, alloc_s, cnt) \
621  do { \
622  arr = av_fast_realloc(str->arr, alloc_s, (cnt + 1)*sizeof(*arr)); \
623  if (!arr) { \
624  ff_vk_exec_discard_deps(s, e); \
625  return AVERROR(ENOMEM); \
626  } \
627  str->arr = arr; \
628  } while (0)
629 
630  ARR_REALLOC(e, layout_dst, &e->layout_dst_alloc, e->nb_frame_deps);
631  ARR_REALLOC(e, queue_family_dst, &e->queue_family_dst_alloc, e->nb_frame_deps);
632  ARR_REALLOC(e, access_dst, &e->access_dst_alloc, e->nb_frame_deps);
633 
634  ARR_REALLOC(e, frame_locked, &e->frame_locked_alloc_size, e->nb_frame_deps);
635  ARR_REALLOC(e, frame_update, &e->frame_update_alloc_size, e->nb_frame_deps);
636  ARR_REALLOC(e, frame_deps, &e->frame_deps_alloc_size, e->nb_frame_deps);
637 
638  e->frame_deps[e->nb_frame_deps] = f->buf[0] ? av_frame_clone(f) : f;
639  if (!e->frame_deps[e->nb_frame_deps]) {
641  return AVERROR(ENOMEM);
642  }
643 
644  vkfc->lock_frame(hwfc, vkf);
645  e->frame_locked[e->nb_frame_deps] = 1;
646  e->frame_update[e->nb_frame_deps] = 0;
647  e->nb_frame_deps++;
648 
649  for (int i = 0; i < nb_images; i++) {
650  VkSemaphoreSubmitInfo *sem_wait;
651  VkSemaphoreSubmitInfo *sem_sig;
652  uint64_t **sem_sig_val_dst;
653 
655  ARR_REALLOC(e, sem_sig, &e->sem_sig_alloc, e->sem_sig_cnt);
656  ARR_REALLOC(e, sem_sig_val_dst, &e->sem_sig_val_dst_alloc, e->sem_sig_val_dst_cnt);
657 
658  e->sem_wait[e->sem_wait_cnt++] = (VkSemaphoreSubmitInfo) {
659  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
660  .semaphore = vkf->sem[i],
661  .value = vkf->sem_value[i],
662  .stageMask = wait_stage,
663  };
664 
665  e->sem_sig[e->sem_sig_cnt++] = (VkSemaphoreSubmitInfo) {
666  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
667  .semaphore = vkf->sem[i],
668  .value = vkf->sem_value[i] + 1,
669  .stageMask = signal_stage,
670  };
671 
672  e->sem_sig_val_dst[e->sem_sig_val_dst_cnt] = &vkf->sem_value[i];
673  e->sem_sig_val_dst_cnt++;
674  }
675 
676  return 0;
677 }
678 
680  VkImageMemoryBarrier2 *bar, uint32_t *nb_img_bar)
681 {
682  int i;
683  for (i = 0; i < e->nb_frame_deps; i++)
684  if (e->frame_deps[i]->data[0] == f->data[0])
685  break;
686  av_assert0(i < e->nb_frame_deps);
687 
688  /* Don't update duplicates */
689  if (nb_img_bar && !e->frame_update[i])
690  (*nb_img_bar)++;
691 
692  e->queue_family_dst[i] = bar->dstQueueFamilyIndex;
693  e->access_dst[i] = bar->dstAccessMask;
694  e->layout_dst[i] = bar->newLayout;
695  e->frame_update[i] = 1;
696 }
697 
699  VkSemaphore *dst, uint64_t *dst_val,
700  AVFrame *f)
701 {
702  uint64_t **sem_sig_val_dst;
703  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
704 
705  /* Reject unknown frames */
706  int i;
707  for (i = 0; i < e->nb_frame_deps; i++)
708  if (e->frame_deps[i]->data[0] == f->data[0])
709  break;
710  if (i == e->nb_frame_deps)
711  return AVERROR(EINVAL);
712 
713  ARR_REALLOC(e, sem_sig_val_dst, &e->sem_sig_val_dst_alloc, e->sem_sig_val_dst_cnt);
714 
715  *dst = vkf->sem[0];
716  *dst_val = vkf->sem_value[0];
717 
718  e->sem_sig_val_dst[e->sem_sig_val_dst_cnt] = dst_val;
719  e->sem_sig_val_dst_cnt++;
720 
721  return 0;
722 }
723 
725 {
726  VkResult ret;
727  FFVulkanFunctions *vk = &s->vkfn;
728  VkCommandBufferSubmitInfo cmd_buf_info = (VkCommandBufferSubmitInfo) {
729  .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
730  .commandBuffer = e->buf,
731  };
732  VkSubmitInfo2 submit_info = (VkSubmitInfo2) {
733  .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
734  .pCommandBufferInfos = &cmd_buf_info,
735  .commandBufferInfoCount = 1,
736  .pWaitSemaphoreInfos = e->sem_wait,
737  .waitSemaphoreInfoCount = e->sem_wait_cnt,
738  .pSignalSemaphoreInfos = e->sem_sig,
739  .signalSemaphoreInfoCount = e->sem_sig_cnt,
740  };
741 
742  ret = vk->EndCommandBuffer(e->buf);
743  if (ret != VK_SUCCESS) {
744  av_log(s, AV_LOG_ERROR, "Unable to finish command buffer: %s\n",
745  ff_vk_ret2str(ret));
747  return AVERROR_EXTERNAL;
748  }
749 
750  s->hwctx->lock_queue(s->device, e->qf, e->qi);
751  ret = vk->QueueSubmit2(e->queue, 1, &submit_info, e->fence);
752  s->hwctx->unlock_queue(s->device, e->qf, e->qi);
753 
754  if (ret != VK_SUCCESS) {
755  av_log(s, AV_LOG_ERROR, "Unable to submit command buffer: %s\n",
756  ff_vk_ret2str(ret));
758  return AVERROR_EXTERNAL;
759  }
760 
761  for (int i = 0; i < e->sem_sig_val_dst_cnt; i++)
762  *e->sem_sig_val_dst[i] += 1;
763 
764  /* Unlock all frames */
765  for (int j = 0; j < e->nb_frame_deps; j++) {
766  if (e->frame_locked[j]) {
767  AVFrame *f = e->frame_deps[j];
768  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
769  AVVulkanFramesContext *vkfc = hwfc->hwctx;
770  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
771 
772  if (e->frame_update[j]) {
773  int nb_images = ff_vk_count_images(vkf);
774  for (int i = 0; i < nb_images; i++) {
775  vkf->layout[i] = e->layout_dst[j];
776  vkf->access[i] = e->access_dst[j];
777  vkf->queue_family[i] = e->queue_family_dst[j];
778  }
779  }
780  vkfc->unlock_frame(hwfc, vkf);
781  e->frame_locked[j] = 0;
782  }
783  }
784 
785  e->had_submission = 1;
786 
787  return 0;
788 }
789 
790 int ff_vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req,
791  VkMemoryPropertyFlagBits req_flags, void *alloc_extension,
792  VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem)
793 {
794  VkResult ret;
795  int index = -1;
796  FFVulkanFunctions *vk = &s->vkfn;
797 
798  VkMemoryAllocateInfo alloc_info = {
799  .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
800  .pNext = alloc_extension,
801  };
802 
803  /* Align if we need to */
804  if ((req_flags != UINT32_MAX) && req_flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
805  req->size = FFALIGN(req->size, s->props.properties.limits.minMemoryMapAlignment);
806 
807  alloc_info.allocationSize = req->size;
808 
809  /* The vulkan spec requires memory types to be sorted in the "optimal"
810  * order, so the first matching type we find will be the best/fastest one */
811  for (int i = 0; i < s->mprops.memoryTypeCount; i++) {
812  /* The memory type must be supported by the requirements (bitfield) */
813  if (!(req->memoryTypeBits & (1 << i)))
814  continue;
815 
816  /* The memory type flags must include our properties */
817  if ((req_flags != UINT32_MAX) &&
818  ((s->mprops.memoryTypes[i].propertyFlags & req_flags) != req_flags))
819  continue;
820 
821  /* Found a suitable memory type */
822  index = i;
823  break;
824  }
825 
826  if (index < 0) {
827  av_log(s->device, AV_LOG_ERROR, "No memory type found for flags 0x%x\n",
828  req_flags);
829  return AVERROR(EINVAL);
830  }
831 
832  alloc_info.memoryTypeIndex = index;
833 
834  ret = vk->AllocateMemory(s->hwctx->act_dev, &alloc_info,
835  s->hwctx->alloc, mem);
836  if (ret != VK_SUCCESS) {
837  av_log(s, AV_LOG_ERROR, "Failed to allocate memory: %s\n",
838  ff_vk_ret2str(ret));
839  return AVERROR(ENOMEM);
840  }
841 
842  if (mem_flags)
843  *mem_flags |= s->mprops.memoryTypes[index].propertyFlags;
844 
845  return 0;
846 }
847 
849  void *pNext, void *alloc_pNext,
850  VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags)
851 {
852  int err;
853  VkResult ret;
854  int use_ded_mem;
855  FFVulkanFunctions *vk = &s->vkfn;
856 
857  VkBufferCreateInfo buf_spawn = {
858  .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
859  .pNext = pNext,
860  .usage = usage,
861  .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
862  .size = size, /* Gets FFALIGNED during alloc if host visible
863  but should be ok */
864  };
865 
866  VkMemoryAllocateFlagsInfo alloc_flags = {
867  .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
868  .flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT,
869  };
870  VkBufferMemoryRequirementsInfo2 req_desc = {
871  .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
872  };
873  VkMemoryDedicatedAllocateInfo ded_alloc = {
874  .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
875  .pNext = alloc_pNext,
876  };
877  VkMemoryDedicatedRequirements ded_req = {
878  .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
879  };
880  VkMemoryRequirements2 req = {
881  .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
882  .pNext = &ded_req,
883  };
884 
885  ret = vk->CreateBuffer(s->hwctx->act_dev, &buf_spawn, NULL, &buf->buf);
886  if (ret != VK_SUCCESS) {
887  av_log(s, AV_LOG_ERROR, "Failed to create buffer: %s\n",
888  ff_vk_ret2str(ret));
889  return AVERROR_EXTERNAL;
890  }
891 
892  req_desc.buffer = buf->buf;
893 
894  vk->GetBufferMemoryRequirements2(s->hwctx->act_dev, &req_desc, &req);
895 
896  /* In case the implementation prefers/requires dedicated allocation */
897  use_ded_mem = ded_req.prefersDedicatedAllocation |
898  ded_req.requiresDedicatedAllocation;
899  if (use_ded_mem) {
900  ded_alloc.buffer = buf->buf;
901  ded_alloc.pNext = alloc_pNext;
902  alloc_pNext = &ded_alloc;
903  }
904 
905  if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) {
906  alloc_flags.pNext = alloc_pNext;
907  alloc_pNext = &alloc_flags;
908  }
909 
910  err = ff_vk_alloc_mem(s, &req.memoryRequirements, flags, alloc_pNext,
911  &buf->flags, &buf->mem);
912  if (err)
913  return err;
914 
915  ret = vk->BindBufferMemory(s->hwctx->act_dev, buf->buf, buf->mem, 0);
916  if (ret != VK_SUCCESS) {
917  av_log(s, AV_LOG_ERROR, "Failed to bind memory to buffer: %s\n",
918  ff_vk_ret2str(ret));
919  return AVERROR_EXTERNAL;
920  }
921 
922  if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) {
923  VkBufferDeviceAddressInfo address_info = {
924  .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
925  .buffer = buf->buf,
926  };
927  buf->address = vk->GetBufferDeviceAddress(s->hwctx->act_dev, &address_info);
928  }
929 
930  buf->size = size;
931 
932  return 0;
933 }
934 
935 static void destroy_avvkbuf(void *opaque, uint8_t *data)
936 {
937  FFVulkanContext *s = opaque;
938  FFVkBuffer *buf = (FFVkBuffer *)data;
939  ff_vk_free_buf(s, buf);
940  av_free(buf);
941 }
942 
944  void *pNext, void *alloc_pNext,
945  VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags)
946 {
947  int err;
948  AVBufferRef *buf;
949  FFVkBuffer *vkb = av_mallocz(sizeof(*vkb));
950  if (!vkb)
951  return AVERROR(ENOMEM);
952 
953  err = ff_vk_create_buf(s, vkb, size, pNext, alloc_pNext, usage, flags);
954  if (err < 0) {
955  av_free(vkb);
956  return err;
957  }
958 
959  buf = av_buffer_create((uint8_t *)vkb, sizeof(*vkb), destroy_avvkbuf, s, 0);
960  if (!buf) {
961  destroy_avvkbuf(s, (uint8_t *)vkb);
962  return AVERROR(ENOMEM);
963  }
964 
965  *ref = buf;
966 
967  return 0;
968 }
969 
970 int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer **buf, uint8_t *mem[],
971  int nb_buffers, int invalidate)
972 {
973  VkResult ret;
974  FFVulkanFunctions *vk = &s->vkfn;
975  VkMappedMemoryRange inval_list[64];
976  int inval_count = 0;
977 
978  for (int i = 0; i < nb_buffers; i++) {
979  void *dst;
980  ret = vk->MapMemory(s->hwctx->act_dev, buf[i]->mem, 0,
981  VK_WHOLE_SIZE, 0, &dst);
982  if (ret != VK_SUCCESS) {
983  av_log(s, AV_LOG_ERROR, "Failed to map buffer memory: %s\n",
984  ff_vk_ret2str(ret));
985  return AVERROR_EXTERNAL;
986  }
987  mem[i] = dst;
988  }
989 
990  if (!invalidate)
991  return 0;
992 
993  for (int i = 0; i < nb_buffers; i++) {
994  const VkMappedMemoryRange ival_buf = {
995  .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
996  .memory = buf[i]->mem,
997  .size = VK_WHOLE_SIZE,
998  };
999  if (buf[i]->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
1000  continue;
1001  inval_list[inval_count++] = ival_buf;
1002  }
1003 
1004  if (inval_count) {
1005  ret = vk->InvalidateMappedMemoryRanges(s->hwctx->act_dev, inval_count,
1006  inval_list);
1007  if (ret != VK_SUCCESS) {
1008  av_log(s, AV_LOG_ERROR, "Failed to invalidate memory: %s\n",
1009  ff_vk_ret2str(ret));
1010  return AVERROR_EXTERNAL;
1011  }
1012  }
1013 
1014  return 0;
1015 }
1016 
1017 int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer **buf, int nb_buffers,
1018  int flush)
1019 {
1020  int err = 0;
1021  VkResult ret;
1022  FFVulkanFunctions *vk = &s->vkfn;
1023  VkMappedMemoryRange flush_list[64];
1024  int flush_count = 0;
1025 
1026  if (flush) {
1027  for (int i = 0; i < nb_buffers; i++) {
1028  const VkMappedMemoryRange flush_buf = {
1029  .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
1030  .memory = buf[i]->mem,
1031  .size = VK_WHOLE_SIZE,
1032  };
1033  if (buf[i]->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
1034  continue;
1035  flush_list[flush_count++] = flush_buf;
1036  }
1037  }
1038 
1039  if (flush_count) {
1040  ret = vk->FlushMappedMemoryRanges(s->hwctx->act_dev, flush_count,
1041  flush_list);
1042  if (ret != VK_SUCCESS) {
1043  av_log(s, AV_LOG_ERROR, "Failed to flush memory: %s\n",
1044  ff_vk_ret2str(ret));
1045  err = AVERROR_EXTERNAL; /* We still want to try to unmap them */
1046  }
1047  }
1048 
1049  for (int i = 0; i < nb_buffers; i++)
1050  vk->UnmapMemory(s->hwctx->act_dev, buf[i]->mem);
1051 
1052  return err;
1053 }
1054 
1056 {
1057  FFVulkanFunctions *vk = &s->vkfn;
1058 
1059  if (!buf || !s->hwctx)
1060  return;
1061 
1062  if (buf->mapped_mem)
1063  ff_vk_unmap_buffer(s, buf, 0);
1064  if (buf->buf != VK_NULL_HANDLE)
1065  vk->DestroyBuffer(s->hwctx->act_dev, buf->buf, s->hwctx->alloc);
1066  if (buf->mem != VK_NULL_HANDLE)
1067  vk->FreeMemory(s->hwctx->act_dev, buf->mem, s->hwctx->alloc);
1068 }
1069 
1070 static void free_data_buf(void *opaque, uint8_t *data)
1071 {
1072  FFVulkanContext *ctx = opaque;
1073  FFVkBuffer *buf = (FFVkBuffer *)data;
1074  ff_vk_free_buf(ctx, buf);
1075  av_free(data);
1076 }
1077 
1078 static AVBufferRef *alloc_data_buf(void *opaque, size_t size)
1079 {
1080  AVBufferRef *ref;
1081  uint8_t *buf = av_mallocz(size);
1082  if (!buf)
1083  return NULL;
1084 
1085  ref = av_buffer_create(buf, size, free_data_buf, opaque, 0);
1086  if (!ref)
1087  av_free(buf);
1088  return ref;
1089 }
1090 
1092  AVBufferRef **buf, VkBufferUsageFlags usage,
1093  void *create_pNext, size_t size,
1094  VkMemoryPropertyFlagBits mem_props)
1095 {
1096  int err;
1097  AVBufferRef *ref;
1098  FFVkBuffer *data;
1099 
1100  if (!(*buf_pool)) {
1101  *buf_pool = av_buffer_pool_init2(sizeof(FFVkBuffer), ctx,
1102  alloc_data_buf, NULL);
1103  if (!(*buf_pool))
1104  return AVERROR(ENOMEM);
1105  }
1106 
1107  *buf = ref = av_buffer_pool_get(*buf_pool);
1108  if (!ref)
1109  return AVERROR(ENOMEM);
1110 
1111  data = (FFVkBuffer *)ref->data;
1112  data->stage = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
1113  data->access = VK_ACCESS_2_NONE;
1114 
1115  if (data->size >= size)
1116  return 0;
1117 
1119  memset(data, 0, sizeof(*data));
1120 
1121  av_log(ctx, AV_LOG_DEBUG, "Allocating buffer of %"SIZE_SPECIFIER" bytes for pool %p\n",
1122  size, *buf_pool);
1123 
1124  err = ff_vk_create_buf(ctx, data, size,
1125  create_pNext, NULL, usage,
1126  mem_props);
1127  if (err < 0) {
1128  av_buffer_unref(&ref);
1129  return err;
1130  }
1131 
1132  if (mem_props & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
1133  err = ff_vk_map_buffer(ctx, data, &data->mapped_mem, 0);
1134  if (err < 0) {
1135  av_buffer_unref(&ref);
1136  return err;
1137  }
1138  }
1139 
1140  return 0;
1141 }
1142 
1144  VkShaderStageFlagBits stage)
1145 {
1146  VkPushConstantRange *pc;
1147 
1148  pl->push_consts = av_realloc_array(pl->push_consts, sizeof(*pl->push_consts),
1149  pl->push_consts_num + 1);
1150  if (!pl->push_consts)
1151  return AVERROR(ENOMEM);
1152 
1153  pc = &pl->push_consts[pl->push_consts_num++];
1154  memset(pc, 0, sizeof(*pc));
1155 
1156  pc->stageFlags = stage;
1157  pc->offset = offset;
1158  pc->size = size;
1159 
1160  return 0;
1161 }
1162 
1163 int ff_vk_init_sampler(FFVulkanContext *s, VkSampler *sampler,
1164  int unnorm_coords, VkFilter filt)
1165 {
1166  VkResult ret;
1167  FFVulkanFunctions *vk = &s->vkfn;
1168 
1169  VkSamplerCreateInfo sampler_info = {
1170  .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
1171  .magFilter = filt,
1172  .minFilter = sampler_info.magFilter,
1173  .mipmapMode = unnorm_coords ? VK_SAMPLER_MIPMAP_MODE_NEAREST :
1174  VK_SAMPLER_MIPMAP_MODE_LINEAR,
1175  .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1176  .addressModeV = sampler_info.addressModeU,
1177  .addressModeW = sampler_info.addressModeU,
1178  .anisotropyEnable = VK_FALSE,
1179  .compareOp = VK_COMPARE_OP_NEVER,
1180  .borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
1181  .unnormalizedCoordinates = unnorm_coords,
1182  };
1183 
1184  ret = vk->CreateSampler(s->hwctx->act_dev, &sampler_info,
1185  s->hwctx->alloc, sampler);
1186  if (ret != VK_SUCCESS) {
1187  av_log(s, AV_LOG_ERROR, "Unable to init sampler: %s\n",
1188  ff_vk_ret2str(ret));
1189  return AVERROR_EXTERNAL;
1190  }
1191 
1192  return 0;
1193 }
1194 
1196 {
1203  return 1;
1204  return 0;
1205 }
1206 
1208 {
1210  const int high = desc->comp[0].depth > 8;
1211  return high ? "rgba16f" : "rgba8";
1212 }
1213 
1214 typedef struct ImageViewCtx {
1217 } ImageViewCtx;
1218 
1219 static void destroy_imageviews(void *opaque, uint8_t *data)
1220 {
1221  FFVulkanContext *s = opaque;
1222  FFVulkanFunctions *vk = &s->vkfn;
1223  ImageViewCtx *iv = (ImageViewCtx *)data;
1224 
1225  for (int i = 0; i < iv->nb_views; i++)
1226  vk->DestroyImageView(s->hwctx->act_dev, iv->views[i], s->hwctx->alloc);
1227 
1228  av_free(iv);
1229 }
1230 
1232  VkImageView views[AV_NUM_DATA_POINTERS],
1233  AVFrame *f)
1234 {
1235  int err;
1236  VkResult ret;
1237  AVBufferRef *buf;
1238  FFVulkanFunctions *vk = &s->vkfn;
1239  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
1240  const VkFormat *rep_fmts = av_vkfmt_from_pixfmt(hwfc->sw_format);
1241  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
1242  const int nb_images = ff_vk_count_images(vkf);
1243  const int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format);
1244 
1245  ImageViewCtx *iv = av_mallocz(sizeof(*iv));
1246  if (!iv)
1247  return AVERROR(ENOMEM);
1248 
1249  for (int i = 0; i < nb_planes; i++) {
1250  VkImageAspectFlags plane_aspect[] = { VK_IMAGE_ASPECT_COLOR_BIT,
1251  VK_IMAGE_ASPECT_PLANE_0_BIT,
1252  VK_IMAGE_ASPECT_PLANE_1_BIT,
1253  VK_IMAGE_ASPECT_PLANE_2_BIT, };
1254 
1255  VkImageViewCreateInfo view_create_info = {
1256  .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
1257  .pNext = NULL,
1258  .image = vkf->img[FFMIN(i, nb_images - 1)],
1259  .viewType = VK_IMAGE_VIEW_TYPE_2D,
1260  .format = rep_fmts[i],
1261  .components = ff_comp_identity_map,
1262  .subresourceRange = {
1263  .aspectMask = plane_aspect[(nb_planes != nb_images) +
1264  i*(nb_planes != nb_images)],
1265  .levelCount = 1,
1266  .layerCount = 1,
1267  },
1268  };
1269 
1270  ret = vk->CreateImageView(s->hwctx->act_dev, &view_create_info,
1271  s->hwctx->alloc, &iv->views[i]);
1272  if (ret != VK_SUCCESS) {
1273  av_log(s, AV_LOG_ERROR, "Failed to create imageview: %s\n",
1274  ff_vk_ret2str(ret));
1275  err = AVERROR_EXTERNAL;
1276  goto fail;
1277  }
1278 
1279  iv->nb_views++;
1280  }
1281 
1282  buf = av_buffer_create((uint8_t *)iv, sizeof(*iv), destroy_imageviews, s, 0);
1283  if (!buf) {
1284  err = AVERROR(ENOMEM);
1285  goto fail;
1286  }
1287 
1288  /* Add to queue dependencies */
1289  err = ff_vk_exec_add_dep_buf(s, e, &buf, 1, 0);
1290  if (err < 0)
1291  av_buffer_unref(&buf);
1292 
1293  memcpy(views, iv->views, nb_planes*sizeof(*views));
1294 
1295  return err;
1296 
1297 fail:
1298  for (int i = 0; i < iv->nb_views; i++)
1299  vk->DestroyImageView(s->hwctx->act_dev, iv->views[i], s->hwctx->alloc);
1300  av_free(iv);
1301  return err;
1302 }
1303 
1305  AVFrame *pic, VkImageMemoryBarrier2 *bar, int *nb_bar,
1306  VkPipelineStageFlags src_stage,
1307  VkPipelineStageFlags dst_stage,
1308  VkAccessFlagBits new_access,
1309  VkImageLayout new_layout,
1310  uint32_t new_qf)
1311 {
1312  int found = -1;
1313  AVVkFrame *vkf = (AVVkFrame *)pic->data[0];
1314  const int nb_images = ff_vk_count_images(vkf);
1315  for (int i = 0; i < e->nb_frame_deps; i++)
1316  if (e->frame_deps[i]->data[0] == pic->data[0]) {
1317  if (e->frame_update[i])
1318  found = i;
1319  break;
1320  }
1321 
1322  for (int i = 0; i < nb_images; i++) {
1323  bar[*nb_bar] = (VkImageMemoryBarrier2) {
1324  .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
1325  .pNext = NULL,
1326  .srcStageMask = src_stage,
1327  .dstStageMask = dst_stage,
1328  .srcAccessMask = found >= 0 ? e->access_dst[found] : vkf->access[i],
1329  .dstAccessMask = new_access,
1330  .oldLayout = found >= 0 ? e->layout_dst[found] : vkf->layout[0],
1331  .newLayout = new_layout,
1332  .srcQueueFamilyIndex = found >= 0 ? e->queue_family_dst[found] : vkf->queue_family[0],
1333  .dstQueueFamilyIndex = new_qf,
1334  .image = vkf->img[i],
1335  .subresourceRange = (VkImageSubresourceRange) {
1336  .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
1337  .layerCount = 1,
1338  .levelCount = 1,
1339  },
1340  };
1341  *nb_bar += 1;
1342  }
1343 
1344  ff_vk_exec_update_frame(s, e, pic, &bar[*nb_bar - nb_images], NULL);
1345 }
1346 
1348  VkShaderStageFlags stage, uint32_t required_subgroup_size)
1349 {
1351 
1352  shd->shader.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
1353  shd->shader.stage = stage;
1354 
1355  if (required_subgroup_size) {
1356  shd->shader.flags |= VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT;
1357  shd->shader.pNext = &shd->subgroup_info;
1358  shd->subgroup_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO;
1359  shd->subgroup_info.requiredSubgroupSize = required_subgroup_size;
1360  }
1361 
1362  shd->name = name;
1363 
1364  GLSLF(0, #version %i ,460);
1365  GLSLC(0, #define IS_WITHIN(v1, v2) ((v1.x < v2.x) && (v1.y < v2.y)) );
1366  GLSLC(0, );
1367  GLSLC(0, #extension GL_EXT_buffer_reference : require );
1368  GLSLC(0, #extension GL_EXT_buffer_reference2 : require );
1369 
1370  return 0;
1371 }
1372 
1373 void ff_vk_shader_set_compute_sizes(FFVkSPIRVShader *shd, int x, int y, int z)
1374 {
1375  shd->local_size[0] = x;
1376  shd->local_size[1] = y;
1377  shd->local_size[2] = z;
1378 
1379  av_bprintf(&shd->src, "layout (local_size_x = %i, "
1380  "local_size_y = %i, local_size_z = %i) in;\n\n",
1381  shd->local_size[0], shd->local_size[1], shd->local_size[2]);
1382 }
1383 
1384 void ff_vk_shader_print(void *ctx, FFVkSPIRVShader *shd, int prio)
1385 {
1386  int line = 0;
1387  const char *p = shd->src.str;
1388  const char *start = p;
1389  const size_t len = strlen(p);
1390 
1391  AVBPrint buf;
1393 
1394  for (int i = 0; i < len; i++) {
1395  if (p[i] == '\n') {
1396  av_bprintf(&buf, "%i\t", ++line);
1397  av_bprint_append_data(&buf, start, &p[i] - start + 1);
1398  start = &p[i + 1];
1399  }
1400  }
1401 
1402  av_log(ctx, prio, "Shader %s: \n%s", shd->name, buf.str);
1403  av_bprint_finalize(&buf, NULL);
1404 }
1405 
1407 {
1408  FFVulkanFunctions *vk = &s->vkfn;
1409  av_bprint_finalize(&shd->src, NULL);
1410 
1411  if (shd->shader.module)
1412  vk->DestroyShaderModule(s->hwctx->act_dev, shd->shader.module, s->hwctx->alloc);
1413 }
1414 
1416  uint8_t *spirv, size_t spirv_size, const char *entrypoint)
1417 {
1418  VkResult ret;
1419  FFVulkanFunctions *vk = &s->vkfn;
1420  VkShaderModuleCreateInfo shader_create;
1421 
1422  shd->shader.pName = entrypoint;
1423 
1424  av_log(s, AV_LOG_VERBOSE, "Shader %s compiled! Size: %zu bytes\n",
1425  shd->name, spirv_size);
1426 
1427  shader_create.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
1428  shader_create.pNext = NULL;
1429  shader_create.codeSize = spirv_size;
1430  shader_create.flags = 0;
1431  shader_create.pCode = (void *)spirv;
1432 
1433  ret = vk->CreateShaderModule(s->hwctx->act_dev, &shader_create, NULL,
1434  &shd->shader.module);
1435  if (ret != VK_SUCCESS) {
1436  av_log(s, AV_LOG_VERBOSE, "Error creating shader module: %s\n",
1437  ff_vk_ret2str(ret));
1438  return AVERROR_EXTERNAL;
1439  }
1440 
1441  return 0;
1442 }
1443 
1444 static const struct descriptor_props {
1445  size_t struct_size; /* Size of the opaque which updates the descriptor */
1446  const char *type;
1448  int mem_quali; /* Can use a memory qualifier */
1449  int dim_needed; /* Must indicate dimension */
1450  int buf_content; /* Must indicate buffer contents */
1451 } descriptor_props[] = {
1452  [VK_DESCRIPTOR_TYPE_SAMPLER] = { sizeof(VkDescriptorImageInfo), "sampler", 1, 0, 0, 0, },
1453  [VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE] = { sizeof(VkDescriptorImageInfo), "texture", 1, 0, 1, 0, },
1454  [VK_DESCRIPTOR_TYPE_STORAGE_IMAGE] = { sizeof(VkDescriptorImageInfo), "image", 1, 1, 1, 0, },
1455  [VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT] = { sizeof(VkDescriptorImageInfo), "subpassInput", 1, 0, 0, 0, },
1456  [VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER] = { sizeof(VkDescriptorImageInfo), "sampler", 1, 0, 1, 0, },
1457  [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER] = { sizeof(VkDescriptorBufferInfo), NULL, 1, 0, 0, 1, },
1458  [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER] = { sizeof(VkDescriptorBufferInfo), "buffer", 0, 1, 0, 1, },
1459  [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo), NULL, 1, 0, 0, 1, },
1460  [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo), "buffer", 0, 1, 0, 1, },
1461  [VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER] = { sizeof(VkBufferView), "samplerBuffer", 1, 0, 0, 0, },
1462  [VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER] = { sizeof(VkBufferView), "imageBuffer", 1, 0, 0, 0, },
1463 };
1464 
1466  FFVkSPIRVShader *shd,
1468  int read_only, int print_to_shader_only)
1469 {
1470  VkResult ret;
1471  int has_sampler = 0;
1472  FFVulkanFunctions *vk = &s->vkfn;
1474  VkDescriptorSetLayoutCreateInfo desc_create_layout;
1475 
1476  if (print_to_shader_only)
1477  goto print;
1478 
1479  /* Actual layout allocated for the pipeline */
1480  set = av_realloc_array(pl->desc_set, sizeof(*pl->desc_set),
1481  pl->nb_descriptor_sets + 1);
1482  if (!set)
1483  return AVERROR(ENOMEM);
1484  pl->desc_set = set;
1485  set = &set[pl->nb_descriptor_sets];
1486  memset(set, 0, sizeof(*set));
1487 
1488  set->binding = av_calloc(nb, sizeof(*set->binding));
1489  if (!set->binding)
1490  return AVERROR(ENOMEM);
1491 
1492  set->binding_offset = av_calloc(nb, sizeof(*set->binding_offset));
1493  if (!set->binding_offset) {
1494  av_freep(&set->binding);
1495  return AVERROR(ENOMEM);
1496  }
1497 
1498  desc_create_layout = (VkDescriptorSetLayoutCreateInfo) {
1499  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
1500  .bindingCount = nb,
1501  .pBindings = set->binding,
1502  .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT,
1503  };
1504 
1505  for (int i = 0; i < nb; i++) {
1506  set->binding[i].binding = i;
1507  set->binding[i].descriptorType = desc[i].type;
1508  set->binding[i].descriptorCount = FFMAX(desc[i].elems, 1);
1509  set->binding[i].stageFlags = desc[i].stages;
1510  set->binding[i].pImmutableSamplers = desc[i].samplers;
1511 
1512  if (desc[i].type == VK_DESCRIPTOR_TYPE_SAMPLER ||
1513  desc[i].type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1514  has_sampler |= 1;
1515  }
1516 
1517  set->usage = VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT |
1518  VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
1519  if (has_sampler)
1520  set->usage |= VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT;
1521 
1522  ret = vk->CreateDescriptorSetLayout(s->hwctx->act_dev, &desc_create_layout,
1523  s->hwctx->alloc, &set->layout);
1524  if (ret != VK_SUCCESS) {
1525  av_log(s, AV_LOG_ERROR, "Unable to init descriptor set layout: %s",
1526  ff_vk_ret2str(ret));
1527  return AVERROR_EXTERNAL;
1528  }
1529 
1530  vk->GetDescriptorSetLayoutSizeEXT(s->hwctx->act_dev, set->layout, &set->layout_size);
1531 
1532  set->aligned_size = FFALIGN(set->layout_size, s->desc_buf_props.descriptorBufferOffsetAlignment);
1533 
1534  for (int i = 0; i < nb; i++)
1535  vk->GetDescriptorSetLayoutBindingOffsetEXT(s->hwctx->act_dev, set->layout,
1536  i, &set->binding_offset[i]);
1537 
1538  set->read_only = read_only;
1539  set->nb_bindings = nb;
1540  pl->nb_descriptor_sets++;
1541 
1542 print:
1543  /* Write shader info */
1544  for (int i = 0; i < nb; i++) {
1545  const struct descriptor_props *prop = &descriptor_props[desc[i].type];
1546  GLSLA("layout (set = %i, binding = %i", pl->nb_descriptor_sets - 1, i);
1547 
1548  if (desc[i].mem_layout)
1549  GLSLA(", %s", desc[i].mem_layout);
1550  GLSLA(")");
1551 
1552  if (prop->is_uniform)
1553  GLSLA(" uniform");
1554 
1555  if (prop->mem_quali && desc[i].mem_quali)
1556  GLSLA(" %s", desc[i].mem_quali);
1557 
1558  if (prop->type)
1559  GLSLA(" %s", prop->type);
1560 
1561  if (prop->dim_needed)
1562  GLSLA("%iD", desc[i].dimensions);
1563 
1564  GLSLA(" %s", desc[i].name);
1565 
1566  if (prop->buf_content)
1567  GLSLA(" {\n %s\n}", desc[i].buf_content);
1568  else if (desc[i].elems > 0)
1569  GLSLA("[%i]", desc[i].elems);
1570 
1571  GLSLA(";");
1572  GLSLA("\n");
1573  }
1574  GLSLA("\n");
1575 
1576  return 0;
1577 }
1578 
1580  FFVulkanPipeline *pl)
1581 {
1582  int err;
1583 
1584  pl->desc_bind = av_calloc(pl->nb_descriptor_sets, sizeof(*pl->desc_bind));
1585  if (!pl->desc_bind)
1586  return AVERROR(ENOMEM);
1587 
1589  sizeof(*pl->bound_buffer_indices));
1590  if (!pl->bound_buffer_indices)
1591  return AVERROR(ENOMEM);
1592 
1593  for (int i = 0; i < pl->nb_descriptor_sets; i++) {
1595  int nb = set->read_only ? 1 : pool->pool_size;
1596 
1597  err = ff_vk_create_buf(s, &set->buf, set->aligned_size*nb,
1598  NULL, NULL, set->usage,
1599  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
1600  VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
1601  if (err < 0)
1602  return err;
1603 
1604  err = ff_vk_map_buffer(s, &set->buf, &set->desc_mem, 0);
1605  if (err < 0)
1606  return err;
1607 
1608  pl->desc_bind[i] = (VkDescriptorBufferBindingInfoEXT) {
1609  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_INFO_EXT,
1610  .usage = set->usage,
1611  .address = set->buf.address,
1612  };
1613 
1614  pl->bound_buffer_indices[i] = i;
1615  }
1616 
1617  return 0;
1618 }
1619 
1622  int bind_idx, int array_idx,
1623  VkDescriptorGetInfoEXT *desc_get_info,
1624  size_t desc_size)
1625 {
1626  FFVulkanFunctions *vk = &s->vkfn;
1627  const size_t exec_offset = set->read_only ? 0 : set->aligned_size*e->idx;
1628  void *desc = set->desc_mem + /* Base */
1629  exec_offset + /* Execution context */
1630  set->binding_offset[bind_idx] + /* Descriptor binding */
1631  array_idx*desc_size; /* Array position */
1632 
1633  vk->GetDescriptorEXT(s->hwctx->act_dev, desc_get_info, desc_size, desc);
1634 }
1635 
1637  FFVkExecContext *e, int set, int bind, int offs,
1638  VkImageView view, VkImageLayout layout,
1639  VkSampler sampler)
1640 {
1641  FFVulkanDescriptorSet *desc_set = &pl->desc_set[set];
1642  VkDescriptorGetInfoEXT desc_get_info = {
1643  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT,
1644  .type = desc_set->binding[bind].descriptorType,
1645  };
1646  VkDescriptorImageInfo desc_img_info = {
1647  .imageView = view,
1648  .sampler = sampler,
1649  .imageLayout = layout,
1650  };
1651  size_t desc_size;
1652 
1653  switch (desc_get_info.type) {
1654  case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
1655  desc_get_info.data.pSampledImage = &desc_img_info;
1656  desc_size = s->desc_buf_props.sampledImageDescriptorSize;
1657  break;
1658  case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
1659  desc_get_info.data.pStorageImage = &desc_img_info;
1660  desc_size = s->desc_buf_props.storageImageDescriptorSize;
1661  break;
1662  case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
1663  desc_get_info.data.pInputAttachmentImage = &desc_img_info;
1664  desc_size = s->desc_buf_props.inputAttachmentDescriptorSize;
1665  break;
1666  case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
1667  desc_get_info.data.pCombinedImageSampler = &desc_img_info;
1668  desc_size = s->desc_buf_props.combinedImageSamplerDescriptorSize;
1669  break;
1670  default:
1671  av_log(s, AV_LOG_ERROR, "Invalid descriptor type at set %i binding %i: %i!\n",
1672  set, bind, desc_get_info.type);
1673  return AVERROR(EINVAL);
1674  break;
1675  };
1676 
1677  update_set_descriptor(s, e, desc_set, bind, offs, &desc_get_info, desc_size);
1678 
1679  return 0;
1680 }
1681 
1683  FFVkExecContext *e, int set, int bind, int offs,
1684  VkDeviceAddress addr, VkDeviceSize len, VkFormat fmt)
1685 {
1686  FFVulkanDescriptorSet *desc_set = &pl->desc_set[set];
1687  VkDescriptorGetInfoEXT desc_get_info = {
1688  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT,
1689  .type = desc_set->binding[bind].descriptorType,
1690  };
1691  VkDescriptorAddressInfoEXT desc_buf_info = {
1692  .address = addr,
1693  .range = len,
1694  .format = fmt,
1695  };
1696  size_t desc_size;
1697 
1698  switch (desc_get_info.type) {
1699  case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1700  desc_get_info.data.pUniformBuffer = &desc_buf_info;
1701  desc_size = s->desc_buf_props.uniformBufferDescriptorSize;
1702  break;
1703  case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1704  desc_get_info.data.pStorageBuffer = &desc_buf_info;
1705  desc_size = s->desc_buf_props.storageBufferDescriptorSize;
1706  break;
1707  case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1708  desc_get_info.data.pUniformTexelBuffer = &desc_buf_info;
1709  desc_size = s->desc_buf_props.uniformTexelBufferDescriptorSize;
1710  break;
1711  case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1712  desc_get_info.data.pStorageTexelBuffer = &desc_buf_info;
1713  desc_size = s->desc_buf_props.storageTexelBufferDescriptorSize;
1714  break;
1715  default:
1716  av_log(s, AV_LOG_ERROR, "Invalid descriptor type at set %i binding %i: %i!\n",
1717  set, bind, desc_get_info.type);
1718  return AVERROR(EINVAL);
1719  break;
1720  };
1721 
1722  update_set_descriptor(s, e, desc_set, bind, offs, &desc_get_info, desc_size);
1723 
1724  return 0;
1725 }
1726 
1728  FFVkExecContext *e, AVFrame *f,
1729  VkImageView *views, int set, int binding,
1730  VkImageLayout layout, VkSampler sampler)
1731 {
1732  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
1733  const int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format);
1734 
1735  for (int i = 0; i < nb_planes; i++)
1736  vk_set_descriptor_image(s, pl, e, set, binding, i,
1737  views[i], layout, sampler);
1738 }
1739 
1741  FFVulkanPipeline *pl,
1742  VkShaderStageFlagBits stage,
1743  int offset, size_t size, void *src)
1744 {
1745  FFVulkanFunctions *vk = &s->vkfn;
1746  vk->CmdPushConstants(e->buf, pl->pipeline_layout,
1747  stage, offset, size, src);
1748 }
1749 
1751 {
1752  VkResult ret;
1753  FFVulkanFunctions *vk = &s->vkfn;
1754  VkPipelineLayoutCreateInfo pipeline_layout_info;
1755 
1756  VkDescriptorSetLayout *desc_layouts = av_malloc(pl->nb_descriptor_sets*
1757  sizeof(desc_layouts));
1758  if (!desc_layouts)
1759  return AVERROR(ENOMEM);
1760 
1761  for (int i = 0; i < pl->nb_descriptor_sets; i++)
1762  desc_layouts[i] = pl->desc_set[i].layout;
1763 
1764  /* Finally create the pipeline layout */
1765  pipeline_layout_info = (VkPipelineLayoutCreateInfo) {
1766  .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1767  .pSetLayouts = desc_layouts,
1768  .setLayoutCount = pl->nb_descriptor_sets,
1769  .pushConstantRangeCount = pl->push_consts_num,
1770  .pPushConstantRanges = pl->push_consts,
1771  };
1772 
1773  ret = vk->CreatePipelineLayout(s->hwctx->act_dev, &pipeline_layout_info,
1774  s->hwctx->alloc, &pl->pipeline_layout);
1775  av_free(desc_layouts);
1776  if (ret != VK_SUCCESS) {
1777  av_log(s, AV_LOG_ERROR, "Unable to init pipeline layout: %s\n",
1778  ff_vk_ret2str(ret));
1779  return AVERROR_EXTERNAL;
1780  }
1781 
1782  return 0;
1783 }
1784 
1786  FFVkSPIRVShader *shd)
1787 {
1788  int err;
1789  VkResult ret;
1790  FFVulkanFunctions *vk = &s->vkfn;
1791 
1792  VkComputePipelineCreateInfo pipeline_create_info;
1793 
1794  err = init_pipeline_layout(s, pl);
1795  if (err < 0)
1796  return err;
1797 
1798  pipeline_create_info = (VkComputePipelineCreateInfo) {
1799  .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
1800  .flags = VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT,
1801  .layout = pl->pipeline_layout,
1802  .stage = shd->shader,
1803  };
1804 
1805  ret = vk->CreateComputePipelines(s->hwctx->act_dev, VK_NULL_HANDLE, 1,
1806  &pipeline_create_info,
1807  s->hwctx->alloc, &pl->pipeline);
1808  if (ret != VK_SUCCESS) {
1809  av_log(s, AV_LOG_ERROR, "Unable to init compute pipeline: %s\n",
1810  ff_vk_ret2str(ret));
1811  return AVERROR_EXTERNAL;
1812  }
1813 
1814  pl->bind_point = VK_PIPELINE_BIND_POINT_COMPUTE;
1815  pl->wg_size[0] = shd->local_size[0];
1816  pl->wg_size[1] = shd->local_size[1];
1817  pl->wg_size[2] = shd->local_size[2];
1818 
1819  return 0;
1820 }
1821 
1823  FFVulkanPipeline *pl)
1824 {
1825  FFVulkanFunctions *vk = &s->vkfn;
1826  VkDeviceSize offsets[1024];
1827 
1828  /* Bind pipeline */
1829  vk->CmdBindPipeline(e->buf, pl->bind_point, pl->pipeline);
1830 
1831  if (pl->nb_descriptor_sets) {
1832  for (int i = 0; i < pl->nb_descriptor_sets; i++)
1833  offsets[i] = pl->desc_set[i].read_only ? 0 : pl->desc_set[i].aligned_size*e->idx;
1834 
1835  /* Bind descriptor buffers */
1836  vk->CmdBindDescriptorBuffersEXT(e->buf, pl->nb_descriptor_sets, pl->desc_bind);
1837  /* Binding offsets */
1838  vk->CmdSetDescriptorBufferOffsetsEXT(e->buf, pl->bind_point, pl->pipeline_layout,
1839  0, pl->nb_descriptor_sets,
1841  }
1842 }
1843 
1845 {
1846  FFVulkanFunctions *vk = &s->vkfn;
1847 
1848  if (pl->pipeline)
1849  vk->DestroyPipeline(s->hwctx->act_dev, pl->pipeline, s->hwctx->alloc);
1850  if (pl->pipeline_layout)
1851  vk->DestroyPipelineLayout(s->hwctx->act_dev, pl->pipeline_layout,
1852  s->hwctx->alloc);
1853 
1854  for (int i = 0; i < pl->nb_descriptor_sets; i++) {
1856  if (set->buf.mem)
1857  ff_vk_unmap_buffer(s, &set->buf, 0);
1858  ff_vk_free_buf(s, &set->buf);
1859  if (set->layout)
1860  vk->DestroyDescriptorSetLayout(s->hwctx->act_dev, set->layout,
1861  s->hwctx->alloc);
1862  av_free(set->binding);
1863  av_free(set->binding_offset);
1864  }
1865 
1866  av_freep(&pl->desc_set);
1867  av_freep(&pl->desc_bind);
1869  av_freep(&pl->push_consts);
1870  pl->push_consts_num = 0;
1871 }
1872 
1874 {
1875  av_freep(&s->query_props);
1876  av_freep(&s->qf_props);
1877  av_freep(&s->video_props);
1878  av_freep(&s->coop_mat_props);
1879 
1880  av_buffer_unref(&s->frames_ref);
1881 }
FFVulkanPipeline::bind_point
VkPipelineBindPoint bind_point
Definition: vulkan.h:132
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:848
ff_vk_load_props
int ff_vk_load_props(FFVulkanContext *s)
Loads props/mprops/driver_props.
Definition: vulkan.c:86
AV_BPRINT_SIZE_UNLIMITED
#define AV_BPRINT_SIZE_UNLIMITED
ff_vk_exec_get
FFVkExecContext * ff_vk_exec_get(FFVkExecPool *pool)
Retrieve an execution pool.
Definition: vulkan.c:497
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
ff_vk_update_descriptor_img_array
void ff_vk_update_descriptor_img_array(FFVulkanContext *s, FFVulkanPipeline *pl, FFVkExecContext *e, AVFrame *f, VkImageView *views, int set, int binding, VkImageLayout layout, VkSampler sampler)
Definition: vulkan.c:1727
ImageViewCtx::nb_views
int nb_views
Definition: vulkan.c:1216
ff_vk_pipeline_free
void ff_vk_pipeline_free(FFVulkanContext *s, FFVulkanPipeline *pl)
Definition: vulkan.c:1844
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:26
FFVkExecContext::frame_deps_alloc_size
unsigned int frame_deps_alloc_size
Definition: vulkan.h:179
av_bprint_init
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
FFVkExecPool::idx
atomic_int_least64_t idx
Definition: vulkan.h:212
AVBufferPool
The buffer pool.
Definition: buffer_internal.h:88
FFVulkanPipeline::pipeline_layout
VkPipelineLayout pipeline_layout
Definition: vulkan.h:135
FFVkExecPool::contexts
FFVkExecContext * contexts
Definition: vulkan.h:211
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2965
pthread_mutex_init
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
Definition: os2threads.h:104
ARR_REALLOC
#define ARR_REALLOC(str, arr, alloc_s, cnt)
FFVkExecContext::qf
int qf
Definition: vulkan.h:160
ff_vk_qf_init
int ff_vk_qf_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf, VkQueueFlagBits dev_family)
Chooses a QF and loads it into a context.
Definition: vulkan.c:225
FFVulkanDescriptorSet::aligned_size
VkDeviceSize aligned_size
Definition: vulkan.h:120
descriptor_props::is_uniform
int is_uniform
Definition: vulkan.c:1447
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:679
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:160
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:374
ff_vk_shader_create
int ff_vk_shader_create(FFVulkanContext *s, FFVkSPIRVShader *shd, uint8_t *spirv, size_t spirv_size, const char *entrypoint)
Definition: vulkan.c:1415
FFVkExecContext::sem_sig_alloc
unsigned int sem_sig_alloc
Definition: vulkan.h:187
alloc_data_buf
static AVBufferRef * alloc_data_buf(void *opaque, size_t size)
Definition: vulkan.c:1078
data
const char data[16]
Definition: mxf.c:148
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:196
FFVkBuffer::address
VkDeviceAddress address
Definition: vulkan.h:100
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_uninit
void ff_vk_uninit(FFVulkanContext *s)
Frees main context.
Definition: vulkan.c:1873
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_pipeline_descriptor_set_add
int ff_vk_pipeline_descriptor_set_add(FFVulkanContext *s, FFVulkanPipeline *pl, FFVkSPIRVShader *shd, FFVulkanDescriptorSetBinding *desc, int nb, int read_only, int print_to_shader_only)
Add descriptor to a pipeline.
Definition: vulkan.c:1465
ff_vk_shader_set_compute_sizes
void ff_vk_shader_set_compute_sizes(FFVkSPIRVShader *shd, int x, int y, int z)
Definition: vulkan.c:1373
FFVkExecPool::query_pool
VkQueryPool query_pool
Definition: vulkan.h:218
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:599
descriptor_props::type
const char * type
Definition: vulkan.c:1446
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:395
FFVkBuffer::buf
VkBuffer buf
Definition: vulkan.h:96
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:30
FFVkExecContext::lock
pthread_mutex_t lock
Definition: vulkan.h:155
ImageViewCtx
Definition: vulkan.c:1214
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:3005
ff_vk_add_push_constant
int ff_vk_add_push_constant(FFVulkanPipeline *pl, int offset, int size, VkShaderStageFlagBits stage)
Add/update push constants for execution.
Definition: vulkan.c:1143
AVVkFrame::img
VkImage img[AV_NUM_DATA_POINTERS]
Vulkan images to which the memory is bound to.
Definition: hwcontext_vulkan.h:271
destroy_avvkbuf
static void destroy_avvkbuf(void *opaque, uint8_t *data)
Definition: vulkan.c:935
fail
#define fail()
Definition: checkasm.h:179
FFVulkanPipeline::wg_size
int wg_size[3]
Definition: vulkan.h:143
ff_vk_unmap_buffers
int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer **buf, int nb_buffers, int flush)
Definition: vulkan.c:1017
FFVulkanDescriptorSet::read_only
int read_only
Definition: vulkan.h:128
AVVulkanFramesContext
Allocated as AVHWFramesContext.hwctx, used to set pool-specific options.
Definition: hwcontext_vulkan.h:177
FFVulkanPipeline::pipeline
VkPipeline pipeline
Definition: vulkan.h:136
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:222
FFVulkanDescriptorSet::layout
VkDescriptorSetLayout layout
Definition: vulkan.h:116
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:180
ff_vk_ret2str
const char * ff_vk_ret2str(VkResult res)
Converts Vulkan return values to strings.
Definition: vulkan.c:34
FF_VK_EXT_COOP_MATRIX
@ FF_VK_EXT_COOP_MATRIX
Definition: vulkan_functions.h:48
FFVkExecPool::query_statuses
int query_statuses
Definition: vulkan.h:221
descriptor_props::struct_size
size_t struct_size
Definition: vulkan.c:1445
FFVulkanDescriptorSet::binding
VkDescriptorSetLayoutBinding * binding
Definition: vulkan.h:124
avassert.h
FFVulkanPipeline::nb_descriptor_sets
int nb_descriptor_sets
Definition: vulkan.h:149
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
FFVkExecContext::frame_deps
AVFrame ** frame_deps
Definition: vulkan.h:178
set
static void set(uint8_t *a[], int ch, int index, int ch_count, enum AVSampleFormat f, double v)
Definition: swresample.c:59
ff_vk_create_avbuf
int ff_vk_create_avbuf(FFVulkanContext *s, AVBufferRef **ref, size_t size, void *pNext, void *alloc_pNext, VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags)
Definition: vulkan.c:943
FFVkExecContext::queue_family_dst
uint32_t * queue_family_dst
Definition: vulkan.h:203
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:384
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
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:698
offsets
static const int offsets[]
Definition: hevc_pel.c:34
av_realloc_array
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Definition: mem.c:217
pix_fmt
static enum AVPixelFormat pix_fmt
Definition: demux_decode.c:41
FFVkExecContext::fence
VkFence fence
Definition: vulkan.h:167
ff_vk_exec_wait
void ff_vk_exec_wait(FFVulkanContext *s, FFVkExecContext *e)
Definition: vulkan.c:504
vk_set_descriptor_image
static int vk_set_descriptor_image(FFVulkanContext *s, FFVulkanPipeline *pl, FFVkExecContext *e, int set, int bind, int offs, VkImageView view, VkImageLayout layout, VkSampler sampler)
Definition: vulkan.c:1636
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:201
FFVkExecContext::nb_buf_deps
int nb_buf_deps
Definition: vulkan.h:174
ctx
AVFormatContext * ctx
Definition: movenc.c:49
av_frame_clone
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
Definition: frame.c:593
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:575
ff_vk_unmap_buffer
static int ff_vk_unmap_buffer(FFVulkanContext *s, FFVkBuffer *buf, int flush)
Definition: vulkan.h:417
ff_vk_exec_bind_pipeline
void ff_vk_exec_bind_pipeline(FFVulkanContext *s, FFVkExecContext *e, FFVulkanPipeline *pl)
Definition: vulkan.c:1822
ff_vk_exec_pool_free
void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool)
Definition: vulkan.c:256
FFVkExecContext::frame_update
uint8_t * frame_update
Definition: vulkan.h:206
FFVkExecContext::query_idx
int query_idx
Definition: vulkan.h:170
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:223
FFVkExecContext::parent
const struct FFVkExecPool * parent
Definition: vulkan.h:154
if
if(ret)
Definition: filter_design.txt:179
ImageViewCtx::views
VkImageView views[AV_NUM_DATA_POINTERS]
Definition: vulkan.c:1215
AV_PIX_FMT_RGBA64
#define AV_PIX_FMT_RGBA64
Definition: pixfmt.h:468
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:790
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:1448
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:210
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
FFVkExecContext::access_dst_alloc
unsigned int access_dst_alloc
Definition: vulkan.h:198
FFVkExecContext::sem_sig_cnt
int sem_sig_cnt
Definition: vulkan.h:188
flush
void(* flush)(AVBSFContext *ctx)
Definition: dts2pts.c:368
FFVkExecContext::qi
int qi
Definition: vulkan.h:161
FFVkExecContext::had_submission
int had_submission
Definition: vulkan.h:156
FFVkBuffer::size
size_t size
Definition: vulkan.h:99
descriptor_props::dim_needed
int dim_needed
Definition: vulkan.c:1449
FFVkExecPool::nb_queries
int nb_queries
Definition: vulkan.h:224
AV_PIX_FMT_BGR0
@ AV_PIX_FMT_BGR0
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
Definition: pixfmt.h:265
ff_vk_init_compute_pipeline
int ff_vk_init_compute_pipeline(FFVulkanContext *s, FFVulkanPipeline *pl, FFVkSPIRVShader *shd)
Definition: vulkan.c:1785
ff_vk_exec_pool_init
int ff_vk_exec_pool_init(FFVulkanContext *s, FFVkQueueFamilyCtx *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:296
FFVkBuffer::mapped_mem
uint8_t * mapped_mem
Definition: vulkan.h:107
FFVulkanContext
Definition: vulkan.h:228
ff_vk_count_images
static int ff_vk_count_images(AVVkFrame *f)
Definition: vulkan.h:270
AV_PIX_FMT_ABGR
@ AV_PIX_FMT_ABGR
packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
Definition: pixfmt.h:101
FFVulkanPipeline
Definition: vulkan.h:131
index
int index
Definition: gxfenc.c:90
FFVkExecContext::query_data
void * query_data
Definition: vulkan.h:169
ff_vk_shader_print
void ff_vk_shader_print(void *ctx, FFVkSPIRVShader *shd, int prio)
Definition: vulkan.c:1384
pthread_mutex_unlock
#define pthread_mutex_unlock(a)
Definition: ffprobe.c:82
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
ff_vk_shader_init
int ff_vk_shader_init(FFVulkanPipeline *pl, FFVkSPIRVShader *shd, const char *name, VkShaderStageFlags stage, uint32_t required_subgroup_size)
Shader management.
Definition: vulkan.c:1347
usage
const char * usage
Definition: floatimg_cmp.c:60
f
f
Definition: af_crystalizer.c:121
FFVkExecContext::layout_dst
VkImageLayout * layout_dst
Definition: vulkan.h:200
destroy_imageviews
static void destroy_imageviews(void *opaque, uint8_t *data)
Definition: vulkan.c:1219
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:295
FFVulkanDescriptorSetBinding
Definition: vulkan.h:83
av_bprint_finalize
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:240
sem_wait
#define sem_wait(psem)
Definition: semaphore.h:27
AVVkFrame
Definition: hwcontext_vulkan.h:266
for
for(k=2;k<=8;++k)
Definition: h264pred_template.c:425
print
static void print(AVTreeNode *t, int depth)
Definition: tree.c:45
AV_PIX_FMT_RGB48
#define AV_PIX_FMT_RGB48
Definition: pixfmt.h:464
size
int size
Definition: twinvq_data.h:10344
AV_NUM_DATA_POINTERS
#define AV_NUM_DATA_POINTERS
Definition: frame.h:375
FFVkExecContext::nb_frame_deps
int nb_frame_deps
Definition: vulkan.h:180
FFVkQueueFamilyCtx
Definition: vulkan.h:110
FFVkExecContext::sem_sig_val_dst_cnt
int sem_sig_val_dst_cnt
Definition: vulkan.h:192
FFVkBuffer::flags
VkMemoryPropertyFlagBits flags
Definition: vulkan.h:98
AVVkFrame::queue_family
uint32_t queue_family[AV_NUM_DATA_POINTERS]
Queue family of the images.
Definition: hwcontext_vulkan.h:330
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:152
line
Definition: graph2dot.c:48
AV_PIX_FMT_RGB0
@ AV_PIX_FMT_RGB0
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
Definition: pixfmt.h:263
ff_vk_update_push_exec
void ff_vk_update_push_exec(FFVulkanContext *s, FFVkExecContext *e, FFVulkanPipeline *pl, VkShaderStageFlagBits stage, int offset, size_t size, void *src)
Definition: vulkan.c:1740
version
version
Definition: libkvazaar.c:321
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:1195
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
vulkan.h
pthread_mutex_destroy
static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
Definition: os2threads.h:112
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:159
descriptor_props
Definition: vulkan.c:1444
ff_vk_exec_start
int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e)
Start/submit/wait an execution.
Definition: vulkan.c:513
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
FFVulkanPipeline::push_consts
VkPushConstantRange * push_consts
Definition: vulkan.h:139
FFVkSPIRVShader::shader
VkPipelineShaderStageCreateInfo shader
Definition: vulkan.h:79
VkFormat
enum VkFormat VkFormat
Definition: hwcontext_stub.c:25
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:31
ff_vk_frame_barrier
void ff_vk_frame_barrier(FFVulkanContext *s, FFVkExecContext *e, AVFrame *pic, VkImageMemoryBarrier2 *bar, int *nb_bar, VkPipelineStageFlags src_stage, VkPipelineStageFlags dst_stage, VkAccessFlagBits new_access, VkImageLayout new_layout, uint32_t new_qf)
Definition: vulkan.c:1304
FFVkExecContext::layout_dst_alloc
unsigned int layout_dst_alloc
Definition: vulkan.h:201
ff_vk_shader_rep_fmt
const char * ff_vk_shader_rep_fmt(enum AVPixelFormat pixfmt)
Returns the format to use for images in shaders.
Definition: vulkan.c:1207
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
FFVkBuffer::mem
VkDeviceMemory mem
Definition: vulkan.h:97
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:256
FFVkSPIRVShader::src
AVBPrint src
Definition: vulkan.h:77
vk_qf_get_index
static int vk_qf_get_index(FFVulkanContext *s, VkQueueFlagBits dev_family, int *nb)
Definition: vulkan.c:190
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:470
filt
static const int8_t filt[NUMTAPS *2]
Definition: af_earwax.c:39
GLSLF
#define GLSLF(N, S,...)
Definition: vulkan.h:54
ff_vk_free_buf
void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf)
Definition: vulkan.c:1055
ff_vk_exec_get_query
VkResult ff_vk_exec_get_query(FFVulkanContext *s, FFVkExecContext *e, void **data, int64_t *status)
Performs nb_queries queries and returns their results and statuses.
Definition: vulkan.c:447
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:264
AV_PIX_FMT_RGB565
#define AV_PIX_FMT_RGB565
Definition: pixfmt.h:465
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:304
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:115
FFVulkanPipeline::push_consts_num
int push_consts_num
Definition: vulkan.h:140
ret
ret
Definition: filter_design.txt:187
pixfmt
enum AVPixelFormat pixfmt
Definition: kmsgrab.c:367
AV_PIX_FMT_0BGR
@ AV_PIX_FMT_0BGR
packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined
Definition: pixfmt.h:264
ff_vk_map_buffer
static int ff_vk_map_buffer(FFVulkanContext *s, FFVkBuffer *buf, uint8_t **mem, int invalidate)
Definition: vulkan.h:410
AVHWFramesContext::hwctx
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition: hwcontext.h:150
FFVkExecPool
Definition: vulkan.h:210
FFVkExecContext::frame_locked
uint8_t * frame_locked
Definition: vulkan.h:194
FFVkExecPool::query_data
void * query_data
Definition: vulkan.h:219
descriptor_props::buf_content
int buf_content
Definition: vulkan.c:1450
FFVkExecContext::sem_sig
VkSemaphoreSubmitInfo * sem_sig
Definition: vulkan.h:186
av_bprintf
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:99
FFVkExecContext::buf
VkCommandBuffer buf
Definition: vulkan.h:164
SIZE_SPECIFIER
#define SIZE_SPECIFIER
Definition: internal.h:129
GLSLA
#define GLSLA(...)
Definition: vulkan.h:49
FFVkQueueFamilyCtx::nb_queues
int nb_queues
Definition: vulkan.h:112
status
ov_status_e status
Definition: dnn_backend_openvino.c:121
free_data_buf
static void free_data_buf(void *opaque, uint8_t *data)
Definition: vulkan.c:1070
FFVkSPIRVShader
Definition: vulkan.h:75
FFVulkanPipeline::desc_set
FFVulkanDescriptorSet * desc_set
Definition: vulkan.h:146
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:112
init_pipeline_layout
static int init_pipeline_layout(FFVulkanContext *s, FFVulkanPipeline *pl)
Definition: vulkan.c:1750
FFVkSPIRVShader::subgroup_info
VkPipelineShaderStageRequiredSubgroupSizeCreateInfo subgroup_info
Definition: vulkan.h:80
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:312
desc
const char * desc
Definition: libsvtav1.c:75
GLSLC
#define GLSLC(N, S)
Definition: vulkan.h:44
ff_vk_set_descriptor_buffer
int ff_vk_set_descriptor_buffer(FFVulkanContext *s, FFVulkanPipeline *pl, FFVkExecContext *e, int set, int bind, int offs, VkDeviceAddress addr, VkDeviceSize len, VkFormat fmt)
Definition: vulkan.c:1682
mem.h
AVVkFrame::layout
VkImageLayout layout[AV_NUM_DATA_POINTERS]
Definition: hwcontext_vulkan.h:296
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
FFVkExecPool::cmd_bufs
VkCommandBuffer * cmd_bufs
Definition: vulkan.h:215
FFVkSPIRVShader::name
const char * name
Definition: vulkan.h:76
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
FFVkSPIRVShader::local_size
int local_size[3]
Definition: vulkan.h:78
ff_vk_exec_discard_deps
void ff_vk_exec_discard_deps(FFVulkanContext *s, FFVkExecContext *e)
Definition: vulkan.c:549
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
ff_vk_init_sampler
int ff_vk_init_sampler(FFVulkanContext *s, VkSampler *sampler, int unnorm_coords, VkFilter filt)
Create a sampler.
Definition: vulkan.c:1163
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
FFVkExecContext::buf_deps_alloc_size
unsigned int buf_deps_alloc_size
Definition: vulkan.h:175
FFVkExecContext::buf_deps
AVBufferRef ** buf_deps
Definition: vulkan.h:173
FFVkBuffer
Definition: vulkan.h:95
ff_vk_exec_pipeline_register
int ff_vk_exec_pipeline_register(FFVulkanContext *s, FFVkExecPool *pool, FFVulkanPipeline *pl)
Register a pipeline with an exec pool.
Definition: vulkan.c:1579
int32_t
int32_t
Definition: audioconvert.c:56
ff_vk_exec_submit
int ff_vk_exec_submit(FFVulkanContext *s, FFVkExecContext *e)
Definition: vulkan.c:724
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:474
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
FFVkExecPool::qd_size
size_t qd_size
Definition: vulkan.h:225
FFVulkanDescriptorSet
Definition: vulkan.h:115
ff_vk_create_imageviews
int ff_vk_create_imageviews(FFVulkanContext *s, FFVkExecContext *e, VkImageView views[AV_NUM_DATA_POINTERS], AVFrame *f)
Create an imageview and add it as a dependency to an execution.
Definition: vulkan.c:1231
FFVulkanPipeline::desc_bind
VkDescriptorBufferBindingInfoEXT * desc_bind
Definition: vulkan.h:147
ff_vk_shader_free
void ff_vk_shader_free(FFVulkanContext *s, FFVkSPIRVShader *shd)
Definition: vulkan.c:1406
FFVkExecPool::query_results
int query_results
Definition: vulkan.h:220
FFVkExecContext::sem_sig_val_dst
uint64_t ** sem_sig_val_dst
Definition: vulkan.h:190
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:163
CASE
#define CASE(VAL)
FFVulkanFunctions
Definition: vulkan_functions.h:226
FFVkExecPool::pool_size
int pool_size
Definition: vulkan.h:216
update_set_descriptor
static void update_set_descriptor(FFVulkanContext *s, FFVkExecContext *e, FFVulkanDescriptorSet *set, int bind_idx, int array_idx, VkDescriptorGetInfoEXT *desc_get_info, size_t desc_size)
Definition: vulkan.c:1620
FFVkExecPool::cmd_buf_pool
VkCommandPool cmd_buf_pool
Definition: vulkan.h:214
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:1091
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:970
FFVkExecContext::idx
uint32_t idx
Definition: vulkan.h:153
FFVulkanPipeline::bound_buffer_indices
uint32_t * bound_buffer_indices
Definition: vulkan.h:148
FFVkQueueFamilyCtx::queue_family
int queue_family
Definition: vulkan.h:111
pthread_mutex_lock
#define pthread_mutex_lock(a)
Definition: ffprobe.c:78
FFVkExecContext::access_dst
VkAccessFlagBits * access_dst
Definition: vulkan.h:197