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 
23 #include "vulkan.h"
24 #include "vulkan_loader.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  qf |= pool->query_64bit ?
460  VK_QUERY_RESULT_64_BIT : 0x0;
461  qf |= pool->query_statuses ?
462  VK_QUERY_RESULT_WITH_STATUS_BIT_KHR : 0x0;
463 
464  ret = vk->GetQueryPoolResults(s->hwctx->act_dev, pool->query_pool,
465  e->query_idx,
466  pool->nb_queries,
467  pool->qd_size, e->query_data,
468  pool->query_64bit ? 8 : 4, qf);
469  if (ret != VK_SUCCESS)
470  return ret;
471 
472  if (pool->query_statuses && pool->query_64bit) {
473  for (int i = 0; i < pool->query_statuses; i++) {
474  res = (res64[i] < res) || (res >= 0 && res64[i] > res) ?
475  res64[i] : res;
476  res64 += pool->query_status_stride;
477  }
478  } else if (pool->query_statuses) {
479  for (int i = 0; i < pool->query_statuses; i++) {
480  res = (res32[i] < res) || (res >= 0 && res32[i] > res) ?
481  res32[i] : res;
482  res32 += pool->query_status_stride;
483  }
484  }
485 
486  if (data)
487  *data = e->query_data;
488  if (status)
489  *status = res;
490 
491  return VK_SUCCESS;
492 }
493 
495 {
496  uint32_t idx = pool->idx++;
497  idx %= pool->pool_size;
498  return &pool->contexts[idx];
499 }
500 
502 {
503  FFVulkanFunctions *vk = &s->vkfn;
505  vk->WaitForFences(s->hwctx->act_dev, 1, &e->fence, VK_TRUE, UINT64_MAX);
508 }
509 
511 {
512  VkResult ret;
513  FFVulkanFunctions *vk = &s->vkfn;
514  const FFVkExecPool *pool = e->parent;
515 
516  VkCommandBufferBeginInfo cmd_start = {
517  .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
518  .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
519  };
520 
521  /* Wait for the fence to be signalled */
522  vk->WaitForFences(s->hwctx->act_dev, 1, &e->fence, VK_TRUE, UINT64_MAX);
523 
524  /* vkResetFences is defined as being host-synchronized */
526  vk->ResetFences(s->hwctx->act_dev, 1, &e->fence);
528 
529  /* Discard queue dependencies */
531 
532  ret = vk->BeginCommandBuffer(e->buf, &cmd_start);
533  if (ret != VK_SUCCESS) {
534  av_log(s, AV_LOG_ERROR, "Failed to start command recoding: %s\n",
535  ff_vk_ret2str(ret));
536  return AVERROR_EXTERNAL;
537  }
538 
539  if (pool->nb_queries)
540  vk->CmdResetQueryPool(e->buf, pool->query_pool,
541  e->query_idx, pool->nb_queries);
542 
543  return 0;
544 }
545 
547 {
548  for (int j = 0; j < e->nb_buf_deps; j++)
549  av_buffer_unref(&e->buf_deps[j]);
550  e->nb_buf_deps = 0;
551 
552  for (int j = 0; j < e->nb_frame_deps; j++) {
553  AVFrame *f = e->frame_deps[j];
554  if (e->frame_locked[j]) {
555  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
556  AVVulkanFramesContext *vkfc = hwfc->hwctx;
557  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
558  vkfc->unlock_frame(hwfc, vkf);
559  e->frame_locked[j] = 0;
560  }
561  e->frame_update[j] = 0;
562  if (f->buf[0])
563  av_frame_free(&e->frame_deps[j]);
564  }
565  e->nb_frame_deps = 0;
566 
567  e->sem_wait_cnt = 0;
568  e->sem_sig_cnt = 0;
569  e->sem_sig_val_dst_cnt = 0;
570 }
571 
573  AVBufferRef **deps, int nb_deps, int ref)
574 {
576  (e->nb_buf_deps + nb_deps) * sizeof(*dst));
577  if (!dst) {
579  return AVERROR(ENOMEM);
580  }
581 
582  e->buf_deps = dst;
583 
584  for (int i = 0; i < nb_deps; i++) {
585  e->buf_deps[e->nb_buf_deps] = ref ? av_buffer_ref(deps[i]) : deps[i];
586  if (!e->buf_deps[e->nb_buf_deps]) {
588  return AVERROR(ENOMEM);
589  }
590  e->nb_buf_deps++;
591  }
592 
593  return 0;
594 }
595 
597  VkPipelineStageFlagBits2 wait_stage,
598  VkPipelineStageFlagBits2 signal_stage)
599 {
600  uint8_t *frame_locked;
601  uint8_t *frame_update;
602  AVFrame **frame_deps;
603  VkImageLayout *layout_dst;
604  uint32_t *queue_family_dst;
605  VkAccessFlagBits *access_dst;
606 
607  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
608  AVVulkanFramesContext *vkfc = hwfc->hwctx;
609  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
610  int nb_images = ff_vk_count_images(vkf);
611 
612  /* Don't add duplicates */
613  for (int i = 0; i < e->nb_frame_deps; i++)
614  if (e->frame_deps[i]->data[0] == f->data[0])
615  return 1;
616 
617 #define ARR_REALLOC(str, arr, alloc_s, cnt) \
618  do { \
619  arr = av_fast_realloc(str->arr, alloc_s, (cnt + 1)*sizeof(*arr)); \
620  if (!arr) { \
621  ff_vk_exec_discard_deps(s, e); \
622  return AVERROR(ENOMEM); \
623  } \
624  str->arr = arr; \
625  } while (0)
626 
627  ARR_REALLOC(e, layout_dst, &e->layout_dst_alloc, e->nb_frame_deps);
628  ARR_REALLOC(e, queue_family_dst, &e->queue_family_dst_alloc, e->nb_frame_deps);
629  ARR_REALLOC(e, access_dst, &e->access_dst_alloc, e->nb_frame_deps);
630 
631  ARR_REALLOC(e, frame_locked, &e->frame_locked_alloc_size, e->nb_frame_deps);
632  ARR_REALLOC(e, frame_update, &e->frame_update_alloc_size, e->nb_frame_deps);
633  ARR_REALLOC(e, frame_deps, &e->frame_deps_alloc_size, e->nb_frame_deps);
634 
635  e->frame_deps[e->nb_frame_deps] = f->buf[0] ? av_frame_clone(f) : f;
636  if (!e->frame_deps[e->nb_frame_deps]) {
638  return AVERROR(ENOMEM);
639  }
640 
641  vkfc->lock_frame(hwfc, vkf);
642  e->frame_locked[e->nb_frame_deps] = 1;
643  e->frame_update[e->nb_frame_deps] = 0;
644  e->nb_frame_deps++;
645 
646  for (int i = 0; i < nb_images; i++) {
647  VkSemaphoreSubmitInfo *sem_wait;
648  VkSemaphoreSubmitInfo *sem_sig;
649  uint64_t **sem_sig_val_dst;
650 
652  ARR_REALLOC(e, sem_sig, &e->sem_sig_alloc, e->sem_sig_cnt);
653  ARR_REALLOC(e, sem_sig_val_dst, &e->sem_sig_val_dst_alloc, e->sem_sig_val_dst_cnt);
654 
655  e->sem_wait[e->sem_wait_cnt++] = (VkSemaphoreSubmitInfo) {
656  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
657  .semaphore = vkf->sem[i],
658  .value = vkf->sem_value[i],
659  .stageMask = wait_stage,
660  };
661 
662  e->sem_sig[e->sem_sig_cnt++] = (VkSemaphoreSubmitInfo) {
663  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
664  .semaphore = vkf->sem[i],
665  .value = vkf->sem_value[i] + 1,
666  .stageMask = signal_stage,
667  };
668 
669  e->sem_sig_val_dst[e->sem_sig_val_dst_cnt] = &vkf->sem_value[i];
670  e->sem_sig_val_dst_cnt++;
671  }
672 
673  return 0;
674 }
675 
677  VkImageMemoryBarrier2 *bar, uint32_t *nb_img_bar)
678 {
679  int i;
680  for (i = 0; i < e->nb_frame_deps; i++)
681  if (e->frame_deps[i]->data[0] == f->data[0])
682  break;
683  av_assert0(i < e->nb_frame_deps);
684 
685  /* Don't update duplicates */
686  if (nb_img_bar && !e->frame_update[i])
687  (*nb_img_bar)++;
688 
689  e->queue_family_dst[i] = bar->dstQueueFamilyIndex;
690  e->access_dst[i] = bar->dstAccessMask;
691  e->layout_dst[i] = bar->newLayout;
692  e->frame_update[i] = 1;
693 }
694 
696  VkSemaphore *dst, uint64_t *dst_val,
697  AVFrame *f)
698 {
699  uint64_t **sem_sig_val_dst;
700  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
701 
702  /* Reject unknown frames */
703  int i;
704  for (i = 0; i < e->nb_frame_deps; i++)
705  if (e->frame_deps[i]->data[0] == f->data[0])
706  break;
707  if (i == e->nb_frame_deps)
708  return AVERROR(EINVAL);
709 
710  ARR_REALLOC(e, sem_sig_val_dst, &e->sem_sig_val_dst_alloc, e->sem_sig_val_dst_cnt);
711 
712  *dst = vkf->sem[0];
713  *dst_val = vkf->sem_value[0];
714 
715  e->sem_sig_val_dst[e->sem_sig_val_dst_cnt] = dst_val;
716  e->sem_sig_val_dst_cnt++;
717 
718  return 0;
719 }
720 
722 {
723  VkResult ret;
724  FFVulkanFunctions *vk = &s->vkfn;
725  VkCommandBufferSubmitInfo cmd_buf_info = (VkCommandBufferSubmitInfo) {
726  .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
727  .commandBuffer = e->buf,
728  };
729  VkSubmitInfo2 submit_info = (VkSubmitInfo2) {
730  .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
731  .pCommandBufferInfos = &cmd_buf_info,
732  .commandBufferInfoCount = 1,
733  .pWaitSemaphoreInfos = e->sem_wait,
734  .waitSemaphoreInfoCount = e->sem_wait_cnt,
735  .pSignalSemaphoreInfos = e->sem_sig,
736  .signalSemaphoreInfoCount = e->sem_sig_cnt,
737  };
738 
739  ret = vk->EndCommandBuffer(e->buf);
740  if (ret != VK_SUCCESS) {
741  av_log(s, AV_LOG_ERROR, "Unable to finish command buffer: %s\n",
742  ff_vk_ret2str(ret));
744  return AVERROR_EXTERNAL;
745  }
746 
747  s->hwctx->lock_queue(s->device, e->qf, e->qi);
748  ret = vk->QueueSubmit2(e->queue, 1, &submit_info, e->fence);
749  s->hwctx->unlock_queue(s->device, e->qf, e->qi);
750 
751  if (ret != VK_SUCCESS) {
752  av_log(s, AV_LOG_ERROR, "Unable to submit command buffer: %s\n",
753  ff_vk_ret2str(ret));
755  return AVERROR_EXTERNAL;
756  }
757 
758  for (int i = 0; i < e->sem_sig_val_dst_cnt; i++)
759  *e->sem_sig_val_dst[i] += 1;
760 
761  /* Unlock all frames */
762  for (int j = 0; j < e->nb_frame_deps; j++) {
763  if (e->frame_locked[j]) {
764  AVFrame *f = e->frame_deps[j];
765  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
766  AVVulkanFramesContext *vkfc = hwfc->hwctx;
767  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
768 
769  if (e->frame_update[j]) {
770  int nb_images = ff_vk_count_images(vkf);
771  for (int i = 0; i < nb_images; i++) {
772  vkf->layout[i] = e->layout_dst[j];
773  vkf->access[i] = e->access_dst[j];
774  vkf->queue_family[i] = e->queue_family_dst[j];
775  }
776  }
777  vkfc->unlock_frame(hwfc, vkf);
778  e->frame_locked[j] = 0;
779  }
780  }
781 
782  return 0;
783 }
784 
785 int ff_vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req,
786  VkMemoryPropertyFlagBits req_flags, void *alloc_extension,
787  VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem)
788 {
789  VkResult ret;
790  int index = -1;
791  FFVulkanFunctions *vk = &s->vkfn;
792 
793  VkMemoryAllocateInfo alloc_info = {
794  .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
795  .pNext = alloc_extension,
796  };
797 
798  /* Align if we need to */
799  if ((req_flags != UINT32_MAX) && req_flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
800  req->size = FFALIGN(req->size, s->props.properties.limits.minMemoryMapAlignment);
801 
802  alloc_info.allocationSize = req->size;
803 
804  /* The vulkan spec requires memory types to be sorted in the "optimal"
805  * order, so the first matching type we find will be the best/fastest one */
806  for (int i = 0; i < s->mprops.memoryTypeCount; i++) {
807  /* The memory type must be supported by the requirements (bitfield) */
808  if (!(req->memoryTypeBits & (1 << i)))
809  continue;
810 
811  /* The memory type flags must include our properties */
812  if ((req_flags != UINT32_MAX) &&
813  ((s->mprops.memoryTypes[i].propertyFlags & req_flags) != req_flags))
814  continue;
815 
816  /* Found a suitable memory type */
817  index = i;
818  break;
819  }
820 
821  if (index < 0) {
822  av_log(s->device, AV_LOG_ERROR, "No memory type found for flags 0x%x\n",
823  req_flags);
824  return AVERROR(EINVAL);
825  }
826 
827  alloc_info.memoryTypeIndex = index;
828 
829  ret = vk->AllocateMemory(s->hwctx->act_dev, &alloc_info,
830  s->hwctx->alloc, mem);
831  if (ret != VK_SUCCESS) {
832  av_log(s, AV_LOG_ERROR, "Failed to allocate memory: %s\n",
833  ff_vk_ret2str(ret));
834  return AVERROR(ENOMEM);
835  }
836 
837  if (mem_flags)
838  *mem_flags |= s->mprops.memoryTypes[index].propertyFlags;
839 
840  return 0;
841 }
842 
844  void *pNext, void *alloc_pNext,
845  VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags)
846 {
847  int err;
848  VkResult ret;
849  int use_ded_mem;
850  FFVulkanFunctions *vk = &s->vkfn;
851 
852  VkBufferCreateInfo buf_spawn = {
853  .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
854  .pNext = pNext,
855  .usage = usage,
856  .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
857  .size = size, /* Gets FFALIGNED during alloc if host visible
858  but should be ok */
859  };
860 
861  VkMemoryAllocateFlagsInfo alloc_flags = {
862  .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
863  .flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT,
864  };
865  VkBufferMemoryRequirementsInfo2 req_desc = {
866  .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
867  };
868  VkMemoryDedicatedAllocateInfo ded_alloc = {
869  .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
870  .pNext = alloc_pNext,
871  };
872  VkMemoryDedicatedRequirements ded_req = {
873  .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
874  };
875  VkMemoryRequirements2 req = {
876  .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
877  .pNext = &ded_req,
878  };
879 
880  ret = vk->CreateBuffer(s->hwctx->act_dev, &buf_spawn, NULL, &buf->buf);
881  if (ret != VK_SUCCESS) {
882  av_log(s, AV_LOG_ERROR, "Failed to create buffer: %s\n",
883  ff_vk_ret2str(ret));
884  return AVERROR_EXTERNAL;
885  }
886 
887  req_desc.buffer = buf->buf;
888 
889  vk->GetBufferMemoryRequirements2(s->hwctx->act_dev, &req_desc, &req);
890 
891  /* In case the implementation prefers/requires dedicated allocation */
892  use_ded_mem = ded_req.prefersDedicatedAllocation |
893  ded_req.requiresDedicatedAllocation;
894  if (use_ded_mem) {
895  ded_alloc.buffer = buf->buf;
896  ded_alloc.pNext = alloc_pNext;
897  alloc_pNext = &ded_alloc;
898  }
899 
900  if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) {
901  alloc_flags.pNext = alloc_pNext;
902  alloc_pNext = &alloc_flags;
903  }
904 
905  err = ff_vk_alloc_mem(s, &req.memoryRequirements, flags, alloc_pNext,
906  &buf->flags, &buf->mem);
907  if (err)
908  return err;
909 
910  ret = vk->BindBufferMemory(s->hwctx->act_dev, buf->buf, buf->mem, 0);
911  if (ret != VK_SUCCESS) {
912  av_log(s, AV_LOG_ERROR, "Failed to bind memory to buffer: %s\n",
913  ff_vk_ret2str(ret));
914  return AVERROR_EXTERNAL;
915  }
916 
917  if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) {
918  VkBufferDeviceAddressInfo address_info = {
919  .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
920  .buffer = buf->buf,
921  };
922  buf->address = vk->GetBufferDeviceAddress(s->hwctx->act_dev, &address_info);
923  }
924 
925  buf->size = size;
926 
927  return 0;
928 }
929 
930 static void destroy_avvkbuf(void *opaque, uint8_t *data)
931 {
932  FFVulkanContext *s = opaque;
933  FFVkBuffer *buf = (FFVkBuffer *)data;
934  ff_vk_free_buf(s, buf);
935  av_free(buf);
936 }
937 
939  void *pNext, void *alloc_pNext,
940  VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags)
941 {
942  int err;
943  AVBufferRef *buf;
944  FFVkBuffer *vkb = av_mallocz(sizeof(*vkb));
945  if (!vkb)
946  return AVERROR(ENOMEM);
947 
948  err = ff_vk_create_buf(s, vkb, size, pNext, alloc_pNext, usage, flags);
949  if (err < 0) {
950  av_free(vkb);
951  return err;
952  }
953 
954  buf = av_buffer_create((uint8_t *)vkb, sizeof(*vkb), destroy_avvkbuf, s, 0);
955  if (!buf) {
956  destroy_avvkbuf(s, (uint8_t *)vkb);
957  return AVERROR(ENOMEM);
958  }
959 
960  *ref = buf;
961 
962  return 0;
963 }
964 
965 int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer **buf, uint8_t *mem[],
966  int nb_buffers, int invalidate)
967 {
968  VkResult ret;
969  FFVulkanFunctions *vk = &s->vkfn;
970  VkMappedMemoryRange inval_list[64];
971  int inval_count = 0;
972 
973  for (int i = 0; i < nb_buffers; i++) {
974  void *dst;
975  ret = vk->MapMemory(s->hwctx->act_dev, buf[i]->mem, 0,
976  VK_WHOLE_SIZE, 0, &dst);
977  if (ret != VK_SUCCESS) {
978  av_log(s, AV_LOG_ERROR, "Failed to map buffer memory: %s\n",
979  ff_vk_ret2str(ret));
980  return AVERROR_EXTERNAL;
981  }
982  mem[i] = dst;
983  }
984 
985  if (!invalidate)
986  return 0;
987 
988  for (int i = 0; i < nb_buffers; i++) {
989  const VkMappedMemoryRange ival_buf = {
990  .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
991  .memory = buf[i]->mem,
992  .size = VK_WHOLE_SIZE,
993  };
994  if (buf[i]->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
995  continue;
996  inval_list[inval_count++] = ival_buf;
997  }
998 
999  if (inval_count) {
1000  ret = vk->InvalidateMappedMemoryRanges(s->hwctx->act_dev, inval_count,
1001  inval_list);
1002  if (ret != VK_SUCCESS) {
1003  av_log(s, AV_LOG_ERROR, "Failed to invalidate memory: %s\n",
1004  ff_vk_ret2str(ret));
1005  return AVERROR_EXTERNAL;
1006  }
1007  }
1008 
1009  return 0;
1010 }
1011 
1012 int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer **buf, int nb_buffers,
1013  int flush)
1014 {
1015  int err = 0;
1016  VkResult ret;
1017  FFVulkanFunctions *vk = &s->vkfn;
1018  VkMappedMemoryRange flush_list[64];
1019  int flush_count = 0;
1020 
1021  if (flush) {
1022  for (int i = 0; i < nb_buffers; i++) {
1023  const VkMappedMemoryRange flush_buf = {
1024  .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
1025  .memory = buf[i]->mem,
1026  .size = VK_WHOLE_SIZE,
1027  };
1028  if (buf[i]->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
1029  continue;
1030  flush_list[flush_count++] = flush_buf;
1031  }
1032  }
1033 
1034  if (flush_count) {
1035  ret = vk->FlushMappedMemoryRanges(s->hwctx->act_dev, flush_count,
1036  flush_list);
1037  if (ret != VK_SUCCESS) {
1038  av_log(s, AV_LOG_ERROR, "Failed to flush memory: %s\n",
1039  ff_vk_ret2str(ret));
1040  err = AVERROR_EXTERNAL; /* We still want to try to unmap them */
1041  }
1042  }
1043 
1044  for (int i = 0; i < nb_buffers; i++)
1045  vk->UnmapMemory(s->hwctx->act_dev, buf[i]->mem);
1046 
1047  return err;
1048 }
1049 
1051 {
1052  FFVulkanFunctions *vk = &s->vkfn;
1053 
1054  if (!buf || !s->hwctx)
1055  return;
1056 
1057  if (buf->mapped_mem)
1058  ff_vk_unmap_buffer(s, buf, 0);
1059  if (buf->buf != VK_NULL_HANDLE)
1060  vk->DestroyBuffer(s->hwctx->act_dev, buf->buf, s->hwctx->alloc);
1061  if (buf->mem != VK_NULL_HANDLE)
1062  vk->FreeMemory(s->hwctx->act_dev, buf->mem, s->hwctx->alloc);
1063 }
1064 
1065 static void free_data_buf(void *opaque, uint8_t *data)
1066 {
1067  FFVulkanContext *ctx = opaque;
1068  FFVkBuffer *buf = (FFVkBuffer *)data;
1069  ff_vk_free_buf(ctx, buf);
1070  av_free(data);
1071 }
1072 
1073 static AVBufferRef *alloc_data_buf(void *opaque, size_t size)
1074 {
1075  AVBufferRef *ref;
1076  uint8_t *buf = av_mallocz(size);
1077  if (!buf)
1078  return NULL;
1079 
1080  ref = av_buffer_create(buf, size, free_data_buf, opaque, 0);
1081  if (!ref)
1082  av_free(buf);
1083  return ref;
1084 }
1085 
1087  AVBufferRef **buf, VkBufferUsageFlags usage,
1088  void *create_pNext, size_t size,
1089  VkMemoryPropertyFlagBits mem_props)
1090 {
1091  int err;
1092  AVBufferRef *ref;
1093  FFVkBuffer *data;
1094 
1095  if (!(*buf_pool)) {
1096  *buf_pool = av_buffer_pool_init2(sizeof(FFVkBuffer), ctx,
1097  alloc_data_buf, NULL);
1098  if (!(*buf_pool))
1099  return AVERROR(ENOMEM);
1100  }
1101 
1102  *buf = ref = av_buffer_pool_get(*buf_pool);
1103  if (!ref)
1104  return AVERROR(ENOMEM);
1105 
1106  data = (FFVkBuffer *)ref->data;
1107  data->stage = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
1108  data->access = VK_ACCESS_2_NONE;
1109 
1110  if (data->size >= size)
1111  return 0;
1112 
1114  memset(data, 0, sizeof(*data));
1115 
1116  av_log(ctx, AV_LOG_DEBUG, "Allocating buffer of %"SIZE_SPECIFIER" bytes for pool %p\n",
1117  size, *buf_pool);
1118 
1119  err = ff_vk_create_buf(ctx, data, size,
1120  create_pNext, NULL, usage,
1121  mem_props);
1122  if (err < 0) {
1123  av_buffer_unref(&ref);
1124  return err;
1125  }
1126 
1127  if (mem_props & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
1128  err = ff_vk_map_buffer(ctx, data, &data->mapped_mem, 0);
1129  if (err < 0) {
1130  av_buffer_unref(&ref);
1131  return err;
1132  }
1133  }
1134 
1135  return 0;
1136 }
1137 
1139  VkShaderStageFlagBits stage)
1140 {
1141  VkPushConstantRange *pc;
1142 
1143  pl->push_consts = av_realloc_array(pl->push_consts, sizeof(*pl->push_consts),
1144  pl->push_consts_num + 1);
1145  if (!pl->push_consts)
1146  return AVERROR(ENOMEM);
1147 
1148  pc = &pl->push_consts[pl->push_consts_num++];
1149  memset(pc, 0, sizeof(*pc));
1150 
1151  pc->stageFlags = stage;
1152  pc->offset = offset;
1153  pc->size = size;
1154 
1155  return 0;
1156 }
1157 
1158 int ff_vk_init_sampler(FFVulkanContext *s, VkSampler *sampler,
1159  int unnorm_coords, VkFilter filt)
1160 {
1161  VkResult ret;
1162  FFVulkanFunctions *vk = &s->vkfn;
1163 
1164  VkSamplerCreateInfo sampler_info = {
1165  .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
1166  .magFilter = filt,
1167  .minFilter = sampler_info.magFilter,
1168  .mipmapMode = unnorm_coords ? VK_SAMPLER_MIPMAP_MODE_NEAREST :
1169  VK_SAMPLER_MIPMAP_MODE_LINEAR,
1170  .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1171  .addressModeV = sampler_info.addressModeU,
1172  .addressModeW = sampler_info.addressModeU,
1173  .anisotropyEnable = VK_FALSE,
1174  .compareOp = VK_COMPARE_OP_NEVER,
1175  .borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
1176  .unnormalizedCoordinates = unnorm_coords,
1177  };
1178 
1179  ret = vk->CreateSampler(s->hwctx->act_dev, &sampler_info,
1180  s->hwctx->alloc, sampler);
1181  if (ret != VK_SUCCESS) {
1182  av_log(s, AV_LOG_ERROR, "Unable to init sampler: %s\n",
1183  ff_vk_ret2str(ret));
1184  return AVERROR_EXTERNAL;
1185  }
1186 
1187  return 0;
1188 }
1189 
1191 {
1198  return 1;
1199  return 0;
1200 }
1201 
1203 {
1205  const int high = desc->comp[0].depth > 8;
1206  return high ? "rgba16f" : "rgba8";
1207 }
1208 
1209 typedef struct ImageViewCtx {
1212 } ImageViewCtx;
1213 
1214 static void destroy_imageviews(void *opaque, uint8_t *data)
1215 {
1216  FFVulkanContext *s = opaque;
1217  FFVulkanFunctions *vk = &s->vkfn;
1218  ImageViewCtx *iv = (ImageViewCtx *)data;
1219 
1220  for (int i = 0; i < iv->nb_views; i++)
1221  vk->DestroyImageView(s->hwctx->act_dev, iv->views[i], s->hwctx->alloc);
1222 
1223  av_free(iv);
1224 }
1225 
1227  VkImageView views[AV_NUM_DATA_POINTERS],
1228  AVFrame *f)
1229 {
1230  int err;
1231  VkResult ret;
1232  AVBufferRef *buf;
1233  FFVulkanFunctions *vk = &s->vkfn;
1234  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
1235  const VkFormat *rep_fmts = av_vkfmt_from_pixfmt(hwfc->sw_format);
1236  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
1237  const int nb_images = ff_vk_count_images(vkf);
1238  const int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format);
1239 
1240  ImageViewCtx *iv = av_mallocz(sizeof(*iv));
1241  if (!iv)
1242  return AVERROR(ENOMEM);
1243 
1244  for (int i = 0; i < nb_planes; i++) {
1245  VkImageAspectFlags plane_aspect[] = { VK_IMAGE_ASPECT_COLOR_BIT,
1246  VK_IMAGE_ASPECT_PLANE_0_BIT,
1247  VK_IMAGE_ASPECT_PLANE_1_BIT,
1248  VK_IMAGE_ASPECT_PLANE_2_BIT, };
1249 
1250  VkImageViewCreateInfo view_create_info = {
1251  .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
1252  .pNext = NULL,
1253  .image = vkf->img[FFMIN(i, nb_images - 1)],
1254  .viewType = VK_IMAGE_VIEW_TYPE_2D,
1255  .format = rep_fmts[i],
1256  .components = ff_comp_identity_map,
1257  .subresourceRange = {
1258  .aspectMask = plane_aspect[(nb_planes != nb_images) +
1259  i*(nb_planes != nb_images)],
1260  .levelCount = 1,
1261  .layerCount = 1,
1262  },
1263  };
1264 
1265  ret = vk->CreateImageView(s->hwctx->act_dev, &view_create_info,
1266  s->hwctx->alloc, &iv->views[i]);
1267  if (ret != VK_SUCCESS) {
1268  av_log(s, AV_LOG_ERROR, "Failed to create imageview: %s\n",
1269  ff_vk_ret2str(ret));
1270  err = AVERROR_EXTERNAL;
1271  goto fail;
1272  }
1273 
1274  iv->nb_views++;
1275  }
1276 
1277  buf = av_buffer_create((uint8_t *)iv, sizeof(*iv), destroy_imageviews, s, 0);
1278  if (!buf) {
1279  err = AVERROR(ENOMEM);
1280  goto fail;
1281  }
1282 
1283  /* Add to queue dependencies */
1284  err = ff_vk_exec_add_dep_buf(s, e, &buf, 1, 0);
1285  if (err < 0)
1286  av_buffer_unref(&buf);
1287 
1288  memcpy(views, iv->views, nb_planes*sizeof(*views));
1289 
1290  return err;
1291 
1292 fail:
1293  for (int i = 0; i < iv->nb_views; i++)
1294  vk->DestroyImageView(s->hwctx->act_dev, iv->views[i], s->hwctx->alloc);
1295  av_free(iv);
1296  return err;
1297 }
1298 
1300  AVFrame *pic, VkImageMemoryBarrier2 *bar, int *nb_bar,
1301  VkPipelineStageFlags src_stage,
1302  VkPipelineStageFlags dst_stage,
1303  VkAccessFlagBits new_access,
1304  VkImageLayout new_layout,
1305  uint32_t new_qf)
1306 {
1307  int i, found;
1308  AVVkFrame *vkf = (AVVkFrame *)pic->data[0];
1309  const int nb_images = ff_vk_count_images(vkf);
1310  for (i = 0; i < e->nb_frame_deps; i++)
1311  if (e->frame_deps[i]->data[0] == pic->data[0])
1312  break;
1313  found = (i < e->nb_frame_deps) && (e->frame_update[i]) ? i : -1;
1314 
1315  for (int i = 0; i < nb_images; i++) {
1316  bar[*nb_bar] = (VkImageMemoryBarrier2) {
1317  .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
1318  .pNext = NULL,
1319  .srcStageMask = src_stage,
1320  .dstStageMask = dst_stage,
1321  .srcAccessMask = found >= 0 ? e->access_dst[found] : vkf->access[i],
1322  .dstAccessMask = new_access,
1323  .oldLayout = found >= 0 ? e->layout_dst[found] : vkf->layout[0],
1324  .newLayout = new_layout,
1325  .srcQueueFamilyIndex = found >= 0 ? e->queue_family_dst[found] : vkf->queue_family[0],
1326  .dstQueueFamilyIndex = new_qf,
1327  .image = vkf->img[i],
1328  .subresourceRange = (VkImageSubresourceRange) {
1329  .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
1330  .layerCount = 1,
1331  .levelCount = 1,
1332  },
1333  };
1334  *nb_bar += 1;
1335  }
1336 
1337  ff_vk_exec_update_frame(s, e, pic, &bar[*nb_bar - nb_images], NULL);
1338 }
1339 
1341  VkShaderStageFlags stage, uint32_t required_subgroup_size)
1342 {
1344 
1345  shd->shader.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
1346  shd->shader.stage = stage;
1347 
1348  if (required_subgroup_size) {
1349  shd->shader.flags |= VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT;
1350  shd->shader.pNext = &shd->subgroup_info;
1351  shd->subgroup_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO;
1352  shd->subgroup_info.requiredSubgroupSize = required_subgroup_size;
1353  }
1354 
1355  shd->name = name;
1356 
1357  GLSLF(0, #version %i ,460);
1358  GLSLC(0, #define IS_WITHIN(v1, v2) ((v1.x < v2.x) && (v1.y < v2.y)) );
1359  GLSLC(0, );
1360  GLSLC(0, #extension GL_EXT_buffer_reference : require );
1361  GLSLC(0, #extension GL_EXT_buffer_reference2 : require );
1362 
1363  return 0;
1364 }
1365 
1366 void ff_vk_shader_set_compute_sizes(FFVkSPIRVShader *shd, int x, int y, int z)
1367 {
1368  shd->local_size[0] = x;
1369  shd->local_size[1] = y;
1370  shd->local_size[2] = z;
1371 
1372  av_bprintf(&shd->src, "layout (local_size_x = %i, "
1373  "local_size_y = %i, local_size_z = %i) in;\n\n",
1374  shd->local_size[0], shd->local_size[1], shd->local_size[2]);
1375 }
1376 
1377 void ff_vk_shader_print(void *ctx, FFVkSPIRVShader *shd, int prio)
1378 {
1379  int line = 0;
1380  const char *p = shd->src.str;
1381  const char *start = p;
1382  const size_t len = strlen(p);
1383 
1384  AVBPrint buf;
1386 
1387  for (int i = 0; i < len; i++) {
1388  if (p[i] == '\n') {
1389  av_bprintf(&buf, "%i\t", ++line);
1390  av_bprint_append_data(&buf, start, &p[i] - start + 1);
1391  start = &p[i + 1];
1392  }
1393  }
1394 
1395  av_log(ctx, prio, "Shader %s: \n%s", shd->name, buf.str);
1396  av_bprint_finalize(&buf, NULL);
1397 }
1398 
1400 {
1401  FFVulkanFunctions *vk = &s->vkfn;
1402  av_bprint_finalize(&shd->src, NULL);
1403 
1404  if (shd->shader.module)
1405  vk->DestroyShaderModule(s->hwctx->act_dev, shd->shader.module, s->hwctx->alloc);
1406 }
1407 
1409  uint8_t *spirv, size_t spirv_size, const char *entrypoint)
1410 {
1411  VkResult ret;
1412  FFVulkanFunctions *vk = &s->vkfn;
1413  VkShaderModuleCreateInfo shader_create;
1414 
1415  shd->shader.pName = entrypoint;
1416 
1417  av_log(s, AV_LOG_VERBOSE, "Shader %s compiled! Size: %zu bytes\n",
1418  shd->name, spirv_size);
1419 
1420  shader_create.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
1421  shader_create.pNext = NULL;
1422  shader_create.codeSize = spirv_size;
1423  shader_create.flags = 0;
1424  shader_create.pCode = (void *)spirv;
1425 
1426  ret = vk->CreateShaderModule(s->hwctx->act_dev, &shader_create, NULL,
1427  &shd->shader.module);
1428  if (ret != VK_SUCCESS) {
1429  av_log(s, AV_LOG_VERBOSE, "Error creating shader module: %s\n",
1430  ff_vk_ret2str(ret));
1431  return AVERROR_EXTERNAL;
1432  }
1433 
1434  return 0;
1435 }
1436 
1437 static const struct descriptor_props {
1438  size_t struct_size; /* Size of the opaque which updates the descriptor */
1439  const char *type;
1441  int mem_quali; /* Can use a memory qualifier */
1442  int dim_needed; /* Must indicate dimension */
1443  int buf_content; /* Must indicate buffer contents */
1444 } descriptor_props[] = {
1445  [VK_DESCRIPTOR_TYPE_SAMPLER] = { sizeof(VkDescriptorImageInfo), "sampler", 1, 0, 0, 0, },
1446  [VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE] = { sizeof(VkDescriptorImageInfo), "texture", 1, 0, 1, 0, },
1447  [VK_DESCRIPTOR_TYPE_STORAGE_IMAGE] = { sizeof(VkDescriptorImageInfo), "image", 1, 1, 1, 0, },
1448  [VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT] = { sizeof(VkDescriptorImageInfo), "subpassInput", 1, 0, 0, 0, },
1449  [VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER] = { sizeof(VkDescriptorImageInfo), "sampler", 1, 0, 1, 0, },
1450  [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER] = { sizeof(VkDescriptorBufferInfo), NULL, 1, 0, 0, 1, },
1451  [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER] = { sizeof(VkDescriptorBufferInfo), "buffer", 0, 1, 0, 1, },
1452  [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo), NULL, 1, 0, 0, 1, },
1453  [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo), "buffer", 0, 1, 0, 1, },
1454  [VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER] = { sizeof(VkBufferView), "samplerBuffer", 1, 0, 0, 0, },
1455  [VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER] = { sizeof(VkBufferView), "imageBuffer", 1, 0, 0, 0, },
1456 };
1457 
1459  FFVkSPIRVShader *shd,
1461  int read_only, int print_to_shader_only)
1462 {
1463  VkResult ret;
1464  int has_sampler = 0;
1465  FFVulkanFunctions *vk = &s->vkfn;
1467  VkDescriptorSetLayoutCreateInfo desc_create_layout;
1468 
1469  if (print_to_shader_only)
1470  goto print;
1471 
1472  /* Actual layout allocated for the pipeline */
1473  set = av_realloc_array(pl->desc_set, sizeof(*pl->desc_set),
1474  pl->nb_descriptor_sets + 1);
1475  if (!set)
1476  return AVERROR(ENOMEM);
1477  pl->desc_set = set;
1478  set = &set[pl->nb_descriptor_sets];
1479  memset(set, 0, sizeof(*set));
1480 
1481  set->binding = av_calloc(nb, sizeof(*set->binding));
1482  if (!set->binding)
1483  return AVERROR(ENOMEM);
1484 
1485  set->binding_offset = av_calloc(nb, sizeof(*set->binding_offset));
1486  if (!set->binding_offset) {
1487  av_freep(&set->binding);
1488  return AVERROR(ENOMEM);
1489  }
1490 
1491  desc_create_layout = (VkDescriptorSetLayoutCreateInfo) {
1492  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
1493  .bindingCount = nb,
1494  .pBindings = set->binding,
1495  .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT,
1496  };
1497 
1498  for (int i = 0; i < nb; i++) {
1499  set->binding[i].binding = i;
1500  set->binding[i].descriptorType = desc[i].type;
1501  set->binding[i].descriptorCount = FFMAX(desc[i].elems, 1);
1502  set->binding[i].stageFlags = desc[i].stages;
1503  set->binding[i].pImmutableSamplers = desc[i].samplers;
1504 
1505  if (desc[i].type == VK_DESCRIPTOR_TYPE_SAMPLER ||
1506  desc[i].type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1507  has_sampler |= 1;
1508  }
1509 
1510  set->usage = VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT |
1511  VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
1512  if (has_sampler)
1513  set->usage |= VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT;
1514 
1515  ret = vk->CreateDescriptorSetLayout(s->hwctx->act_dev, &desc_create_layout,
1516  s->hwctx->alloc, &set->layout);
1517  if (ret != VK_SUCCESS) {
1518  av_log(s, AV_LOG_ERROR, "Unable to init descriptor set layout: %s",
1519  ff_vk_ret2str(ret));
1520  return AVERROR_EXTERNAL;
1521  }
1522 
1523  vk->GetDescriptorSetLayoutSizeEXT(s->hwctx->act_dev, set->layout, &set->layout_size);
1524 
1525  set->aligned_size = FFALIGN(set->layout_size, s->desc_buf_props.descriptorBufferOffsetAlignment);
1526 
1527  for (int i = 0; i < nb; i++)
1528  vk->GetDescriptorSetLayoutBindingOffsetEXT(s->hwctx->act_dev, set->layout,
1529  i, &set->binding_offset[i]);
1530 
1531  set->read_only = read_only;
1532  set->nb_bindings = nb;
1533  pl->nb_descriptor_sets++;
1534 
1535 print:
1536  /* Write shader info */
1537  for (int i = 0; i < nb; i++) {
1538  const struct descriptor_props *prop = &descriptor_props[desc[i].type];
1539  GLSLA("layout (set = %i, binding = %i", pl->nb_descriptor_sets - 1, i);
1540 
1541  if (desc[i].mem_layout)
1542  GLSLA(", %s", desc[i].mem_layout);
1543  GLSLA(")");
1544 
1545  if (prop->is_uniform)
1546  GLSLA(" uniform");
1547 
1548  if (prop->mem_quali && desc[i].mem_quali)
1549  GLSLA(" %s", desc[i].mem_quali);
1550 
1551  if (prop->type)
1552  GLSLA(" %s", prop->type);
1553 
1554  if (prop->dim_needed)
1555  GLSLA("%iD", desc[i].dimensions);
1556 
1557  GLSLA(" %s", desc[i].name);
1558 
1559  if (prop->buf_content)
1560  GLSLA(" {\n %s\n}", desc[i].buf_content);
1561  else if (desc[i].elems > 0)
1562  GLSLA("[%i]", desc[i].elems);
1563 
1564  GLSLA(";");
1565  GLSLA("\n");
1566  }
1567  GLSLA("\n");
1568 
1569  return 0;
1570 }
1571 
1573  FFVulkanPipeline *pl)
1574 {
1575  int err;
1576 
1577  pl->desc_bind = av_calloc(pl->nb_descriptor_sets, sizeof(*pl->desc_bind));
1578  if (!pl->desc_bind)
1579  return AVERROR(ENOMEM);
1580 
1582  sizeof(*pl->bound_buffer_indices));
1583  if (!pl->bound_buffer_indices)
1584  return AVERROR(ENOMEM);
1585 
1586  for (int i = 0; i < pl->nb_descriptor_sets; i++) {
1588  int nb = set->read_only ? 1 : pool->pool_size;
1589 
1590  err = ff_vk_create_buf(s, &set->buf, set->aligned_size*nb,
1591  NULL, NULL, set->usage,
1592  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
1593  VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
1594  if (err < 0)
1595  return err;
1596 
1597  err = ff_vk_map_buffer(s, &set->buf, &set->desc_mem, 0);
1598  if (err < 0)
1599  return err;
1600 
1601  pl->desc_bind[i] = (VkDescriptorBufferBindingInfoEXT) {
1602  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_INFO_EXT,
1603  .usage = set->usage,
1604  .address = set->buf.address,
1605  };
1606 
1607  pl->bound_buffer_indices[i] = i;
1608  }
1609 
1610  return 0;
1611 }
1612 
1615  int bind_idx, int array_idx,
1616  VkDescriptorGetInfoEXT *desc_get_info,
1617  size_t desc_size)
1618 {
1619  FFVulkanFunctions *vk = &s->vkfn;
1620  const size_t exec_offset = set->read_only ? 0 : set->aligned_size*e->idx;
1621  void *desc = set->desc_mem + /* Base */
1622  exec_offset + /* Execution context */
1623  set->binding_offset[bind_idx] + /* Descriptor binding */
1624  array_idx*desc_size; /* Array position */
1625 
1626  vk->GetDescriptorEXT(s->hwctx->act_dev, desc_get_info, desc_size, desc);
1627 }
1628 
1630  FFVkExecContext *e, int set, int bind, int offs,
1631  VkSampler *sampler)
1632 {
1633  FFVulkanDescriptorSet *desc_set = &pl->desc_set[set];
1634  VkDescriptorGetInfoEXT desc_get_info = {
1635  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT,
1636  .type = desc_set->binding[bind].descriptorType,
1637  };
1638 
1639  switch (desc_get_info.type) {
1640  case VK_DESCRIPTOR_TYPE_SAMPLER:
1641  desc_get_info.data.pSampler = sampler;
1642  break;
1643  default:
1644  av_log(s, AV_LOG_ERROR, "Invalid descriptor type at set %i binding %i: %i!\n",
1645  set, bind, desc_get_info.type);
1646  return AVERROR(EINVAL);
1647  break;
1648  };
1649 
1650  update_set_descriptor(s, e, desc_set, bind, offs, &desc_get_info,
1651  s->desc_buf_props.samplerDescriptorSize);
1652 
1653  return 0;
1654 }
1655 
1657  FFVkExecContext *e, int set, int bind, int offs,
1658  VkImageView view, VkImageLayout layout, VkSampler sampler)
1659 {
1660  FFVulkanDescriptorSet *desc_set = &pl->desc_set[set];
1661  VkDescriptorGetInfoEXT desc_get_info = {
1662  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT,
1663  .type = desc_set->binding[bind].descriptorType,
1664  };
1665  VkDescriptorImageInfo desc_img_info = {
1666  .imageView = view,
1667  .sampler = sampler,
1668  .imageLayout = layout,
1669  };
1670  size_t desc_size;
1671 
1672  switch (desc_get_info.type) {
1673  case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
1674  desc_get_info.data.pSampledImage = &desc_img_info;
1675  desc_size = s->desc_buf_props.sampledImageDescriptorSize;
1676  break;
1677  case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
1678  desc_get_info.data.pStorageImage = &desc_img_info;
1679  desc_size = s->desc_buf_props.storageImageDescriptorSize;
1680  break;
1681  case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
1682  desc_get_info.data.pInputAttachmentImage = &desc_img_info;
1683  desc_size = s->desc_buf_props.inputAttachmentDescriptorSize;
1684  break;
1685  case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
1686  desc_get_info.data.pCombinedImageSampler = &desc_img_info;
1687  desc_size = s->desc_buf_props.combinedImageSamplerDescriptorSize;
1688  break;
1689  default:
1690  av_log(s, AV_LOG_ERROR, "Invalid descriptor type at set %i binding %i: %i!\n",
1691  set, bind, desc_get_info.type);
1692  return AVERROR(EINVAL);
1693  break;
1694  };
1695 
1696  update_set_descriptor(s, e, desc_set, bind, offs, &desc_get_info, desc_size);
1697 
1698  return 0;
1699 }
1700 
1702  FFVkExecContext *e, int set, int bind, int offs,
1703  VkDeviceAddress addr, VkDeviceSize len, VkFormat fmt)
1704 {
1705  FFVulkanDescriptorSet *desc_set = &pl->desc_set[set];
1706  VkDescriptorGetInfoEXT desc_get_info = {
1707  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT,
1708  .type = desc_set->binding[bind].descriptorType,
1709  };
1710  VkDescriptorAddressInfoEXT desc_buf_info = {
1711  .address = addr,
1712  .range = len,
1713  .format = fmt,
1714  };
1715  size_t desc_size;
1716 
1717  switch (desc_get_info.type) {
1718  case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1719  desc_get_info.data.pUniformBuffer = &desc_buf_info;
1720  desc_size = s->desc_buf_props.uniformBufferDescriptorSize;
1721  break;
1722  case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1723  desc_get_info.data.pStorageBuffer = &desc_buf_info;
1724  desc_size = s->desc_buf_props.storageBufferDescriptorSize;
1725  break;
1726  case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1727  desc_get_info.data.pUniformTexelBuffer = &desc_buf_info;
1728  desc_size = s->desc_buf_props.uniformTexelBufferDescriptorSize;
1729  break;
1730  case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1731  desc_get_info.data.pStorageTexelBuffer = &desc_buf_info;
1732  desc_size = s->desc_buf_props.storageTexelBufferDescriptorSize;
1733  break;
1734  default:
1735  av_log(s, AV_LOG_ERROR, "Invalid descriptor type at set %i binding %i: %i!\n",
1736  set, bind, desc_get_info.type);
1737  return AVERROR(EINVAL);
1738  break;
1739  };
1740 
1741  update_set_descriptor(s, e, desc_set, bind, offs, &desc_get_info, desc_size);
1742 
1743  return 0;
1744 }
1745 
1747  FFVkExecContext *e, AVFrame *f,
1748  VkImageView *views, int set, int binding,
1749  VkImageLayout layout, VkSampler sampler)
1750 {
1751  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
1752  const int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format);
1753 
1754  for (int i = 0; i < nb_planes; i++)
1755  ff_vk_set_descriptor_image(s, pl, e, set, binding, i,
1756  views[i], layout, sampler);
1757 }
1758 
1760  FFVulkanPipeline *pl,
1761  VkShaderStageFlagBits stage,
1762  int offset, size_t size, void *src)
1763 {
1764  FFVulkanFunctions *vk = &s->vkfn;
1765  vk->CmdPushConstants(e->buf, pl->pipeline_layout,
1766  stage, offset, size, src);
1767 }
1768 
1770 {
1771  VkResult ret;
1772  FFVulkanFunctions *vk = &s->vkfn;
1773  VkPipelineLayoutCreateInfo pipeline_layout_info;
1774 
1775  VkDescriptorSetLayout *desc_layouts = av_malloc(pl->nb_descriptor_sets*
1776  sizeof(desc_layouts));
1777  if (!desc_layouts)
1778  return AVERROR(ENOMEM);
1779 
1780  for (int i = 0; i < pl->nb_descriptor_sets; i++)
1781  desc_layouts[i] = pl->desc_set[i].layout;
1782 
1783  /* Finally create the pipeline layout */
1784  pipeline_layout_info = (VkPipelineLayoutCreateInfo) {
1785  .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1786  .pSetLayouts = desc_layouts,
1787  .setLayoutCount = pl->nb_descriptor_sets,
1788  .pushConstantRangeCount = pl->push_consts_num,
1789  .pPushConstantRanges = pl->push_consts,
1790  };
1791 
1792  ret = vk->CreatePipelineLayout(s->hwctx->act_dev, &pipeline_layout_info,
1793  s->hwctx->alloc, &pl->pipeline_layout);
1794  av_free(desc_layouts);
1795  if (ret != VK_SUCCESS) {
1796  av_log(s, AV_LOG_ERROR, "Unable to init pipeline layout: %s\n",
1797  ff_vk_ret2str(ret));
1798  return AVERROR_EXTERNAL;
1799  }
1800 
1801  return 0;
1802 }
1803 
1805  FFVkSPIRVShader *shd)
1806 {
1807  int err;
1808  VkResult ret;
1809  FFVulkanFunctions *vk = &s->vkfn;
1810 
1811  VkComputePipelineCreateInfo pipeline_create_info;
1812 
1813  err = init_pipeline_layout(s, pl);
1814  if (err < 0)
1815  return err;
1816 
1817  pipeline_create_info = (VkComputePipelineCreateInfo) {
1818  .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
1819  .flags = VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT,
1820  .layout = pl->pipeline_layout,
1821  .stage = shd->shader,
1822  };
1823 
1824  ret = vk->CreateComputePipelines(s->hwctx->act_dev, VK_NULL_HANDLE, 1,
1825  &pipeline_create_info,
1826  s->hwctx->alloc, &pl->pipeline);
1827  if (ret != VK_SUCCESS) {
1828  av_log(s, AV_LOG_ERROR, "Unable to init compute pipeline: %s\n",
1829  ff_vk_ret2str(ret));
1830  return AVERROR_EXTERNAL;
1831  }
1832 
1833  pl->bind_point = VK_PIPELINE_BIND_POINT_COMPUTE;
1834  pl->wg_size[0] = shd->local_size[0];
1835  pl->wg_size[1] = shd->local_size[1];
1836  pl->wg_size[2] = shd->local_size[2];
1837 
1838  return 0;
1839 }
1840 
1842  FFVulkanPipeline *pl)
1843 {
1844  FFVulkanFunctions *vk = &s->vkfn;
1845  VkDeviceSize offsets[1024];
1846 
1847  /* Bind pipeline */
1848  vk->CmdBindPipeline(e->buf, pl->bind_point, pl->pipeline);
1849 
1850  if (pl->nb_descriptor_sets) {
1851  for (int i = 0; i < pl->nb_descriptor_sets; i++)
1852  offsets[i] = pl->desc_set[i].read_only ? 0 : pl->desc_set[i].aligned_size*e->idx;
1853 
1854  /* Bind descriptor buffers */
1855  vk->CmdBindDescriptorBuffersEXT(e->buf, pl->nb_descriptor_sets, pl->desc_bind);
1856  /* Binding offsets */
1857  vk->CmdSetDescriptorBufferOffsetsEXT(e->buf, pl->bind_point, pl->pipeline_layout,
1858  0, pl->nb_descriptor_sets,
1860  }
1861 }
1862 
1864 {
1865  FFVulkanFunctions *vk = &s->vkfn;
1866 
1867  if (pl->pipeline)
1868  vk->DestroyPipeline(s->hwctx->act_dev, pl->pipeline, s->hwctx->alloc);
1869  if (pl->pipeline_layout)
1870  vk->DestroyPipelineLayout(s->hwctx->act_dev, pl->pipeline_layout,
1871  s->hwctx->alloc);
1872 
1873  for (int i = 0; i < pl->nb_descriptor_sets; i++) {
1875  if (set->buf.mem)
1876  ff_vk_unmap_buffer(s, &set->buf, 0);
1877  ff_vk_free_buf(s, &set->buf);
1878  if (set->layout)
1879  vk->DestroyDescriptorSetLayout(s->hwctx->act_dev, set->layout,
1880  s->hwctx->alloc);
1881  av_free(set->binding);
1882  av_free(set->binding_offset);
1883  }
1884 
1885  av_freep(&pl->desc_set);
1886  av_freep(&pl->desc_bind);
1888  av_freep(&pl->push_consts);
1889  pl->push_consts_num = 0;
1890 }
1891 
1893 {
1894  av_freep(&s->query_props);
1895  av_freep(&s->qf_props);
1896  av_freep(&s->video_props);
1897  av_freep(&s->coop_mat_props);
1898 
1899  av_buffer_unref(&s->frames_ref);
1900 }
vulkan_loader.h
FFVulkanPipeline::bind_point
VkPipelineBindPoint bind_point
Definition: vulkan.h:133
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:843
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:494
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
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:1746
ImageViewCtx::nb_views
int nb_views
Definition: vulkan.c:1211
ff_vk_pipeline_free
void ff_vk_pipeline_free(FFVulkanContext *s, FFVulkanPipeline *pl)
Definition: vulkan.c:1863
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:136
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:2936
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:121
descriptor_props::is_uniform
int is_uniform
Definition: vulkan.c:1440
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:676
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:100
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:340
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:1408
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:1073
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:101
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:69
AV_PIX_FMT_BGRA
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:95
ff_vk_uninit
void ff_vk_uninit(FFVulkanContext *s)
Frees main context.
Definition: vulkan.c:1892
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:1458
ff_vk_shader_set_compute_sizes
void ff_vk_shader_set_compute_sizes(FFVkSPIRVShader *shd, int x, int y, int z)
Definition: vulkan.c:1366
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:596
descriptor_props::type
const char * type
Definition: vulkan.c:1439
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:361
FFVkBuffer::buf
VkBuffer buf
Definition: vulkan.h:97
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:30
FFVkExecContext::lock
pthread_mutex_t lock
Definition: vulkan.h:156
ImageViewCtx
Definition: vulkan.c:1209
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:2976
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:1138
AVVkFrame::img
VkImage img[AV_NUM_DATA_POINTERS]
Vulkan images to which the memory is bound to.
Definition: hwcontext_vulkan.h:270
destroy_avvkbuf
static void destroy_avvkbuf(void *opaque, uint8_t *data)
Definition: vulkan.c:930
fail
#define fail()
Definition: checkasm.h:138
FFVulkanPipeline::wg_size
int wg_size[3]
Definition: vulkan.h:144
ff_vk_unmap_buffers
int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer **buf, int nb_buffers, int flush)
Definition: vulkan.c:1012
FFVulkanDescriptorSet::read_only
int read_only
Definition: vulkan.h:129
AVVulkanFramesContext
Allocated as AVHWFramesContext.hwctx, used to set pool-specific options.
Definition: hwcontext_vulkan.h:176
FFVulkanPipeline::pipeline
VkPipeline pipeline
Definition: vulkan.h:137
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:117
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_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:1438
FFVulkanDescriptorSet::binding
VkDescriptorSetLayoutBinding * binding
Definition: vulkan.h:125
avassert.h
FFVulkanPipeline::nb_descriptor_sets
int nb_descriptor_sets
Definition: vulkan.h:150
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:938
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:495
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:695
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:215
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:501
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:48
av_frame_clone
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
Definition: frame.c:609
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:572
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:1841
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:93
FFVkExecPool::query_status_stride
int query_status_stride
Definition: vulkan.h:223
FFVkExecContext::parent
const struct FFVkExecPool * parent
Definition: vulkan.h:155
if
if(ret)
Definition: filter_design.txt:179
ImageViewCtx::views
VkImageView views[AV_NUM_DATA_POINTERS]
Definition: vulkan.c:1210
AV_PIX_FMT_RGBA64
#define AV_PIX_FMT_RGBA64
Definition: pixfmt.h:455
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:785
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:1441
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:222
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
ff_vk_set_descriptor_image
int ff_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:1656
FFVkExecContext::qi
int qi
Definition: vulkan.h:161
FFVkBuffer::size
size_t size
Definition: vulkan.h:100
descriptor_props::dim_needed
int dim_needed
Definition: vulkan.c:1442
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:258
ff_vk_init_compute_pipeline
int ff_vk_init_compute_pipeline(FFVulkanContext *s, FFVulkanPipeline *pl, FFVkSPIRVShader *shd)
Definition: vulkan.c:1804
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:108
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:94
FFVulkanPipeline
Definition: vulkan.h:132
index
int index
Definition: gxfenc.c:89
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:1377
pthread_mutex_unlock
#define pthread_mutex_unlock(a)
Definition: ffprobe.c:79
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:1340
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:1214
AV_PIX_FMT_RGB24
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:68
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:294
FFVulkanDescriptorSetBinding
Definition: vulkan.h:84
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:265
for
for(k=2;k<=8;++k)
Definition: h264pred_template.c:425
print
static void print(AVTreeNode *t, int depth)
Definition: tree.c:44
AV_PIX_FMT_RGB48
#define AV_PIX_FMT_RGB48
Definition: pixfmt.h:451
size
int size
Definition: twinvq_data.h:10344
AV_NUM_DATA_POINTERS
#define AV_NUM_DATA_POINTERS
Definition: frame.h:341
FFVkExecContext::nb_frame_deps
int nb_frame_deps
Definition: vulkan.h:180
FFVkQueueFamilyCtx
Definition: vulkan.h:111
FFVkExecContext::sem_sig_val_dst_cnt
int sem_sig_val_dst_cnt
Definition: vulkan.h:192
FFVkBuffer::flags
VkMemoryPropertyFlagBits flags
Definition: vulkan.h:99
AVVkFrame::queue_family
uint32_t queue_family[AV_NUM_DATA_POINTERS]
Queue family of the images.
Definition: hwcontext_vulkan.h:329
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:153
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:256
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:1759
version
version
Definition: libkvazaar.c:314
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:1190
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:1437
ff_vk_exec_start
int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e)
Start/submit/wait an execution.
Definition: vulkan.c:510
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:244
FFVulkanPipeline::push_consts
VkPushConstantRange * push_consts
Definition: vulkan.h:140
FFVkSPIRVShader::shader
VkPipelineShaderStageCreateInfo shader
Definition: vulkan.h:80
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:1299
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:1202
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
FFVkBuffer::mem
VkDeviceMemory mem
Definition: vulkan.h:98
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:254
FFVkSPIRVShader::src
AVBPrint src
Definition: vulkan.h:78
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:457
filt
static const int8_t filt[NUMTAPS *2]
Definition: af_earwax.c:39
GLSLF
#define GLSLF(N, S,...)
Definition: vulkan.h:55
ff_vk_free_buf
void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf)
Definition: vulkan.c:1050
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:262
AV_PIX_FMT_RGB565
#define AV_PIX_FMT_RGB565
Definition: pixfmt.h:452
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:303
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:124
FFVulkanPipeline::push_consts_num
int push_consts_num
Definition: vulkan.h:141
ret
ret
Definition: filter_design.txt:187
pixfmt
enum AVPixelFormat pixfmt
Definition: kmsgrab.c:365
AV_PIX_FMT_0BGR
@ AV_PIX_FMT_0BGR
packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined
Definition: pixfmt.h:257
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:162
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:1443
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:141
GLSLA
#define GLSLA(...)
Definition: vulkan.h:50
FFVkQueueFamilyCtx::nb_queues
int nb_queues
Definition: vulkan.h:113
status
ov_status_e status
Definition: dnn_backend_openvino.c:110
free_data_buf
static void free_data_buf(void *opaque, uint8_t *data)
Definition: vulkan.c:1065
FFVkSPIRVShader
Definition: vulkan.h:76
FFVulkanPipeline::desc_set
FFVulkanDescriptorSet * desc_set
Definition: vulkan.h:147
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:1769
FFVkSPIRVShader::subgroup_info
VkPipelineShaderStageRequiredSubgroupSizeCreateInfo subgroup_info
Definition: vulkan.h:81
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:311
desc
const char * desc
Definition: libsvtav1.c:83
GLSLC
#define GLSLC(N, S)
Definition: vulkan.h:45
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:1701
flush
void(* flush)(AVBSFContext *ctx)
Definition: dts2pts_bsf.c:367
AVVkFrame::layout
VkImageLayout layout[AV_NUM_DATA_POINTERS]
Definition: hwcontext_vulkan.h:295
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:77
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:79
ff_vk_exec_discard_deps
void ff_vk_exec_discard_deps(FFVulkanContext *s, FFVkExecContext *e)
Definition: vulkan.c:546
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:1158
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:96
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:1572
int32_t
int32_t
Definition: audioconvert.c:56
ff_vk_exec_submit
int ff_vk_exec_submit(FFVulkanContext *s, FFVkExecContext *e)
Definition: vulkan.c:721
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:467
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:116
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:1226
FFVulkanPipeline::desc_bind
VkDescriptorBufferBindingInfoEXT * desc_bind
Definition: vulkan.h:148
ff_vk_shader_free
void ff_vk_shader_free(FFVulkanContext *s, FFVkSPIRVShader *shd)
Definition: vulkan.c:1399
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:1613
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:1086
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:965
FFVkExecContext::idx
uint32_t idx
Definition: vulkan.h:154
ff_vk_set_descriptor_sampler
int ff_vk_set_descriptor_sampler(FFVulkanContext *s, FFVulkanPipeline *pl, FFVkExecContext *e, int set, int bind, int offs, VkSampler *sampler)
Definition: vulkan.c:1629
FFVulkanPipeline::bound_buffer_indices
uint32_t * bound_buffer_indices
Definition: vulkan.h:149
FFVkQueueFamilyCtx::queue_family
int queue_family
Definition: vulkan.h:112
pthread_mutex_lock
#define pthread_mutex_lock(a)
Definition: ffprobe.c:75
FFVkExecContext::access_dst
VkAccessFlagBits * access_dst
Definition: vulkan.h:197