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