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